#ifdef PRECOMPILEDHEADERS #include "Strategic All.h" #else #include "Strategic Event Handler.h" #include "MemMan.h" #include "message.h" #include "Items.h" #include "Handle Items.h" #include "LaptopSave.h" #include "Tactical Save.h" #include "StrategicMap.h" #include "Quests.h" #include "Soldier Profile.h" #include "Game Event Hook.h" #include "Game Clock.h" #include "Interface Dialogue.h" #include "Random.h" #include "Overhead.h" #include "Strategic Town Loyalty.h" #include "Soldier Init List.h" #include "SaveLoadMap.h" #include "Soldier Create.h" #include "Soldier Add.h" #include "Renderworld.h" #include "Soldier Profile.h" #include "email.h" #include "strategic.h" #include "GameSettings.h" #include "history.h" #include "Town Militia.h" // added by Flugente #include "Campaign.h" // added by Flugente #endif #include "Luaglobal.h" #include "connect.h" #include "LuaInitNPCs.h" //forward declarations of common classes to eliminate includes class OBJECTTYPE; class SOLDIERTYPE; #define MEDUNA_ITEM_DROP_OFF_GRIDNO 10959 #define MEDUNA_ITEM_DROP_OFF_SECTOR_X 3 #define MEDUNA_ITEM_DROP_OFF_SECTOR_Y 14 #define MEDUNA_ITEM_DROP_OFF_SECTOR_Z 0 extern INT32 gsRobotGridNo; UINT32 guiPabloExtraDaysBribed = 0; UINT8 gubCambriaMedicalObjects; extern INT8 NumMercsNear( UINT8 ubProfileID, UINT8 ubMaxDist ); extern SECTOR_EXT_DATA SectorExternalData[256][4]; // WANNE: No more used for the new airport code //void DropOffItemsInMeduna( UINT8 ubOrderNum ); /* // WANNE: Dieser Code wird nicht mehr ausgeführt. Es gibt jetzt das PostalService.cpp::DeliverShipment() // In der Methode DeliverShipment() fehlt eine ganze Menge (PABLO Quests, ...) void BobbyRayPurchaseEventCallback( UINT8 ubOrderID ) { UINT8 i,j; UINT16 usItem; INT16 sMapPos, sStandardMapPos; UINT16 usNumberOfItems; BOOLEAN fSectorLoaded = FALSE; UINT16 usTotalNumberOfItemTypes; UINT32 uiCount = 0,uiStolenCount = 0; static UINT8 ubShipmentsSinceNoBribes = 0; UINT32 uiChanceOfTheft; BOOLEAN fPablosStoleSomething = FALSE; BOOLEAN fPablosStoleLastItem = FALSE; OBJECTTYPE *pObject=NULL; OBJECTTYPE *pStolenObject=NULL; BOOLEAN fThisShipmentIsFromJohnKulba = FALSE; //if it is, dont add an email UINT8 ubItemsDelivered; UINT8 ubTempNumItems; UINT8 ubItemsPurchased; sStandardMapPos = BOBBYR_SHIPPING_DEST_GRIDNO; // Haydent if(gpNewBobbyrShipments[ ubOrderID ].fActive && is_client) { DropOffItemsInSector( ubOrderID );//hayden return; } // if the delivery is for meduna, drop the items off there instead if( gpNewBobbyrShipments[ ubOrderID ].fActive && gpNewBobbyrShipments[ ubOrderID ].ubDeliveryLoc == BR_MEDUNA ) { DropOffItemsInMeduna( ubOrderID ); return; } if (CheckFact( FACT_NEXT_PACKAGE_CAN_BE_LOST, 0 )) { SetFactFalse( FACT_NEXT_PACKAGE_CAN_BE_LOST ); if (Random( 100 ) < 50) { // lose the whole shipment! gpNewBobbyrShipments[ ubOrderID ].fActive = FALSE; SetFactTrue( FACT_LAST_SHIPMENT_CRASHED ); return; } } else if (CheckFact( FACT_NEXT_PACKAGE_CAN_BE_DELAYED, 0 )) { // shipment went to wrong airport... reroute all items to a temporary // gridno to represent the other airport (and damage them) SetFactTrue( FACT_LAST_SHIPMENT_WENT_TO_WRONG_AIRPORT ); sStandardMapPos = LOST_SHIPMENT_GRIDNO; SetFactFalse( FACT_NEXT_PACKAGE_CAN_BE_DELAYED ); } else if ( (gTownLoyalty[ DRASSEN ].ubRating < 20) || StrategicMap[ CALCULATE_STRATEGIC_INDEX( 13, MAP_ROW_B ) ].fEnemyControlled ) { // loss of the whole shipment gpNewBobbyrShipments[ ubOrderID ].fActive = FALSE; SetFactTrue( FACT_AGENTS_PREVENTED_SHIPMENT ); return; } //Get the number of item types usTotalNumberOfItemTypes = gpNewBobbyrShipments[ ubOrderID ].ubNumberPurchases; //Must get the total number of items ( all item types plus how many of each item type ordered ) usNumberOfItems = 0; for(i=0; idata.gun.ubGunShotsLeft = 0; } ubItemsDelivered = 0; //add all the items that were purchased ubItemsPurchased = gpNewBobbyrShipments[ ubOrderID ].BobbyRayPurchase[i].ubNumberPurchased; for( j=0; j < ubItemsPurchased; j++) { // Pablos might steal stuff but only: // - if it's one of a group of items // - if he didn't steal the previous item in the group (so he never steals > 50%) // - if he has been bribed, he only sneaks out stuff which is cheap if( fSectorLoaded ) { // add ubItemsPurchased to the chance of theft so the chance increases when there are more items of a kind being ordered if ( !fPablosStoleLastItem && uiChanceOfTheft > 0 && Random( 100 ) < (uiChanceOfTheft + ubItemsPurchased) ) { uiStolenCount++; sMapPos = PABLOS_STOLEN_DEST_GRIDNO; // off screen! fPablosStoleSomething = TRUE; fPablosStoleLastItem = TRUE; } else { sMapPos = sStandardMapPos; fPablosStoleLastItem = FALSE; if (sStandardMapPos == LOST_SHIPMENT_GRIDNO) { // damage the item a random amount! gTempObject[0]->data.objectStatus = (INT8) ( ( (70 + Random( 11 )) * (INT32) gTempObject[0]->data.objectStatus ) / 100 ); // make damn sure it can't hit 0 if (gTempObject[0]->data.objectStatus == 0) { gTempObject[0]->data.objectStatus = 1; } AddItemToPool( sMapPos, &gTempObject, -1, 0, 0, 0 ); } else { // record # delivered for later addition... ubItemsDelivered++; } } } else { if ( j > 1 && !fPablosStoleLastItem && uiChanceOfTheft > 0 && Random( 100 ) < (uiChanceOfTheft + j) ) { pStolenObject[ uiStolenCount ] = gTempObject; uiStolenCount++; fPablosStoleSomething = TRUE; fPablosStoleLastItem = TRUE; } else { fPablosStoleLastItem = FALSE; //else we are not currently in the sector, so we build an array of items to add in one lump //add the item to the item array if (sStandardMapPos == LOST_SHIPMENT_GRIDNO) { // damage the item a random amount! gTempObject[0]->data.objectStatus = (INT8) ( ( (70 + Random( 11 )) * (INT32) gTempObject[0]->data.objectStatus ) / 100 ); // make damn sure it can't hit 0 if (gTempObject[0]->data.objectStatus == 0) { gTempObject[0]->data.objectStatus = 1; } pObject[ uiCount ] = gTempObject; uiCount++; } else { ubItemsDelivered++; } } } } if ( gpNewBobbyrShipments[ ubOrderID ].BobbyRayPurchase[i].ubNumberPurchased == 1 && ubItemsDelivered == 1 ) { // the item in gTempObject will be the item to deliver if( fSectorLoaded ) { AddItemToPool( sStandardMapPos, &gTempObject, -1, 0, 0, 0 ); } else { pObject[ uiCount ] = gTempObject; uiCount++; } } else { while ( ubItemsDelivered ) { // treat 0s as 1s :-) ubTempNumItems = __min( ubItemsDelivered, ItemSlotLimit(&gTempObject, STACK_SIZE_LIMIT) ); CreateItems( usItem, gpNewBobbyrShipments[ ubOrderID ].BobbyRayPurchase[i].bItemQuality, ubTempNumItems, &gTempObject ); // stack as many as possible if( fSectorLoaded ) { AddItemToPool( sStandardMapPos, &gTempObject, -1, 0, 0, 0 ); } else { pObject[ uiCount ] = gTempObject; uiCount++; } ubItemsDelivered -= ubTempNumItems; } } } //if we are NOT currently in the sector if( !fSectorLoaded ) { //add all the items from the array that was built above sMapPos = PABLOS_STOLEN_DEST_GRIDNO; //The item are to be added to the Top part of Drassen, grid loc's 10112, 9950 if( !AddItemsToUnLoadedSector( BOBBYR_SHIPPING_DEST_SECTOR_X, BOBBYR_SHIPPING_DEST_SECTOR_Y, BOBBYR_SHIPPING_DEST_SECTOR_Z, sStandardMapPos, uiCount, pObject, 0, 0, 0, -1, FALSE ) ) { //Error adding the items //return; } if (uiStolenCount > 0) { if( !AddItemsToUnLoadedSector( BOBBYR_SHIPPING_DEST_SECTOR_X, BOBBYR_SHIPPING_DEST_SECTOR_Y, BOBBYR_SHIPPING_DEST_SECTOR_Z, PABLOS_STOLEN_DEST_GRIDNO, uiStolenCount, pStolenObject, 0, 0, 0, -1, FALSE ) ) { //Error adding the items //return; } } delete[] pObject ; delete[]( pStolenObject ); pObject = NULL; pStolenObject = NULL; } if (fPablosStoleSomething) { SetFactTrue( FACT_PABLOS_STOLE_FROM_LATEST_SHIPMENT ); } else { SetFactFalse( FACT_PABLOS_STOLE_FROM_LATEST_SHIPMENT ); } SetFactFalse( FACT_PLAYER_FOUND_ITEMS_MISSING ); SetFactFalse( FACT_LARGE_SIZED_OLD_SHIPMENT_WAITING ); if ( CheckFact( FACT_NEXT_PACKAGE_CAN_BE_DELAYED, 0 ) ) { SetFactFalse( FACT_MEDIUM_SIZED_SHIPMENT_WAITING ); SetFactFalse( FACT_LARGE_SIZED_SHIPMENT_WAITING ); SetFactFalse( FACT_REALLY_NEW_BOBBYRAY_SHIPMENT_WAITING ); } else { if (usNumberOfItems - uiStolenCount <= 5) { SetFactFalse( FACT_MEDIUM_SIZED_SHIPMENT_WAITING ); SetFactFalse( FACT_LARGE_SIZED_SHIPMENT_WAITING ); } else if (usNumberOfItems - uiStolenCount <= 15) { SetFactTrue( FACT_MEDIUM_SIZED_SHIPMENT_WAITING ); SetFactFalse( FACT_LARGE_SIZED_SHIPMENT_WAITING ); } else { SetFactFalse( FACT_MEDIUM_SIZED_SHIPMENT_WAITING ); SetFactTrue( FACT_LARGE_SIZED_SHIPMENT_WAITING ); } // this shipment isn't old yet... SetFactTrue( FACT_REALLY_NEW_BOBBYRAY_SHIPMENT_WAITING ); // set up even to make shipment "old" AddSameDayStrategicEvent( EVENT_SET_BY_NPC_SYSTEM, GetWorldMinutesInDay() + 120, FACT_REALLY_NEW_BOBBYRAY_SHIPMENT_WAITING ); } //We have received the shipment so fActice becomes fALSE gpNewBobbyrShipments[ ubOrderID ].fActive = FALSE; //Stop time compression the game StopTimeCompression( ); //if the shipment is NOT from John Kulba, send an email if( !fThisShipmentIsFromJohnKulba ) { //Add an email from Bobby r telling the user the shipment 'Should' be there AddEmail( BOBBYR_SHIPMENT_ARRIVED, BOBBYR_SHIPMENT_ARRIVED_LENGTH, BOBBY_R, GetWorldTotalMin(), -1 ); } else { //if the shipment is from John Kulba //Add an email from kulba telling the user the shipment is there AddEmail( JOHN_KULBA_GIFT_IN_DRASSEN, JOHN_KULBA_GIFT_IN_DRASSEN_LENGTH, JOHN_KULBA, GetWorldTotalMin(), -1 ); } } */ void HandleDelayedItemsArrival( UINT32 uiReason ) { // LuaHandleDelayedItemsArrival( uiReason, 0); // This function moves all the items that Pablos has stolen // (or items that were delayed) to the arrival location for new shipments, INT32 sStartGridNo; UINT32 uiNumWorldItems, uiLoop; BOOLEAN fOk; std::vector pTemp;//dnl ch75 271013 UINT8 ubLoop; if (uiReason == NPC_SYSTEM_EVENT_ACTION_PARAM_BONUS + NPC_ACTION_RETURN_STOLEN_SHIPMENT_ITEMS ) { if ( gMercProfiles[ PABLO ].bMercStatus == MERC_IS_DEAD ) { // nothing arrives then! return; } // update some facts... SetFactTrue( FACT_PABLO_RETURNED_GOODS ); SetFactFalse( FACT_PABLO_PUNISHED_BY_PLAYER ); sStartGridNo = PABLOS_STOLEN_DEST_GRIDNO; // add random items for (ubLoop = 0; ubLoop < 2; ubLoop++) { switch( Random( 10 ) ) { case 0: // 1 in 10 chance of a badly damaged gas mask CreateItem( GASMASK, (INT8) (20 + Random( 10 )), &gTempObject ); break; case 1: case 2: // 2 in 10 chance of a battered Desert Eagle CreateItem( DESERTEAGLE, (INT8) (40 + Random( 10 )), &gTempObject ); break; case 3: case 4: case 5: // 3 in 10 chance of a stun grenade CreateItem( STUN_GRENADE, (INT8) (70 + Random( 10 )), &gTempObject ); break; case 6: case 7: case 8: case 9: // 4 in 10 chance of two 38s! CreateItems( SW38, (INT8) (90 + Random( 10 )), 2, &gTempObject ); break; } if ( ( gWorldSectorX == BOBBYR_SHIPPING_DEST_SECTOR_X ) && ( gWorldSectorY == BOBBYR_SHIPPING_DEST_SECTOR_Y ) && ( gbWorldSectorZ == BOBBYR_SHIPPING_DEST_SECTOR_Z ) ) { AddItemToPool( BOBBYR_SHIPPING_DEST_GRIDNO, &gTempObject, -1, 0, 0, 0 ); } else { AddItemsToUnLoadedSector( BOBBYR_SHIPPING_DEST_SECTOR_X, BOBBYR_SHIPPING_DEST_SECTOR_Y, BOBBYR_SHIPPING_DEST_SECTOR_Z, BOBBYR_SHIPPING_DEST_GRIDNO, 1, &gTempObject, 0, 0, 0, -1, FALSE ); } } } else if (uiReason == FACT_PACKAGE_DAMAGED) { sStartGridNo = LOST_SHIPMENT_GRIDNO; } else { return; } // If the Drassen airport sector is already loaded, move the item pools... if ( ( gWorldSectorX == BOBBYR_SHIPPING_DEST_SECTOR_X ) && ( gWorldSectorY == BOBBYR_SHIPPING_DEST_SECTOR_Y ) && ( gbWorldSectorZ == BOBBYR_SHIPPING_DEST_SECTOR_Z ) ) { // sector is loaded! // just move the hidden item pool MoveItemPools( sStartGridNo, BOBBYR_SHIPPING_DEST_GRIDNO, 0, 0 ); } else { // otherwise load the saved items from the item file and change the records of their locations fOk = GetNumberOfWorldItemsFromTempItemFile( BOBBYR_SHIPPING_DEST_SECTOR_X, BOBBYR_SHIPPING_DEST_SECTOR_Y, BOBBYR_SHIPPING_DEST_SECTOR_Z, &uiNumWorldItems, FALSE ); if (!fOk) { return; } pTemp.resize(uiNumWorldItems);//dnl ch75 271013 fOk = LoadWorldItemsFromTempItemFile( BOBBYR_SHIPPING_DEST_SECTOR_X, BOBBYR_SHIPPING_DEST_SECTOR_Y, BOBBYR_SHIPPING_DEST_SECTOR_Z, pTemp ); if (fOk) { for (uiLoop = 0; uiLoop < uiNumWorldItems; uiLoop++) { if (pTemp[uiLoop].sGridNo == PABLOS_STOLEN_DEST_GRIDNO) { pTemp[uiLoop].sGridNo = BOBBYR_SHIPPING_DEST_GRIDNO; } } AddWorldItemsToUnLoadedSector( BOBBYR_SHIPPING_DEST_SECTOR_X, BOBBYR_SHIPPING_DEST_SECTOR_Y, BOBBYR_SHIPPING_DEST_SECTOR_Z, 0, uiNumWorldItems, pTemp, TRUE ); } } } void AddSecondAirportAttendant( void ) { //LetLuaHandleEarlyMorningEvents(2); //#if 0 // add the second airport attendant to the Drassen airport... gMercProfiles[99].sSectorX = BOBBYR_SHIPPING_DEST_SECTOR_X; gMercProfiles[99].sSectorY = BOBBYR_SHIPPING_DEST_SECTOR_Y; gMercProfiles[99].bSectorZ = BOBBYR_SHIPPING_DEST_SECTOR_Z; //#endif } void SetPabloToUnbribed( void ) { // LetLuaHandleEarlyMorningEvents(3); //#if 0 if (guiPabloExtraDaysBribed > 0) { // set new event for later on, because the player gave Pablo more money! AddFutureDayStrategicEvent( EVENT_SET_BY_NPC_SYSTEM, GetWorldMinutesInDay(), FACT_PABLOS_BRIBED, guiPabloExtraDaysBribed ); guiPabloExtraDaysBribed = 0; } else { SetFactFalse( FACT_PABLOS_BRIBED ); } //#endif } void HandlePossiblyDamagedPackage( void ) { // LetLuaHandleEarlyMorningEvents(1); //#if 0 if (Random( 100 ) < 70) { SetFactTrue( FACT_PACKAGE_DAMAGED ); HandleDelayedItemsArrival( FACT_PACKAGE_DAMAGED ); } else { // shipment lost forever! SetFactTrue( FACT_PACKAGE_LOST_PERMANENTLY ); } // whatever happened, the shipment is no longer delayed SetFactFalse( FACT_SHIPMENT_DELAYED_24_HOURS ); //#endif } void CheckForKingpinsMoneyMissing( BOOLEAN fFirstCheck ) { // LuaCheckForKingpinsMoneyMissing ( fFirstCheck , 0 ); //#if 0 UINT32 uiLoop; UINT32 uiTotalCash = 0; BOOLEAN fKingpinWillDiscover = FALSE, fKingpinDiscovers = FALSE; // money in D5b1 must be less than 30k for ( uiLoop = 0; uiLoop < guiNumWorldItems; uiLoop++ ) { // loop through all items, look for ownership if ( gWorldItems[ uiLoop ].fExists && gWorldItems[ uiLoop ].object.usItem == MONEY ) { uiTotalCash += gWorldItems[uiLoop].object[0]->data.money.uiMoneyAmount; } } // This function should be called every time sector D5/B1 is unloaded! if ( fFirstCheck ) { if ( CheckFact( FACT_KINGPIN_WILL_LEARN_OF_MONEY_GONE, 0 ) == TRUE ) { // unnecessary return; } if ( uiTotalCash < 30000 ) { // add history log here AddHistoryToPlayersLog( HISTORY_FOUND_MONEY, 0, GetWorldTotalMin(), gWorldSectorX, gWorldSectorY ); SetFactTrue( FACT_KINGPIN_WILL_LEARN_OF_MONEY_GONE ); } } if ( CheckFact( FACT_KINGPIN_DEAD, 0 ) == TRUE ) { return; } if ( uiTotalCash < 30000 ) { if ( fFirstCheck ) { // add event to make Kingpin aware, two days from now fKingpinWillDiscover = TRUE; } else { fKingpinDiscovers = TRUE; } } if ( fKingpinWillDiscover ) { // set event for next day to check for real AddFutureDayStrategicEvent( EVENT_SET_BY_NPC_SYSTEM, Random( 120 ), FACT_KINGPIN_KNOWS_MONEY_GONE, 1 ); // the sector is unloaded NOW so set Kingpin's balance and remove the cash gMercProfiles[ KINGPIN ].iBalance = - (30000 - (INT32) uiTotalCash); // remove all money from map for ( uiLoop = 0; uiLoop < guiNumWorldItems; uiLoop++ ) { // loop through all items, look for ownership if ( gWorldItems[ uiLoop ].fExists && gWorldItems[ uiLoop ].object.usItem == MONEY ) { // remove! gWorldItems[ uiLoop ].fExists = FALSE; } } } else if ( fKingpinDiscovers ) { // ok start things up here! SetFactTrue( FACT_KINGPIN_KNOWS_MONEY_GONE ); // set event 2 days from now that if the player has not given Kingpin his money back, // he sends email to the player AddFutureDayStrategicEvent( EVENT_SET_BY_NPC_SYSTEM, Random( 120 ), FACT_KINGPIN_KNOWS_MONEY_GONE, 2 ); } //#endif } void HandleNPCSystemEvent( UINT32 uiEvent ) { // LetLuaHandleNPCSystemEvent( uiEvent, 0 ); //#if 0 if (uiEvent < NPC_SYSTEM_EVENT_ACTION_PARAM_BONUS) { switch( uiEvent ) { case FACT_PABLOS_BRIBED: // set Pacos to unbribed SetPabloToUnbribed(); break; case FACT_REALLY_NEW_BOBBYRAY_SHIPMENT_WAITING: // the shipment is no longer really new SetFactFalse( FACT_REALLY_NEW_BOBBYRAY_SHIPMENT_WAITING ); if (CheckFact( FACT_LARGE_SIZED_SHIPMENT_WAITING, 0 )) { // set "really heavy old shipment" fact SetFactTrue( FACT_LARGE_SIZED_OLD_SHIPMENT_WAITING ); } break; case FACT_SHIPMENT_DELAYED_24_HOURS: case FACT_24_HOURS_SINCE_DOCTOR_TALKED_TO: case FACT_24_HOURS_SINCE_JOEY_RESCUED: SetFactTrue( (UINT16) uiEvent ); break; case FACT_KINGPIN_KNOWS_MONEY_GONE: // more generally events for kingpin quest if ( CheckFact( FACT_KINGPIN_KNOWS_MONEY_GONE, 0 ) == FALSE ) { // check for real whether to start quest CheckForKingpinsMoneyMissing( FALSE ); } else if ( CheckFact( FACT_KINGPIN_DEAD, 0 ) == FALSE ) { if ( gubQuest[ QUEST_KINGPIN_MONEY ] == QUESTNOTSTARTED ) { // KP knows money is gone, hasn't told player, if this event is called then the 2 // days are up... send email #ifdef JA2UB // no UB #else AddEmail( KING_PIN_LETTER, KING_PIN_LETTER_LENGTH, KING_PIN, GetWorldTotalMin(), -1, -1 , TYPE_EMAIL_EMAIL_EDT ); #endif StartQuest( QUEST_KINGPIN_MONEY, gMercProfiles[ KINGPIN ].sSectorX, gMercProfiles[ KINGPIN ].sSectorY ); // add event to send terrorists two days from now AddFutureDayStrategicEvent( EVENT_SET_BY_NPC_SYSTEM, Random( 120 ), FACT_KINGPIN_KNOWS_MONEY_GONE, 2 ); } else if ( gubQuest[ QUEST_KINGPIN_MONEY ] == QUESTINPROGRESS ) { // knows money gone, quest is still in progress // event indicates Kingpin can start to send terrorists SetFactTrue( FACT_KINGPIN_CAN_SEND_ASSASSINS ); gMercProfiles[ SPIKE ].sSectorX = gModSettings.ubSpikeNewSectorX; //5 gMercProfiles[ SPIKE ].sSectorY = gModSettings.ubSpikeNewSectorY; //MAP_ROW_C gMercProfiles[ SPIKE ].bSectorZ = gModSettings.ubSpikeNewSectorZ; //0 gTacticalStatus.fCivGroupHostile[ KINGPIN_CIV_GROUP ] = CIV_GROUP_WILL_BECOME_HOSTILE; } } break; } } else { switch( uiEvent - NPC_SYSTEM_EVENT_ACTION_PARAM_BONUS ) { case NPC_ACTION_RETURN_STOLEN_SHIPMENT_ITEMS: HandleDelayedItemsArrival( uiEvent ); break; case NPC_ACTION_SET_RANDOM_PACKAGE_DAMAGE_TIMER: HandlePossiblyDamagedPackage(); break; case NPC_ACTION_ENABLE_CAMBRIA_DOCTOR_BONUS: SetFactTrue( FACT_WILLIS_HEARD_ABOUT_JOEY_RESCUE ); break; case NPC_ACTION_TRIGGER_END_OF_FOOD_QUEST: if ( gMercProfiles[ FATHER ].bMercStatus != MERC_IS_DEAD ) { EndQuest( QUEST_FOOD_ROUTE, 10, MAP_ROW_A ); SetFactTrue( FACT_FOOD_QUEST_OVER ); } break; case NPC_ACTION_DELAYED_MAKE_BRENDA_LEAVE: // silversurfer: reenabled this // but only play Brendas quote when we are near enough to hear her if ( NumMercsNear( 85, 8 ) > 0 ) TriggerNPCRecord( 85, 9 ); SetFactTrue( FACT_BRENDA_PATIENCE_TIMER_EXPIRED ); break; case NPC_ACTION_SET_DELAY_TILL_GIRLS_AVAILABLE: HandleNPCDoAction( 107, NPC_ACTION_SET_GIRLS_AVAILABLE, 0 ); break; case NPC_ACTION_READY_ROBOT: { if ( CheckFact( FACT_FIRST_ROBOT_DESTROYED, 0 ) ) { // second robot ready SetFactTrue( FACT_ROBOT_READY_SECOND_TIME ); // resurrect robot gMercProfiles[ ROBOT ].bLife = gMercProfiles[ ROBOT ].bLifeMax; gMercProfiles[ ROBOT ].bMercStatus = MERC_OK; } else { // first robot ready SetFactTrue( FACT_ROBOT_READY ); } gMercProfiles[ ROBOT ].sSectorX = gMercProfiles[ MADLAB ].sSectorX; gMercProfiles[ ROBOT ].sSectorY = gMercProfiles[ MADLAB ].sSectorY; gMercProfiles[ ROBOT ].bSectorZ = gMercProfiles[ MADLAB ].bSectorZ; } break; case NPC_ACTION_ADD_JOEY_TO_WORLD: // If Joey is not dead, escorted, or already delivered if ( gMercProfiles[ JOEY ].bMercStatus != MERC_IS_DEAD && !CheckFact( FACT_JOEY_ESCORTED, 0 ) && gMercProfiles[ JOEY ].sSectorX == gModSettings.ubJoeyPrimarySectorX && //4 gMercProfiles[ JOEY ].sSectorY == gModSettings.ubJoeyPrimarySectorY && //MAP_ROW_D gMercProfiles[ JOEY ].bSectorZ == gModSettings.ubJoeyPrimarySectorZ ) //1 { SOLDIERTYPE * pJoey; pJoey = FindSoldierByProfileID( JOEY, FALSE ); if (pJoey ) { // he's in the currently loaded sector...delay this an hour! AddSameDayStrategicEvent( EVENT_SET_BY_NPC_SYSTEM, GetWorldMinutesInDay() + 60, NPC_SYSTEM_EVENT_ACTION_PARAM_BONUS + NPC_ACTION_ADD_JOEY_TO_WORLD ); } else { // move Joey from caves to San Mona gMercProfiles[ JOEY ].sSectorX = gModSettings.ubJoeyAlternateSectorX; //5 gMercProfiles[ JOEY ].sSectorY = gModSettings.ubJoeyAlternateSectorY; //MAP_ROW_C gMercProfiles[ JOEY ].bSectorZ = gModSettings.ubJoeyAlternateSectorZ; //0 } } break; case NPC_ACTION_SEND_ENRICO_MIGUEL_EMAIL: #ifdef JA2UB // no UB #else AddEmail( ENRICO_MIGUEL, ENRICO_MIGUEL_LENGTH, MAIL_ENRICO, GetWorldTotalMin(), -1, -1 , TYPE_EMAIL_EMAIL_EDT); #endif break; case NPC_ACTION_TIMER_FOR_VEHICLE: SetFactTrue( FACT_OK_USE_HUMMER ); break; case NPC_ACTION_FREE_KIDS: SetFactTrue( FACT_KIDS_ARE_FREE ); break; default: break; } } //#endif } void HandleEarlyMorningEvents( void ) { // Flugente: no reason to put this into LUA for ( UINT8 sX = 1; sX < MAP_WORLD_X - 1; ++sX ) { for ( UINT8 sY = 1; sY < MAP_WORLD_X - 1; ++sY ) { UINT8 sector = SECTOR( sX, sY ); SECTORINFO *pSectorInfo = &(SectorInfo[sector]); // A flag prevents us from exploiting the civilian recruitment mechanic. Every x hours, we reset it if ( pSectorInfo ) { pSectorInfo->usSectorInfoFlag &= ~SECTORINFO_VOLUNTEERS_RECENTLY_RECRUITED; } } } #ifdef LUA_STRATEGY_EVENT_HANDLER LetLuaHandleEarlyMorningEvents(0); #else UINT32 cnt; UINT32 uiAmount; // loop through all *NPCs* and reset "default response used recently" flags for (cnt = 0; cnt < NUM_PROFILES; ++cnt) { if ( gMercProfiles[cnt].Type == PROFILETYPE_RPC || gMercProfiles[cnt].Type == PROFILETYPE_NPC || gMercProfiles[cnt].Type == PROFILETYPE_VEHICLE ) { gMercProfiles[cnt].bFriendlyOrDirectDefaultResponseUsedRecently = FALSE; gMercProfiles[cnt].bRecruitDefaultResponseUsedRecently = FALSE; gMercProfiles[cnt].bThreatenDefaultResponseUsedRecently = FALSE; gMercProfiles[cnt].ubMiscFlags2 &= (~PROFILE_MISC_FLAG2_BANDAGED_TODAY); } } // reset Father Walker's drunkenness level! gMercProfiles[ FATHER ].bNPCData = (INT8) Random( 4 ); // set Walker's location if ( Random( 2 ) ) { // move the father to the other sector, provided neither are loaded if ( ! ( ( gWorldSectorX == 13) && ( ( gWorldSectorY == MAP_ROW_C) || gWorldSectorY == MAP_ROW_D ) && ( gbWorldSectorZ == 0 ) ) ) { gMercProfiles[ FATHER ].sSectorX = 13; // swap his location if (gMercProfiles[ FATHER ].sSectorY == MAP_ROW_C) { gMercProfiles[ FATHER ].sSectorY = MAP_ROW_D; } else { gMercProfiles[ FATHER ].sSectorY = MAP_ROW_C; } } } if( gMercProfiles[ TONY ].ubLastDateSpokenTo > 0 && !( gWorldSectorX == 5 && gWorldSectorY == MAP_ROW_C && gbWorldSectorZ == 0 ) ) { // San Mona C5 is not loaded so make Tony possibly not availableif if (Random( 99 ) < gGameExternalOptions.ubChanceTonyAvailable) // silversurfer/SANDRO { // Tony IS available SetFactFalse( FACT_TONY_NOT_AVAILABLE ); gMercProfiles[ TONY ].sSectorX = 5; gMercProfiles[ TONY ].sSectorY = MAP_ROW_C; } else { // Tony is NOT available SetFactTrue( FACT_TONY_NOT_AVAILABLE ); gMercProfiles[ TONY ].sSectorX = 0; gMercProfiles[ TONY ].sSectorY = 0; } } if ( gMercProfiles[ DEVIN ].ubLastDateSpokenTo == 0 ) { // Does Devin move? gMercProfiles[ DEVIN ].bNPCData++; if ( gMercProfiles[ DEVIN ].bNPCData > 3 ) { if ( ! ( (gWorldSectorX == gMercProfiles[ DEVIN ].sSectorX) && (gWorldSectorY == gMercProfiles[DEVIN].sSectorY) && (gbWorldSectorZ == 0) ) ) { // ok, Devin's sector not loaded, so time to move! // might be same sector as before, if so, oh well! switch( Random( 5 ) ) { case 0: gMercProfiles[ DEVIN ].sSectorX = 9; gMercProfiles[ DEVIN ].sSectorY = MAP_ROW_G; break; case 1: gMercProfiles[ DEVIN ].sSectorX = 13; gMercProfiles[ DEVIN ].sSectorY = MAP_ROW_D; break; case 2: gMercProfiles[ DEVIN ].sSectorX = 5; gMercProfiles[ DEVIN ].sSectorY = MAP_ROW_C; break; case 3: gMercProfiles[ DEVIN ].sSectorX = 2; gMercProfiles[ DEVIN ].sSectorY = MAP_ROW_H; break; case 4: gMercProfiles[ DEVIN ].sSectorX = 6; gMercProfiles[ DEVIN ].sSectorY = MAP_ROW_C; break; } } } } // Does Hamous move? // stop moving the truck if Hamous is dead!! // stop moving them if the player has the truck or Hamous is hired! if ( gMercProfiles[ HAMOUS ].bLife > 0 && FindSoldierByProfileID( HAMOUS, TRUE ) == NULL && FindSoldierByProfileID( PROF_ICECREAM, TRUE ) == NULL && (! ( (gWorldSectorX == gMercProfiles[ HAMOUS ].sSectorX) && (gWorldSectorY == gMercProfiles[HAMOUS].sSectorY) && (gbWorldSectorZ == 0) )) ) { // ok, HAMOUS's sector not loaded, so time to move! // might be same sector as before, if so, oh well! switch( Random( 5 ) ) { case 0: gMercProfiles[ HAMOUS ].sSectorX = 6; gMercProfiles[ HAMOUS ].sSectorY = MAP_ROW_G; gMercProfiles[ PROF_ICECREAM ].sSectorX = 6; gMercProfiles[ PROF_ICECREAM ].sSectorY = MAP_ROW_G; break; case 1: gMercProfiles[ HAMOUS ].sSectorX = 12; gMercProfiles[ HAMOUS ].sSectorY = MAP_ROW_F; gMercProfiles[ PROF_ICECREAM ].sSectorX = 12; gMercProfiles[ PROF_ICECREAM ].sSectorY = MAP_ROW_F; break; case 2: gMercProfiles[ HAMOUS ].sSectorX = 7; gMercProfiles[ HAMOUS ].sSectorY = MAP_ROW_D; gMercProfiles[ PROF_ICECREAM ].sSectorX = 7; gMercProfiles[ PROF_ICECREAM ].sSectorY = MAP_ROW_D; break; case 3: gMercProfiles[ HAMOUS ].sSectorX = 3; gMercProfiles[ HAMOUS ].sSectorY = MAP_ROW_D; gMercProfiles[ PROF_ICECREAM ].sSectorX = 3; gMercProfiles[ PROF_ICECREAM ].sSectorY = MAP_ROW_D; break; case 4: gMercProfiles[ HAMOUS ].sSectorX = 9; gMercProfiles[ HAMOUS ].sSectorY = MAP_ROW_D; gMercProfiles[ PROF_ICECREAM ].sSectorX = 9; gMercProfiles[ PROF_ICECREAM ].sSectorY = MAP_ROW_D; break; } } // Does Rat take off? if ( gMercProfiles[ RAT ].bNPCData != 0 ) { gMercProfiles[ RAT ].sSectorX = 0; gMercProfiles[ RAT ].sSectorY = 0; gMercProfiles[ RAT ].bSectorZ = 0; } // Does John leave country after quest completion? if ( gubQuest[ QUEST_ESCORT_TOURISTS ] == QUESTDONE && (gMercProfiles[ JOHN ].sSectorX == 13) && (gMercProfiles[ JOHN ].sSectorY == MAP_ROW_B) && (gMercProfiles[ JOHN ].bSectorZ == 0) ) { gMercProfiles[ JOHN ].sSectorX = 0; gMercProfiles[ JOHN ].sSectorY = 0; gMercProfiles[ JOHN ].bSectorZ = 0; } // Does Mary leave country after quest completion? if ( gubQuest[ QUEST_ESCORT_TOURISTS ] == QUESTDONE && (gMercProfiles[ MARY ].sSectorX == 13) && (gMercProfiles[ MARY ].sSectorY == MAP_ROW_B) && (gMercProfiles[ MARY ].bSectorZ == 0) ) { gMercProfiles[ MARY ].sSectorX = 0; gMercProfiles[ MARY ].sSectorY = 0; gMercProfiles[ MARY ].bSectorZ = 0; } // Empty money from pockets of Vince 69, Willis 80, and Jenny 132 SetMoneyInSoldierProfile( VINCE, 0 ); SetMoneyInSoldierProfile( STEVE, 0 ); // Steven Willis SetMoneyInSoldierProfile( JENNY, 0 ); // Vince is no longer expecting money SetFactFalse( FACT_VINCE_EXPECTING_MONEY ); // Reset Darren's balance and money gMercProfiles[ DARREN ].iBalance = 0; SetMoneyInSoldierProfile( DARREN, 15000 ); // set Carmen to be placed on the map in case he moved and is waiting off screen if (gMercProfiles[ CARMEN ].ubMiscFlags2 & PROFILE_MISC_FLAG2_DONT_ADD_TO_SECTOR) { gMercProfiles[ CARMEN ].ubMiscFlags2 &= ~(PROFILE_MISC_FLAG2_DONT_ADD_TO_SECTOR); // move Carmen to C13 gMercProfiles[ CARMEN ].sSectorX = 13; gMercProfiles[ CARMEN ].sSectorY = MAP_ROW_C; gMercProfiles[ CARMEN ].bSectorZ = 0; // we should also reset # of terrorist heads and give him cash if (gMercProfiles[ CARMEN ].bNPCData2 > 0) { if (gMercProfiles[ CARMEN ].uiMoney < 10000) { uiAmount = 0; } else { uiAmount = gMercProfiles[ CARMEN ].uiMoney; } uiAmount += 10000 * gMercProfiles[ CARMEN ].bNPCData2; SetMoneyInSoldierProfile( CARMEN, uiAmount ); gMercProfiles[ CARMEN ].bNPCData2 = 0; for ( cnt = HEAD_1; cnt <= HEAD_7; cnt++ ) { RemoveObjectFromSoldierProfile( CARMEN, (UINT8) cnt ); } } } else { // randomize where he'll be today... so long as his sector's not loaded if ( gMercProfiles[ CARMEN ].sSectorX != gWorldSectorX || gMercProfiles[ CARMEN ].sSectorY != gWorldSectorY ) { switch( Random( 3 ) ) { case 0: gMercProfiles[ CARMEN ].sSectorX = 5; gMercProfiles[ CARMEN ].sSectorY = MAP_ROW_C; break; case 1: gMercProfiles[ CARMEN ].sSectorX = 13; gMercProfiles[ CARMEN ].sSectorY = MAP_ROW_C; break; case 2: gMercProfiles[ CARMEN ].sSectorX = 9; gMercProfiles[ CARMEN ].sSectorY = MAP_ROW_G; break; } // he should have $5000... unless the player forgot to meet him if (gMercProfiles[ CARMEN ].uiMoney < 5000) { SetMoneyInSoldierProfile( CARMEN, 5000 ); } } } if ( PreRandom( 3 ) == 0 ) { SetFactTrue( FACT_DAVE_HAS_GAS ); } else { SetFactFalse( FACT_DAVE_HAS_GAS ); } if ( gWorldSectorX == gModSettings.ubHospitalSectorX && gWorldSectorY == gModSettings.ubHospitalSectorY && gbWorldSectorZ == gModSettings.ubHospitalSectorZ ) { CheckForMissingHospitalSupplies(); } #endif } // Flugente: creature raids void HandleRaidEventPlanning() { INT32 personnelgain[3]; // the raid order is bloodcats/zombies/bandits for ( int raidtype = 0; raidtype < 3; ++raidtype ) { // reset knowledge of these raids - if the player wants to know, they will have to buy anew SetFactFalse( FACT_RAID_KNOWN_BLOODCATS + raidtype ); personnelgain[raidtype] = 0; if ( raidtype == 0 ) { if ( !gGameExternalOptions.gRaid_Bloodcats ) continue; // if the lair has been cleared, way less growth if ( CheckFact(FACT_BLOODCAT_LAIR_CLEANED, NO_PROFILE) ) personnelgain[raidtype] += gGameExternalOptions.gRaidReplenish_BaseValue; else personnelgain[raidtype] += 3 * gGameExternalOptions.gRaidReplenish_BaseValue; } else if ( raidtype == 1 ) { if ( !gGameExternalOptions.gRaid_Zombies || !gGameSettings.fOptions[TOPTION_ZOMBIES] ) continue; // zombies grow very fast personnelgain[raidtype] += 15 * gGameExternalOptions.gRaidReplenish_BaseValue; } else if ( raidtype == 2 ) { if ( !gGameExternalOptions.gRaid_Bandits ) continue; // bandit growth depends on progress personnelgain[raidtype] += gGameExternalOptions.gRaidReplenish_BaseValue * (150 + HighestPlayerProgressPercentage()) / 100; } std::vector attacksectors; for ( INT16 sector = 0; sector <= 255; ++sector ) { if ( !StrategicMap[SECTOR_INFO_TO_STRATEGIC_INDEX( sector )].fEnemyControlled ) { if ( ( SectorExternalData[sector][0].usSectorFlagMask & (SECTORFLAG_RAIDPOSSIBLE_BLOODCAT << raidtype ) ) ) { attacksectors.push_back( sector ); } } } if ( attacksectors.empty() ) continue; int numattacks = gGameExternalOptions.gRaid_MaxAttackPerNight_Bandits; if ( raidtype == 0 ) numattacks = gGameExternalOptions.gRaid_MaxAttackPerNight_Bloodcats; else if ( raidtype == 1 ) numattacks = gGameExternalOptions.gRaid_MaxAttackPerNight_Zombies; for ( int attack = 0; attack < numattacks; ++attack ) { UINT32 sector = attacksectors[Random(attacksectors.size())]; // attack random sector if ( raidtype == 0 ) // bloodcats only attack at night (it is 7:00 now) AddStrategicEvent( EVENT_BLOODCAT_ATTACK, GetWorldTotalMin() + 14 * 60 + Random(10 * 60), sector ); else // other attacks can happen all the time AddStrategicEvent( EVENT_BLOODCAT_ATTACK + raidtype, GetWorldTotalMin() + Random( 24 * 60 ), sector ); } } // every day we refill our available personnel // this also means that at day 1 we have no personnel for raids, forces have to slowly be built up AddRaidPersonnel( personnelgain[0], personnelgain[1], personnelgain[2] ); } void MakeCivGroupHostileOnNextSectorEntrance( UINT8 ubCivGroup ) { // if it's the rebels that will become hostile, reduce town loyalties NOW, not later if ( ubCivGroup == REBEL_CIV_GROUP && gTacticalStatus.fCivGroupHostile[ ubCivGroup ] == CIV_GROUP_NEUTRAL ) { ReduceLoyaltyForRebelsBetrayed(); } gTacticalStatus.fCivGroupHostile[ ubCivGroup ] = CIV_GROUP_WILL_BECOME_HOSTILE; } void RemoveAssassin( UINT8 ubProfile ) { gMercProfiles[ ubProfile ].sSectorX = 0; gMercProfiles[ ubProfile ].sSectorY = 0; gMercProfiles[ ubProfile ].bLife = gMercProfiles[ ubProfile ].bLifeMax; } void CheckForMissingHospitalSupplies( void ) { UINT32 uiLoop; ITEM_POOL * pItemPool; OBJECTTYPE * pObj; UINT8 ubMedicalObjects = 0; for ( uiLoop = 0; uiLoop < guiNumWorldItems; uiLoop++ ) { // loop through all items, look for ownership if ( gWorldItems[ uiLoop ].fExists && gWorldItems[ uiLoop ].object.usItem == OWNERSHIP && gWorldItems[ uiLoop ].object[0]->data.owner.ubOwnerCivGroup == DOCTORS_CIV_GROUP ) { GetItemPoolFromGround( gWorldItems[ uiLoop ].sGridNo, &pItemPool ) ; while( pItemPool ) { pObj = &( gWorldItems[ pItemPool->iItemIndex ].object ); #ifdef obsoleteCode if ( (*pObj)[0]->data.objectStatus > 60 ) { if ( Item[pObj->usItem].firstaidkit || Item[pObj->usItem].medicalkit || pObj->usItem == REGEN_BOOSTER || pObj->usItem == ADRENALINE_BOOSTER ) { ubMedicalObjects++; } } #endif//obsoleteCode if ( Item[pObj->usItem].firstaidkit || Item[pObj->usItem].medicalkit || pObj->usItem == REGEN_BOOSTER || pObj->usItem == ADRENALINE_BOOSTER ) { for (StackedObjects::iterator iter = pObj->objectStack.begin(); iter != pObj->objectStack.end(); ++iter) { if ( iter->data.objectStatus > 60 ) { ubMedicalObjects++; } } } pItemPool = pItemPool->pNext; } } } if ( CheckFact( FACT_PLAYER_STOLE_MEDICAL_SUPPLIES_AGAIN, 0 ) == TRUE ) { // player returning stuff! if back to full then can operate if ( ubMedicalObjects >= gubCambriaMedicalObjects ) { SetFactFalse( FACT_PLAYER_STOLE_MEDICAL_SUPPLIES_AGAIN ); SetFactFalse( FACT_PLAYER_STOLE_MEDICAL_SUPPLIES ); return; } } if ( ubMedicalObjects < gubCambriaMedicalObjects ) { // player's stolen something! if ( CheckFact( FACT_PLAYER_STOLE_MEDICAL_SUPPLIES, 0 ) == FALSE ) { SetFactTrue( FACT_PLAYER_STOLE_MEDICAL_SUPPLIES ); } // if only 1/5 or less left, give up the ghost if ( ubMedicalObjects * 5 <= gubCambriaMedicalObjects ) { // run out! SetFactTrue( FACT_PLAYER_STOLE_MEDICAL_SUPPLIES_AGAIN ); } } } // WANNE: No more used for the new airport code /* void DropOffItemsInMeduna( UINT8 ubOrderNum ) { BOOLEAN fSectorLoaded = FALSE; UINT32 uiCount = 0; OBJECTTYPE *pObject=NULL; UINT16 usNumberOfItems=0, usItem; UINT8 ubItemsDelivered, ubTempNumItems; UINT32 i; //if the player doesnt "own" the sector, if( StrategicMap[ CALCULATE_STRATEGIC_INDEX( MEDUNA_ITEM_DROP_OFF_SECTOR_X, MEDUNA_ITEM_DROP_OFF_SECTOR_Y ) ].fEnemyControlled ) { //the items disappear gpNewBobbyrShipments[ ubOrderNum ].fActive = FALSE; return; } // determine if the sector is loaded if( ( gWorldSectorX == MEDUNA_ITEM_DROP_OFF_SECTOR_X ) && ( gWorldSectorY == MEDUNA_ITEM_DROP_OFF_SECTOR_Y ) && ( gbWorldSectorZ == MEDUNA_ITEM_DROP_OFF_SECTOR_Z ) ) fSectorLoaded = TRUE; else fSectorLoaded = FALSE; // set crate to closed! if ( fSectorLoaded ) { SetOpenableStructureToClosed( MEDUNA_ITEM_DROP_OFF_GRIDNO, 0 ); } else { ChangeStatusOfOpenableStructInUnloadedSector( MEDUNA_ITEM_DROP_OFF_SECTOR_X, MEDUNA_ITEM_DROP_OFF_SECTOR_Y, MEDUNA_ITEM_DROP_OFF_SECTOR_Z, MEDUNA_ITEM_DROP_OFF_GRIDNO, FALSE ); } for(i=0; iubNumberPurchases; i++) { ubItemsDelivered = gpNewBobbyrShipments[ ubOrderNum ].BobbyRayPurchase[i].ubNumberPurchased; usItem = gpNewBobbyrShipments[ ubOrderNum ].BobbyRayPurchase[i].usItemIndex; CreateItem(usItem, 100, &gTempObject);//to get the ItemSlotLimit only! while ( ubItemsDelivered ) { // treat 0s as 1s :-) ubTempNumItems = __min( ubItemsDelivered, ItemSlotLimit(&gTempObject, STACK_SIZE_LIMIT) ); CreateItems( usItem, gpNewBobbyrShipments[ ubOrderNum ].BobbyRayPurchase[i].bItemQuality, ubTempNumItems, &gTempObject ); // stack as many as possible if( fSectorLoaded ) { AddItemToPool( MEDUNA_ITEM_DROP_OFF_GRIDNO, &gTempObject, -1, 0, 0, 0 ); } else { pObject[ uiCount ] = gTempObject; uiCount++; } ubItemsDelivered -= ubTempNumItems; } } //if the sector WASNT loaded if( !fSectorLoaded ) { //add all the items from the array that was built above //The item are to be added to the Top part of Drassen, grid loc's 10112, 9950 if( !AddItemsToUnLoadedSector( MEDUNA_ITEM_DROP_OFF_SECTOR_X, MEDUNA_ITEM_DROP_OFF_SECTOR_Y, MEDUNA_ITEM_DROP_OFF_SECTOR_Z, MEDUNA_ITEM_DROP_OFF_GRIDNO, uiCount, pObject, 0, 0, 0, -1, FALSE ) ) { //error Assert( 0 ); } delete[]( pObject ); pObject = NULL; } //mark that the shipment has arrived gpNewBobbyrShipments[ ubOrderNum ].fActive = FALSE; //Add an email from kulba telling the user the shipment is there AddEmail( BOBBY_R_MEDUNA_SHIPMENT, BOBBY_R_MEDUNA_SHIPMENT_LENGTH, BOBBY_R, GetWorldTotalMin(), -1 ); } */