#include "items.h" #include "handle Items.h" #include "overhead.h" #include "weapons.h" #include "tiledef.h" #include "worlddef.h" #include "interface.h" #include "renderworld.h" #include "Animation Control.h" #include "font control.h" #include "World items.h" #include "debug.h" #include "Isometric utils.h" #include "sys globals.h" #include "Tactical Save.h" #include "strategicmap.h" #include "Campaign Types.h" #include "random.h" #include "Action Items.h" #include "pits.h" #include "GameSettings.h" #include "Quests.h" #include "Soldier Profile.h" #include "message.h" #include "map screen interface map inventory.h" // added by Flugente #include "connect.h" #ifdef JA2EDITOR//dnl ch84 290114 #include "Item Statistics.h" #endif //Global dynamic array of all of the items in a loaded map. std::vector gWorldItems;//dnl ch75 261013 UINT32 guiNumWorldItems = 0; WorldItems gAllWorldItems; // World items for all unloaded sectors INT32 FindWorldItemSector(INT16 x, INT16 y, INT16 z) { for (size_t i = 0; i < gAllWorldItems.sectors.size(); i++) { const auto sector = gAllWorldItems.sectors[i]; if (sector.x == x && sector.y == y && sector.z == z) { return i; } } return -1; } bool SectorIsInWorldItems(INT16 x, INT16 y, INT16 z) { for (size_t i = 0; i < gAllWorldItems.sectors.size(); i++) { const auto sector = gAllWorldItems.sectors[i]; if (sector.x == x && sector.y == y && sector.z == z) { return true; } } return false; } void AddSectorItemsToWorldItems(INT16 x, INT16 y, INT16 z, UINT32 nItems, std::vector &Items) { gAllWorldItems.sectors.push_back(SectorCoords{ x, y, z }); gAllWorldItems.NumItems.push_back(nItems); gAllWorldItems.Items.push_back(Items); } void RemoveSectorFromWorldItems(INT16 x, INT16 y, INT16 z) { for (size_t i = 0; i < gAllWorldItems.sectors.size(); i++) { const auto sector = gAllWorldItems.sectors[i]; if (sector.x == x && sector.y == y && sector.z == z) { gAllWorldItems.sectors.erase(gAllWorldItems.sectors.begin() + i); gAllWorldItems.NumItems.erase(gAllWorldItems.NumItems.begin() + i); gAllWorldItems.Items.erase(gAllWorldItems.Items.begin() + i); } } } void UpdateWorldItems(INT16 x, INT16 y, INT16 z, UINT32 nItems, std::vector &Items) { if (nItems == 0) { RemoveSectorFromWorldItems(x, y, z); ReSetSectorFlag(x, y, z, SF_ITEM_TEMP_FILE_EXISTS); } else if (SectorIsInWorldItems(x, y, z)) { const auto i = FindWorldItemSector(x, y, z); gAllWorldItems.NumItems[i] = nItems; gAllWorldItems.Items[i] = Items; } else { AddSectorItemsToWorldItems(x, y, z, nItems, Items); SetSectorFlag(x, y, z, SF_ITEM_TEMP_FILE_EXISTS); } UINT32 visibleItemCount = 0; for (size_t i = 0; i < nItems; ++i) { // if visible to player, then state fact if (IsMapScreenWorldItemVisibleInMapInventory(&Items[i])) { visibleItemCount += Items[i].object.ubNumberOfObjects; } } SetNumberOfVisibleWorldItemsInSectorStructureForSector(x, y, z, visibleItemCount); } void ClearAllWorldItems(void) { gAllWorldItems.sectors.clear(); gAllWorldItems.NumItems.clear(); gAllWorldItems.Items.clear(); } INT32 GetAmountOfWorldItems(INT16 x, INT16 y, INT16 z) { const auto i = FindWorldItemSector(x,y, z); if (i != -1) { return gAllWorldItems.NumItems[i]; } else { return 0; } } void PruneWorldItems(void) { for (size_t i = 0; i < gAllWorldItems.Items.size(); i++) { std::vector& items = gAllWorldItems.Items[i]; for (INT32 j = items.size()-1; j >= 0; j--) { if (items[j].fExists == false) { items.erase(items.begin()+j); } } if (gAllWorldItems.Items[i].size() > 0) { gAllWorldItems.NumItems[i] = gAllWorldItems.Items[i].size(); } else { auto x = gAllWorldItems.sectors[i].x; auto y = gAllWorldItems.sectors[i].y; auto z = gAllWorldItems.sectors[i].z; ReSetSectorFlag(x, y, z, SF_ITEM_TEMP_FILE_EXISTS); gAllWorldItems.sectors.erase(gAllWorldItems.sectors.begin() + i); gAllWorldItems.NumItems.erase(gAllWorldItems.NumItems.begin() + i); gAllWorldItems.Items.erase(gAllWorldItems.Items.begin() + i); } } } WORLDBOMB * gWorldBombs = NULL; UINT32 guiNumWorldBombs = 0; void DeleteWorldItemsBelongingToTerroristsWhoAreNotThere( void ); void DeleteWorldItemsBelongingToQueenIfThere( void ); //extern UINT16 StandardGunListAmmoReplacement( UINT16 usAmmo ); extern UINT8 GetDealerItemCategoryNumber( UINT16 usItemIndex ); //dnl ch33 120909 OLD_WORLDITEM_101& OLD_WORLDITEM_101::operator=(WORLDITEM& src) { if((void*)this != (void*)&src) { memset(this, 0, sizeof(OLD_WORLDITEM_101)); this->fExists = src.fExists; this->sGridNo = src.sGridNo; this->ubLevel = src.ubLevel; this->usFlags = src.usFlags; this->bRenderZHeightAboveLevel = src.bRenderZHeightAboveLevel; this->bVisible = src.bVisible; this->ubNonExistChance = src.ubNonExistChance; this->oldObject = src.object; } return(*this); } bool WORLDITEM::operator<(WORLDITEM& compare) { if ( this->fExists == false || this->object.exists() == false) { return false; } if ( compare.fExists == false || compare.object.exists() == false) { return true; } UINT8 ubItem1Category = GetDealerItemCategoryNumber( this->object.usItem ); UINT8 ubItem2Category = GetDealerItemCategoryNumber( compare.object.usItem ); // lower category first if ( ubItem1Category < ubItem2Category ) { return( true ); } else if ( ubItem1Category > ubItem2Category ) { return false; } // the same category //Madd: sort by name (for now at least): int retVal = _wcsicmp(Item[this->object.usItem].szBRName,Item[compare.object.usItem].szBRName); if ( retVal < 0 ) { return true; } else if ( retVal > 0 ) { return false; } if (this->object.ubNumberOfObjects > compare.object.ubNumberOfObjects) { return true; } else if (this->object.ubNumberOfObjects < compare.object.ubNumberOfObjects) { return false; } /* if (this->object[0]->attachments.size() > compare.object[0]->attachments.size()) { return true; } else if (this->object[0]->attachments.size() < compare.object[0]->attachments.size()) { return false; } */ // higher quality first if ( this->object[0]->data.objectStatus > compare.object[0]->data.objectStatus ) { return( true ); } else { // identical items! return( false ); } return false; } void WORLDITEM::initialize() { this->fExists = 0; this->sGridNo = 0; this->ubLevel = 0; this->usFlags = 0; this->bRenderZHeightAboveLevel = 0; this->bVisible = 0; this->ubNonExistChance = 0; this->soldierID = NOBODY; this->object.initialize(); } WORLDITEM& WORLDITEM::operator=(OLD_WORLDITEM_101& src) { //the first conversion is simple enough that it can be done here this->fExists = src.fExists; this->sGridNo = src.sGridNo; this->ubLevel = src.ubLevel; this->usFlags = src.usFlags; this->bRenderZHeightAboveLevel = src.bRenderZHeightAboveLevel; this->bVisible = src.bVisible; this->ubNonExistChance = src.ubNonExistChance; this->soldierID = NOBODY; //convert the OBJECTTYPE this->object = src.oldObject; return *this; } WORLDITEM& WORLDITEM::operator=(_OLD_WORLDITEM& src)//dnl ch42 280909 { if((void*)this != (void*)&src) { fExists = src.fExists; sGridNo = src.sGridNo; ubLevel = src.ubLevel; usFlags = src.usFlags; bRenderZHeightAboveLevel = src.bRenderZHeightAboveLevel; bVisible = src.bVisible; ubNonExistChance = src.ubNonExistChance; soldierID = NOBODY; object = src.object; } return(*this); } WORLDITEM& WORLDITEM::operator=(const WORLDITEM& src) { this->fExists = src.fExists; this->sGridNo = src.sGridNo; this->ubLevel = src.ubLevel; this->usFlags = src.usFlags; this->bRenderZHeightAboveLevel = src.bRenderZHeightAboveLevel; this->bVisible = src.bVisible; this->ubNonExistChance = src.ubNonExistChance; this->soldierID = src.soldierID; this->object = src.object; return *this; } WORLDITEM::WORLDITEM(const WORLDITEM& src) { this->fExists = src.fExists; this->sGridNo = src.sGridNo; this->ubLevel = src.ubLevel; this->usFlags = src.usFlags; this->bRenderZHeightAboveLevel = src.bRenderZHeightAboveLevel; this->bVisible = src.bVisible; this->ubNonExistChance = src.ubNonExistChance; this->soldierID = src.soldierID; this->object = src.object; } INT32 GetFreeWorldBombIndex( void ) { UINT32 uiCount; WORLDBOMB *newWorldBombs; UINT32 uiOldNumWorldBombs; for(uiCount=0; uiCount < guiNumWorldBombs; uiCount++) { if ( gWorldBombs[ uiCount ].fExists == FALSE ) return( (INT32)uiCount ); } uiOldNumWorldBombs = guiNumWorldBombs; guiNumWorldBombs += 10; //Allocate new table with max+10 items. newWorldBombs = (WORLDBOMB*)MemRealloc( gWorldBombs, sizeof( WORLDBOMB ) * guiNumWorldBombs ); if (newWorldBombs == NULL) { return( -1 ); } //Clear the rest of the new array memset( &newWorldBombs[ uiOldNumWorldBombs ], 0, sizeof( WORLDBOMB ) * ( guiNumWorldBombs - uiOldNumWorldBombs ) ); gWorldBombs = newWorldBombs; // Return uiCount..... return( uiCount ); } UINT32 GetNumUsedWorldBombs( void ) { UINT32 uiCount, uiNumItems; uiNumItems = 0; if ( guiNumWorldBombs == 0 ) { return( 0 ); } for( uiCount = 0; uiCount < guiNumWorldBombs; uiCount++ ) { if( gWorldBombs[ uiCount ].fExists ) { uiNumItems++; } } return( uiNumItems ); } INT32 AddBombToWorld( INT32 iItemIndex ) { UINT32 iBombIndex; iBombIndex = GetFreeWorldBombIndex( ); //Add the new world item to the table. gWorldBombs[ iBombIndex ].fExists = TRUE; gWorldBombs[ iBombIndex ].iItemIndex = iItemIndex; return ( iBombIndex ); } void RemoveBombFromWorld( INT32 iBombIndex ) { //Remove the world bomb from the table. gWorldBombs[ iBombIndex ].fExists = FALSE; } void RemoveBombFromWorldByItemIndex( INT32 iItemIndex ) { // Find the world bomb which corresponds with a particular world item, then // remove the world bomb from the table. UINT32 uiBombIndex; for (uiBombIndex = 0; uiBombIndex < guiNumWorldBombs; uiBombIndex++) { if (gWorldBombs[ uiBombIndex ].fExists && gWorldBombs[ uiBombIndex].iItemIndex == iItemIndex ) { RemoveBombFromWorld( uiBombIndex ); return; } } } INT32 FindWorldItemForBombInGridNo( INT32 sGridNo, INT8 bLevel ) { UINT32 uiBombIndex; for (uiBombIndex = 0; uiBombIndex < guiNumWorldBombs; uiBombIndex++) { if (gWorldBombs[ uiBombIndex ].fExists && gWorldItems[ gWorldBombs[ uiBombIndex ].iItemIndex ].sGridNo == sGridNo && gWorldItems[ gWorldBombs[ uiBombIndex ].iItemIndex ].ubLevel == bLevel ) { return( gWorldBombs[ uiBombIndex ].iItemIndex ); } } return( -1 ); } INT32 FindWorldItemForBuriedBombInGridNo( INT32 sGridNo, INT8 bLevel ) { UINT32 uiBombIndex; OBJECTTYPE* pObj = NULL; for (uiBombIndex = 0; uiBombIndex < guiNumWorldBombs; uiBombIndex++) { if (gWorldBombs[ uiBombIndex ].fExists && gWorldItems[ gWorldBombs[ uiBombIndex ].iItemIndex ].sGridNo == sGridNo && gWorldItems[ gWorldBombs[ uiBombIndex ].iItemIndex ].ubLevel == bLevel ) { pObj=&gWorldItems[ gWorldBombs[ uiBombIndex ].iItemIndex ].object; if( pObj && pObj->exists() ) //if ( ( (*pObj)[0]->data.misc.bDetonatorType != BOMB_TIMED ) && ( (*pObj)[0]->data.misc.bDetonatorType != BOMB_REMOTE ) ) if( !HasAttachmentOfClass( pObj, AC_REMOTEDET | AC_DETONATOR ) ) return( gWorldBombs[ uiBombIndex ].iItemIndex ); } } return( -1 ); } // Flugente: is there a planted tripwire at this gridno? fKnown = TRUE: only return true if we know of that one already INT32 FindWorldItemForTripwireInGridNo( INT32 sGridNo, INT8 bLevel, BOOLEAN fKnown ) { UINT32 uiBombIndex; OBJECTTYPE* pObj = NULL; for (uiBombIndex = 0; uiBombIndex < guiNumWorldBombs; uiBombIndex++) { if (gWorldBombs[ uiBombIndex ].fExists && gWorldItems[ gWorldBombs[ uiBombIndex ].iItemIndex ].sGridNo == sGridNo && gWorldItems[ gWorldBombs[ uiBombIndex ].iItemIndex ].ubLevel == bLevel ) { pObj = &( gWorldItems[ gWorldBombs[ uiBombIndex ].iItemIndex ].object ); if ( pObj && ItemIsTripwire(pObj->usItem) ) { if ( !fKnown ) return( gWorldBombs[ uiBombIndex ].iItemIndex ); // owned by the player team - we know of this thing if ( (*pObj)[0]->data.ubWireNetworkFlag & TRIPWIRE_NETWORK_OWNER_PLAYER ) return( gWorldBombs[ uiBombIndex ].iItemIndex ); // something is here, as a blue flag is planted if ( gpWorldLevelData[sGridNo].uiFlags & MAPELEMENT_PLAYER_MINE_PRESENT ) return( gWorldBombs[ uiBombIndex ].iItemIndex ); } } } return( -1 ); } void FindPanicBombsAndTriggers( void ) { // This function searches the bomb table to find panic-trigger-tuned bombs and triggers UINT32 uiBombIndex; OBJECTTYPE * pObj; STRUCTURE * pSwitch; INT32 sGridNo = NOWHERE; INT8 bPanicIndex; for (uiBombIndex = 0; uiBombIndex < guiNumWorldBombs; uiBombIndex++) { if (gWorldBombs[ uiBombIndex ].fExists) { pObj = &(gWorldItems[ gWorldBombs[ uiBombIndex ].iItemIndex ].object); if ((*pObj)[0]->data.misc.bFrequency == PANIC_FREQUENCY || (*pObj)[0]->data.misc.bFrequency == PANIC_FREQUENCY_2 || (*pObj)[0]->data.misc.bFrequency == PANIC_FREQUENCY_3 ) { if (pObj->usItem == SWITCH) { sGridNo = gWorldItems[ gWorldBombs[ uiBombIndex ].iItemIndex ].sGridNo; switch( (*pObj)[0]->data.misc.bFrequency ) { case PANIC_FREQUENCY: bPanicIndex = 0; break; case PANIC_FREQUENCY_2: bPanicIndex = 1; break; case PANIC_FREQUENCY_3: bPanicIndex = 2; break; default: // augh!!! continue; } pSwitch = FindStructure( sGridNo, STRUCTURE_SWITCH ); if (pSwitch) { switch( pSwitch->ubWallOrientation ) { case INSIDE_TOP_LEFT: case OUTSIDE_TOP_LEFT: sGridNo += DirectionInc( SOUTH ); break; case INSIDE_TOP_RIGHT: case OUTSIDE_TOP_RIGHT: sGridNo += DirectionInc( EAST ); break; default: break; } } gTacticalStatus.sPanicTriggerGridNo[ bPanicIndex ] = sGridNo; gTacticalStatus.ubPanicTolerance[ bPanicIndex ] = (*pObj)[0]->data.misc.ubTolerance; if ((*pObj).fFlags & OBJECT_ALARM_TRIGGER) { gTacticalStatus.bPanicTriggerIsAlarm[ bPanicIndex ] = TRUE; } gTacticalStatus.fPanicFlags |= PANIC_TRIGGERS_HERE; bPanicIndex++; if (bPanicIndex == NUM_PANIC_TRIGGERS) { return; } } else { gTacticalStatus.fPanicFlags |= PANIC_BOMBS_HERE; } } } } } UINT32 GetFreeWorldItemIndex(void)//dnl ch75 271013 { UINT32 uiCount; for(uiCount=0; uiCountusItem, sGridNo); #endif return( -1 ); } iItemIndex = GetFreeWorldItemIndex( ); //Add the new world item to the table. gWorldItems[ iItemIndex ].fExists = TRUE; gWorldItems[ iItemIndex ].sGridNo = sGridNo; gWorldItems[ iItemIndex ].ubLevel = ubLevel; gWorldItems[ iItemIndex ].usFlags = usFlags; gWorldItems[ iItemIndex ].bVisible = bVisible; gWorldItems[ iItemIndex ].bRenderZHeightAboveLevel = bRenderZHeightAboveLevel; gWorldItems[ iItemIndex ].soldierID = soldierID; gWorldItems[ iItemIndex ].object = *pObject; // Add a bomb reference if needed // Flugente: we can arm bombs in our inventory and then throw them out, which will cause them to be added to the world. Only way to identify those items is via a check for their bDetonatorType if (usFlags & WORLD_ITEM_ARMED_BOMB || ( (Item[pObject->usItem].usItemClass & (IC_BOMB)) && ( ( (*pObject)[0]->data.misc.bDetonatorType == BOMB_TIMED ) || ( (*pObject)[0]->data.misc.bDetonatorType == BOMB_REMOTE ) ) ) ) { // sevenfm: added flag WORLD_ITEM_ARMED_BOMB // this fixes bug with remote explosives not being removed after activation, if they were armed in inventory and thrown afterwards gWorldItems[ iItemIndex ].usFlags |= WORLD_ITEM_ARMED_BOMB; iReturn = AddBombToWorld( iItemIndex ); if (iReturn == -1) { return( -1 ); } else { // OJW - 20091002 - Explosives if (is_networked && is_client) { SOLDIERTYPE* pSoldier = NULL; if (soldierID == NOBODY) { if (gWorldItems[ iItemIndex ].object[0]->data.misc.ubBombOwner > 1) { soldierID = gWorldItems[ iItemIndex ].object[0]->data.misc.ubBombOwner - 2; // undo the hack if ( soldierID < NOBODY ) { pSoldier = soldierID; } } } if (pSoldier != NULL) { // if soldier is on our team, or is AI and we are the server if (pSoldier->bTeam == 0 || (pSoldier->bTeam == 1 && is_server)) { // this is a local bomb, so init it that way gWorldBombs[iReturn].iMPWorldItemIndex = 0; gWorldBombs[iReturn].ubMPTeamIndex = pSoldier->bTeam; gWorldBombs[iReturn].bIsFromRemotePlayer = false; // the 99 is a hack..though probably doesnt matter send_plant_explosive(soldierID , pObject->usItem , 99 , usFlags , sGridNo , ubLevel , iItemIndex ); } } } } } return ( iItemIndex ); } void RemoveItemFromWorld( INT32 iItemIndex ) { // Ensure the item still exists, then if it's a bomb, // remove the appropriate entry from the bomb table if (gWorldItems[ iItemIndex ].fExists) { if (gWorldItems[ iItemIndex ].usFlags & WORLD_ITEM_ARMED_BOMB) { RemoveBombFromWorldByItemIndex( iItemIndex ); } gWorldItems[ iItemIndex ].fExists = FALSE; } } void TrashWorldItems() { UINT32 i; if( !gWorldItems.empty() )//dnl ch75 271013 { for( i = 0; i < guiNumWorldItems; i++ ) { if( gWorldItems[ i ].fExists ) { RemoveItemFromPool( gWorldItems[ i ].sGridNo, i, gWorldItems[ i ].ubLevel ); } } #ifdef INVFIX_Moa//dnl ch75 311013 gWorldItems.clear(); #endif } if ( gWorldBombs ) { MemFree( gWorldBombs ); gWorldBombs = NULL; guiNumWorldBombs = 0; } } //dnl ch33 150909 //dnl ch74 191013 void SaveWorldItemsToMap(HWFILE fp, float dMajorMapVersion, UINT8 ubMinorMapVersion) { UINT32 i, uiBytesWritten, uiActualNumWorldItems=0; OLD_WORLDITEM_101 oldWorldItem; for(i=0; i= OLD_MAXITEMS) continue; uiActualNumWorldItems++; } } FileWrite(fp, &uiActualNumWorldItems, sizeof(UINT32), &uiBytesWritten); for(i=0; i= OLD_MAXITEMS) continue; oldWorldItem = gWorldItems[i]; FileWrite(fp, &oldWorldItem, sizeof(OLD_WORLDITEM_101), &uiBytesWritten); } else gWorldItems[i].Save(fp, TRUE); } } } // WANNE - BMP: DONE! void LoadWorldItemsFromMap( INT8 **hBuffer, float dMajorMapVersion, int ubMinorMapVersion ) { // Start loading itmes... UINT32 i; WORLDITEM dummyItem; INT32 iItemIndex; UINT32 uiNumWorldItems; //If any world items exist, we must delete them now. TrashWorldItems(); //Read the number of items that were saved in the map. LOADDATA( &uiNumWorldItems, *hBuffer, 4 ); if( gTacticalStatus.uiFlags & LOADING_SAVED_GAME && !gfEditMode ) { //The sector has already been visited. The items are saved in a different format that will be //loaded later on. So, all we need to do is skip the data entirely. if (dMajorMapVersion >= 6.0 && ubMinorMapVersion > 26 ) { for (unsigned int x = 0; x < uiNumWorldItems; ++x) { //ADB WORLDITEM's size on disk is unknown dummyItem.Load(hBuffer, dMajorMapVersion, ubMinorMapVersion); } } else { *hBuffer += sizeof ( OLD_WORLDITEM_101 ) * uiNumWorldItems; } return; } else for ( i = 0; i < uiNumWorldItems; i++ ) { //Add all of the items to the world indirectly through AddItemToPool, but only if the chance //associated with them succeed. dummyItem.Load(hBuffer, dMajorMapVersion, ubMinorMapVersion); gMapTrn.GetTrnCnt(dummyItem.sGridNo);//dnl ch44 270909 WORLDITEM translation if( dummyItem.object.usItem == OWNERSHIP ) { dummyItem.ubNonExistChance = 0; } if( gfEditMode || dummyItem.ubNonExistChance <= PreRandom( 100 ) || (gGameExternalOptions.ubMapItemChanceOverride > 0 && (gGameExternalOptions.ubMapItemChanceOverride >= PreRandom(100)) ) ) //Madd: map item chance override, note this calc is done in reverse { if( !gfEditMode ) { //check for matching item existance modes and only add if there is a match! //if we are in platinum mode, REALISTIC items are allowed, but not SCIFI items if( dummyItem.usFlags & WORLD_ITEM_SCIFI_ONLY && !(gGameOptions.ubGameStyle == STYLE_SCIFI) || dummyItem.usFlags & WORLD_ITEM_REALISTIC_ONLY && (gGameOptions.ubGameStyle == STYLE_SCIFI) ) { //no match, so don't add item to world continue; } /* if ( !gGameOptions.fGunNut ) { UINT16 usReplacement; // do replacements? if ( Item[ dummyItem.object.usItem ].usItemClass == IC_GUN ) { INT8 bAmmo, bNewAmmo; usReplacement = StandardGunListReplacement( dummyItem.object.usItem ); if ( usReplacement ) { // everything else can be the same? no. bAmmo = dummyItem.object[0]->data.gun.ubGunShotsLeft; bNewAmmo = (Weapon[ usReplacement ].ubMagSize * bAmmo) / Weapon[ dummyItem.object.usItem ].ubMagSize; if ( bAmmo > 0 && bNewAmmo == 0 ) { bNewAmmo = 1; } dummyItem.object.usItem = usReplacement; dummyItem.object[0]->data.gun.ubGunShotsLeft = bNewAmmo; } } if ( Item[ dummyItem.object.usItem ].usItemClass == IC_AMMO ) { usReplacement = StandardGunListAmmoReplacement( dummyItem.object.usItem ); if ( usReplacement ) { UINT8 ubLoop; // go through status values and scale up/down for ( ubLoop = 0; ubLoop < dummyItem.object.ubNumberOfObjects; ubLoop++ ) { dummyItem.object.status.bStatus[ ubLoop ] = dummyItem.object.status.bStatus[ ubLoop ] * Magazine[ Item[ usReplacement ].ubClassIndex ].ubMagSize / Magazine[ Item[ dummyItem.object.usItem ].ubClassIndex ].ubMagSize; } // then replace item # dummyItem.object.usItem = usReplacement; } } } */ } if( dummyItem.object.usItem == ACTION_ITEM && gfLoadPitsWithoutArming ) { //if we are loading a pit, they are typically loaded without being armed. if( dummyItem.object[0]->data.misc.bActionValue == ACTION_ITEM_SMALL_PIT || dummyItem.object[0]->data.misc.bActionValue == ACTION_ITEM_LARGE_PIT ) { dummyItem.usFlags &= ~WORLD_ITEM_ARMED_BOMB; dummyItem.bVisible = BURIED; dummyItem.object[0]->data.misc.bDetonatorType = 0; } } else if ( dummyItem.bVisible == HIDDEN_ITEM && dummyItem.object[0]->data.bTrap > 0 && (ItemIsMine(dummyItem.object.usItem) || dummyItem.object.usItem == TRIP_FLARE || dummyItem.object.usItem == TRIP_KLAXON) ) { ArmBomb( &dummyItem.object, BOMB_PRESSURE ); dummyItem.usFlags |= WORLD_ITEM_ARMED_BOMB; // this is coming from the map so the enemy must know about it. gpWorldLevelData[ dummyItem.sGridNo ].uiFlags |= MAPELEMENT_ENEMY_MINE_PRESENT; } if ( dummyItem.usFlags & WORLD_ITEM_ARMED_BOMB ) { //all armed bombs are buried dummyItem.bVisible = BURIED; } // sevenfm: don't allow max repair threshold less than current object status dummyItem.object[0]->data.sRepairThreshold = __max(dummyItem.object[0]->data.sRepairThreshold, dummyItem.object[0]->data.objectStatus); AddItemToPoolAndGetIndex( dummyItem.sGridNo, &dummyItem.object, dummyItem.bVisible, dummyItem.ubLevel, dummyItem.usFlags, dummyItem.bRenderZHeightAboveLevel, dummyItem.soldierID, &iItemIndex ); gWorldItems[ iItemIndex ].ubNonExistChance = dummyItem.ubNonExistChance; } } if ( !gfEditMode ) { DeleteWorldItemsBelongingToTerroristsWhoAreNotThere(); if ( gWorldSectorX == 3 && gWorldSectorY == MAP_ROW_P && gbWorldSectorZ == 1 ) { DeleteWorldItemsBelongingToQueenIfThere(); } } } void DeleteWorldItemsBelongingToTerroristsWhoAreNotThere( void ) { UINT32 uiLoop; UINT32 uiLoop2; INT32 sGridNo; UINT8 ubLevel; // only do this after Carmen has talked to player and terrorists have been placed //if ( CheckFact( FACT_CARMEN_EXPLAINED_DEAL, 0 ) == TRUE ) { for ( uiLoop = 0; uiLoop < guiNumWorldItems; uiLoop++ ) { // loop through all items, look for ownership if ( gWorldItems[ uiLoop ].fExists && gWorldItems[ uiLoop ].object.usItem == OWNERSHIP ) { // if owner is a terrorist if ( IsProfileATerrorist( (UINT8) gWorldItems[ uiLoop ].object[0]->data.owner.ubOwnerProfile ) ) { // and they were not set in the current sector if ( gMercProfiles[ gWorldItems[ uiLoop ].object[0]->data.owner.ubOwnerProfile ].sSectorX != gWorldSectorX || gMercProfiles[ gWorldItems[ uiLoop ].object[0]->data.owner.ubOwnerProfile ].sSectorY != gWorldSectorY ) { // then all items in this location should be deleted sGridNo = gWorldItems[ uiLoop ].sGridNo; ubLevel = gWorldItems[ uiLoop ].ubLevel; for ( uiLoop2 = 0; uiLoop2 < guiNumWorldItems; uiLoop2++ ) { // loop through all items, look for ownership if ( gWorldItems[ uiLoop2 ].fExists && gWorldItems[ uiLoop2 ].sGridNo == sGridNo && gWorldItems[ uiLoop2 ].ubLevel == ubLevel ) { RemoveItemFromPool( sGridNo, uiLoop2, ubLevel ); } } } } } } } // else the terrorists haven't been placed yet! } void DeleteWorldItemsBelongingToQueenIfThere( void ) { UINT32 uiLoop; UINT32 uiLoop2; INT32 sGridNo; UINT8 ubLevel; INT8 bSlot; if ( gMercProfiles[ QUEEN ].sSectorX == gWorldSectorX && gMercProfiles[ QUEEN ].sSectorY == gWorldSectorY && gMercProfiles[ QUEEN ].bSectorZ == gbWorldSectorZ ) { for ( uiLoop = 0; uiLoop < guiNumWorldItems; uiLoop++ ) { // loop through all items, look for ownership if ( gWorldItems[ uiLoop ].fExists && gWorldItems[ uiLoop ].object.usItem == OWNERSHIP ) { // if owner is the Queen if ( gWorldItems[ uiLoop ].object[0]->data.owner.ubOwnerProfile == QUEEN ) { // then all items in this location should be deleted sGridNo = gWorldItems[ uiLoop ].sGridNo; ubLevel = gWorldItems[ uiLoop ].ubLevel; for ( uiLoop2 = 0; uiLoop2 < guiNumWorldItems; uiLoop2++ ) { // loop through all items, look for those in same tile if ( gWorldItems[ uiLoop2 ].fExists && gWorldItems[ uiLoop2 ].sGridNo == sGridNo && gWorldItems[ uiLoop2 ].ubLevel == ubLevel ) { // upgrade equipment switch ( gWorldItems[ uiLoop2 ].object.usItem ) { case AUTO_ROCKET_RIFLE: bSlot = FindObjectInSoldierProfile( QUEEN, ROCKET_RIFLE ); if ( bSlot != NO_SLOT ) { // give her auto rifle gMercProfiles[ QUEEN ].inv[ bSlot ] = AUTO_ROCKET_RIFLE; } break; case SPECTRA_HELMET_18: gMercProfiles[ QUEEN ].inv[ HELMETPOS ] = SPECTRA_HELMET_18; break; case SPECTRA_VEST_18: gMercProfiles[ QUEEN ].inv[ VESTPOS ] = SPECTRA_VEST_18; break; case SPECTRA_LEGGINGS_18: gMercProfiles[ QUEEN ].inv[ LEGPOS ] = SPECTRA_LEGGINGS_18; break; default: break; } RemoveItemFromPool( sGridNo, uiLoop2, ubLevel ); } } } } } } } // Refresh item pools void RefreshWorldItemsIntoItemPools( std::vector& pItemList, INT32 iNumberOfItems )//dnl ch75 271013 { INT32 i; for ( i = 0; i < iNumberOfItems; i++ ) { if( pItemList[ i ].fExists ) { WORLDITEM& dummyItem = pItemList[ i ]; AddItemToPool( dummyItem.sGridNo, &dummyItem.object, dummyItem.bVisible, dummyItem.ubLevel, dummyItem.usFlags, dummyItem.bRenderZHeightAboveLevel, dummyItem.soldierID ); } } } // Flugente: Cool/decay down all items in this sector void CoolDownWorldItems() { HandleSectorCooldownFunctions( gWorldSectorX, gWorldSectorY, gbWorldSectorZ, gWorldItems, guiNumWorldItems, FALSE ); }