Added memory leak detection to "new" operator

Prevent merc in slot 0 from disappearing due to errant schedule.  Still need to find and fix schedule though
Prevent attempts to turn or climb roof when soldier collapsed
Fix problems when mortar or RPG randomly assigned to a soldier but cannot be added for whatever reason
Pathing favors beginning path on orthogonal and using as few turns as possible (mostly old behavior).
Prevent interruptions when soldier climbs up, which can cause fall into building just below the target roof position
Fix pauses due to soldiers hurt in previous turn
Fix soldier path not reaching destination when thrown by explosion damage or heavy gunfire
Restore pathing to cave and underground exits
Fix too many AI ending up on the roofs


git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@1588 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Overhaul
2007-11-09 09:10:40 +00:00
parent 51539605f5
commit 11c4d9648e
19 changed files with 197 additions and 102 deletions
+2 -2
View File
@@ -1966,7 +1966,7 @@ void InitDetailedPlacementForMerc()
Assert( !gpSelected->pDetailedPlacement );
// WDS - Clean up inventory handling
gpSelected->pDetailedPlacement = new (MemAlloc(SIZEOF_SOLDIERCREATE_STRUCT)) SOLDIERCREATE_STRUCT;
gpSelected->pDetailedPlacement = new SOLDIERCREATE_STRUCT;
Assert( gpSelected->pDetailedPlacement );
gpSelected->pBasicPlacement->fDetailedPlacement = TRUE;
@@ -3710,7 +3710,7 @@ void PasteMercPlacement( INT32 iMapIndex )
gTempBasicPlacement.fDetailedPlacement = TRUE;
gTempBasicPlacement.fPriorityExistance = gSaveBufferBasicPlacement.fPriorityExistance;
// WDS - Clean up inventory handling
pNode->pDetailedPlacement = new (MemAlloc( SIZEOF_SOLDIERCREATE_STRUCT )) SOLDIERCREATE_STRUCT;
pNode->pDetailedPlacement = new SOLDIERCREATE_STRUCT;
if( !pNode->pDetailedPlacement )
{
AssertMsg( 0, "Failed to allocate memory for new detailed placement in PasteMercPlacement." );
+16 -16
View File
@@ -389,8 +389,8 @@ void LoadGameExternalOptions()
gGameExternalOptions.iStartAttribute = iniReader.ReadInteger("JA2 Laptop Settings","START_ATTRIBUTE",55);
//gGameExternalOptions.fPers_att = iniReader.ReadBoolean("JA2 Laptop Settings","USE_RANDOM_PERSONALITY",FALSE);
gGameExternalOptions.iCustomPersonality = iniReader.ReadInteger("JA2 Laptop Settings","CUSTOM_PERSONALITY",0);
gGameExternalOptions.iCustomAttitude = iniReader.ReadInteger("JA2 Laptop Settings","CUSTOM_ATTITUDE",0);
gGameExternalOptions.iCustomPersonality = (INT8) iniReader.ReadInteger("JA2 Laptop Settings","CUSTOM_PERSONALITY",0);
gGameExternalOptions.iCustomAttitude = (INT8) iniReader.ReadInteger("JA2 Laptop Settings","CUSTOM_ATTITUDE",0);
//Merc settings
gGameExternalOptions.fMercDayOne = iniReader.ReadBoolean("JA2 Laptop Settings","MERC_AVAILABLE_DAY_ONE",FALSE);
@@ -404,7 +404,7 @@ void LoadGameExternalOptions()
gGameExternalOptions.giInsaneMercDeaths = iniReader.ReadInteger("JA2 Laptop Settings","INSANE_MERC_DEATHS",4);
//################# System Settings #################
gGameExternalOptions.gubDeadLockDelay = iniReader.ReadInteger("JA2 System Settings","DEAD_LOCK_DELAY",15);
gGameExternalOptions.gubDeadLockDelay = (UINT8) iniReader.ReadInteger("JA2 System Settings","DEAD_LOCK_DELAY",15);
gGameExternalOptions.gfEnableEmergencyButton_SkipStrategicEvents = iniReader.ReadBoolean("JA2 System Settings","ENABLE_EMERGENCY_BUTTON_NUMLOCK_TO_SKIP_STRATEGIC_EVENTS",0);
@@ -433,11 +433,11 @@ void LoadGameExternalOptions()
gGameExternalOptions.fAllowTacticalMilitiaCommand = iniReader.ReadBoolean("JA2 Tactical Settings","ALLOW_TACTICAL_MILITIA_COMMAND",0);
// Enemy AP settings
gGameExternalOptions.iEasyAPBonus = iniReader.ReadInteger("JA2 Tactical Settings","NOVICE_AP_BONUS",0);
gGameExternalOptions.iExperiencedAPBonus = iniReader.ReadInteger("JA2 Tactical Settings","EXPERIENCED_AP_BONUS",0);
gGameExternalOptions.iExpertAPBonus = iniReader.ReadInteger("JA2 Tactical Settings","EXPERT_AP_BONUS",0);
gGameExternalOptions.iInsaneAPBonus = iniReader.ReadInteger("JA2 Tactical Settings","INSANE_AP_BONUS",0);
gGameExternalOptions.iPlayerAPBonus = iniReader.ReadInteger("JA2 Tactical Settings","PLAYER_AP_BONUS",0);
gGameExternalOptions.iEasyAPBonus = (INT8) iniReader.ReadInteger("JA2 Tactical Settings","NOVICE_AP_BONUS",0);
gGameExternalOptions.iExperiencedAPBonus = (INT8) iniReader.ReadInteger("JA2 Tactical Settings","EXPERIENCED_AP_BONUS",0);
gGameExternalOptions.iExpertAPBonus = (INT8) iniReader.ReadInteger("JA2 Tactical Settings","EXPERT_AP_BONUS",0);
gGameExternalOptions.iInsaneAPBonus = (INT8) iniReader.ReadInteger("JA2 Tactical Settings","INSANE_AP_BONUS",0);
gGameExternalOptions.iPlayerAPBonus = (INT8) iniReader.ReadInteger("JA2 Tactical Settings","PLAYER_AP_BONUS",0);
// Sight range
gGameExternalOptions.ubStraightSightRange = iniReader.ReadInteger("JA2 Tactical Settings","BASE_SIGHT_RANGE",13);
@@ -451,7 +451,7 @@ void LoadGameExternalOptions()
gGameExternalOptions.gfAllowSoldierToolTips = iniReader.ReadBoolean("JA2 Tactical Settings","ALLOW_SOLDIER_TOOL_TIPS",0);
// ShadoWarrior: Tooltip changes (start)
gGameExternalOptions.ubSoldierTooltipDetailLevel = iniReader.ReadInteger("JA2 Tactical Settings", "SOLDIER_TOOLTIP_DETAIL_LEVEL", 1);
gGameExternalOptions.ubSoldierTooltipDetailLevel = (UINT8) iniReader.ReadInteger("JA2 Tactical Settings", "SOLDIER_TOOLTIP_DETAIL_LEVEL", 1);
gGameExternalOptions.fEnableDynamicSoldierTooltips = iniReader.ReadBoolean("JA2 Tactical Settings", "DYNAMIC_SOLDIER_TOOLTIPS", TRUE);
gGameExternalOptions.fEnableSoldierTooltipLocation = iniReader.ReadBoolean("JA2 Tactical Settings", "SOLDIER_TOOLTIP_DISPLAY_LOCATION", TRUE);
@@ -531,7 +531,7 @@ void LoadGameExternalOptions()
gGameExternalOptions.fSellAll = iniReader.ReadBoolean("JA2 Gameplay Settings","CAN_SELL_ALT_LMB",FALSE);
gGameExternalOptions.iPriceModifier = iniReader.ReadInteger("JA2 Gameplay Settings","PRICE_MODIFIER",10);
gGameExternalOptions.iPriceModifier = (INT16) iniReader.ReadInteger("JA2 Gameplay Settings","PRICE_MODIFIER",10);
// WDS - Option to turn off stealing
@@ -582,10 +582,10 @@ void LoadGameExternalOptions()
gGameExternalOptions.iPercentElitesBonusExpert = iniReader.ReadInteger("JA2 Gameplay Settings","EXPERT_ELITE_BONUS",25);
gGameExternalOptions.iPercentElitesBonusInsane = iniReader.ReadInteger("JA2 Gameplay Settings","INSANE_ELITE_BONUS",50);
gGameExternalOptions.ubMinEnemyGroupSizeNovice = iniReader.ReadInteger("JA2 Gameplay Settings","NOVICE_MIN_ENEMY_GROUP_SIZE",3);
gGameExternalOptions.ubMinEnemyGroupSizeExperienced = iniReader.ReadInteger("JA2 Gameplay Settings","EXPERIENCED_MIN_ENEMY_GROUP_SIZE",4);
gGameExternalOptions.ubMinEnemyGroupSizeExpert = iniReader.ReadInteger("JA2 Gameplay Settings","EXPERT_MIN_ENEMY_GROUP_SIZE",6);
gGameExternalOptions.ubMinEnemyGroupSizeInsane = iniReader.ReadInteger("JA2 Gameplay Settings","INSANE_MIN_ENEMY_GROUP_SIZE",12);
gGameExternalOptions.ubMinEnemyGroupSizeNovice = (UINT8) iniReader.ReadInteger("JA2 Gameplay Settings","NOVICE_MIN_ENEMY_GROUP_SIZE",3);
gGameExternalOptions.ubMinEnemyGroupSizeExperienced = (UINT8) iniReader.ReadInteger("JA2 Gameplay Settings","EXPERIENCED_MIN_ENEMY_GROUP_SIZE",4);
gGameExternalOptions.ubMinEnemyGroupSizeExpert = (UINT8) iniReader.ReadInteger("JA2 Gameplay Settings","EXPERT_MIN_ENEMY_GROUP_SIZE",6);
gGameExternalOptions.ubMinEnemyGroupSizeInsane = (UINT8) iniReader.ReadInteger("JA2 Gameplay Settings","INSANE_MIN_ENEMY_GROUP_SIZE",12);
gGameExternalOptions.ubEasyEnemyStartingAlertLevel = iniReader.ReadInteger("JA2 Gameplay Settings","NOVICE_ENEMY_STARTING_ALERT_LEVEL", 5);
gGameExternalOptions.ubNormalEnemyStartingAlertLevel = iniReader.ReadInteger("JA2 Gameplay Settings","NORMAL_ENEMY_STARTING_ALERT_LEVEL", 20);
@@ -717,7 +717,7 @@ BOOLEAN GetCDLocation( )
{
UINT32 uiStrngLength = 0;
CHAR8 zCdLocation[ SGPFILENAME_LEN ];
UINT32 uiDriveType=0;
//UINT32 uiDriveType=0;
UINT32 uiRetVal=0;
//Do a crude check to make sure the Ja2.ini file is the right on
@@ -889,7 +889,7 @@ BOOLEAN CheckIfGameCdromIsInCDromDrive()
CHAR8 zCdFile[ SGPFILENAME_LEN ];
CHAR8 zCdromRootDrive[512];
BOOLEAN fFailed = FALSE;
//BOOLEAN fFailed = FALSE;
UINT32 uiVolumeReturnValue;
UINT32 uiLastError = ERROR_SUCCESS;
+5
View File
@@ -68,6 +68,7 @@ extern void ShutdownMemoryManager( void );
extern PTR MemReallocXDebug( PTR ptr, UINT32 size, const STR8 szCodeString, INT32 iLineNum, void *pSpecial );
#else
#ifdef _DEBUG
#include <crtdbg.h>
//This is another debug feature. Not as sophistocated, but definately not the pig the extreme system is.
//This system reports all memory allocations/deallocations in the debug output.
#define MemAlloc( size ) MemAllocReal( (size), __FILE__, __LINE__ )
@@ -76,6 +77,10 @@ extern void ShutdownMemoryManager( void );
extern PTR MemAllocReal( UINT32 size, const STR8 , INT32 );
extern void MemFreeReal( PTR ptr, const STR8 , INT32 );
extern PTR MemReallocReal( PTR ptr, UINT32 size, const STR8 , INT32 );
//void* ::operator new( size_t sz, const char* file, int line);
//void* ::operator new[]( size_t sz, const char *file, int line);
#define NEW new
#define new NEW(_NORMAL_BLOCK, __FILE__, __LINE__)
#else
//Release build verison
#include <malloc.h>
+1 -1
View File
@@ -1958,7 +1958,7 @@ static void ARCreateMilitia( UINT8 mclass, INT32 i, INT16 sX, INT16 sY)
ResetMortarsOnTeamCount();
if( !gpBattleGroup ) {
AssertMsg(0, "No battle group set while creating militia");
//AssertMsg(0, "No battle group set while creating militia");
}
if( mclass == SOLDIER_CLASS_ELITE_MILITIA )
+10
View File
@@ -182,6 +182,11 @@ void ProcessTacticalSchedule( UINT8 ubScheduleID )
#endif
return;
}
if (pSchedule->ubSoldierID == 0)
{
ScreenMsg( FONT_RED, MSG_INTERFACE, L"Schedule callback: Illegal soldier ID of %d.", pSchedule->ubSoldierID );
return;
}
//Validate the existance of the soldier.
pSoldier = MercPtrs[ pSchedule->ubSoldierID ];
@@ -661,6 +666,11 @@ void AutoProcessSchedule( SCHEDULENODE *pSchedule, INT32 index )
pSoldier = MercPtrs[ pSchedule->ubSoldierID ];
if (pSoldier->ubID == 0)
{
ScreenMsg( FONT_MCOLOR_LTGREEN, MSG_INTERFACE, L"Soldier %s moved to away slot by schedule ID %d!", pSoldier->name, pSchedule->ubScheduleID );
}
#ifdef JA2EDITOR
if ( pSoldier->ubProfile != NO_PROFILE )
{
+4 -4
View File
@@ -282,7 +282,7 @@ BOOLEAN LoadEnemySoldiersFromTempFile()
curr->pBasicPlacement->fPriorityExistance = TRUE;
if( !curr->pDetailedPlacement )
{ //need to upgrade the placement to detailed placement
curr->pDetailedPlacement = new (MemAlloc( SIZEOF_SOLDIERCREATE_STRUCT )) SOLDIERCREATE_STRUCT; //(SOLDIERCREATE_STRUCT*)MemAlloc( SIZEOF_SOLDIERCREATE_STRUCT );
curr->pDetailedPlacement = new SOLDIERCREATE_STRUCT; //(SOLDIERCREATE_STRUCT*)MemAlloc( SIZEOF_SOLDIERCREATE_STRUCT );
}
//now replace the map pristine placement info with the temp map file version..
//memcpy( curr->pDetailedPlacement, &tempDetailedPlacement, SIZEOF_SOLDIERCREATE_STRUCT );
@@ -475,7 +475,7 @@ BOOLEAN SaveEnemySoldiersToTempFile( INT16 sSectorX, INT16 sSectorY, INT8 bSecto
{ //need to upgrade the placement to detailed placement
curr->pBasicPlacement->fDetailedPlacement = TRUE;
// WDS - Clean up inventory handling
curr->pDetailedPlacement = new (MemAlloc( SIZEOF_SOLDIERCREATE_STRUCT )) SOLDIERCREATE_STRUCT; //(SOLDIERCREATE_STRUCT*)MemAlloc( SIZEOF_SOLDIERCREATE_STRUCT );
curr->pDetailedPlacement = new SOLDIERCREATE_STRUCT; //(SOLDIERCREATE_STRUCT*)MemAlloc( SIZEOF_SOLDIERCREATE_STRUCT );
//memset( curr->pDetailedPlacement, 0, SIZEOF_SOLDIERCREATE_STRUCT );
curr->pDetailedPlacement->initialize();
}
@@ -1009,7 +1009,7 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile()
curr->pBasicPlacement->fPriorityExistance = TRUE;
if( !curr->pDetailedPlacement )
{ //need to upgrade the placement to detailed placement
curr->pDetailedPlacement = new (MemAlloc( SIZEOF_SOLDIERCREATE_STRUCT )) SOLDIERCREATE_STRUCT; //(SOLDIERCREATE_STRUCT*)MemAlloc( SIZEOF_SOLDIERCREATE_STRUCT );
curr->pDetailedPlacement = new SOLDIERCREATE_STRUCT; //(SOLDIERCREATE_STRUCT*)MemAlloc( SIZEOF_SOLDIERCREATE_STRUCT );
}
//now replace the map pristine placement info with the temp map file version..
//memcpy( curr->pDetailedPlacement, &tempDetailedPlacement, SIZEOF_SOLDIERCREATE_STRUCT );
@@ -1582,7 +1582,7 @@ BOOLEAN NewWayOfSavingEnemyAndCivliansToTempFile( INT16 sSectorX, INT16 sSectorY
{ //need to upgrade the placement to detailed placement
curr->pBasicPlacement->fDetailedPlacement = TRUE;
// WDS - Clean up inventory handling
curr->pDetailedPlacement = new (MemAlloc( SIZEOF_SOLDIERCREATE_STRUCT )) SOLDIERCREATE_STRUCT;
curr->pDetailedPlacement = new SOLDIERCREATE_STRUCT;
curr->pDetailedPlacement->initialize();
//memset( curr->pDetailedPlacement, 0, SIZEOF_SOLDIERCREATE_STRUCT );
}
+14 -1
View File
@@ -4626,6 +4626,18 @@ BOOLEAN MakeSoldierTurn( SOLDIERTYPE *pSoldier, INT16 sXPos, INT16 sYPos )
INT16 sFacingDir, sAPCost, sAPCostToReady;
UINT16 usAnimState;
// Make sure the merc is not collapsed!
if (!IsValidStance(pSoldier, ANIM_CROUCH) )
{
if ( pSoldier->bCollapsed && pSoldier->bBreath < OKBREATH )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, gzLateLocalizedString[ 4 ], pSoldier->name );
}
return FALSE;
}
// Get direction from mouse pos
sFacingDir = GetDirectionFromXY( sXPos, sYPos, pSoldier );
@@ -4730,7 +4742,8 @@ UINT32 UIHandleLCLook( UI_EVENT *pUIEvent )
if ( MakeSoldierTurn( pSoldier, sXPos, sYPos ) )
{
SetUIBusy( pSoldier->ubID );
// 0verhaul: Why do we set UI busy for a single soldier but not for a group of selected soldiers?
//SetUIBusy( pSoldier->ubID );
}
}
return( GAME_SCREEN );
+37 -20
View File
@@ -978,33 +978,50 @@ void ChooseGrenadesForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bGrena
return;
// special mortar shell handling
if (bGrenadeClass == MORTAR_GRENADE_CLASS && itemMortar > 0 )
if (bGrenadeClass == MORTAR_GRENADE_CLASS)
{
usItem = PickARandomLaunchable ( itemMortar );
if ( usItem > 0 )
// 0verhaul: itemMortar can be 0 if the previous function
// 1) failed to find a Mortar that the soldier would want to use (due to XML prefs)
// 2) randomly chose not to supply a Mortar (always possible, even if choices exist).
// Since we should not go beyond this point in the case where Mortar Rounds are desired,
// return here in any case
if (itemMortar > 0 )
{
CreateItems( usItem, (INT8) (80 + Random(21)), bGrenades, &Object );
Object.fFlags |= OBJECT_UNDROPPABLE;
PlaceObjectInSoldierCreateStruct( pp, &Object );
return;
}
}
// special rpg rocket handling
if (bGrenadeClass == RPG_GRENADE_CLASS && itemRPG > 0 )
{
usItem = PickARandomLaunchable ( itemRPG );
if ( usItem > 0 )
{
for ( int i = 0; i < bGrenades; i++ )
usItem = PickARandomLaunchable ( itemMortar );
if ( usItem > 0 )
{
CreateItem( usItem, (INT8) (70 + Random(31)), &Object );
CreateItems( usItem, (INT8) (80 + Random(21)), bGrenades, &Object );
Object.fFlags |= OBJECT_UNDROPPABLE;
PlaceObjectInSoldierCreateStruct( pp, &Object );
}
return;
}
return;
}
// special rpg rocket handling
if (bGrenadeClass == RPG_GRENADE_CLASS)
{
// 0verhaul: itemRPG can be 0 if the previous function
// 1) failed to find an RPG that the soldier would want to use (due to XML prefs)
// 2) randomly chose not to supply an RPG (always possible, even if choices exist).
// Since we should not go beyond this point in the case where RPG grenades are desired,
// return here in any case
if (itemRPG > 0 )
{
usItem = PickARandomLaunchable ( itemRPG );
if ( usItem > 0 )
{
for ( int i = 0; i < bGrenades; i++ )
{
CreateItem( usItem, (INT8) (70 + Random(31)), &Object );
Object.fFlags |= OBJECT_UNDROPPABLE;
PlaceObjectInSoldierCreateStruct( pp, &Object );
}
}
}
return;
}
Assert( bGrenadeClass <= 11 );
+12 -2
View File
@@ -1096,7 +1096,16 @@ void AStarPathfinder::ExecuteAStarLogic()
//movementG = (INT16) CalcG( &prevCost);
//movementG = CalcAP( movementG, direction);
movementG = terrainCost * 100;
//movementG = terrainCost * 100;
movementG = terrainCost;
// Favor continuing in the same direction by increasing the cost for changing direction
int ParentParentNode = GetAStarParent( ParentNode);
if ((ParentParentNode != -1 &&
ParentNode - ParentParentNode != CurrentNode - ParentNode) ||
(ParentParentNode == -1 && (direction & 1) ) )
{
movementG++;
}
INT16 AStarG = baseGCost + movementG;
//if the node is more costly in this path than in another open path, continue
@@ -1629,7 +1638,7 @@ int AStarPathfinder::CalcH()
int x = abs(n1->x - n2->x);
int y = abs(n1->y - n2->y);
#if 0
#if 1
if (x >= y)
{
return this->travelcostDiag * y + this->travelcostOrth * (x-y);
@@ -4703,3 +4712,4 @@ UINT8 DoorTravelCost( SOLDIERTYPE * pSoldier, INT32 iGridNo, UINT8 ubMovementCos
return( InternalDoorTravelCost( pSoldier, iGridNo, ubMovementCost, fReturnPerceivedValue, piDoorGridNo, FALSE ) );
}
+12 -5
View File
@@ -252,8 +252,11 @@ BOOLEAN AdjustToNextAnimationFrame( SOLDIERTYPE *pSoldier )
// CODE: SPECIAL MOVE CLIMB UP ROOF EVENT
// re-enable sight
gTacticalStatus.uiFlags &= (~DISALLOW_SIGHT);
// Moved here because this represents "already on the roof", so breath collapses and interrupts should
// keep the soldier on the roof where he belongs
// Move merc up specific height
SetSoldierHeight( pSoldier, (FLOAT)50 );
{
INT16 sXPos, sYPos;
@@ -261,6 +264,10 @@ BOOLEAN AdjustToNextAnimationFrame( SOLDIERTYPE *pSoldier )
ConvertMapPosToWorldTileCenter( pSoldier->sTempNewGridNo, &sXPos, &sYPos );
EVENT_SetSoldierPosition( pSoldier, (FLOAT)sXPos, (FLOAT)sYPos );
}
// re-enable sight
gTacticalStatus.uiFlags &= (~DISALLOW_SIGHT);
// Move two CC directions
EVENT_SetSoldierDirection( pSoldier, gTwoCCDirection[ pSoldier->ubDirection ] );
@@ -273,9 +280,6 @@ BOOLEAN AdjustToNextAnimationFrame( SOLDIERTYPE *pSoldier )
usUIMovementMode = GetMoveStateBasedOnStance( pSoldier, gAnimControl[ pSoldier->usAnimState ].ubEndHeight );
pSoldier->usUIMovementMode = usUIMovementMode;
// Move merc up specific height
SetSoldierHeight( pSoldier, (FLOAT)50 );
// ATE: Change interface level.....
// CJC: only if we are a player merc
if (pSoldier->bTeam == gbPlayerNum)
@@ -326,6 +330,9 @@ BOOLEAN AdjustToNextAnimationFrame( SOLDIERTYPE *pSoldier )
// Move two C directions
EVENT_SetSoldierDirection( pSoldier, gTwoCDirection[ pSoldier->ubDirection ] );
// Remove the roof marker
HandlePlacingRoofMarker( pSoldier, pSoldier->sGridNo, FALSE, TRUE );
EVENT_SetSoldierDesiredDirection( pSoldier, pSoldier->ubDirection );
// Adjust height
SetSoldierHeight( pSoldier, (FLOAT)gClimbDownRoofStartDist[ pSoldier->ubBodyType ] );
+16 -2
View File
@@ -3000,7 +3000,10 @@ void InternalSetSoldierHeight( SOLDIERTYPE *pSoldier, FLOAT dNewHeight, BOOLEAN
return;
}
if ( pSoldier->sHeightAdjustment > 0 )
// 0verhaul: Changed this to half the wall height. During a climb up, a soldier's height increases to about 8, then falls
// to near 0 before being set to 50 at the end. The animation offsets should probably be changed to make this unnecessary
// but this is good enough to keep him from bouncing between level 1 and level 0 (and also triggering weird sight bugs).
if ( pSoldier->sHeightAdjustment > 25 )
{
pSoldier->bLevel = SECOND_LEVEL;
@@ -6084,6 +6087,7 @@ void TurnSoldier( SOLDIERTYPE *pSoldier)
else
{
pSoldier->uiStatusFlags &= (~SOLDIER_TURNINGFROMHIT );
pSoldier->fGettingHit = FALSE;
}
}
else if ( pSoldier->fGettingHit == 2 )
@@ -6100,7 +6104,7 @@ void TurnSoldier( SOLDIERTYPE *pSoldier)
//ReduceAttackBusyCount( );
//FREEUP GETTING HIT FLAG
// pSoldier->fGettingHit = FALSE;
pSoldier->fGettingHit = FALSE;
}
}
@@ -11598,6 +11602,11 @@ void ChangeToFlybackAnimation( SOLDIERTYPE *pSoldier, UINT8 ubDirection )
// Remove any previous actions
pSoldier->ubPendingAction = NO_PENDING_ACTION;
// Since we're manually setting our path, we have to reset these @#$@# flags too. Otherwise we don't reach the
// destination a lot of the time
pSoldier->fPastXDest = 0;
pSoldier->fPastYDest = 0;
// Set path....
pSoldier->usPathDataSize = 0;
pSoldier->usPathIndex = 0;
@@ -11638,6 +11647,11 @@ void ChangeToFallbackAnimation( SOLDIERTYPE *pSoldier, UINT8 ubDirection )
// Remove any previous actions
pSoldier->ubPendingAction = NO_PENDING_ACTION;
// Since we're manually setting our path, we have to reset these @#$@# flags too. Otherwise we don't reach the
// destination a lot of the time
pSoldier->fPastXDest = 0;
pSoldier->fPastYDest = 0;
// Set path....
pSoldier->usPathDataSize = 0;
pSoldier->usPathIndex = 0;
+3 -3
View File
@@ -751,7 +751,7 @@ SOLDIERTYPE* TacticalCreateSoldier( SOLDIERCREATE_STRUCT *pCreateStruct, UINT8 *
UINT8 ubSectorID;
ubSectorID = GetAutoResolveSectorID();
// WDS - Clean up inventory handling
pSoldier = new (MemAlloc( SIZEOF_SOLDIERTYPE )) SOLDIERTYPE; //(SOLDIERTYPE*)MemAlloc( SIZEOF_SOLDIERTYPE );
pSoldier = new SOLDIERTYPE; //(SOLDIERTYPE*)MemAlloc( SIZEOF_SOLDIERTYPE );
if( !pSoldier )
return NULL;
//memcpy( pSoldier, &Soldier, SIZEOF_SOLDIERTYPE );
@@ -2205,7 +2205,7 @@ SOLDIERTYPE* ReserveTacticalSoldierForAutoresolve( UINT8 ubSoldierClass )
// WDS - Clean up inventory handling
//Allocate and copy the soldier
pSoldier = new (MemAlloc( SIZEOF_SOLDIERTYPE )) SOLDIERTYPE; //(SOLDIERTYPE*)MemAlloc( SIZEOF_SOLDIERTYPE );
pSoldier = new SOLDIERTYPE; //(SOLDIERTYPE*)MemAlloc( SIZEOF_SOLDIERTYPE );
if( !pSoldier )
return NULL;
// memcpy( pSoldier, MercPtrs[ i ], SIZEOF_SOLDIERTYPE );
@@ -2360,7 +2360,7 @@ SOLDIERTYPE* ReserveTacticalMilitiaSoldierForAutoresolve( UINT8 ubSoldierClass )
// WDS - Clean up inventory handling
//Allocate and copy the soldier
pSoldier = new (MemAlloc( SIZEOF_SOLDIERTYPE )) SOLDIERTYPE; //(SOLDIERTYPE*)MemAlloc( SIZEOF_SOLDIERTYPE );
pSoldier = new SOLDIERTYPE; //(SOLDIERTYPE*)MemAlloc( SIZEOF_SOLDIERTYPE );
if( !pSoldier )
return NULL;
// memcpy( pSoldier, MercPtrs[ i ], SIZEOF_SOLDIERTYPE );
+12 -22
View File
@@ -516,6 +516,12 @@ BOOLEAN HandleNextTileWaiting( SOLDIERTYPE *pSoldier )
{
RESETTIMECOUNTER( pSoldier->NextTileCounter, NEXT_TILE_CHECK_DELAY );
// ATE: Allow path to exit grid!
if ( pSoldier->ubWaitActionToDo == 1 && gubWaitingForAllMercsToExitCode == WAIT_FOR_MERCS_TO_WALK_TO_GRIDNO )
{
gfPlotPathToExitGrid = TRUE;
}
// Get direction from gridno...
bCauseDirection = (INT8)GetDirectionToGridNoFromGridNo( pSoldier->sGridNo, pSoldier->sDelayedMovementCauseGridNo );
@@ -534,6 +540,7 @@ BOOLEAN HandleNextTileWaiting( SOLDIERTYPE *pSoldier )
SetFinalTile( pSoldier, pSoldier->sGridNo, TRUE );
pSoldier->fDelayedMovement = FALSE;
}
gfPlotPathToExitGrid = FALSE;
return( TRUE );
}
@@ -595,15 +602,7 @@ BOOLEAN HandleNextTileWaiting( SOLDIERTYPE *pSoldier )
sCheckGridNo = pSoldier->sFinalDestination;
}
// Try another path to destination
// ATE: Allow path to exit grid!
if ( pSoldier->ubWaitActionToDo == 1 && gubWaitingForAllMercsToExitCode == WAIT_FOR_MERCS_TO_WALK_TO_GRIDNO )
{
gfPlotPathToExitGrid = TRUE;
}
sCost = (INT16) FindBestPath( pSoldier, sCheckGridNo, pSoldier->bLevel, pSoldier->usUIMovementMode, NO_COPYROUTE, fFlags );
gfPlotPathToExitGrid = FALSE;
// Can we get there
if ( sCost > 0 )
@@ -617,15 +616,8 @@ BOOLEAN HandleNextTileWaiting( SOLDIERTYPE *pSoldier )
{
// Try to path around everyone except dest person
if ( pSoldier->ubWaitActionToDo == 1 && gubWaitingForAllMercsToExitCode == WAIT_FOR_MERCS_TO_WALK_TO_GRIDNO )
{
gfPlotPathToExitGrid = TRUE;
}
sCost = (INT16) FindBestPath( pSoldier, sCheckGridNo, pSoldier->bLevel, pSoldier->usUIMovementMode, NO_COPYROUTE, PATH_IGNORE_PERSON_AT_DEST );
gfPlotPathToExitGrid = FALSE;
// Is the next tile in this new path blocked too?
sNewGridNo = NewGridNo( (UINT16)pSoldier->sGridNo, DirectionInc( (UINT8)guiPathingData[ 0 ] ) );
@@ -633,6 +625,7 @@ BOOLEAN HandleNextTileWaiting( SOLDIERTYPE *pSoldier )
// now working with a path which does not go through people
pSoldier->ubDelayedMovementFlags &= (~DELAYED_MOVEMENT_FLAG_PATH_THROUGH_PEOPLE);
}
else
{
@@ -646,12 +639,6 @@ BOOLEAN HandleNextTileWaiting( SOLDIERTYPE *pSoldier )
// Are we clear?
if ( bPathBlocked == MOVE_TILE_CLEAR )
{
// Go for it path!
if ( pSoldier->ubWaitActionToDo == 1 && gubWaitingForAllMercsToExitCode == WAIT_FOR_MERCS_TO_WALK_TO_GRIDNO )
{
gfPlotPathToExitGrid = TRUE;
}
//pSoldier->fDelayedMovement = FALSE;
// ATE: THis will get set in EENT_GetNewSoldierPath....
pSoldier->usActionData = sCheckGridNo;
@@ -659,8 +646,8 @@ BOOLEAN HandleNextTileWaiting( SOLDIERTYPE *pSoldier )
pSoldier->bPathStored = FALSE;
EVENT_GetNewSoldierPath( pSoldier, sCheckGridNo, pSoldier->usUIMovementMode );
gfPlotPathToExitGrid = FALSE;
gfPlotPathToExitGrid = FALSE;
return( TRUE );
}
}
@@ -707,6 +694,7 @@ BOOLEAN HandleNextTileWaiting( SOLDIERTYPE *pSoldier )
NPCReachedDestination( pSoldier, FALSE );
pSoldier->bNextAction = AI_ACTION_WAIT;
pSoldier->usNextActionData = 500;
gfPlotPathToExitGrid = FALSE;
return( TRUE );
}
}
@@ -743,6 +731,8 @@ BOOLEAN HandleNextTileWaiting( SOLDIERTYPE *pSoldier )
}
}
}
gfPlotPathToExitGrid = FALSE;
return( TRUE );
}
+12 -1
View File
@@ -250,7 +250,7 @@ void QueryTBLeftButton( UINT32 *puiNewEvent )
SOLDIERTYPE *pSoldier;
UINT16 usMapPos;
static BOOLEAN fClickHoldIntercepted = FALSE;
BOOLEAN fOnInterTile = FALSE;
//BOOLEAN fOnInterTile = FALSE;
static BOOLEAN fCanCheckForSpeechAdvance = FALSE;
static INT16 sMoveClickGridNo = 0;
@@ -2347,6 +2347,17 @@ void GetKeyboardInput( UINT32 *puiNewEvent )
BOOLEAN fNearLowerLevel;
INT8 bDirection;
// Make sure the merc is not collapsed!
if (!IsValidStance(pjSoldier, ANIM_CROUCH) )
{
if ( pjSoldier->bCollapsed && pjSoldier->bBreath < OKBREATH )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, gzLateLocalizedString[ 4 ], pjSoldier->name );
}
break;
}
GetMercClimbDirection( pjSoldier->ubID, &fNearLowerLevel, &fNearHeigherLevel );
if ( fNearLowerLevel )
+6
View File
@@ -51,6 +51,7 @@
#include "Quests.h"
#include "Campaign Types.h"
#include "Queen Command.h"
#include "cheats.h"
#endif
extern void PauseAITemporarily( void );
@@ -1922,6 +1923,11 @@ void TurnBasedHandleNPCAI(SOLDIERTYPE *pSoldier)
// to get here, we MUST have an action selected, but not in progress...
if ( CHEATER_CHEAT_LEVEL( ) )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Soldier %d decides action %d with data %d", pSoldier->ubID, pSoldier->bAction, pSoldier->usActionData );
}
// see if we can afford to do this action
if (IsActionAffordable(pSoldier))
{
+3 -1
View File
@@ -2283,7 +2283,8 @@ INT16 RoamingRange(SOLDIERTYPE *pSoldier, INT16 * pusFromGridNo)
else
{
return( 5 );
} case ONGUARD: return( 5 );
}
case ONGUARD: return( 5 );
case CLOSEPATROL: return( 15 );
case RNDPTPATROL:
case POINTPATROL: return(10 ); // from nextPatrolGrid, not whereIWas
@@ -2305,6 +2306,7 @@ INT16 RoamingRange(SOLDIERTYPE *pSoldier, INT16 * pusFromGridNo)
}
case SEEKENEMY: *pusFromGridNo = pSoldier->sGridNo; // from current position!
return(MAX_ROAMING_RANGE);
case SNIPER: return ( 5 );
default:
#ifdef BETAVERSION
sprintf(tempstr,"%s has invalid orders = %d",pSoldier->name,pSoldier->bOrders);
+29 -19
View File
@@ -924,7 +924,7 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
// CLIMB A BUILDING
////////////////////////////////////////////////////////////////////////////
if (!fCivilian)
if (!fCivilian && pSoldier->bLastAction != AI_ACTION_CLIMB_ROOF)
{
iChance = 10 + pSoldier->bBypassToGreen;
@@ -965,30 +965,40 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
// reduce chance if breath is down
//iChance -= (100 - pSoldier->bBreath); // don't care
// This is the chance that we want to be on the roof. If already there, invert the chance to see if we want back
// down
if (pSoldier->bLevel > 0)
{
iChance = 100 - iChance;
}
if ((INT16) PreRandom(100) < iChance)
{
BOOLEAN fUp = FALSE;
if ( pSoldier->bLevel == 0 )
{
BOOLEAN fUp = TRUE;
if (pSoldier->bLevel > 0 )
fUp = FALSE;
fUp = TRUE;
}
else if (pSoldier->bLevel > 0 )
{
fUp = FALSE;
}
if ( CanClimbFromHere ( pSoldier, fUp ) )
if ( CanClimbFromHere ( pSoldier, fUp ) )
{
DebugMsg ( TOPIC_JA2AI , DBG_LEVEL_3 , String("Soldier %d is climbing roof",pSoldier->ubID) );
return( AI_ACTION_CLIMB_ROOF );
}
else
{
pSoldier->usActionData = FindClosestClimbPoint(pSoldier, fUp );
// Added the check here because sniper militia who are locked inside of a building without keys
// will still have a >100% chance to want to climb, which means an infinite loop. In fact, any
// time a move is desired, there probably also will be a need to check for a path.
if ( pSoldier->usActionData != NOWHERE &&
LegalNPCDestination(pSoldier,pSoldier->usActionData,ENSURE_PATH,WATEROK, 0 ))
{
DebugMsg ( TOPIC_JA2AI , DBG_LEVEL_3 , String("Soldier %d is climbing roof",pSoldier->ubID) );
return( AI_ACTION_CLIMB_ROOF );
}
else
{
pSoldier->usActionData = FindClosestClimbPoint(pSoldier, fUp );
// Added the check here because sniper militia who are locked inside of a building without keys
// will still have a >100% chance to want to climb, which means an infinite loop. In fact, any
// time a move is desired, there probably also will be a need to check for a path.
if ( pSoldier->usActionData != NOWHERE &&
LegalNPCDestination(pSoldier,pSoldier->usActionData,ENSURE_PATH,WATEROK, 0 ))
{
return( AI_ACTION_MOVE_TO_CLIMB );
}
return( AI_ACTION_MOVE_TO_CLIMB );
}
}
}
+2 -2
View File
@@ -299,8 +299,6 @@ UINT16 FindGridNoFromSweetSpotCloseToExitGrid( SOLDIERTYPE *pSoldier, INT16 sSwe
//(use the fake soldier and the pathing settings)
FindBestPath( &soldier, NOWHERE, 0, WALKING, COPYREACHABLE, PATH_THROUGH_PEOPLE );
gfPlotPathToExitGrid = FALSE;
uiLowestRange = 999999;
for( cnt1 = sBottom; cnt1 <= sTop; cnt1++ )
@@ -337,6 +335,8 @@ UINT16 FindGridNoFromSweetSpotCloseToExitGrid( SOLDIERTYPE *pSoldier, INT16 sSwe
}
}
}
gfPlotPathToExitGrid = FALSE;
gubNPCAPBudget = ubSaveNPCAPBudget;
gubNPCDistLimit = ubSaveNPCDistLimit;
+1 -1
View File
@@ -583,7 +583,7 @@ UINT32 MainGameScreenHandle(void)
// Check timer that could have been set to do anything
CheckCustomizableTimer();
// HAndle physics engine
// Handle physics engine
SimulateWorld( );
// Handle strategic engine