mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
1. Ja2Options.ini option to override chance of items appearing in maps (MAP_ITEM_CHANCE_OVERRIDE). Useful for debugging maps. Not including this one in the ini file for everyone to mess with though. Value range = 0-100%, where 0 (default) = use map settings. 2. AttachmentComboMerges is underused, so it's been extended to use up to 20 attachments to make it more useful. Build your own guns, anyone? 3. New merge types: Easy Explosive (existing one renamed to Hard), Easy Mechanical, Hard Mechanical. git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5300 3b4a5df2-a311-0410-b5c6-a8a6f20db521
900 lines
26 KiB
C++
900 lines
26 KiB
C++
#ifdef PRECOMPILEDHEADERS
|
|
#include "Tactical All.h"
|
|
#else
|
|
#include "items.h"
|
|
#include "handle Items.h"
|
|
#include "overhead.h"
|
|
#include "weapons.h"
|
|
#include "points.h"
|
|
#include "tiledef.h"
|
|
#include "worlddef.h"
|
|
#include "worldman.h"
|
|
#include "interface.h"
|
|
#include "renderworld.h"
|
|
#include "Animation Control.h"
|
|
#include "font control.h"
|
|
#include "render dirty.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 "connect.h"
|
|
#endif
|
|
|
|
//Global dynamic array of all of the items in a loaded map.
|
|
WORLDITEM * gWorldItems = NULL;
|
|
UINT32 guiNumWorldItems = 0;
|
|
|
|
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 = -1;
|
|
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 = -1;
|
|
|
|
//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 = -1;
|
|
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;
|
|
}
|
|
|
|
|
|
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 );
|
|
}
|
|
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
INT32 GetFreeWorldItemIndex( void )
|
|
{
|
|
UINT32 uiCount;
|
|
WORLDITEM *newWorldItems;
|
|
UINT32 uiOldNumWorldItems;
|
|
|
|
for(uiCount=0; uiCount < guiNumWorldItems; uiCount++)
|
|
{
|
|
if ( gWorldItems[ uiCount ].fExists == FALSE )
|
|
return( (INT32)uiCount );
|
|
}
|
|
|
|
uiOldNumWorldItems = guiNumWorldItems;
|
|
// grow by 3/2 as a better strategy, minimum 10
|
|
guiNumWorldItems = max(10, guiNumWorldItems * 3 / 2);
|
|
//Allocate new table with max+10 items.
|
|
newWorldItems = new WORLDITEM [ guiNumWorldItems ];
|
|
if (newWorldItems == NULL)
|
|
{
|
|
return( -1 );
|
|
}
|
|
|
|
if (gWorldItems)
|
|
{
|
|
for (unsigned int x = 0; x < uiOldNumWorldItems; ++x)
|
|
{
|
|
newWorldItems[x] = gWorldItems[x];
|
|
}
|
|
delete[] gWorldItems;
|
|
}
|
|
gWorldItems = newWorldItems;
|
|
|
|
// Return uiCount.....
|
|
return( uiCount );
|
|
}
|
|
|
|
|
|
UINT32 GetNumUsedWorldItems( void )
|
|
{
|
|
UINT32 uiCount, uiNumItems;
|
|
uiNumItems = 0;
|
|
|
|
for( uiCount = 0; uiCount < guiNumWorldItems; uiCount++ )
|
|
{
|
|
if( gWorldItems[ uiCount ].fExists )
|
|
{
|
|
uiNumItems++;
|
|
}
|
|
}
|
|
|
|
return( uiNumItems );
|
|
}
|
|
|
|
|
|
|
|
INT32 AddItemToWorld( INT32 sGridNo, OBJECTTYPE *pObject, UINT8 ubLevel, UINT16 usFlags, INT8 bRenderZHeightAboveLevel, INT8 bVisible, INT8 soldierID )
|
|
{
|
|
UINT32 iItemIndex;
|
|
INT32 iReturn;
|
|
|
|
// ATE: Check if the gridno is OK
|
|
if ( TileIsOutOfBounds(sGridNo))
|
|
{
|
|
// Display warning.....
|
|
#ifdef JA2BETAVERSION
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"Error: Item %d was given invalid grid location %d. Please report", pObject->usItem, 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
|
|
if (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 == -1)
|
|
{
|
|
if (gWorldItems[ iItemIndex ].object[0]->data.misc.ubBombOwner > 1)
|
|
{
|
|
soldierID = gWorldItems[ iItemIndex ].object[0]->data.misc.ubBombOwner - 2; // undo the hack
|
|
pSoldier = MercPtrs[ 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;
|
|
// <TODO> 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 )
|
|
{
|
|
for( i = 0; i < guiNumWorldItems; i++ )
|
|
{
|
|
if( gWorldItems[ i ].fExists )
|
|
{
|
|
RemoveItemFromPool( gWorldItems[ i ].sGridNo, i, gWorldItems[ i ].ubLevel );
|
|
}
|
|
}
|
|
delete[] gWorldItems;
|
|
gWorldItems = NULL;
|
|
guiNumWorldItems = 0;
|
|
}
|
|
if ( gWorldBombs )
|
|
{
|
|
MemFree( gWorldBombs );
|
|
gWorldBombs = NULL;
|
|
guiNumWorldBombs = 0;
|
|
}
|
|
}
|
|
|
|
//dnl ch33 150909
|
|
void SaveWorldItemsToMap(HWFILE fp, float dMajorMapVersion, UINT8 ubMinorMapVersion)
|
|
{
|
|
UINT32 i, uiBytesWritten, uiActualNumWorldItems;
|
|
OLD_WORLDITEM_101 oldWorldItem;
|
|
|
|
uiActualNumWorldItems = GetNumUsedWorldItems();
|
|
FileWrite(fp, &uiActualNumWorldItems, sizeof(UINT32), &uiBytesWritten);
|
|
for(i=0; i<guiNumWorldItems; i++)
|
|
{
|
|
if(gWorldItems[i].fExists)
|
|
{
|
|
if(dMajorMapVersion == VANILLA_MAJOR_MAP_VERSION && ubMinorMapVersion == VANILLA_MINOR_MAP_VERSION)
|
|
{
|
|
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 && ( Item[dummyItem.object.usItem].mine || 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;
|
|
}
|
|
|
|
//Madd: ok, so this drives me nuts -- why bother with default attachments if the map isn't going to load them for you?
|
|
//this should fix that...
|
|
for(UINT8 cnt = 0; cnt < MAX_DEFAULT_ATTACHMENTS; cnt++)
|
|
{
|
|
if(Item [ dummyItem.object.usItem ].defaultattachments[cnt] == 0)
|
|
break;
|
|
|
|
OBJECTTYPE defaultAttachment;
|
|
CreateItem(Item [ dummyItem.object.usItem ].defaultattachments[cnt],100,&defaultAttachment);
|
|
dummyItem.object.AttachObject(NULL,&defaultAttachment, FALSE);
|
|
}
|
|
|
|
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( WORLDITEM * pItemList, INT32 iNumberOfItems )
|
|
{
|
|
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 FTW 1: Cool down all items in the world (no, really)
|
|
// fSetZero sets all temperatures to 0 (used in old sector upon loading a new sector)
|
|
void CoolDownWorldItems( BOOLEAN fSetZero )
|
|
{
|
|
if ( gGameOptions.fWeaponOverheating ) // if Overheating is used ...
|
|
{
|
|
for( UINT32 uiCount = 0; uiCount < guiNumWorldItems; ++uiCount ) // ... for all items in the world ...
|
|
{
|
|
if( gWorldItems[ uiCount ].fExists ) // ... if item exists ...
|
|
{
|
|
// ... if Item exists and is a gun, a launcher or a barrel ...
|
|
if (Item[gWorldItems[ uiCount ].object.usItem].usItemClass & (IC_GUN|IC_LAUNCHER) || Item[gWorldItems[ uiCount ].object.usItem].barrel == TRUE )
|
|
{
|
|
OBJECTTYPE* pObj = &(gWorldItems[ uiCount ].object); // ... get pointer for this item ...
|
|
|
|
if ( pObj != NULL ) // ... if pointer is not obviously useless ...
|
|
{
|
|
for(INT16 i = 0; i < pObj->ubNumberOfObjects; ++i) // ... there might be multiple items here (item stack), so for each one ...
|
|
{
|
|
FLOAT newguntemperature = 0.0;
|
|
|
|
if ( !fSetZero && gGameExternalOptions.fSetZeroUponNewSector )
|
|
{
|
|
FLOAT guntemperature = (*pObj)[i]->data.bTemperature; // ... get temperature ...
|
|
|
|
FLOAT cooldownfactor = GetItemCooldownFactor(pObj); // ... get item cooldown factor provided of attachments ...
|
|
|
|
if ( Item[gWorldItems[ uiCount ].object.usItem].barrel == TRUE ) // ... a barrel lying around cools down a bit faster ...
|
|
cooldownfactor *= gGameExternalOptions.iCooldownModificatorLonelyBarrel;
|
|
|
|
newguntemperature = max(0.0, guntemperature - cooldownfactor); // ... calculate new temperature ...
|
|
}
|
|
|
|
(*pObj)[i]->data.bTemperature = newguntemperature; // ... set new temperature
|
|
|
|
#if 0//def JA2TESTVERSION
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"World: Item temperature lowered from %4.2f to %4.2f", guntemperature, newguntemperatre );
|
|
#endif
|
|
// for every objects, we also have to check wether there are weapon attachments (eg. underbarrel grenade launchers), and cool them down too
|
|
attachmentList::iterator iterend = (*pObj)[i]->attachments.end();
|
|
for (attachmentList::iterator iter = (*pObj)[i]->attachments.begin(); iter != iterend; ++iter)
|
|
{
|
|
if ( iter->exists() && Item[ iter->usItem ].usItemClass & (IC_GUN|IC_LAUNCHER) )
|
|
{
|
|
FLOAT newtemperature = 0.0;
|
|
|
|
if ( !fSetZero && gGameExternalOptions.fSetZeroUponNewSector )
|
|
{
|
|
FLOAT temperature = (*iter)[i]->data.bTemperature; // ... get temperature of item ...
|
|
|
|
FLOAT cooldownfactor = GetItemCooldownFactor( &(*iter) ); // ... get cooldown factor ...
|
|
|
|
newtemperature = max(0.0, temperature - cooldownfactor); // ... calculate new temperature ...
|
|
}
|
|
|
|
(*iter)[i]->data.bTemperature = newtemperature; // ... set new temperature
|
|
|
|
#if 0//def JA2TESTVERSION
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"World: Item temperature lowered from %4.2f to %4.2f", temperature, newtemperature );
|
|
#endif
|
|
|
|
// we assume that there can exist only 1 UGL per weapon
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|