Fixed appearance of save game corruption when a game with different inventory set is loaded. Note that such games can still cause odd behavior and CTD's

Fixed old-style behavior when creating a soldier struct (caused memory corruption and leaks)
Fixed soldiers unable to fire if an error happened while firing the off-hand weapon
Fix animation system problems with soldiers interrupted while changing stance, such as twitching and not being able to navigate around obstacles
Prevent splitting money while an item is in the hand, which would result in losing the original item
Fix reverse of X,Y when checking visibility through a roof, which could make soldiers falsely visible/invisible
Prevent militia from simply waiting on the border when enemies are known to be in the sector
Fix stack overflow for soldier inventory debug display
Optimized A* pathing and cleaned up VS2K5 specific code
AI can now use all climb points for climbable buildings, not just a random few
Fix to not allow flat roof butted against slanted roof to be identified as a climb point
Prevent soldiers who cause an interrupt from a special action from continuing on their path after being interrupted
Prevent soldiers who enter or leave deep water from moving a space too far and turning back
Prevent soldiers from trying to crouch while in shallow water
Make soldier turn in the closest direction when he must get up from prone and turn then fall back to prone
Allow a soldier to swat for a tile before returning to prone if unable to return to prone immediately after a turn
Fix civilians that should show up in a sector, missing because of others that aren't
Fix a memset on a C++ class
Place Skyrider in a sector near his helecopter once available and the helicopter is present
Fix soldier corruption if too many shots burst-spread into too few tiles
Include both first and last tile in spread when some locations must be skipped
Fix to shoot at last location in burst
Fix to remove other previous spread locations when calculating a new spread
Fix to reload or rechamber off-hand when necessary, such as having a pistol shotgun in that hand


git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@1532 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Overhaul
2007-10-20 08:09:03 +00:00
parent eeb82168b5
commit dd0d6ea66d
35 changed files with 1322 additions and 863 deletions
+12
View File
@@ -2663,6 +2663,8 @@ void InitAnimationSurfacesPerBodytype( )
gubAnimSurfaceIndex[ FATCIV ][ GENERIC_HIT_DEATHTWITCHNB ] = FATMANDIE;
gubAnimSurfaceIndex[ FATCIV ][ GENERIC_HIT_DEATHTWITCHB ] = FATMANDIE;
gubAnimSurfaceIndex[ FATCIV ][ FALLFORWARD_FROMHIT_STAND ] = FATMANDIE;
gubAnimSurfaceIndex[ FATCIV ][ FALLFORWARD_FROMHIT_CROUCH ] = FATMANDIE;
gubAnimSurfaceIndex[ FATCIV ][ ENDFALLFORWARD_FROMHIT_CROUCH ] = FATMANDIE;
gubAnimSurfaceIndex[ FATCIV ][ FALLFORWARD_HITDEATH_STOP ] = FATMANDIE;
gubAnimSurfaceIndex[ FATCIV ][ STAND_FALLFORWARD_STOP ] = FATMANDIE;
gubAnimSurfaceIndex[ FATCIV ][ GENERIC_HIT_DEATH ] = FATMANDIE;
@@ -2699,6 +2701,8 @@ void InitAnimationSurfacesPerBodytype( )
gubAnimSurfaceIndex[ MANCIV ][ GENERIC_HIT_DEATHTWITCHNB ] = MANCIVDIE;
gubAnimSurfaceIndex[ MANCIV ][ GENERIC_HIT_DEATHTWITCHB ] = MANCIVDIE;
gubAnimSurfaceIndex[ MANCIV ][ FALLFORWARD_FROMHIT_STAND ] = MANCIVDIE;
gubAnimSurfaceIndex[ MANCIV ][ FALLFORWARD_FROMHIT_CROUCH ] = MANCIVDIE;
gubAnimSurfaceIndex[ MANCIV ][ ENDFALLFORWARD_FROMHIT_CROUCH ] = MANCIVDIE;
gubAnimSurfaceIndex[ MANCIV ][ FALLFORWARD_HITDEATH_STOP ] = MANCIVDIE;
gubAnimSurfaceIndex[ MANCIV ][ STAND_FALLFORWARD_STOP ] = MANCIVDIE;
gubAnimSurfaceIndex[ MANCIV ][ GENERIC_HIT_DEATH ] = MANCIVDIE;
@@ -2734,6 +2738,8 @@ void InitAnimationSurfacesPerBodytype( )
gubAnimSurfaceIndex[ MINICIV ][ GENERIC_HIT_DEATHTWITCHNB ] = MINICIVDIE;
gubAnimSurfaceIndex[ MINICIV ][ GENERIC_HIT_DEATHTWITCHB ] = MINICIVDIE;
gubAnimSurfaceIndex[ MINICIV ][ FALLFORWARD_FROMHIT_STAND ] = MINICIVDIE;
gubAnimSurfaceIndex[ MINICIV ][ FALLFORWARD_FROMHIT_CROUCH ] = MINICIVDIE;
gubAnimSurfaceIndex[ MINICIV ][ ENDFALLFORWARD_FROMHIT_CROUCH ] = MINICIVDIE;
gubAnimSurfaceIndex[ MINICIV ][ FALLFORWARD_HITDEATH_STOP ] = MINICIVDIE;
gubAnimSurfaceIndex[ MINICIV ][ STAND_FALLFORWARD_STOP ] = MINICIVDIE;
gubAnimSurfaceIndex[ MINICIV ][ GENERIC_HIT_DEATH ] = MINICIVDIE;
@@ -2771,6 +2777,8 @@ void InitAnimationSurfacesPerBodytype( )
gubAnimSurfaceIndex[ DRESSCIV ][ GENERIC_HIT_DEATHTWITCHNB ] = DRESSCIVDIE;
gubAnimSurfaceIndex[ DRESSCIV ][ GENERIC_HIT_DEATHTWITCHB ] = DRESSCIVDIE;
gubAnimSurfaceIndex[ DRESSCIV ][ FALLFORWARD_FROMHIT_STAND ] = DRESSCIVDIE;
gubAnimSurfaceIndex[ DRESSCIV ][ FALLFORWARD_FROMHIT_CROUCH ] = DRESSCIVDIE;
gubAnimSurfaceIndex[ DRESSCIV ][ ENDFALLFORWARD_FROMHIT_CROUCH ] = DRESSCIVDIE;
gubAnimSurfaceIndex[ DRESSCIV ][ FALLFORWARD_HITDEATH_STOP ] = DRESSCIVDIE;
gubAnimSurfaceIndex[ DRESSCIV ][ STAND_FALLFORWARD_STOP ] = DRESSCIVDIE;
gubAnimSurfaceIndex[ DRESSCIV ][ GENERIC_HIT_DEATH ] = DRESSCIVDIE;
@@ -2798,6 +2806,8 @@ void InitAnimationSurfacesPerBodytype( )
gubAnimSurfaceIndex[ HATKIDCIV ][ GENERIC_HIT_DEATHTWITCHNB ] = HATKIDCIVDIE;
gubAnimSurfaceIndex[ HATKIDCIV ][ GENERIC_HIT_DEATHTWITCHB ] = HATKIDCIVDIE;
gubAnimSurfaceIndex[ HATKIDCIV ][ FALLFORWARD_FROMHIT_STAND ] = HATKIDCIVDIE;
gubAnimSurfaceIndex[ HATKIDCIV ][ FALLFORWARD_FROMHIT_CROUCH ] = HATKIDCIVDIE;
gubAnimSurfaceIndex[ HATKIDCIV ][ ENDFALLFORWARD_FROMHIT_CROUCH ] = HATKIDCIVDIE;
gubAnimSurfaceIndex[ HATKIDCIV ][ FALLFORWARD_HITDEATH_STOP ] = HATKIDCIVDIE;
gubAnimSurfaceIndex[ HATKIDCIV ][ STAND_FALLFORWARD_STOP ] = HATKIDCIVDIE;
gubAnimSurfaceIndex[ HATKIDCIV ][ GENERIC_HIT_DEATH ] = HATKIDCIVDIE;
@@ -2839,6 +2849,8 @@ void InitAnimationSurfacesPerBodytype( )
gubAnimSurfaceIndex[ KIDCIV ][ GENERIC_HIT_DEATHTWITCHNB ] = KIDCIVDIE;
gubAnimSurfaceIndex[ KIDCIV ][ GENERIC_HIT_DEATHTWITCHB ] = KIDCIVDIE;
gubAnimSurfaceIndex[ KIDCIV ][ FALLFORWARD_FROMHIT_STAND ] = KIDCIVDIE;
gubAnimSurfaceIndex[ KIDCIV ][ FALLFORWARD_FROMHIT_CROUCH ] = KIDCIVDIE;
gubAnimSurfaceIndex[ KIDCIV ][ ENDFALLFORWARD_FROMHIT_CROUCH ] = KIDCIVDIE;
gubAnimSurfaceIndex[ KIDCIV ][ FALLFORWARD_HITDEATH_STOP ] = KIDCIVDIE;
gubAnimSurfaceIndex[ KIDCIV ][ STAND_FALLFORWARD_STOP ] = KIDCIVDIE;
gubAnimSurfaceIndex[ KIDCIV ][ GENERIC_HIT_DEATH ] = KIDCIVDIE;
+3 -3
View File
@@ -778,7 +778,7 @@ BOOLEAN DeInitAnimationSystem( )
STRUCTURE_FILE_REF *InternalGetAnimationStructureRef( UINT16 usSoldierID, UINT16 usSurfaceIndex, UINT16 usAnimState, BOOLEAN fUseAbsolute )
STRUCTURE_FILE_REF *InternalGetAnimationStructureRef( UINT8 usSoldierID, UINT16 usSurfaceIndex, UINT16 usAnimState, BOOLEAN fUseAbsolute )
{
INT8 bStructDataType;
@@ -807,13 +807,13 @@ STRUCTURE_FILE_REF *InternalGetAnimationStructureRef( UINT16 usSoldierID, UINT16
}
STRUCTURE_FILE_REF *GetAnimationStructureRef( UINT16 usSoldierID, UINT16 usSurfaceIndex, UINT16 usAnimState )
STRUCTURE_FILE_REF *GetAnimationStructureRef( UINT8 usSoldierID, UINT16 usSurfaceIndex, UINT16 usAnimState )
{
return( InternalGetAnimationStructureRef( usSoldierID, usSurfaceIndex, usAnimState, FALSE ) );
}
STRUCTURE_FILE_REF *GetDefaultStructureRef( UINT16 usSoldierID )
STRUCTURE_FILE_REF *GetDefaultStructureRef( UINT8 usSoldierID )
{
return( gAnimStructureDatabase[ MercPtrs[ usSoldierID ]->ubBodyType ][ DEFAULT_STRUCT ].pStructureFileRef );
}
+2 -2
View File
@@ -565,8 +565,8 @@ void ClearAnimationSurfacesUsageHistory( UINT16 usSoldierID );
void DeleteAnimationProfiles( );
BOOLEAN LoadAnimationProfiles( );
STRUCTURE_FILE_REF *GetAnimationStructureRef( UINT16 usSoldierID, UINT16 usSurfaceIndex, UINT16 usAnimState );
STRUCTURE_FILE_REF *GetDefaultStructureRef( UINT16 usSoldierID );
STRUCTURE_FILE_REF *GetAnimationStructureRef( UINT8 usSoldierID, UINT16 usSurfaceIndex, UINT16 usAnimState );
STRUCTURE_FILE_REF *GetDefaultStructureRef( UINT8 usSoldierID );
// Profile data
extern ANIM_PROF *gpAnimProfiles;
+4 -4
View File
@@ -198,8 +198,8 @@ void ShutDownArmsDealers()
//loop through all the item types
for( usItemIndex = 1; usItemIndex < MAXITEMS; usItemIndex++ )
{
if ( Item[usItemIndex].usItemClass == 0 )
break;
//if ( Item[usItemIndex].usItemClass == 0 )
// break;
if( gArmsDealersInventory[ ubArmsDealer ][ usItemIndex ].ubElementsAlloced > 0 )
{
FreeSpecialItemArray( &gArmsDealersInventory[ ubArmsDealer ][ usItemIndex ] );
@@ -294,8 +294,8 @@ BOOLEAN LoadArmsDealerInventoryFromSavedGameFile( HWFILE hFile, BOOLEAN fInclude
//loop through this dealer's individual items
for(usItemIndex = 1; usItemIndex < MAXITEMS; usItemIndex++ )
{
if ( Item[usItemIndex].usItemClass == 0 )
break;
//if ( Item[usItemIndex].usItemClass == 0 )
// break;
//if there are any elements allocated for this item, load them
if( gArmsDealersInventory[ubArmsDealer][usItemIndex].ubElementsAlloced > 0 )
{
+2 -2
View File
@@ -463,10 +463,10 @@ void AutoBandage( BOOLEAN fStart )
if ( pSoldier->bSlotItemTakenFrom != NO_SLOT )
{
// swap our old hand item back to the main hand
SwapObjs( &( pSoldier->inv[ HANDPOS ] ), &( pSoldier->inv[ pSoldier->bSlotItemTakenFrom ] ) );
SwapObjs( pSoldier, HANDPOS, pSoldier->bSlotItemTakenFrom );
}
// ATE: Mkae everyone stand up!
// ATE: Make everyone stand up!
if ( pSoldier->bLife >= OKLIFE && !pSoldier->bCollapsed )
{
if ( gAnimControl[ pSoldier->usAnimState ].ubHeight != ANIM_STAND )
+11 -19
View File
@@ -14,8 +14,7 @@ public:
HEAP<KEY, T>(T data, int key) {HEAP::data = data; HEAP::key = key; return;};
bool operator==(HEAP<KEY, T> &compare) {
if (this->key == compare.key && this->data == compare.data) return true;
else return false;
return (this->key == compare.key && this->data == compare.data);
}
};
@@ -54,13 +53,15 @@ private:
public:
typedef HEAP<KEY, T> CBinaryHeap_t;
void clear ()
{
heapCount = 1;
return;
}
CBinaryHeap(int size)
CBinaryHeap(int size=WORLD_MAX)
{
if (size <= 0) {
size = WORLD_MAX;
@@ -72,21 +73,12 @@ public:
return;
}
CBinaryHeap()
{
//size must be maxSize + 1, because 1 element is unused.
BinaryHeap = new HEAP<KEY, T>[WORLD_MAX+1];
maxSize = WORLD_MAX;
heapCount = 1;
return;
}
~CBinaryHeap()
{
delete BinaryHeap;
}
HEAP<KEY, T> removeElement(const T data)
CBinaryHeap_t removeElement(const T data)
{
HEAP<KEY, T> returnHeap;
int index = findData(data);
@@ -98,7 +90,7 @@ public:
return (returnHeap);
}
HEAP<KEY, T> removeElement(const T data, const KEY key)
CBinaryHeap_t removeElement(const T data, const KEY key)
{
HEAP<KEY, T> returnHeap;
int index = findData(data, key);
@@ -250,7 +242,7 @@ insert:
}*/
}
HEAP<KEY, T> popTopHeap(int& returnSize)
CBinaryHeap_t popTopHeap(int& returnSize)
{
returnSize = heapCount-1;
if (heapCount != 1) {
@@ -259,7 +251,7 @@ insert:
return (BinaryHeap[0]);
}
HEAP<KEY, T> popTopHeap()
CBinaryHeap_t popTopHeap()
{
HEAP<KEY, T> returnHeap;
if (heapCount != 1) {
@@ -295,12 +287,12 @@ insert:
return (returnHeap);
}
HEAP<KEY, T> peekTopHeap() const
CBinaryHeap_t peekTopHeap() const
{
return (BinaryHeap[(heapCount != 1)]);
}
HEAP<KEY, T> peekElement(int index) const
CBinaryHeap_t peekElement(int index) const
{
if (index < heapCount) {
return (BinaryHeap[index]);
@@ -352,7 +344,7 @@ insert:
private:
int heapCount;
int maxSize;
HEAP<KEY, T>* BinaryHeap;
CBinaryHeap_t* BinaryHeap;
};
#endif
+2 -2
View File
@@ -1369,7 +1369,7 @@ BOOLEAN NewWayOfLoadingCiviliansFromTempFile()
if( !curr->pDetailedPlacement )
{
//need to upgrade the placement to detailed placement
curr->pDetailedPlacement = new (MemAlloc( SIZEOF_SOLDIERCREATE_STRUCT )) SOLDIERCREATE_STRUCT;
curr->pDetailedPlacement = new SOLDIERCREATE_STRUCT;
}
//now replace the map pristine placement info with the temp map file version..
//memcpy( curr->pDetailedPlacement, &tempDetailedPlacement, SIZEOF_SOLDIERCREATE_STRUCT );
@@ -1558,7 +1558,7 @@ BOOLEAN NewWayOfSavingEnemyAndCivliansToTempFile( INT16 sSectorX, INT16 sSectorY
//STEP ONE: Prep the soldiers for saving...
//modify the map's soldier init list to reflect the changes to the member's still alive...
//modify the map's soldier init list to reflect the changes to the members still alive...
for( i = gTacticalStatus.Team[ ubStartID ].bFirstID; i <= gTacticalStatus.Team[ ubEndID ].bLastID; i++ )
{
pSoldier = MercPtrs[ i ];
+8 -1
View File
@@ -284,6 +284,7 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT8 bLevel, UINT16 usHa
// Check HAND ITEM
if ( Item[ usHandItem ].usItemClass == IC_GUN || Item[ usHandItem ].usItemClass == IC_THROWING_KNIFE )
{
// WEAPONS
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleItem: checking for fingerprintID, item id = %d,id required = %d, imprint id = %d, soldier id = %d",usHandItem,Item[usHandItem].fingerprintid,pSoldier->inv[ pSoldier->ubAttackingHand ].ubImprintID,pSoldier->ubProfile));
if ( Item[usHandItem].fingerprintid )
@@ -545,6 +546,8 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT8 bLevel, UINT16 usHa
if ( Item[ usHandItem ].usItemClass != IC_THROWING_KNIFE )
{
pSoldier->ubAttackingHand = HANDPOS;
pSoldier->usAttackingWeapon = usHandItem;
// If doing spread, set down the first gridno.....
if ( pSoldier->fDoSpread )
{
@@ -2144,7 +2147,11 @@ OBJECTTYPE* InternalAddItemToPool( INT16 *psGridNo, OBJECTTYPE *pObject, INT8 bV
(*psGridNo) = sNewGridNo = gMapInformation.sCenterGridNo;
//return( NULL );
// If no center grid number exists, shrug it off
if (sNewGridNo == -1)
{
return( NULL );
}
}
// CHECK IF THIS ITEM IS IN DEEP WATER....
+2 -2
View File
@@ -102,7 +102,7 @@ BOOLEAN AddUIPlan( UINT16 sGridNo, UINT8 ubPlanID )
ConvertGridNoToCenterCellXY( sGridNo, &sXPos, &sYPos );
EVENT_SetSoldierPosition( pPlanSoldier, sXPos, sYPos );
EVENT_SetSoldierDestination( pPlanSoldier, sGridNo );
EVENT_SetSoldierDestination( pPlanSoldier, (UINT8) sGridNo ); // Hopefully this code is never used anymore because the second param is now direction, not grid
pPlanSoldier->bVisible = 1;
pPlanSoldier->usUIMovementMode = gpUIPlannedSoldier->usUIMovementMode;
@@ -181,7 +181,7 @@ BOOLEAN AddUIPlan( UINT16 sGridNo, UINT8 ubPlanID )
}
EVENT_SetSoldierPosition( pPlanSoldier, gpUIPlannedSoldier->dXPos, gpUIPlannedSoldier->dYPos );
EVENT_SetSoldierDestination( pPlanSoldier, gpUIPlannedSoldier->sGridNo );
EVENT_SetSoldierDestination( pPlanSoldier, (UINT8) gpUIPlannedSoldier->sGridNo );
pPlanSoldier->bVisible = 1;
pPlanSoldier->usUIMovementMode = gpUIPlannedSoldier->usUIMovementMode;
+5 -2
View File
@@ -3386,7 +3386,7 @@ void UIHandleSoldierStanceChange( UINT8 ubSoldierID, INT8 bNewStance )
// IF turn-based - adjust stance now!
if ( gTacticalStatus.uiFlags & TURNBASED && ( gTacticalStatus.uiFlags & INCOMBAT ) )
{
pSoldier->fTurningFromPronePosition = FALSE;
pSoldier->bTurningFromPronePosition = TURNING_FROM_PRONE_OFF;
// Check if we have enough APS
if ( SoldierCanAffordNewStance( pSoldier, bNewStance ) )
@@ -3420,13 +3420,16 @@ void UIHandleSoldierStanceChange( UINT8 ubSoldierID, INT8 bNewStance )
// LOCK VARIBLE FOR NO UPDATE INDEX...
pSoldier->usUIMovementMode = GetMoveStateBasedOnStance( pSoldier, bNewStance );
pSoldier->ubDesiredHeight = NO_DESIRED_HEIGHT;
#if 0
if ( pSoldier->usUIMovementMode == CRAWLING && gAnimControl[ pSoldier->usAnimState ].ubEndHeight != ANIM_PRONE )
{
pSoldier->usDontUpdateNewGridNoOnMoveAnimChange = LOCKED_NO_NEWGRIDNO;
pSoldier->bPathStored = FALSE;
}
else
#endif
{
pSoldier->usDontUpdateNewGridNoOnMoveAnimChange = 1;
}
@@ -6319,7 +6322,7 @@ BOOLEAN ValidQuickExchangePosition( )
BOOLEAN IsValidJumpLocation( SOLDIERTYPE *pSoldier, INT16 sGridNo, BOOLEAN fCheckForPath )
{
INT16 sFourGrids[4], sDistance=0, sSpot, sIntSpot;
INT8 sDirs[4] = { NORTH, EAST, SOUTH, WEST };
static const UINT8 sDirs[4] = { NORTH, EAST, SOUTH, WEST };
//INT32 cnt;
UINT8 ubGuyThere;
UINT8 ubMovementCost;
+3 -3
View File
@@ -1166,7 +1166,7 @@ BOOLEAN HandleTalkingMenuEscape( BOOLEAN fCanDelete , BOOLEAN fFromEscKey )
{
ShutupaYoFace( gTalkPanel.iFaceIndex );
}
// Else if our queue is empty, delete emnu
// Else if our queue is empty, delete menu
else
{
if ( DialogueQueueIsEmpty( ) && fCanDelete )
@@ -2225,7 +2225,7 @@ void HandleNPCDoAction( UINT8 ubTargetNPC, UINT16 usActionCode, UINT8 ubQuoteNum
bItemIn = FindAIUsableObjClass( pSoldier, IC_GUN );
if (bItemIn != NO_SLOT && bItemIn != HANDPOS)
{
SwapObjs( &(pSoldier->inv[HANDPOS]), &(pSoldier->inv[bItemIn]) );
SwapObjs( pSoldier, HANDPOS, bItemIn );
sGridNo = pSoldier->sGridNo + DirectionInc( pSoldier->ubDirection );
SoldierReadyWeapon( pSoldier, (INT16) (sGridNo % WORLD_COLS), (INT16) (sGridNo / WORLD_COLS), FALSE );
}
@@ -3114,7 +3114,7 @@ void HandleNPCDoAction( UINT8 ubTargetNPC, UINT16 usActionCode, UINT8 ubQuoteNum
if (bMoneySlot < bEmptySlot)
{
// move main stash to later in inventory!
SwapObjs( &(pSoldier->inv[ bEmptySlot ] ), &(pSoldier->inv[ bMoneySlot ] ) );
SwapObjs( pSoldier, bEmptySlot, bMoneySlot );
SoldierGiveItem( pSoldier, pSoldier2, &(pSoldier->inv[ bMoneySlot ] ), bMoneySlot );
}
else
+11 -3
View File
@@ -610,7 +610,7 @@ void GenerateProsString( STR16 zItemPros, OBJECTTYPE * pObject, UINT32 uiPixLimi
ubWeight = Item[ usItem ].ubWeight;
if (Item[ usItem ].usItemClass == IC_GUN)
{
ubWeight += Item[ pObject->ItemData.Gun.usGunAmmoItem ].ubWeight;
ubWeight = ubWeight + Item[ pObject->ItemData.Gun.usGunAmmoItem ].ubWeight;
}
if (Weapon[usItem].bAccuracy >= EXCEPTIONAL_ACCURACY )
@@ -753,7 +753,7 @@ void GenerateConsString( STR16 zItemCons, OBJECTTYPE * pObject, UINT32 uiPixLimi
ubWeight = Item[ usItem ].ubWeight;
if (Item[ usItem ].usItemClass == IC_GUN)
{
ubWeight += Item[ pObject->ItemData.Gun.usGunAmmoItem ].ubWeight;
ubWeight = ubWeight + Item[ pObject->ItemData.Gun.usGunAmmoItem ].ubWeight;
}
if (ubWeight >= BAD_WEIGHT)
@@ -2390,6 +2390,14 @@ BOOLEAN InternalInitItemDescriptionBox( OBJECTTYPE *pObject, INT16 sX, INT16 sY,
INT16 sForeColour;
INT16 sProsConsIndent;
// ADB: Make sure the current object isn't money if there's something in hand
if (Item[ pObject->usItem].usItemClass & IC_MONEY && gpItemPointer != NULL && gpItemPointer->usItem != 0) {
//ADB oops, money splits and puts a new item on the cursor, which would replace what's already on the cursor!
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Unable to split money due to having an item on your cursor." );
return FALSE;
}
//Set the current screen
guiCurrentItemDescriptionScreen = guiCurrentScreen;
@@ -5539,7 +5547,7 @@ BOOLEAN InitKeyRingPopup( SOLDIERTYPE *pSoldier, INT16 sInvX, INT16 sInvY, INT16
HVOBJECT hVObject;
INT32 cnt;
UINT16 usPopupWidth, usPopupHeight;
UINT8 ubSlotSimilarToKeySlot = 10;
//UINT8 ubSlotSimilarToKeySlot = 10;
INT16 sKeyRingItemWidth = 0;
INT16 sOffSetY = 0, sOffSetX = 0;
+29 -8
View File
@@ -2378,6 +2378,26 @@ void SwapObjs( OBJECTTYPE * pObj1, OBJECTTYPE * pObj2 )
*/
}
//ADB these 2 functions were created because the code calls SwapObjs all over the place
//but never handles the effects of that swap!
void SwapObjs(SOLDIERTYPE* pSoldier, int leftSlot, int rightSlot)
{
PERFORMANCE_MARKER
SwapObjs(&pSoldier->inv[ leftSlot ], &pSoldier->inv[ rightSlot ]);
//old usItem for the left slot is now stored in the right slot, and vice versa
HandleTacticalEffectsOfEquipmentChange(pSoldier, leftSlot, pSoldier->inv[ rightSlot ].usItem, pSoldier->inv[ leftSlot ].usItem);
HandleTacticalEffectsOfEquipmentChange(pSoldier, rightSlot, pSoldier->inv[ leftSlot ].usItem, pSoldier->inv[ rightSlot ].usItem);
}
void SwapObjs(SOLDIERTYPE* pSoldier, int slot, OBJECTTYPE* pObject)
{
PERFORMANCE_MARKER
SwapObjs(&pSoldier->inv[ slot ], pObject);
HandleTacticalEffectsOfEquipmentChange(pSoldier, slot, pObject->usItem, pSoldier->inv[ slot ].usItem);
}
void RemoveObjFrom( OBJECTTYPE * pObj, UINT8 ubRemoveIndex )
{
// remove 1 object from an OBJECTTYPE, starting at index bRemoveIndex
@@ -3922,7 +3942,7 @@ BOOLEAN PlaceObject( SOLDIERTYPE * pSoldier, INT8 bPos, OBJECTTYPE * pObj )
if (pSoldier->inv[SECONDHANDPOS].usItem != 0)
{
// swap what WAS in the second hand into the cursor
SwapObjs( pObj, &(pSoldier->inv[SECONDHANDPOS]));
SwapObjs( pSoldier, SECONDHANDPOS, pObj);
}
}
}
@@ -3932,7 +3952,8 @@ BOOLEAN PlaceObject( SOLDIERTYPE * pSoldier, INT8 bPos, OBJECTTYPE * pObj )
{
// replacement/reloading/merging/stacking
// keys have an additional check for key ID being the same
if ( (pObj->usItem == pInSlot->usItem) && ( Item[ pObj->usItem ].usItemClass != IC_KEY || pObj->ItemData.Key.ubKeyID == pInSlot->ItemData.Key.ubKeyID ) )
if ( (pObj->usItem == pInSlot->usItem) &&
( Item[ pObj->usItem ].usItemClass != IC_KEY || pObj->ItemData.Key.ubKeyID == pInSlot->ItemData.Key.ubKeyID ) )
{
if (Item[ pObj->usItem ].usItemClass == IC_MONEY)
{
@@ -3967,7 +3988,7 @@ BOOLEAN PlaceObject( SOLDIERTYPE * pSoldier, INT8 bPos, OBJECTTYPE * pObj )
if (pObj->ubNumberOfObjects <= 1)
{
// swapping
SwapObjs( pObj, pInSlot );
SwapObjs( pSoldier, bPos, pObj );
}
else
{
@@ -4031,13 +4052,13 @@ BOOLEAN PlaceObject( SOLDIERTYPE * pSoldier, INT8 bPos, OBJECTTYPE * pObj )
}
else
{
SwapObjs( pObj, pInSlot );
SwapObjs( pSoldier, bPos, pObj );
}
}
else if (pObj->ubNumberOfObjects <= __max( ubSlotLimit, 1 ) )
{
// swapping
SwapObjs( pObj, pInSlot );
SwapObjs( pSoldier, bPos, pObj );
}
else
{
@@ -5647,7 +5668,7 @@ void SwapHandItems( SOLDIERTYPE * pSoldier )
if (pSoldier->inv[HANDPOS].usItem == NOTHING || pSoldier->inv[SECONDHANDPOS].usItem == NOTHING)
{
// whatever is in the second hand can be swapped to the main hand!
SwapObjs( &(pSoldier->inv[HANDPOS]), &(pSoldier->inv[SECONDHANDPOS]) );
SwapObjs( pSoldier, HANDPOS, SECONDHANDPOS );
DirtyMercPanelInterface( pSoldier, DIRTYLEVEL2 );
}
else
@@ -5662,7 +5683,7 @@ void SwapHandItems( SOLDIERTYPE * pSoldier )
}
// the main hand is now empty so a swap is going to work...
}
SwapObjs( &(pSoldier->inv[HANDPOS]), &(pSoldier->inv[SECONDHANDPOS]) );
SwapObjs( pSoldier, HANDPOS, SECONDHANDPOS );
DirtyMercPanelInterface( pSoldier, DIRTYLEVEL2 );
}
}
@@ -5679,7 +5700,7 @@ void SwapOutHandItem( SOLDIERTYPE * pSoldier )
if (pSoldier->inv[SECONDHANDPOS].usItem == NOTHING)
{
// just swap the hand item to the second hand
SwapObjs( &(pSoldier->inv[HANDPOS]), &(pSoldier->inv[SECONDHANDPOS]) );
SwapObjs( pSoldier, HANDPOS, SECONDHANDPOS );
DirtyMercPanelInterface( pSoldier, DIRTYLEVEL2 );
return;
}
+2
View File
@@ -35,6 +35,8 @@ extern INT8 FindUsableObj( SOLDIERTYPE * pSoldier, UINT16 usItem );
extern void DeleteObj(OBJECTTYPE * pObj );
extern void CopyObj( OBJECTTYPE * pSourceObj, OBJECTTYPE * pTargetObj );
extern void SwapObjs( OBJECTTYPE * pObj1, OBJECTTYPE * pObj2 );
extern void SwapObjs(SOLDIERTYPE* pSoldier, int leftSlot, int rightSlot);
extern void SwapObjs(SOLDIERTYPE* pSoldier, int slot, OBJECTTYPE* pObject);
extern void SwapWithinObj( OBJECTTYPE * pObj, UINT8 ubIndex1, UINT8 ubIndex2 );
extern void RemoveObjFrom( OBJECTTYPE * pObj, UINT8 ubRemoveIndex );
+2 -2
View File
@@ -799,7 +799,7 @@ INT32 LineOfSightTest( FLOAT dStartX, FLOAT dStartY, FLOAT dStartZ, FLOAT dEndX,
fCheckForRoof = FALSE;
// figure out starting and ending cubes
iGridNo = GETWORLDINDEXFROMWORLDCOORDS( (INT32)dStartX, (INT32)dStartY );
iGridNo = GETWORLDINDEXFROMWORLDCOORDS( (INT32)dStartY, (INT32)dStartX );
qCurrZ = FloatToFixed( dStartZ );
qLandHeight = INT32_TO_FIXEDPT( CONVERT_PIXELS_TO_HEIGHTUNITS( gpWorldLevelData[ iGridNo ].sHeight ) );
iCurrAboveLevelZ = FIXEDPT_TO_INT32( qCurrZ - qLandHeight );
@@ -835,7 +835,7 @@ INT32 LineOfSightTest( FLOAT dStartX, FLOAT dStartY, FLOAT dStartZ, FLOAT dEndX,
}
}
iGridNo = GETWORLDINDEXFROMWORLDCOORDS( (INT32)dEndX, (INT32)dEndY );
iGridNo = GETWORLDINDEXFROMWORLDCOORDS( (INT32)dEndY, (INT32)dEndX );
qCurrZ = FloatToFixed( dEndZ );
qLandHeight = INT32_TO_FIXEDPT( CONVERT_PIXELS_TO_HEIGHTUNITS( gpWorldLevelData[ iGridNo ].sHeight ) );
iCurrAboveLevelZ = FIXEDPT_TO_INT32( qCurrZ - qLandHeight );
+4 -1
View File
@@ -231,7 +231,10 @@ void PrepareMilitiaForTactical( BOOLEAN fPrepareAll)
ubGreen = pSector->ubNumberOfCivsAtLevel[ GREEN_MILITIA ];
ubRegs = pSector->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ];
ubElites = pSector->ubNumberOfCivsAtLevel[ ELITE_MILITIA ];
// Prevent militia from just waiting on the border
gTacticalStatus.Team[MILITIA_TEAM].bAwareOfOpposition = (pSector->uiFlags & SF_PLAYER_KNOWS_ENEMIES_ARE_HERE) != 0;
if(guiDirNumber)
{
if (fPrepareAll)
+14 -9
View File
@@ -110,6 +110,7 @@
#include "Strategic Status.h"
#include "PreBattle Interface.h"
#include "Militia Control.h"
#include "Lua Interpreter.h"
#endif
extern void HandleBestSightingPositionInRealtime();
@@ -707,6 +708,8 @@ BOOLEAN InitOverhead( )
ZeroAnimSurfaceCounts( );
InitializeLua();
return( TRUE );
}
@@ -714,6 +717,8 @@ BOOLEAN ShutdownOverhead( )
{
UINT32 cnt;
ShutdownLua( );
// Delete any soldiers which have been created!
for( cnt = 0; cnt < TOTAL_SOLDIERS; cnt++ )
{
@@ -1575,7 +1580,7 @@ BOOLEAN ExecuteOverhead( )
{
// Change desired direction
// Just change direction
EVENT_InternalSetSoldierDestination( pSoldier, pSoldier->usPathingData[ pSoldier->usPathIndex ], FALSE, pSoldier->usAnimState );
EVENT_InternalSetSoldierDestination( pSoldier, (UINT8) pSoldier->usPathingData[ pSoldier->usPathIndex ], FALSE, pSoldier->usAnimState );
}
if ( gTacticalStatus.bBoxingState != NOT_BOXING && (gTacticalStatus.bBoxingState == BOXING_WAITING_FOR_PLAYER || gTacticalStatus.bBoxingState == PRE_BOXING || gTacticalStatus.bBoxingState == BOXING) )
@@ -2273,7 +2278,7 @@ BOOLEAN HandleGotoNewGridNo( SOLDIERTYPE *pSoldier, BOOLEAN *pfKeepMoving, BOOLE
if ( !fDontContinue )
{
// Don't apply the first deduction in points...
if ( usAnimState == CRAWLING && pSoldier->fTurningFromPronePosition > 1 )
if ( usAnimState == CRAWLING && pSoldier->bTurningFromPronePosition > TURNING_FROM_PRONE_ON )
{
}
else
@@ -2325,7 +2330,7 @@ BOOLEAN HandleGotoNewGridNo( SOLDIERTYPE *pSoldier, BOOLEAN *pfKeepMoving, BOOLE
}
// Change desired direction
EVENT_InternalSetSoldierDestination( pSoldier, pSoldier->usPathingData[ pSoldier->usPathIndex ], fInitialMove, usAnimState );
EVENT_InternalSetSoldierDestination( pSoldier, (UINT8) pSoldier->usPathingData[ pSoldier->usPathIndex ], fInitialMove, usAnimState );
// CONTINUE
// IT'S SAVE TO GO AGAIN, REFRESH flag
@@ -4586,7 +4591,7 @@ INT16 FindAdjacentGridEx( SOLDIERTYPE *pSoldier, INT16 sGridNo, UINT8 *pubDirect
// fDoor determines whether special door-handling code should be used (for interacting with doors)
INT16 sFourGrids[4], sDistance=0;
INT8 sDirs[4] = { NORTH, EAST, SOUTH, WEST };
static const UINT8 sDirs[4] = { NORTH, EAST, SOUTH, WEST };
//INT32 cnt;
INT16 sClosest=NOWHERE, sSpot, sOkTest;
INT16 sCloseGridNo=NOWHERE;
@@ -4730,7 +4735,7 @@ INT16 FindAdjacentGridEx( SOLDIERTYPE *pSoldier, INT16 sGridNo, UINT8 *pubDirect
// MOVE OUT TWO DIRECTIONS
sFourGrids[cnt] = sSpot = NewGridNo( sGridNo, DirectionInc( sDirs[ cnt ] ) );
ubTestDirection = (UINT8)sDirs[ cnt ];
ubTestDirection = sDirs[ cnt ];
// For switches, ALLOW them to walk through walls to reach it....
if ( pDoor && pDoor->fFlags & STRUCTURE_SWITCH )
@@ -4874,7 +4879,7 @@ INT16 FindNextToAdjacentGridEx( SOLDIERTYPE *pSoldier, INT16 sGridNo, UINT8 *pub
// fDoor determines whether special door-handling code should be used (for interacting with doors)
INT16 sFourGrids[4], sDistance=0;
INT8 sDirs[4] = { NORTH, EAST, SOUTH, WEST };
static const UINT8 sDirs[4] = { NORTH, EAST, SOUTH, WEST };
//INT32 cnt;
INT16 sClosest=WORLD_MAX, sSpot, sSpot2, sOkTest;
INT16 sCloseGridNo=NOWHERE;
@@ -4957,7 +4962,7 @@ INT16 FindNextToAdjacentGridEx( SOLDIERTYPE *pSoldier, INT16 sGridNo, UINT8 *pub
// MOVE OUT TWO DIRECTIONS
sFourGrids[cnt] = sSpot = NewGridNo( sGridNo, DirectionInc( sDirs[ cnt ] ) );
ubTestDirection = (UINT8)sDirs[ cnt ];
ubTestDirection = sDirs[ cnt ];
if ( pDoor && pDoor->fFlags & STRUCTURE_SWITCH )
{
@@ -5274,7 +5279,7 @@ void HandleTeamServices( UINT8 ubTeamNum )
}
if ( bSlot != NO_SLOT )
{
SwapObjs( &(pTeamSoldier->inv[HANDPOS]), &(pTeamSoldier->inv[bSlot] ) );
SwapObjs( pTeamSoldier, HANDPOS, bSlot );
}
else
{
@@ -5361,7 +5366,7 @@ void HandlePlayerServices( SOLDIERTYPE *pTeamSoldier )
if ( bSlot != NO_SLOT )
{
SwapObjs( &(pTeamSoldier->inv[HANDPOS]), &(pTeamSoldier->inv[bSlot] ) );
SwapObjs( pTeamSoldier, HANDPOS, bSlot );
}
else
{
+69 -63
View File
@@ -10,6 +10,7 @@
#define _PATHAI_H
#include "isometric utils.h"
#define USE_ASTAR_PATHS
#ifdef USE_ASTAR_PATHS
@@ -30,30 +31,25 @@ class AStar_Data
public:
AStar_Data()
{
cost = f = APCost = direction = prevCost = 0;
#ifdef ASTAR_USING_EXTRACOVER
cost = directionFromPrev = 0;
extraGCoverCost = -1;//-1 means we have not stopped at this node
#endif
wasBackwards = false;
status = AStar_Init;
parent = GridNode(-1,-1);
parent = -1;
};
//no H
int cost;//G
int f;//F
int APCost;//the APs spent to get here
#ifdef ASTAR_USING_EXTRACOVER
// h is calculated on the fly
INT16 cost;//G
//int f;//F is also calculated on the fly
//int APCost;//the APs spent to get here // Isn't this the same as "cost"?
int extraGCoverCost;//an extra cost that makes stopping in midpath at a node with little cover worse
#endif
GridNode parent;
INT16 parent;
eAStar status;
int prevCost;
//int prevCost;
bool wasBackwards;
int direction;
UINT8 directionFromPrev;
int numSteps;
};
typedef HEAP<int, GridNode> AStarHeap;
class AStarPathfinder
{
public:
@@ -68,13 +64,19 @@ public:
private:
static AStarPathfinder* pThis;
std::vector<GridNode> ClosedList;
CBinaryHeap<int, GridNode> OpenHeap;
CBinaryHeap<int, INT16> OpenHeap;
int direction;//current direction
int startDir;
int endDir;
int lastDir;
// The "closed list" is the AStarData array below which is also the path backtrace when a path is found.
// For PythSpacesAway, we do not really need the distance, but rather something to compare against.
// So I will eliminate the sqrt function from the result for the sake of speed. This means that when comparing against
// input distances, we should square them. This is one of the variables that needs to hold the squared value.
int gubNPCDistLimitSq;
UINT8 direction;//current direction
UINT8 startDir;
UINT8 endDir;
UINT8 lastDir;
bool startingLoop;
SOLDIERTYPE* pSoldier;
@@ -84,7 +86,7 @@ private:
bool fPathingForPlayer;
bool fPathAroundPeople;
bool fGoingThroughDoor;
int bOKToAddStructID;
INT16 bOKToAddStructID;
int bLoopState;
bool bWaterToWater;
bool fVisitSpotsOnlyOnce;
@@ -95,13 +97,16 @@ private:
bool fConsiderPersonAtDestAsObstacle;
bool fCopyReachable;
bool fCopyPathCosts;
bool fFindClimbPoints;
int maxAPBudget;//the gubNPCAPBudget
int mercsMaxAPs;//the merc only has so many points to move with
int movementMode;
int sClosePathLimit;
UINT16 movementMode;
int sClosePathLimitSq;
int PATHAI_VISIBLE_DEBUG_Counter;
int travelcostDiag;
int travelcostOrth;
INT16 PATHAI_VISIBLE_DEBUG_Counter;
//vehicle defined in cpp
//#ifdef VEHICLE
@@ -110,20 +115,18 @@ private:
//#endif
// member variables to prevent passing them around
GridNode StartNode;
GridNode DestNode;
GridNode CurrentNode;
GridNode ParentNode;
INT16 ParentNodeIndex;
INT16 CurrentNodeIndex;
INT16 StartNode;
INT16 DestNode;
INT16 CurrentNode;
INT16 ParentNode;
AStar_Data AStarData[WORLD_COLS][WORLD_ROWS];
AStar_Data AStarData[WORLD_MAX];
AStarHeap AStar ();
INT16 AStar ();
void ExecuteAStarLogic();
@@ -131,49 +134,49 @@ private:
int TerrainCostToAStarG(int const terrainCost);
int CalcG (int* pPrevCost);
int CalcAP (int const terrainCost);
INT16 CalcAP (int const terrainCost, UINT8 const direction);
int CalcH ();
int CalcGCover (int const NodeIndex,
int const APCost);
int CalcStartingAP ();
INT16 CalcStartingAP ();
//including THREATTYPE was a pain, so pass by value
int CalcCoverValue (INT16 sMyGridNo, INT32 iMyThreat, INT32 iMyAPsLeft,
INT32 myThreatsiOrigRange, INT16 myThreatssGridNo, SOLDIERTYPE* myThreatspOpponent,
INT32 myThreatsiValue, INT32 myThreatsiAPs, INT32 myThreatsiCertainty);
eAStar GetAStarStatus (const GridNode node) const {return AStarData[node.x][node.y].status;};
GridNode GetAStarParent (const GridNode node) const {return AStarData[node.x][node.y].parent;};
int GetAStarG (const GridNode node) const {return AStarData[node.x][node.y].cost;};
int GetAStarF (const GridNode node) const {return AStarData[node.x][node.y].f;};
int GetActionPoints (const GridNode node) const {return AStarData[node.x][node.y].APCost;};
bool GetLoopState (const GridNode node) const {return AStarData[node.x][node.y].wasBackwards;};
int GetPrevCost (const GridNode node) const {return AStarData[node.x][node.y].prevCost;};
int GetDirection (const GridNode node) const {return AStarData[node.x][node.y].direction;};
#ifdef ASTAR_USING_EXTRACOVER
int GetExtraGCover (const GridNode node) const {return AStarData[node.x][node.y].extraGCoverCost;};
eAStar GetAStarStatus (const INT16 node) const {return AStarData[node].status;};
INT16 GetAStarParent (const INT16 node) const {return AStarData[node].parent;};
INT16 GetAStarG (INT16 node) const {return AStarData[node].cost;};
int GetExtraGCover (const INT16 node) const {return AStarData[node].extraGCoverCost;};
//int GetAStarF (const INT16 node) const {return AStarData[node].f;};
//int GetActionPoints (const INT16 node) const {return AStarData[node].APCost;};
bool GetLoopState (const INT16 node) const {return AStarData[node].wasBackwards;};
//int GetPrevCost (const INT16 node) const {return AStarData[node].prevCost;};
UINT8 GetDirection (const INT16 node) const {return AStarData[node].directionFromPrev;};
int GetNumSteps (const INT16 node) const {return AStarData[node].numSteps;};
void SetExtraGCover (const GridNode node, const int extraGCoverCost) {AStarData[node.x][node.y].extraGCoverCost = extraGCoverCost;};
#endif
void SetAStarStatus (const GridNode node, const eAStar status) {AStarData[node.x][node.y].status = status;};
void SetAStarParent (const GridNode node, const GridNode parent) {AStarData[node.x][node.y].parent = parent;};
void SetAStarG (const GridNode node, const int cost) {AStarData[node.x][node.y].cost = cost;};
void SetAStarF (const GridNode node, const int f) {AStarData[node.x][node.y].f = f;};
void SetActionPoints (const GridNode node, const int APCost) {AStarData[node.x][node.y].APCost = APCost;};
void SetLoopState (const GridNode node, const int loopState);
void SetPrevCost (const GridNode node, const int prevCost) {AStarData[node.x][node.y].prevCost = prevCost;};
void SetDirection (const GridNode node, const int direction) {AStarData[node.x][node.y].direction = direction;};
void SetAStarStatus (const INT16 node, const eAStar status) {AStarData[node].status = status;};
void SetAStarParent (const INT16 node, const INT16 parent) {AStarData[node].parent = parent;};
void SetAStarG (const INT16 node, const INT16 cost) {AStarData[node].cost = cost;};
void SetExtraGCover (const INT16 node, const int extraGCoverCost) {AStarData[node].extraGCoverCost = extraGCoverCost;};
//void SetAStarF (const INT16 node, const int f) {AStarData[node].f = f;};
//void SetActionPoints (const INT16 node, const int APCost) {AStarData[node].APCost = APCost;};
void SetLoopState (const INT16 node, const int loopState);
//void SetPrevCost (const INT16 node, const int prevCost) {AStarData[node].prevCost = prevCost;};
void SetDirection (const INT16 node, const UINT8 direction) {AStarData[node].directionFromPrev = direction;};
void SetNumSteps (const INT16 node, const int steps) {AStarData[node].numSteps = steps;};
INT16 PythSpacesAway (GridNode const node1,
GridNode const node2);
INT16 SpacesAway (GridNode const node1,
GridNode const node2);
//bool IsDiagonal (GridNode const node1,
// GridNode const node2) {return (abs(node1.x - node2.x) && abs(node1.y - node2.y));};
int PythSpacesAway (const INT16 node1,
const INT16 node2);
INT16 SpacesAway (const INT16 node1,
const INT16 node2);
//bool IsDiagonal (const INT16 node1,
// const INT16 node2) {return (abs(node1.x - node2.x) && abs(node1.y - node2.y));};
bool IsDiagonal (int const direction) {return (direction & 1);};
void InitVehicle ();
int VehicleObstacleCheck();
bool CanTraverse ();
bool WantToTraverse (); // Renamed this because it doesn't mean "can we traverse" but rather, if it is profitable to.
bool IsSomeoneInTheWay();
void IncrementLoop ();
void InitLoop ();
@@ -182,7 +185,7 @@ private:
};//end namespace ASTAR
#endif//end #ifdef USE_ASTAR_PATHS
#endif// USE_ASTAR_PATHS
BOOLEAN InitPathAI( void );
@@ -289,12 +292,15 @@ extern UINT8 gubGlobalPathFlags;
#define COPYROUTE 1
#define COPYREACHABLE 2
#define COPYREACHABLE_AND_APS 3
#define FINDCLIMBPOINTS 4
#define PATH_THROUGH_PEOPLE 0x01
#define PATH_IGNORE_PERSON_AT_DEST 0x02
#define PATH_CLOSE_GOOD_ENOUGH 0x04
#define PATH_CLOSE_RADIUS 5
#define PATH_CLOSE_RADIUS_SQ 25
// ------------------------------------------
+679 -376
View File
File diff suppressed because it is too large Load Diff
+25 -8
View File
@@ -83,12 +83,21 @@ INT16 TerrainActionPoints( SOLDIERTYPE *pSoldier, INT16 sGridno, INT8 bDir, INT8
}
else if (IS_TRAVELCOST_DOOR( sSwitchValue ))
{
// Can't travel diagonally through a door
if (bDir & 1)
{
return -1;
}
sSwitchValue = DoorTravelCost( pSoldier, sGridno, (UINT8) sSwitchValue, (BOOLEAN) (pSoldier->bTeam == gbPlayerNum), NULL );
}
if (sSwitchValue >= TRAVELCOST_BLOCKED && sSwitchValue != TRAVELCOST_DOOR )
else if (gfPlotPathToExitGrid && sSwitchValue == TRAVELCOST_EXITGRID)
{
return(100); // Cost too much to be considered!
sSwitchValue = gTileTypeMovementCost[ gpWorldLevelData[ sGridno ].ubTerrainID ];
}
if (sSwitchValue >= TRAVELCOST_BLOCKED && sSwitchValue != TRAVELCOST_DOOR)
{
return(-1); // Cost too much to be considered!
}
switch( sSwitchValue )
@@ -115,7 +124,7 @@ INT16 TerrainActionPoints( SOLDIERTYPE *pSoldier, INT16 sGridno, INT8 bDir, INT8
case TRAVELCOST_VEINMID : sAPCost += AP_MOVEMENT_FLAT;
break;
*/
case TRAVELCOST_DOOR : sAPCost += AP_MOVEMENT_FLAT;
case TRAVELCOST_DOOR : sAPCost += AP_MOVEMENT_FLAT + AP_OPEN_DOOR + AP_OPEN_DOOR; // Include open and close costs!
break;
// cost for jumping a fence REPLACES all other AP costs!
@@ -265,6 +274,10 @@ INT16 ActionPointCost( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT8 bDir, UINT16 u
// get the tile cost for that tile based on WALKING
sTileCost = TerrainActionPoints( pSoldier, sGridNo, bDir, pSoldier->bLevel );
if (sTileCost == -1)
{
return 100;
}
// Get switch value...
sSwitchValue = gubWorldMovementCosts[ sGridNo ][ bDir ][ pSoldier->bLevel ];
@@ -343,6 +356,10 @@ INT16 EstimateActionPointCost( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT8 bDir,
// get the tile cost for that tile based on WALKING
sTileCost = TerrainActionPoints( pSoldier, sGridNo, bDir, pSoldier->bLevel );
if (sTileCost == -1)
{
return 100;
}
// so, then we must modify it for other movement styles and accumulate
if (sTileCost > 0)
@@ -1484,7 +1501,7 @@ UINT8 MinAPsToPunch(SOLDIERTYPE *pSoldier, INT16 sGridNo, UINT8 ubAddTurningCost
INT8 MinPtsToMove(SOLDIERTYPE *pSoldier)
{
// look around all 8 directions and return lowest terrain cost
INT8 cnt;
UINT8 cnt;
INT16 sLowest=127;
INT16 sGridno,sCost;
@@ -1493,9 +1510,9 @@ INT8 MinPtsToMove(SOLDIERTYPE *pSoldier)
return( (INT8)sLowest);
}
for (cnt=0; cnt <= 7; cnt++)
for (cnt=0; cnt < 8; cnt++)
{
sGridno = NewGridNo(pSoldier->sGridNo, DirectionInc( cnt ));
sGridno = NewGridNo(pSoldier->sGridNo,DirectionInc(cnt));
if (sGridno != pSoldier->sGridNo)
{
if ( (sCost=ActionPointCost( pSoldier, sGridno, cnt , pSoldier->usUIMovementMode ) ) < sLowest )
@@ -1513,7 +1530,7 @@ INT8 PtsToMoveDirection(SOLDIERTYPE *pSoldier, INT8 bDirection )
INT8 bOverTerrainType;
UINT16 usMoveModeToUse;
sGridno = NewGridNo( pSoldier->sGridNo, DirectionInc( bDirection ) );
sGridno = NewGridNo( pSoldier->sGridNo, DirectionInc(bDirection ) );
usMoveModeToUse = pSoldier->usUIMovementMode;
+1
View File
@@ -3,5 +3,6 @@
BOOLEAN IsItAllowedToRenderRain();
void RenderRain();
void ResetRain();
#endif
+2 -2
View File
@@ -1817,7 +1817,7 @@ void GetBloodFromCorpse( SOLDIERTYPE *pSoldier )
{
ROTTING_CORPSE *pCorpse;
INT8 bObjSlot;
OBJECTTYPE Object;
OBJECTTYPE Object = {};
// OK, get corpse
pCorpse = &( gRottingCorpse[ pSoldier->uiPendingActionData4 ] );
@@ -1847,7 +1847,7 @@ void GetBloodFromCorpse( SOLDIERTYPE *pSoldier )
if ( bObjSlot != NO_SLOT )
{
SwapObjs( &(pSoldier->inv[ bObjSlot ] ), &Object );
SwapObjs( pSoldier, bObjSlot, &Object );
}
}
+14 -4
View File
@@ -2020,7 +2020,9 @@ BOOLEAN AdjustToNextAnimationFrame( SOLDIERTYPE *pSoldier )
// ReduceAttackBusyCount( pSoldier->ubSuppressorID, FALSE );
// }
if ( pSoldier->usPendingAnimation == NO_PENDING_ANIMATION && ( pSoldier->fTurningFromPronePosition != 3 ) && ( pSoldier->fTurningFromPronePosition != 1 ) )
if ( pSoldier->usPendingAnimation == NO_PENDING_ANIMATION &&
( pSoldier->bTurningFromPronePosition != TURNING_FROM_PRONE_ENDING_UP_FROM_MOVE ) &&
( pSoldier->bTurningFromPronePosition != TURNING_FROM_PRONE_ON ) )
{
if ( gTacticalStatus.ubAttackBusyCount == 0 )
{
@@ -2033,7 +2035,10 @@ BOOLEAN AdjustToNextAnimationFrame( SOLDIERTYPE *pSoldier )
// Check to see if we have changed stance and need to update visibility
if ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_STANCECHANGEANIM)
{
if ( pSoldier->usPendingAnimation == NO_PENDING_ANIMATION && gTacticalStatus.ubAttackBusyCount == 0 && pSoldier->fTurningFromPronePosition != 3 && pSoldier->fTurningFromPronePosition != 1 )
if ( pSoldier->usPendingAnimation == NO_PENDING_ANIMATION &&
gTacticalStatus.ubAttackBusyCount == 0 &&
pSoldier->bTurningFromPronePosition != TURNING_FROM_PRONE_ENDING_UP_FROM_MOVE &&
pSoldier->bTurningFromPronePosition != TURNING_FROM_PRONE_ON )
{
HandleSight(pSoldier,SIGHT_LOOK | SIGHT_RADIO | SIGHT_INTERRUPT );
}
@@ -2057,7 +2062,12 @@ BOOLEAN AdjustToNextAnimationFrame( SOLDIERTYPE *pSoldier )
}
// Have we finished opening doors?
if ( pSoldier->usAnimState == END_OPEN_DOOR || pSoldier->usAnimState == END_OPEN_DOOR_CROUCHED || pSoldier->usAnimState == CRIPPLE_CLOSE_DOOR || pSoldier->usAnimState == CRIPPLE_END_OPEN_DOOR )
// 0verhaul: Added additional check: Are we told to stop at this point, maybe due to being interrupted?
if ( !pSoldier->fNoAPToFinishMove &&
(pSoldier->usAnimState == END_OPEN_DOOR ||
pSoldier->usAnimState == END_OPEN_DOOR_CROUCHED ||
pSoldier->usAnimState == CRIPPLE_CLOSE_DOOR ||
pSoldier->usAnimState == CRIPPLE_END_OPEN_DOOR ) )
{
// Are we told to continue movement...?
if ( pSoldier->bEndDoorOpenCode == 1 )
@@ -3565,7 +3575,7 @@ void CheckForAndHandleSoldierIncompacitated( SOLDIERTYPE *pSoldier )
return;
}
}
else if ( pSoldier->usAnimState == GENERIC_HIT_CROUCH )
else if ( pSoldier->usAnimState == GENERIC_HIT_CROUCH || pSoldier->usAnimState == CIV_COWER_HIT)
{
ChangeSoldierState( pSoldier, FALLFORWARD_FROMHIT_CROUCH, 0 , FALSE);
BeginTyingToFall( pSoldier );
+89 -49
View File
@@ -94,6 +94,7 @@
#include "Campaign Types.h"
#include "Strategic Status.h"
#include "civ quotes.h"
#include "Strategic Pathing.h"
#endif
//turnspeed
@@ -113,11 +114,6 @@ extern INT16 DirIncrementer[8];
#define LOW_MORALE_BATTLE_SND_THREASHOLD 35
#define TURNING_FROM_PRONE_OFF 0
#define TURNING_FROM_PRONE_ON 1
#define TURNING_FROM_PRONE_START_UP_FROM_MOVE 2
#define TURNING_FROM_PRONE_ENDING_UP_FROM_MOVE 3
#define MIN_SUBSEQUENT_SNDS_DELAY 2000
// Enumerate extended directions
@@ -1756,7 +1752,7 @@ BOOLEAN ReevaluateEnemyStance( SOLDIERTYPE *pSoldier, UINT16 usAnimState )
// make the chosen one not turn to face us
if ( OK_ENEMY_MERC( pSoldier ) && pSoldier->ubID != gTacticalStatus.ubTheChosenOne && gAnimControl[ usAnimState ].ubEndHeight == ANIM_STAND && !( pSoldier->uiStatusFlags & SOLDIER_UNDERAICONTROL) )
{
if ( pSoldier->fTurningFromPronePosition == TURNING_FROM_PRONE_OFF )
if ( pSoldier->bTurningFromPronePosition == TURNING_FROM_PRONE_OFF )
{
// If we are a queen and see enemies, goto ready
if ( pSoldier->ubBodyType == QUEENMONSTER )
@@ -2000,7 +1996,7 @@ BOOLEAN EVENT_InitNewSoldierAnim( SOLDIERTYPE *pSoldier, UINT16 usNewState, UINT
EVENT_SetSoldierDesiredDirection( pSoldier, pSoldier->ubPendingDirection );
pSoldier->ubPendingDirection = NO_PENDING_DIRECTION;
pSoldier->usPendingAnimation = CLIMBDOWNROOF;
pSoldier->fTurningFromPronePosition = FALSE;
pSoldier->bTurningFromPronePosition = TURNING_FROM_PRONE_OFF;
pSoldier->fTurningUntilDone = TRUE;
SoldierGotoStationaryStance( pSoldier );
return( TRUE );
@@ -2236,20 +2232,29 @@ BOOLEAN EVENT_InitNewSoldierAnim( SOLDIERTYPE *pSoldier, UINT16 usNewState, UINT
// Unset paused for no APs.....
AdjustNoAPToFinishMove( pSoldier, FALSE );
#if 0
// 0verhaul: This is a test. The only time I have been able to make this code hit is when
// the player goes prone while moving. And that is not what this part is intended for. I
// have seen the soldier in the middle of crawling, get up, turn, and then go prone again to
// continue along his path. But this code was not hit for that part. And this code seems
// to be made for that part. So apparently they found another way to deal with it. So
// I disabled the "locked" code for usDontUpdateNewGridNoOnMoveAnimChange since it can cause
// problems of its own. Now we see if we can do without this part too.
if ( usNewState == CRAWLING && pSoldier->usDontUpdateNewGridNoOnMoveAnimChange == 1 )
{
if ( pSoldier->fTurningFromPronePosition != TURNING_FROM_PRONE_ENDING_UP_FROM_MOVE )
if ( pSoldier->bTurningFromPronePosition != TURNING_FROM_PRONE_ENDING_UP_FROM_MOVE )
{
pSoldier->fTurningFromPronePosition = TURNING_FROM_PRONE_START_UP_FROM_MOVE;
pSoldier->bTurningFromPronePosition = TURNING_FROM_PRONE_START_UP_FROM_MOVE;
}
// ATE: IF we are starting to crawl, but have to getup to turn first......
if ( pSoldier->fTurningFromPronePosition == TURNING_FROM_PRONE_START_UP_FROM_MOVE )
if ( pSoldier->bTurningFromPronePosition == TURNING_FROM_PRONE_START_UP_FROM_MOVE )
{
usNewState = PRONE_UP;
pSoldier->fTurningFromPronePosition = TURNING_FROM_PRONE_ENDING_UP_FROM_MOVE;
pSoldier->bTurningFromPronePosition = TURNING_FROM_PRONE_ENDING_UP_FROM_MOVE;
}
}
#endif
// We are about to start moving
// Handle buddy beginning to move...
@@ -2303,7 +2308,7 @@ BOOLEAN EVENT_InitNewSoldierAnim( SOLDIERTYPE *pSoldier, UINT16 usNewState, UINT
{
// Change desired direction
// Just change direction
EVENT_InternalSetSoldierDestination( pSoldier, pSoldier->usPathingData[ pSoldier->usPathIndex ], FALSE, pSoldier->usAnimState );
EVENT_InternalSetSoldierDestination( pSoldier, (UINT8) pSoldier->usPathingData[ pSoldier->usPathIndex ], FALSE, pSoldier->usAnimState );
}
//check for services
@@ -2336,7 +2341,14 @@ BOOLEAN EVENT_InitNewSoldierAnim( SOLDIERTYPE *pSoldier, UINT16 usNewState, UINT
// ( Unless locked )
if ( gAnimControl[ usNewState ].uiFlags & ANIM_MOVING )
{
if ( pSoldier->usDontUpdateNewGridNoOnMoveAnimChange != LOCKED_NO_NEWGRIDNO )
// 0verhaul: **** Special hack!!!!
// If a merc begins to go prone while moving, the LOCKED_NO_NEWGRIDNO is set. If the merc never finishes
// going prone, either due to interrupting the stance change with a different stance change, or other possible
// factors such as maybe getting shot (this is realtime so an enemy could see him), it stays on locked. Once
// it stays on locked, the soldier will be unable to navigate around obstacles but will simply stay put
// twitching. Since the LOCKED is only set when going prone, this unsets it.
if ( pSoldier->usDontUpdateNewGridNoOnMoveAnimChange != LOCKED_NO_NEWGRIDNO ||
(pSoldier->usDontUpdateNewGridNoOnMoveAnimChange == LOCKED_NO_NEWGRIDNO && pSoldier->usAnimState != PRONE_DOWN))
{
pSoldier->usDontUpdateNewGridNoOnMoveAnimChange = FALSE;
}
@@ -2367,7 +2379,7 @@ BOOLEAN EVENT_InitNewSoldierAnim( SOLDIERTYPE *pSoldier, UINT16 usNewState, UINT
uiOldAnimFlags = gAnimControl[ pSoldier->usAnimState ].uiFlags;
uiNewAnimFlags = gAnimControl[ usNewState ].uiFlags;
usNewGridNo = NewGridNo( pSoldier->sGridNo, DirectionInc( pSoldier->usPathingData[ pSoldier->usPathIndex ] ) );
usNewGridNo = NewGridNo( pSoldier->sGridNo, DirectionInc( (UINT8) pSoldier->usPathingData[ pSoldier->usPathIndex ] ) );
// CHECKING IF WE HAVE A HIT FINISH BUT NO DEATH IS DONE WITH A SPECIAL ANI CODE
@@ -2479,7 +2491,7 @@ BOOLEAN EVENT_InitNewSoldierAnim( SOLDIERTYPE *pSoldier, UINT16 usNewState, UINT
case CRAWLING:
// Turn off flag...
pSoldier->fTurningFromPronePosition = TURNING_FROM_PRONE_OFF;
pSoldier->bTurningFromPronePosition = TURNING_FROM_PRONE_OFF;
pSoldier->ubPendingActionAnimCount = 0;
pSoldier->usPendingAnimation = NO_PENDING_ANIMATION;
break;
@@ -2521,7 +2533,7 @@ BOOLEAN EVENT_InitNewSoldierAnim( SOLDIERTYPE *pSoldier, UINT16 usNewState, UINT
case PRONE_DOWN:
// ATE: If we are NOT waiting for prone down...
if ( pSoldier->fTurningFromPronePosition < TURNING_FROM_PRONE_START_UP_FROM_MOVE && !pSoldier->fDontChargeAPsForStanceChange )
if ( pSoldier->bTurningFromPronePosition < TURNING_FROM_PRONE_START_UP_FROM_MOVE && !pSoldier->fDontChargeAPsForStanceChange )
{
// ATE: Don't do this if we are still 'moving'....
if ( pSoldier->sGridNo == pSoldier->sFinalDestination || pSoldier->usPathIndex == 0 )
@@ -2649,7 +2661,7 @@ BOOLEAN EVENT_InitNewSoldierAnim( SOLDIERTYPE *pSoldier, UINT16 usNewState, UINT
pSoldier->usPathDataSize++;
pSoldier->sFinalDestination = usNewGridNo;
// Set direction
EVENT_InternalSetSoldierDestination( pSoldier, pSoldier->usPathingData[ pSoldier->usPathIndex ], FALSE, JUMP_OVER_BLOCKING_PERSON );
EVENT_InternalSetSoldierDestination( pSoldier, (UINT8) pSoldier->usPathingData[ pSoldier->usPathIndex ], FALSE, JUMP_OVER_BLOCKING_PERSON );
}
break;
@@ -3256,7 +3268,7 @@ void SetSoldierGridNo( SOLDIERTYPE *pSoldier, INT16 sNewGridNo, BOOLEAN fForceRe
// Make transition from low to deep
EVENT_InitNewSoldierAnim( pSoldier, LOW_TO_DEEP_WATER, 0 , FALSE );
pSoldier->usPendingAnimation = DEEP_WATER_SWIM;
pSoldier->usDontUpdateNewGridNoOnMoveAnimChange = 1;
PlayJA2Sample( ENTER_DEEP_WATER_1, RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
}
@@ -3273,6 +3285,7 @@ void SetSoldierGridNo( SOLDIERTYPE *pSoldier, INT16 sNewGridNo, BOOLEAN fForceRe
{
// Make transition from low to deep
EVENT_InitNewSoldierAnim( pSoldier, DEEP_TO_LOW_WATER, 0 , FALSE );
pSoldier->usDontUpdateNewGridNoOnMoveAnimChange = 1;
pSoldier->usPendingAnimation = pSoldier->usUIMovementMode;
}
}
@@ -3494,7 +3507,7 @@ void EVENT_FireSoldierWeapon( SOLDIERTYPE *pSoldier, INT16 sTargetGridNo )
pSoldier->fDontUnsetLastTargetFromTurn = TRUE;
// Make sure we don't try and do fancy prone turning.....
pSoldier->fTurningFromPronePosition = FALSE;
pSoldier->bTurningFromPronePosition = TURNING_FROM_PRONE_OFF;
// Force our direction!
EVENT_SetSoldierDirection( pSoldier, pSoldier->bDesiredDirection );
@@ -5032,7 +5045,7 @@ BOOLEAN EVENT_InternalGetNewSoldierPath( SOLDIERTYPE *pSoldier, UINT16 sDestGrid
pSoldier->sGridNo = pSoldier->sDestination;
// Check if path is good before copying it into guy's path...
if ( FindBestPath( pSoldier, sDestGridNo, pSoldier->bLevel, pSoldier->usUIMovementMode, NO_COPYROUTE, fFlags ) == 0 )
if ( !(uiDist = FindBestPath( pSoldier, sDestGridNo, pSoldier->bLevel, pSoldier->usUIMovementMode, COPYROUTE, fFlags ) ) )
{
// Set to old....
pSoldier->sGridNo = sMercGridNo;
@@ -5040,7 +5053,7 @@ BOOLEAN EVENT_InternalGetNewSoldierPath( SOLDIERTYPE *pSoldier, UINT16 sDestGrid
return( FALSE );
}
uiDist = FindBestPath( pSoldier, sDestGridNo, pSoldier->bLevel, pSoldier->usUIMovementMode, COPYROUTE, fFlags );
//uiDist = FindBestPath( pSoldier, sDestGridNo, pSoldier->bLevel, pSoldier->usUIMovementMode, COPYROUTE, fFlags );
pSoldier->sGridNo = sMercGridNo;
pSoldier->sFinalDestination = sDestGridNo;
@@ -5124,6 +5137,11 @@ BOOLEAN EVENT_InternalGetNewSoldierPath( SOLDIERTYPE *pSoldier, UINT16 sDestGrid
{
usMoveAnimState = DEEP_WATER_SWIM;
}
// Can't forget shallow water! AI will sometimes attempt to swat through it, which is not legal either
else if ( MercInWater( pSoldier) )
{
usMoveAnimState = WALKING;
}
// If we were aiming, end aim!
usAnimState = PickSoldierReadyAnimation( pSoldier, TRUE );
@@ -5330,9 +5348,9 @@ void EVENT_InternalSetSoldierDestination( SOLDIERTYPE *pSoldier, UINT8 ubNewDire
}
}
void EVENT_SetSoldierDestination( SOLDIERTYPE *pSoldier, UINT16 usNewDirection )
void EVENT_SetSoldierDestination( SOLDIERTYPE *pSoldier, UINT8 ubNewDirection )
{
EVENT_InternalSetSoldierDestination( pSoldier, usNewDirection, FALSE, pSoldier->usAnimState );
EVENT_InternalSetSoldierDestination( pSoldier, ubNewDirection, FALSE, pSoldier->usAnimState );
}
@@ -5402,7 +5420,7 @@ INT8 MultiTiledTurnDirection( SOLDIERTYPE * pSoldier, INT8 bStartDirection, INT8
}
bLoop++;
if ( bLoop < 2 )
//if ( bLoop < 2 )
{
// change direction of loop etc
bCurrentDirection = bStartDirection;
@@ -5469,9 +5487,9 @@ void EVENT_InternalSetSoldierDesiredDirection( SOLDIERTYPE *pSoldier, UINT8 ubNe
{
if ( gAnimControl[ usAnimState ].ubHeight == ANIM_PRONE )
{
if ( pSoldier->fTurningFromPronePosition != TURNING_FROM_PRONE_ENDING_UP_FROM_MOVE )
if ( pSoldier->bTurningFromPronePosition != TURNING_FROM_PRONE_ENDING_UP_FROM_MOVE )
{
pSoldier->fTurningFromPronePosition = TURNING_FROM_PRONE_START_UP_FROM_MOVE;
pSoldier->bTurningFromPronePosition = TURNING_FROM_PRONE_START_UP_FROM_MOVE;
}
}
}
@@ -5485,7 +5503,7 @@ void EVENT_InternalSetSoldierDesiredDirection( SOLDIERTYPE *pSoldier, UINT8 ubNe
//if ( pSoldier->sDestination == pSoldier->sGridNo )
if ( !fInitalMove )
{
pSoldier->fTurningFromPronePosition = TURNING_FROM_PRONE_ON;
pSoldier->bTurningFromPronePosition = TURNING_FROM_PRONE_ON;
// Set a pending animation to change stance first...
SendChangeSoldierStanceEvent( pSoldier, ANIM_CROUCH );
@@ -5922,7 +5940,11 @@ void TurnSoldier( SOLDIERTYPE *pSoldier)
{
if ( pSoldier->ubDirection == pSoldier->bDesiredDirection )
{
if ( ( (gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_FIREREADY ) && !pSoldier->fTurningFromPronePosition ) || pSoldier->ubBodyType == ROBOTNOWEAPON || pSoldier->ubBodyType == TANK_NW || pSoldier->ubBodyType == TANK_NE )
if ( ( (gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_FIREREADY ) &&
pSoldier->bTurningFromPronePosition == TURNING_FROM_PRONE_OFF) ||
pSoldier->ubBodyType == ROBOTNOWEAPON ||
pSoldier->ubBodyType == TANK_NW ||
pSoldier->ubBodyType == TANK_NE )
{
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("TurnSoldier: EVENT_InitNewSoldierAnim") );
EVENT_InitNewSoldierAnim( pSoldier, SelectFireAnimation( pSoldier, gAnimControl[ pSoldier->usAnimState ].ubEndHeight ), 0, FALSE );
@@ -5933,7 +5955,7 @@ void TurnSoldier( SOLDIERTYPE *pSoldier)
}
// Else check if we are trying to shoot and once was prone, but am now crouched because we needed to turn...
else if ( pSoldier->fTurningFromPronePosition )
else if ( pSoldier->bTurningFromPronePosition != TURNING_FROM_PRONE_OFF )
{
if ( IsValidStance( pSoldier, ANIM_PRONE ) )
{
@@ -5945,7 +5967,7 @@ void TurnSoldier( SOLDIERTYPE *pSoldier)
EVENT_InitNewSoldierAnim( pSoldier, SelectFireAnimation( pSoldier, ANIM_CROUCH ), 0, FALSE );
}
pSoldier->fTurningToShoot = FALSE;
pSoldier->fTurningFromPronePosition = TURNING_FROM_PRONE_OFF;
pSoldier->bTurningFromPronePosition = TURNING_FROM_PRONE_OFF;
}
}
}
@@ -6002,7 +6024,9 @@ void TurnSoldier( SOLDIERTYPE *pSoldier)
pSoldier->fDontUnsetLastTargetFromTurn = FALSE;
// Unset ui busy if from ui
if ( pSoldier->bTurningFromUI && ( pSoldier->fTurningFromPronePosition != 3 ) && ( pSoldier->fTurningFromPronePosition != 1 ) )
if ( pSoldier->bTurningFromUI &&
( pSoldier->bTurningFromPronePosition != TURNING_FROM_PRONE_ENDING_UP_FROM_MOVE ) &&
( pSoldier->bTurningFromPronePosition != TURNING_FROM_PRONE_ON ) )
{
UnSetUIBusy( pSoldier->ubID );
pSoldier->bTurningFromUI = FALSE;
@@ -6017,23 +6041,30 @@ void TurnSoldier( SOLDIERTYPE *pSoldier)
// Undo our flag for prone turning...
// Else check if we are trying to shoot and once was prone, but am now crouched because we needed to turn...
if ( pSoldier->fTurningFromPronePosition == TURNING_FROM_PRONE_ON )
if ( pSoldier->bTurningFromPronePosition == TURNING_FROM_PRONE_ON )
{
// ATE: Don't do this if we have something in our hands we are going to throw!
if ( IsValidStance( pSoldier, ANIM_PRONE ) && pSoldier->pTempObject == NULL )
{
SendChangeSoldierStanceEvent( pSoldier, ANIM_PRONE );
}
pSoldier->fTurningFromPronePosition = TURNING_FROM_PRONE_OFF;
pSoldier->bTurningFromPronePosition = TURNING_FROM_PRONE_OFF;
}
// If a special code, make guy crawl after stance change!
if ( pSoldier->fTurningFromPronePosition == TURNING_FROM_PRONE_ENDING_UP_FROM_MOVE && pSoldier->usAnimState != PRONE_UP && pSoldier->usAnimState != PRONE_DOWN )
if ( pSoldier->bTurningFromPronePosition == TURNING_FROM_PRONE_ENDING_UP_FROM_MOVE &&
pSoldier->usAnimState != PRONE_UP &&
pSoldier->usAnimState != PRONE_DOWN )
{
if ( IsValidStance( pSoldier, ANIM_PRONE ) )
{
EVENT_InitNewSoldierAnim( pSoldier, CRAWLING, 0, FALSE );
}
// Else swat for a tile so that there's room to resume prone
else
{
EVENT_InitNewSoldierAnim( pSoldier, pSoldier->usUIMovementMode, 0 , FALSE );
}
}
if ( pSoldier->uiStatusFlags & SOLDIER_TURNINGFROMHIT )
@@ -6181,7 +6212,7 @@ void TurnSoldier( SOLDIERTYPE *pSoldier)
{
// OK, we want to getup, turn and go prone again....
SendChangeSoldierStanceEvent( pSoldier, ANIM_CROUCH );
pSoldier->fTurningFromPronePosition = TURNING_FROM_PRONE_ENDING_UP_FROM_MOVE;
pSoldier->bTurningFromPronePosition = TURNING_FROM_PRONE_ENDING_UP_FROM_MOVE;
}
// If we are a creature, or multi-tiled, cancel AI action.....?
else if ( pSoldier->uiStatusFlags & SOLDIER_MULTITILE )
@@ -7090,7 +7121,7 @@ void BeginSoldierClimbFence( SOLDIERTYPE *pSoldier )
EVENT_InternalSetSoldierDesiredDirection( pSoldier, bDirection, FALSE, pSoldier->usAnimState );
pSoldier->fTurningUntilDone = TRUE;
// ATE: Reset flag to go back to prone...
pSoldier->fTurningFromPronePosition = TURNING_FROM_PRONE_OFF;
pSoldier->bTurningFromPronePosition = TURNING_FROM_PRONE_OFF;
pSoldier->usPendingAnimation = HOPFENCE;
}
@@ -9603,7 +9634,7 @@ void EVENT_SoldierBeginKnifeThrowAttack( SOLDIERTYPE *pSoldier, INT16 sGridNo, U
// SET TARGET GRIDNO
pSoldier->sTargetGridNo = sGridNo;
pSoldier->sLastTarget = sGridNo;
pSoldier->fTurningFromPronePosition = 0;
pSoldier->bTurningFromPronePosition = TURNING_FROM_PRONE_OFF;
// NB target level must be set by functions outside of here... but I think it
// is already set in HandleItem or in the AI code - CJC
pSoldier->ubTargetID = WhoIsThere2( sGridNo, pSoldier->bTargetLevel );
@@ -10158,7 +10189,7 @@ void HaultSoldierFromSighting( SOLDIERTYPE *pSoldier, BOOLEAN fFromSightingEnemy
if ( !pSoldier->fTurningToShoot )
{
pSoldier->fTurningFromPronePosition = FALSE;
pSoldier->bTurningFromPronePosition = TURNING_FROM_PRONE_OFF;
}
}
@@ -10195,7 +10226,7 @@ void EVENT_StopMerc( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT8 bDirection )
}
pSoldier->bEndDoorOpenCode = 0;
pSoldier->fTurningFromPronePosition = 0;
pSoldier->bTurningFromPronePosition = TURNING_FROM_PRONE_OFF;
// Cancel path data!
pSoldier->usPathIndex = pSoldier->usPathDataSize = 0;
@@ -10982,15 +11013,17 @@ void SoldierCollapse( SOLDIERTYPE *pSoldier )
// Crouched or prone, only for mercs!
BeginTyingToFall( pSoldier );
if ( fMerc )
{
// 0verhaul: No special case here! First the FALLFORWARD_FROMHIT_CROUCH can be filled in to use the FALLFORWARD_FROMHIT_STAND anim
// then when real anims come, use them instead.
//if ( fMerc )
//{
EVENT_InitNewSoldierAnim( pSoldier, FALLFORWARD_FROMHIT_CROUCH, 0 , FALSE);
}
else
{
// For civs... use fall from stand...
EVENT_InitNewSoldierAnim( pSoldier, FALLFORWARD_FROMHIT_STAND, 0 , FALSE);
}
//}
//else
//{
// // For civs... use fall from stand...
// EVENT_InitNewSoldierAnim( pSoldier, FALLFORWARD_FROMHIT_STAND, 0 , FALSE);
//}
break;
case ANIM_PRONE:
@@ -11572,7 +11605,7 @@ void ChangeToFlybackAnimation( SOLDIERTYPE *pSoldier, UINT8 ubDirection )
pSoldier->usPathingData[ pSoldier->usPathDataSize ] = ubOppositeDir;
pSoldier->usPathDataSize++;
pSoldier->sFinalDestination = sNewGridNo;
EVENT_InternalSetSoldierDestination( pSoldier, pSoldier->usPathingData[ pSoldier->usPathIndex ], FALSE, FLYBACK_HIT );
EVENT_InternalSetSoldierDestination( pSoldier, (UINT8) pSoldier->usPathingData[ pSoldier->usPathIndex ], FALSE, FLYBACK_HIT );
// Get a new direction based on direction
EVENT_InitNewSoldierAnim( pSoldier, FLYBACK_HIT, 0 , FALSE );
@@ -12047,14 +12080,21 @@ void HandleSoldierTakeDamageFeedback( SOLDIERTYPE *pSoldier )
void HandleSystemNewAISituation( SOLDIERTYPE *pSoldier, BOOLEAN fResetABC )
{
// Are we an AI guy?
// 0verhaul:
// This code will only stop a soldier if it is not the player's turn. The problem here is that the soldier's
// actions may have triggered an interrupt. This code is called in order to cancel the soldier's movement
// after the interrupt is triggered, so if the AI causes an interrupt and it's the player's turn, he will
// continue doing what he was going to do. We need this function to work even when it's the player's turn,
// at least in this case.
if ( gTacticalStatus.ubCurrentTeam != gbPlayerNum && pSoldier->bTeam != gbPlayerNum )
//if ( pSoldier->bTeam != gbPlayerNum )
{
if ( pSoldier->bNewSituation == IS_NEW_SITUATION )
{
// Cancel what they were doing....
pSoldier->usPendingAnimation = NO_PENDING_ANIMATION;
pSoldier->usPendingAnimation2 = NO_PENDING_ANIMATION;
pSoldier->fTurningFromPronePosition = FALSE;
pSoldier->bTurningFromPronePosition = TURNING_FROM_PRONE_OFF;
pSoldier->ubPendingDirection = NO_PENDING_DIRECTION;
pSoldier->ubPendingAction = NO_PENDING_ACTION;
pSoldier->bEndDoorOpenCode = 0;
+7 -2
View File
@@ -172,6 +172,11 @@ extern UINT16 CivLastNames[MAXCIVLASTNAMES][10];
//so that we can increase it if we can stand breaking the saves
#define MAX_BURST_SPREAD_TARGETS 6
#define TURNING_FROM_PRONE_OFF 0
#define TURNING_FROM_PRONE_ON 1
#define TURNING_FROM_PRONE_START_UP_FROM_MOVE 2
#define TURNING_FROM_PRONE_ENDING_UP_FROM_MOVE 3
//ENUMERATIONS FOR ACTIONS
enum
{
@@ -633,7 +638,7 @@ public:
INT8 bMarksmanship;
INT8 bExplosive;
THROW_PARAMS *pThrowParams;
BOOLEAN fTurningFromPronePosition;
INT8 bTurningFromPronePosition;
INT8 bReverse;
LEVELNODE *pLevelNode;
LEVELNODE *pExternShadowLevelNode;
@@ -1153,7 +1158,7 @@ BOOLEAN EVENT_InitNewSoldierAnim( SOLDIERTYPE *pSoldier, UINT16 usNewState, UINT
BOOLEAN ChangeSoldierState( SOLDIERTYPE *pSoldier, UINT16 usNewState, UINT16 usStartingAniCode, BOOLEAN fForce );
void EVENT_SetSoldierPosition( SOLDIERTYPE *pSoldier, FLOAT dNewXPos, FLOAT dNewYPos );
void EVENT_SetSoldierDestination( SOLDIERTYPE *pSoldier, UINT16 usNewDirection );
void EVENT_SetSoldierDestination( SOLDIERTYPE *pSoldier, UINT8 ubNewDirection );
void EVENT_GetNewSoldierPath( SOLDIERTYPE *pSoldier, UINT16 sDestGridNo, UINT16 usMovementAnim );
BOOLEAN EVENT_InternalGetNewSoldierPath( SOLDIERTYPE *pSoldier, UINT16 sDestGridNo, UINT16 usMovementAnim, BOOLEAN fFromUI, BOOLEAN fForceRestart );
+280 -270
View File
@@ -1,51 +1,51 @@
#ifdef PRECOMPILEDHEADERS
#include "Tactical All.h"
#include "Tactical All.h"
#else
#include "builddefines.h"
#include <stdio.h>
#include <memory.h>
#include "builddefines.h"
#include <stdio.h>
#include <memory.h>
#include "types.h"
#include "types.h"
#include "strategicmap.h"
#include "overhead.h"
#include "isometric utils.h"
#include "strategicmap.h"
#include "overhead.h"
#include "isometric utils.h"
#include "soldier add.h"
#include "soldier create.h"
#include "Soldier Init List.h"
#include "debug.h"
#include "Random.h"
#include "items.h"
#include "soldier add.h"
#include "soldier create.h"
#include "Soldier Init List.h"
#include "debug.h"
#include "Random.h"
#include "items.h"
#include "cursors.h"
#include "cursors.h"
#include "Map Information.h"
#include "soldier profile.h"
#include "Sys Globals.h"
#include "EditorMercs.h"
#include "Animation Data.h"
#include "message.h"
#include "Font Control.h"
#include "Sound Control.h"
#include "Quests.h"
#include "Render Fun.h"
#include "meanwhile.h"
#include "Map Screen Interface Map.h"
#include "mapscreen.h"
#include "Debug Control.h"
#include "Inventory Choosing.h"
#include "Strategic AI.h"
#include "strategic.h"
#include "Campaign Types.h"
#include "ai.h"
#include "NPC.h"
#include "Scheduling.h"
#include "opplist.h"
#include "MessageBoxScreen.h"
#include "screenids.h"
#include "SaveLoadScreen.h"
#include "Rotting Corpses.h"
#include "Map Information.h"
#include "soldier profile.h"
#include "Sys Globals.h"
#include "EditorMercs.h"
#include "Animation Data.h"
#include "message.h"
#include "Font Control.h"
#include "Sound Control.h"
#include "Quests.h"
#include "Render Fun.h"
#include "meanwhile.h"
#include "Map Screen Interface Map.h"
#include "mapscreen.h"
#include "Debug Control.h"
#include "Inventory Choosing.h"
#include "Strategic AI.h"
#include "strategic.h"
#include "Campaign Types.h"
#include "ai.h"
#include "NPC.h"
#include "Scheduling.h"
#include "opplist.h"
#include "MessageBoxScreen.h"
#include "screenids.h"
#include "SaveLoadScreen.h"
#include "Rotting Corpses.h"
#endif
#include "Map Edgepoints.h"
@@ -58,8 +58,8 @@ SOLDIERINITNODE *gOriginalSoldierInitListHead = NULL;
SOLDIERINITNODE *gAlternateSoldierInitListHead = NULL;
#ifdef JA2BETAVERSION
BOOLEAN ValidateSoldierInitLinks( UINT8 ubCode );
BOOLEAN gfDoDialogOnceGameScreenFadesIn = FALSE;
BOOLEAN ValidateSoldierInitLinks( UINT8 ubCode );
BOOLEAN gfDoDialogOnceGameScreenFadesIn = FALSE;
#endif
UINT32 CountNumberOfNodesWithSoldiers()
@@ -83,14 +83,14 @@ void SortSoldierInitList();
void InitSoldierInitList()
{
if( gSoldierInitHead )
KillSoldierInitList();
KillSoldierInitList();
gSoldierInitHead = NULL;
gSoldierInitTail = NULL;
}
void KillSoldierInitList()
{
while( gSoldierInitHead )
while( gSoldierInitHead )
RemoveSoldierNodeFromInitList( gSoldierInitTail );
if( gfOriginalList )
gOriginalSoldierInitListHead = NULL;
@@ -206,7 +206,7 @@ BOOLEAN SaveSoldiersToMap( HWFILE fp )
UINT32 i;
UINT32 uiBytesWritten;
SOLDIERINITNODE *curr;
if( !fp )
return FALSE;
@@ -220,11 +220,11 @@ BOOLEAN SaveSoldiersToMap( HWFILE fp )
//mode, and kill them all, while replacing them with the proper ones. Not only that, the alternate
//editing mode is turned off, and if intentions are to play the game, the user will be facing many
//enemies!
#ifdef JA2EDITOR
if( !gfOriginalList )
ResetAllMercPositions();
#endif
#ifdef JA2EDITOR
if( !gfOriginalList )
ResetAllMercPositions();
#endif
curr = gSoldierInitHead;
for( i=0; i < gMapInformation.ubNumIndividuals; i++ )
{
@@ -237,7 +237,7 @@ BOOLEAN SaveSoldiersToMap( HWFILE fp )
{
if( !curr->pDetailedPlacement )
return FALSE;
// WDS - Clean up inventory handling
// WDS - Clean up inventory handling
curr->pDetailedPlacement->CopyNewInventoryToOld();
FileWrite( fp, curr->pDetailedPlacement, SIZEOF_SOLDIERCREATE_STRUCT_POD /*SIZEOF_SOLDIERCREATE_STRUCT*/, &uiBytesWritten );
}
@@ -263,7 +263,7 @@ BOOLEAN LoadSoldiersFromMap( INT8 **hBuffer )
KillSoldierInitList();
UseEditorOriginalList();
KillSoldierInitList();
InitSoldierInitList();
if( ubNumIndividuals > MAX_INDIVIDUALS )
@@ -275,7 +275,7 @@ BOOLEAN LoadSoldiersFromMap( INT8 **hBuffer )
{
return TRUE; //no mercs
}
//Because we are loading the map, we needed to know how many
//guys are being loaded, but when we add them to the list here, it
//automatically increments that number, effectively doubling it, which
@@ -295,7 +295,7 @@ BOOLEAN LoadSoldiersFromMap( INT8 **hBuffer )
}
if( tempBasicPlacement.fDetailedPlacement )
{ //Add the static detailed placement information in the same newly created node as the basic placement.
// WDS - Clean up inventory handling
// WDS - Clean up inventory handling
tempDetailedPlacement.initialize();
//read static detailed placement from file
LOADDATA( &tempDetailedPlacement, *hBuffer, SIZEOF_SOLDIERCREATE_STRUCT_POD );
@@ -553,7 +553,7 @@ BOOLEAN AddPlacementToWorld( SOLDIERINITNODE *curr, GROUP *pGroup = NULL )
}
//else
//{
//break;
//break;
//}
} while (pCorpse);
}
@@ -567,13 +567,13 @@ BOOLEAN AddPlacementToWorld( SOLDIERINITNODE *curr, GROUP *pGroup = NULL )
if( ubProfile != NO_PROFILE && !gfEditMode )
{
if( gMercProfiles[ ubProfile ].sSectorX != gWorldSectorX ||
gMercProfiles[ ubProfile ].sSectorY != gWorldSectorY ||
gMercProfiles[ ubProfile ].bSectorZ != gbWorldSectorZ ||
gMercProfiles[ ubProfile ].ubMiscFlags & (PROFILE_MISC_FLAG_RECRUITED | PROFILE_MISC_FLAG_EPCACTIVE) ||
// gMercProfiles[ ubProfile ].ubMiscFlags2 & PROFILE_MISC_FLAG2_DONT_ADD_TO_SECTOR ||
!gMercProfiles[ ubProfile ].bLife ||
gMercProfiles[ ubProfile ].fUseProfileInsertionInfo
)
gMercProfiles[ ubProfile ].sSectorY != gWorldSectorY ||
gMercProfiles[ ubProfile ].bSectorZ != gbWorldSectorZ ||
gMercProfiles[ ubProfile ].ubMiscFlags & (PROFILE_MISC_FLAG_RECRUITED | PROFILE_MISC_FLAG_EPCACTIVE) ||
// gMercProfiles[ ubProfile ].ubMiscFlags2 & PROFILE_MISC_FLAG2_DONT_ADD_TO_SECTOR ||
!gMercProfiles[ ubProfile ].bLife ||
gMercProfiles[ ubProfile ].fUseProfileInsertionInfo
)
{
return FALSE;
}
@@ -587,8 +587,8 @@ BOOLEAN AddPlacementToWorld( SOLDIERINITNODE *curr, GROUP *pGroup = NULL )
if( curr->pDetailedPlacement->bBodyType == ICECREAMTRUCK )
{ //Check to see if Hamous is here and not recruited. If so, add truck
if( gMercProfiles[ HAMOUS ].sSectorX != gWorldSectorX ||
gMercProfiles[ HAMOUS ].sSectorY != gWorldSectorY ||
gMercProfiles[ HAMOUS ].bSectorZ )
gMercProfiles[ HAMOUS ].sSectorY != gWorldSectorY ||
gMercProfiles[ HAMOUS ].bSectorZ )
{ //not here, so don't add
return TRUE;
}
@@ -632,15 +632,15 @@ BOOLEAN AddPlacementToWorld( SOLDIERINITNODE *curr, GROUP *pGroup = NULL )
switch( PreRandom( 3 ) )
{
case 0:
tempDetailedPlacement.bOrders = ONGUARD;
break;
case 1:
tempDetailedPlacement.bOrders = CLOSEPATROL;
break;
case 2:
tempDetailedPlacement.bOrders = ONCALL;
break;
case 0:
tempDetailedPlacement.bOrders = ONGUARD;
break;
case 1:
tempDetailedPlacement.bOrders = CLOSEPATROL;
break;
case 2:
tempDetailedPlacement.bOrders = ONCALL;
break;
}
}
@@ -707,7 +707,7 @@ BOOLEAN AddPlacementToWorld( SOLDIERINITNODE *curr, GROUP *pGroup = NULL )
}
}
}
//SPECIAL! Certain events in the game can cause profiled NPCs to become enemies. The two cases are
//adding Mike and Iggy. We will only add one NPC in any given combat and the conditions for setting
//the associated facts are done elsewhere. There is also another place where NPCs can get added, which
@@ -776,7 +776,7 @@ UINT8 AddSoldierInitListTeamToWorld( INT8 bTeam, UINT8 ubMaxNum )
UINT8 ubSlotsToFill;
UINT8 ubSlotsAvailable;
SOLDIERINITNODE *curr;
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("AddSoldierInitListTeamToWorld"));
//Sort the list in the following manner:
//-Priority placements first
@@ -857,6 +857,7 @@ UINT8 AddSoldierInitListTeamToWorld( INT8 bTeam, UINT8 ubMaxNum )
if( AddPlacementToWorld( curr ) )
{
ubNumAdded++;
ubSlotsToFill--;
}
else
{
@@ -864,9 +865,17 @@ UINT8 AddSoldierInitListTeamToWorld( INT8 bTeam, UINT8 ubMaxNum )
//engine are already full. Besides, the strategic AI shouldn't be trying to fill a map with
//more than the maximum allowable soldiers of team. All teams can have a max of 32 individuals,
//except for the player which is 20. Players aren't processed in this list anyway.
return ubNumAdded;
// 0verhaul: Bzzzzzzzttttt.... Wrong! Other reasons for a false return:
// Profiled merc not in sector
// Profiled merc is recruited
// Profiled merc is escorted
// Profiled merc is dead
// Profiled merc needs to use profile insertion data instead of placement
// None of these instances is a reason to give up on the rest of the placements.
//return ubNumAdded;
}
ubSlotsToFill--;
// 0verhaul: However, move this to the point of successful insertion!
//ubSlotsToFill--;
}
ubSlotsAvailable--;
//With the decrementing of the slot vars in this manner, the chances increase so that all slots
@@ -884,7 +893,7 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
INT32 iRandom;
UINT8 ubMaxNum;
INT8 bTeam = ENEMY_TEAM;
UINT8 ubElitePDSlots = 0, ubEliteDSlots = 0, ubElitePSlots = 0, ubEliteBSlots = 0;
UINT8 ubElitePDSlots = 0, ubEliteDSlots = 0, ubElitePSlots = 0, ubEliteBSlots = 0;
UINT8 ubTroopPDSlots = 0, ubTroopDSlots = 0, ubTroopPSlots = 0, ubTroopBSlots = 0;
UINT8 ubAdminPDSlots = 0, ubAdminDSlots = 0, ubAdminPSlots = 0, ubAdminBSlots = 0;
UINT8 ubFreeSlots;
@@ -898,13 +907,13 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
//Specs call for only one profiled enemy can be in a sector at a time due to flavor reasons.
gfProfiledEnemyAdded = FALSE;
//Because the enemy defence forces work differently than the regular map placements, the numbers
//of each type of enemy may not be the same. Elites will choose the best placements, then army, then
//administrators.
ubMaxNum = ubTotalAdmin + ubTotalTroops + ubTotalElite;
//Sort the list in the following manner:
//-Priority placements first
//-Basic placements next
@@ -921,36 +930,36 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
{
switch( curr->pBasicPlacement->ubSoldierClass )
{
case SOLDIER_CLASS_ELITE:
if( curr->pBasicPlacement->fPriorityExistance && curr->pDetailedPlacement )
ubElitePDSlots++;
else if( curr->pBasicPlacement->fPriorityExistance )
ubElitePSlots++;
else if( curr->pDetailedPlacement )
ubEliteDSlots++;
else
ubEliteBSlots++;
break;
case SOLDIER_CLASS_ADMINISTRATOR:
if( curr->pBasicPlacement->fPriorityExistance && curr->pDetailedPlacement )
ubAdminPDSlots++;
else if( curr->pBasicPlacement->fPriorityExistance )
ubAdminPSlots++;
else if( curr->pDetailedPlacement )
ubAdminDSlots++;
else
ubAdminBSlots++;
break;
case SOLDIER_CLASS_ARMY:
if( curr->pBasicPlacement->fPriorityExistance && curr->pDetailedPlacement )
ubTroopPDSlots++;
else if( curr->pBasicPlacement->fPriorityExistance )
ubTroopPSlots++;
else if( curr->pDetailedPlacement )
ubTroopDSlots++;
else
ubTroopBSlots++;
break;
case SOLDIER_CLASS_ELITE:
if( curr->pBasicPlacement->fPriorityExistance && curr->pDetailedPlacement )
ubElitePDSlots++;
else if( curr->pBasicPlacement->fPriorityExistance )
ubElitePSlots++;
else if( curr->pDetailedPlacement )
ubEliteDSlots++;
else
ubEliteBSlots++;
break;
case SOLDIER_CLASS_ADMINISTRATOR:
if( curr->pBasicPlacement->fPriorityExistance && curr->pDetailedPlacement )
ubAdminPDSlots++;
else if( curr->pBasicPlacement->fPriorityExistance )
ubAdminPSlots++;
else if( curr->pDetailedPlacement )
ubAdminDSlots++;
else
ubAdminBSlots++;
break;
case SOLDIER_CLASS_ARMY:
if( curr->pBasicPlacement->fPriorityExistance && curr->pDetailedPlacement )
ubTroopPDSlots++;
else if( curr->pBasicPlacement->fPriorityExistance )
ubTroopPSlots++;
else if( curr->pDetailedPlacement )
ubTroopDSlots++;
else
ubTroopBSlots++;
break;
}
}
curr = curr->next;
@@ -964,23 +973,23 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
//First, prepare the counters.
switch( ubCurrClass )
{
case SOLDIER_CLASS_ADMINISTRATOR:
pCurrSlots = &ubAdminPDSlots;
pCurrTotal = &ubTotalAdmin;
break;
case SOLDIER_CLASS_ELITE:
pCurrSlots = &ubElitePDSlots;
pCurrTotal = &ubTotalElite;
break;
case SOLDIER_CLASS_ARMY:
pCurrSlots = &ubTroopPDSlots;
pCurrTotal = &ubTotalTroops;
break;
case SOLDIER_CLASS_ADMINISTRATOR:
pCurrSlots = &ubAdminPDSlots;
pCurrTotal = &ubTotalAdmin;
break;
case SOLDIER_CLASS_ELITE:
pCurrSlots = &ubElitePDSlots;
pCurrTotal = &ubTotalElite;
break;
case SOLDIER_CLASS_ARMY:
pCurrSlots = &ubTroopPDSlots;
pCurrTotal = &ubTotalTroops;
break;
}
//Now, loop through the priority existance and detailed placement section of the list.
curr = gSoldierInitHead;
while( curr && ubMaxNum && *pCurrTotal && *pCurrSlots &&
curr->pDetailedPlacement && curr->pBasicPlacement->fPriorityExistance )
curr->pDetailedPlacement && curr->pBasicPlacement->fPriorityExistance )
{
if( !curr->pSoldier && curr->pBasicPlacement->bTeam == ENEMY_TEAM )
{
@@ -1020,23 +1029,23 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
//First, prepare the counters.
switch( ubCurrClass )
{
case SOLDIER_CLASS_ADMINISTRATOR:
pCurrSlots = &ubAdminPSlots;
pCurrTotal = &ubTotalAdmin;
break;
case SOLDIER_CLASS_ELITE:
pCurrSlots = &ubElitePSlots;
pCurrTotal = &ubTotalElite;
break;
case SOLDIER_CLASS_ARMY:
pCurrSlots = &ubTroopPSlots;
pCurrTotal = &ubTotalTroops;
break;
case SOLDIER_CLASS_ADMINISTRATOR:
pCurrSlots = &ubAdminPSlots;
pCurrTotal = &ubTotalAdmin;
break;
case SOLDIER_CLASS_ELITE:
pCurrSlots = &ubElitePSlots;
pCurrTotal = &ubTotalElite;
break;
case SOLDIER_CLASS_ARMY:
pCurrSlots = &ubTroopPSlots;
pCurrTotal = &ubTotalTroops;
break;
}
//Now, loop through the priority existance and non detailed placement section of the list.
curr = mark;
while( curr && ubMaxNum && *pCurrTotal && *pCurrSlots &&
!curr->pDetailedPlacement && curr->pBasicPlacement->fPriorityExistance )
!curr->pDetailedPlacement && curr->pBasicPlacement->fPriorityExistance )
{
if( !curr->pSoldier && curr->pBasicPlacement->bTeam == ENEMY_TEAM )
{
@@ -1067,7 +1076,7 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
while( curr && !curr->pDetailedPlacement && curr->pBasicPlacement->fPriorityExistance )
curr = curr->next;
mark = curr;
//ADD PLACEMENTS WITH NO DETAILED PLACEMENT AND PRIORITY EXISTANCE INFORMATION SECOND
//we now have the numbers of available slots for each soldier class, so loop through three times
//and randomly choose some (or all) of the matching slots to fill. This is done randomly.
@@ -1076,23 +1085,23 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
//First, prepare the counters.
switch( ubCurrClass )
{
case SOLDIER_CLASS_ADMINISTRATOR:
pCurrSlots = &ubAdminDSlots;
pCurrTotal = &ubTotalAdmin;
break;
case SOLDIER_CLASS_ELITE:
pCurrSlots = &ubEliteDSlots;
pCurrTotal = &ubTotalElite;
break;
case SOLDIER_CLASS_ARMY:
pCurrSlots = &ubTroopDSlots;
pCurrTotal = &ubTotalTroops;
break;
case SOLDIER_CLASS_ADMINISTRATOR:
pCurrSlots = &ubAdminDSlots;
pCurrTotal = &ubTotalAdmin;
break;
case SOLDIER_CLASS_ELITE:
pCurrSlots = &ubEliteDSlots;
pCurrTotal = &ubTotalElite;
break;
case SOLDIER_CLASS_ARMY:
pCurrSlots = &ubTroopDSlots;
pCurrTotal = &ubTotalTroops;
break;
}
//Now, loop through the priority existance and detailed placement section of the list.
curr = mark;
while( curr && ubMaxNum && *pCurrTotal && *pCurrSlots &&
curr->pDetailedPlacement && !curr->pBasicPlacement->fPriorityExistance )
curr->pDetailedPlacement && !curr->pBasicPlacement->fPriorityExistance )
{
if( !curr->pSoldier && curr->pBasicPlacement->bTeam == ENEMY_TEAM )
{
@@ -1165,7 +1174,7 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
}
if( !ubMaxNum )
return;
//ADD REMAINING PLACEMENTS WITH BASIC PLACEMENT INFORMATION
//we now have the numbers of available slots for each soldier class, so loop through three times
//and randomly choose some (or all) of the matching slots to fill. This is done randomly.
@@ -1174,18 +1183,18 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
//First, prepare the counters.
switch( ubCurrClass )
{
case SOLDIER_CLASS_ADMINISTRATOR:
pCurrSlots = &ubAdminBSlots;
pCurrTotal = &ubTotalAdmin;
break;
case SOLDIER_CLASS_ELITE:
pCurrSlots = &ubEliteBSlots;
pCurrTotal = &ubTotalElite;
break;
case SOLDIER_CLASS_ARMY:
pCurrSlots = &ubTroopBSlots;
pCurrTotal = &ubTotalTroops;
break;
case SOLDIER_CLASS_ADMINISTRATOR:
pCurrSlots = &ubAdminBSlots;
pCurrTotal = &ubTotalAdmin;
break;
case SOLDIER_CLASS_ELITE:
pCurrSlots = &ubEliteBSlots;
pCurrTotal = &ubTotalElite;
break;
case SOLDIER_CLASS_ARMY:
pCurrSlots = &ubTroopBSlots;
pCurrTotal = &ubTotalTroops;
break;
}
//Now, loop through the regular basic placements section of the list.
curr = mark;
@@ -1266,9 +1275,9 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
/* DISABLE THE OVERRIDE FOR NOW...
if( curr->pDetailedPlacement )
{ //delete the detailed placement information.
MemFree( curr->pDetailedPlacement );
curr->pDetailedPlacement = NULL;
curr->pBasicPlacement->fDetailedPlacement = FALSE;
MemFree( curr->pDetailedPlacement );
curr->pDetailedPlacement = NULL;
curr->pBasicPlacement->fDetailedPlacement = FALSE;
}
*/
if( AddPlacementToWorld( curr ) )
@@ -1299,7 +1308,7 @@ void AddSoldierInitListMilitia( UINT8 ubNumGreen, UINT8 ubNumRegs, UINT8 ubNumEl
UINT8 ubMaxNum;
BOOLEAN fDoPlacement;
INT8 bTeam = ENEMY_TEAM;
UINT8 ubEliteSlots = 0;
UINT8 ubEliteSlots = 0;
UINT8 ubRegSlots = 0;
UINT8 ubGreenSlots = 0;
UINT8 ubFreeSlots;
@@ -1310,7 +1319,7 @@ void AddSoldierInitListMilitia( UINT8 ubNumGreen, UINT8 ubNumRegs, UINT8 ubNumEl
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("AddSoldierInitListMilitia"));
ubMaxNum = ubNumGreen + ubNumRegs + ubNumElites;
//Sort the list in the following manner:
//-Priority placements first
//-Basic placements next
@@ -1380,9 +1389,9 @@ void AddSoldierInitListMilitia( UINT8 ubNumGreen, UINT8 ubNumRegs, UINT8 ubNumEl
{
switch( curr->pBasicPlacement->ubSoldierClass )
{
case SOLDIER_CLASS_ELITE: ubEliteSlots++; break;
case SOLDIER_CLASS_ADMINISTRATOR: ubGreenSlots++; break;
case SOLDIER_CLASS_ARMY: ubRegSlots++; break;
case SOLDIER_CLASS_ELITE: ubEliteSlots++; break;
case SOLDIER_CLASS_ADMINISTRATOR: ubGreenSlots++; break;
case SOLDIER_CLASS_ARMY: ubRegSlots++; break;
}
}
curr = curr->next;
@@ -1395,18 +1404,18 @@ void AddSoldierInitListMilitia( UINT8 ubNumGreen, UINT8 ubNumRegs, UINT8 ubNumEl
//First, prepare the counters.
switch( ubCurrClass )
{
case SOLDIER_CLASS_ADMINISTRATOR:
pCurrSlots = &ubGreenSlots;
pCurrTotal = &ubNumGreen;
break;
case SOLDIER_CLASS_ELITE:
pCurrSlots = &ubEliteSlots;
pCurrTotal = &ubNumElites;
break;
case SOLDIER_CLASS_ARMY:
pCurrSlots = &ubRegSlots;
pCurrTotal = &ubNumRegs;
break;
case SOLDIER_CLASS_ADMINISTRATOR:
pCurrSlots = &ubGreenSlots;
pCurrTotal = &ubNumGreen;
break;
case SOLDIER_CLASS_ELITE:
pCurrSlots = &ubEliteSlots;
pCurrTotal = &ubNumElites;
break;
case SOLDIER_CLASS_ARMY:
pCurrSlots = &ubRegSlots;
pCurrTotal = &ubNumRegs;
break;
}
//Now, loop through the basic placement of the list.
curr = mark; //mark is the marker where the basic placements start.
@@ -1422,15 +1431,15 @@ void AddSoldierInitListMilitia( UINT8 ubNumGreen, UINT8 ubNumRegs, UINT8 ubNumEl
curr->pBasicPlacement->bOrders = STATIONARY;
switch( ubCurrClass )
{
case SOLDIER_CLASS_ADMINISTRATOR:
curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_GREEN_MILITIA;
break;
case SOLDIER_CLASS_ARMY:
curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_REG_MILITIA;
break;
case SOLDIER_CLASS_ELITE:
curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_ELITE_MILITIA;
break;
case SOLDIER_CLASS_ADMINISTRATOR:
curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_GREEN_MILITIA;
break;
case SOLDIER_CLASS_ARMY:
curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_REG_MILITIA;
break;
case SOLDIER_CLASS_ELITE:
curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_ELITE_MILITIA;
break;
}
//found matching team, so add this soldier to the game.
if( AddPlacementToWorld( curr ) )
@@ -1524,8 +1533,8 @@ void AddSoldierInitListMilitia( UINT8 ubNumGreen, UINT8 ubNumRegs, UINT8 ubNumEl
}
void AddSoldierInitListCreatures( BOOLEAN fQueen, UINT8 ubNumLarvae, UINT8 ubNumInfants,
UINT8 ubNumYoungMales, UINT8 ubNumYoungFemales, UINT8 ubNumAdultMales,
UINT8 ubNumAdultFemales )
UINT8 ubNumYoungMales, UINT8 ubNumYoungFemales, UINT8 ubNumAdultMales,
UINT8 ubNumAdultFemales )
{
SOLDIERINITNODE *curr;
INT32 iRandom;
@@ -1556,9 +1565,9 @@ void AddSoldierInitListCreatures( BOOLEAN fQueen, UINT8 ubNumLarvae, UINT8 ubNum
}
if( !fQueen )
{
#ifdef JA2BETAVERSION
ScreenMsg( FONT_RED, MSG_ERROR, L"Couldn't place the queen." );
#endif
#ifdef JA2BETAVERSION
ScreenMsg( FONT_RED, MSG_ERROR, L"Couldn't place the queen." );
#endif
}
}
@@ -1622,7 +1631,7 @@ void AddSoldierInitListCreatures( BOOLEAN fQueen, UINT8 ubNumLarvae, UINT8 ubNum
{
//Choose which team to use.
iRandom = Random( ubNumCreatures );
if( ubNumLarvae && iRandom < ubNumLarvae )
{
ubNumLarvae--;
@@ -1839,7 +1848,7 @@ BOOLEAN LoadSoldierInitListLinks( HWFILE hfile )
UINT32 uiNumBytesRead;
SOLDIERINITNODE *curr;
UINT8 ubSlots, ubSoldierID, ubNodeID;
FileRead( hfile, &ubSlots, 1, &uiNumBytesRead );
if( uiNumBytesRead != 1 )
{
@@ -1867,9 +1876,9 @@ BOOLEAN LoadSoldierInitListLinks( HWFILE hfile )
{
curr->ubSoldierID = ubSoldierID;
if( ubSoldierID >= gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID &&
ubSoldierID <= gTacticalStatus.Team[ CREATURE_TEAM ].bLastID ||
ubSoldierID >= gTacticalStatus.Team[ CIV_TEAM ].bFirstID &&
ubSoldierID <= gTacticalStatus.Team[ CIV_TEAM ].bLastID )
ubSoldierID <= gTacticalStatus.Team[ CREATURE_TEAM ].bLastID ||
ubSoldierID >= gTacticalStatus.Team[ CIV_TEAM ].bFirstID &&
ubSoldierID <= gTacticalStatus.Team[ CIV_TEAM ].bLastID )
{ //only enemies and creatures.
curr->pSoldier = MercPtrs[ ubSoldierID ];
}
@@ -1900,7 +1909,7 @@ void AddSoldierInitListBloodcats()
{ //This map has no bloodcat placements, so don't waste CPU time.
return;
}
if( pSector->bBloodCatPlacements )
{ //We don't yet know the number of bloodcat placements in this sector so
//count them now, and permanently record it.
@@ -1915,14 +1924,14 @@ void AddSoldierInitListBloodcats()
curr = curr->next;
}
if( bBloodCatPlacements != pSector->bBloodCatPlacements &&
ubSectorID != SEC_I16 && ubSectorID != SEC_N5 )
ubSectorID != SEC_I16 && ubSectorID != SEC_N5 )
{
#ifdef JA2BETAVERSION
CHAR16 str[200];
swprintf( str, L"Table specifies that there are %d bloodcat placements in sector %c%d, but the map actually has %d bloodcat placements. Map value takes precedence. KM,LC:1",
pSector->bBloodCatPlacements, gWorldSectorY + 'A' - 1, gWorldSectorX, bBloodCatPlacements );
DoScreenIndependantMessageBox( str, MSG_BOX_FLAG_OK, NULL );
#endif
#ifdef JA2BETAVERSION
CHAR16 str[200];
swprintf( str, L"Table specifies that there are %d bloodcat placements in sector %c%d, but the map actually has %d bloodcat placements. Map value takes precedence. KM,LC:1",
pSector->bBloodCatPlacements, gWorldSectorY + 'A' - 1, gWorldSectorX, bBloodCatPlacements );
DoScreenIndependantMessageBox( str, MSG_BOX_FLAG_OK, NULL );
#endif
pSector->bBloodCatPlacements = bBloodCatPlacements;
pSector->bBloodCats = -1;
if( !bBloodCatPlacements )
@@ -1939,7 +1948,7 @@ void AddSoldierInitListBloodcats()
UINT8 ubSlotsToFill;
UINT8 ubSlotsAvailable;
SOLDIERINITNODE *curr;
//Sort the list in the following manner:
//-Priority placements first
//-Basic placements next
@@ -2057,13 +2066,13 @@ void AddProfilesUsingProfileInsertionData()
//Perform various checks to make sure the soldier is actually in the same sector, alive, and so on.
//More importantly, the flag to use profile insertion data must be set.
if( gMercProfiles[ i ].sSectorX != gWorldSectorX ||
gMercProfiles[ i ].sSectorY != gWorldSectorY ||
gMercProfiles[ i ].bSectorZ != gbWorldSectorZ ||
gMercProfiles[ i ].ubMiscFlags & PROFILE_MISC_FLAG_RECRUITED ||
gMercProfiles[ i ].ubMiscFlags & PROFILE_MISC_FLAG_EPCACTIVE ||
// gMercProfiles[ i ].ubMiscFlags2 & PROFILE_MISC_FLAG2_DONT_ADD_TO_SECTOR ||
!gMercProfiles[ i ].bLife ||
!gMercProfiles[ i ].fUseProfileInsertionInfo
gMercProfiles[ i ].sSectorY != gWorldSectorY ||
gMercProfiles[ i ].bSectorZ != gbWorldSectorZ ||
gMercProfiles[ i ].ubMiscFlags & PROFILE_MISC_FLAG_RECRUITED ||
gMercProfiles[ i ].ubMiscFlags & PROFILE_MISC_FLAG_EPCACTIVE ||
// gMercProfiles[ i ].ubMiscFlags2 & PROFILE_MISC_FLAG2_DONT_ADD_TO_SECTOR ||
!gMercProfiles[ i ].bLife ||
!gMercProfiles[ i ].fUseProfileInsertionInfo
)
{ //Don't add, so skip to the next soldier.
continue;
@@ -2075,7 +2084,8 @@ void AddProfilesUsingProfileInsertionData()
UINT8 ubID;
//Set up the create struct so that we can properly create the profile soldier.
memset( &MercCreateStruct, 0, sizeof( MercCreateStruct ) );
// It's been C++'d, so don't do this!
//memset( &MercCreateStruct, 0, sizeof( MercCreateStruct ) );
MercCreateStruct.bTeam = CIV_TEAM;
MercCreateStruct.ubProfile = (UINT8)i;
MercCreateStruct.sSectorX = gWorldSectorX;
@@ -2135,11 +2145,11 @@ void AddProfilesNotUsingProfileInsertionData()
while( curr )
{
if( !curr->pSoldier &&
curr->pBasicPlacement->bTeam == CIV_TEAM &&
curr->pDetailedPlacement &&
curr->pDetailedPlacement->ubProfile != NO_PROFILE &&
!gMercProfiles[ curr->pDetailedPlacement->ubProfile ].fUseProfileInsertionInfo &&
gMercProfiles[ curr->pDetailedPlacement->ubProfile ].bLife )
curr->pBasicPlacement->bTeam == CIV_TEAM &&
curr->pDetailedPlacement &&
curr->pDetailedPlacement->ubProfile != NO_PROFILE &&
!gMercProfiles[ curr->pDetailedPlacement->ubProfile ].fUseProfileInsertionInfo &&
gMercProfiles[ curr->pDetailedPlacement->ubProfile ].bLife )
{
AddPlacementToWorld( curr );
}
@@ -2171,31 +2181,31 @@ BOOLEAN ValidateSoldierInitLinks( UINT8 ubCode )
{
switch( ubCode )
{
case 1: //loading save
swprintf( str, L"Error detected in save file WHILE LOADING. Please send save and text files associated with save to Kris and Dave."
L" After doing so, go back into the game and immediately resave the game which will fix the problem."
L" This is the bug responsible for mercs disappearing. Be prepared to answer lots of questions..." );
DoSaveLoadMessageBox( MSG_BOX_BASIC_STYLE, str, SAVE_LOAD_SCREEN, MSG_BOX_FLAG_OK, ErrorDetectedInSaveCallback );
break;
case 2: //saving game
//swprintf( str, L"Error detected WHILE SAVING file. Please send save and text files associated with save to Kris and Dave."
// L" After doing so, go back into the game and try reloading the new save and saving it again which *could* fix the problem."
// L" This is the bug responsible for mercs disappearing. Be prepared to answer lots of questions..." );
//if( guiPreviousOptionScreen == MAP_SCREEN )
// DoMapMessageBox( MSG_BOX_BASIC_STYLE, str, MAP_SCREEN, MSG_BOX_FLAG_OK, NULL );
//else
// DoMessageBox( MSG_BOX_BASIC_STYLE, str, GAME_SCREEN, MSG_BOX_FLAG_OK, NULL, NULL );
break;
case 3: //entering sector using temp files (before fade in)
gfDoDialogOnceGameScreenFadesIn = TRUE;
break;
case 4: //after fade in
gfDoDialogOnceGameScreenFadesIn = FALSE;
swprintf( str, L"Error detected while entering sector USING TEMP FILES. Please send previous save and text files associated with save to Kris and Dave."
L" After doing so, go back into the game and saving the game, reloading it, and saving it again *could* fix it."
L" This is the bug responsible for mercs disappearing. Be prepared to answer lots of questions..." );
DoMessageBox( MSG_BOX_BASIC_STYLE, str, GAME_SCREEN, MSG_BOX_FLAG_OK, NULL, NULL );
break;
case 1: //loading save
swprintf( str, L"Error detected in save file WHILE LOADING. Please send save and text files associated with save to Kris and Dave."
L" After doing so, go back into the game and immediately resave the game which will fix the problem."
L" This is the bug responsible for mercs disappearing. Be prepared to answer lots of questions..." );
DoSaveLoadMessageBox( MSG_BOX_BASIC_STYLE, str, SAVE_LOAD_SCREEN, MSG_BOX_FLAG_OK, ErrorDetectedInSaveCallback );
break;
case 2: //saving game
//swprintf( str, L"Error detected WHILE SAVING file. Please send save and text files associated with save to Kris and Dave."
// L" After doing so, go back into the game and try reloading the new save and saving it again which *could* fix the problem."
// L" This is the bug responsible for mercs disappearing. Be prepared to answer lots of questions..." );
//if( guiPreviousOptionScreen == MAP_SCREEN )
// DoMapMessageBox( MSG_BOX_BASIC_STYLE, str, MAP_SCREEN, MSG_BOX_FLAG_OK, NULL );
//else
// DoMessageBox( MSG_BOX_BASIC_STYLE, str, GAME_SCREEN, MSG_BOX_FLAG_OK, NULL, NULL );
break;
case 3: //entering sector using temp files (before fade in)
gfDoDialogOnceGameScreenFadesIn = TRUE;
break;
case 4: //after fade in
gfDoDialogOnceGameScreenFadesIn = FALSE;
swprintf( str, L"Error detected while entering sector USING TEMP FILES. Please send previous save and text files associated with save to Kris and Dave."
L" After doing so, go back into the game and saving the game, reloading it, and saving it again *could* fix it."
L" This is the bug responsible for mercs disappearing. Be prepared to answer lots of questions..." );
DoMessageBox( MSG_BOX_BASIC_STYLE, str, GAME_SCREEN, MSG_BOX_FLAG_OK, NULL, NULL );
break;
}
return FALSE;
}
@@ -2209,7 +2219,7 @@ BOOLEAN NewWayOfLoadingEnemySoldierInitListLinks( HWFILE hfile )
UINT32 uiNumBytesRead;
SOLDIERINITNODE *curr;
UINT8 ubSlots, ubSoldierID, ubNodeID;
FileRead( hfile, &ubSlots, 1, &uiNumBytesRead );
if( uiNumBytesRead != 1 )
{
@@ -2237,7 +2247,7 @@ BOOLEAN NewWayOfLoadingEnemySoldierInitListLinks( HWFILE hfile )
{
curr->ubSoldierID = ubSoldierID;
if( ubSoldierID >= gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID &&
ubSoldierID <= gTacticalStatus.Team[ CREATURE_TEAM ].bLastID )
ubSoldierID <= gTacticalStatus.Team[ CREATURE_TEAM ].bLastID )
{ //only enemies and creatures.
curr->pSoldier = MercPtrs[ ubSoldierID ];
}
@@ -2255,7 +2265,7 @@ BOOLEAN NewWayOfLoadingCivilianInitListLinks( HWFILE hfile )
UINT32 uiNumBytesRead;
SOLDIERINITNODE *curr;
UINT8 ubSlots, ubSoldierID, ubNodeID;
FileRead( hfile, &ubSlots, 1, &uiNumBytesRead );
if( uiNumBytesRead != 1 )
{
@@ -2283,7 +2293,7 @@ BOOLEAN NewWayOfLoadingCivilianInitListLinks( HWFILE hfile )
{
curr->ubSoldierID = ubSoldierID;
if( ubSoldierID >= gTacticalStatus.Team[ CIV_TEAM ].bFirstID &&
ubSoldierID <= gTacticalStatus.Team[ CIV_TEAM ].bLastID )
ubSoldierID <= gTacticalStatus.Team[ CIV_TEAM ].bLastID )
{ //only enemies and creatures.
curr->pSoldier = MercPtrs[ ubSoldierID ];
}
@@ -2301,7 +2311,7 @@ BOOLEAN LookAtButDontProcessEnemySoldierInitListLinks( HWFILE hfile )
UINT32 uiNumBytesRead;
SOLDIERINITNODE *curr;
UINT8 ubSlots, ubSoldierID, ubNodeID;
FileRead( hfile, &ubSlots, 1, &uiNumBytesRead );
if( uiNumBytesRead != 1 )
{
@@ -2329,7 +2339,7 @@ BOOLEAN LookAtButDontProcessEnemySoldierInitListLinks( HWFILE hfile )
{
curr->ubSoldierID = ubSoldierID;
if( ubSoldierID >= gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID &&
ubSoldierID <= gTacticalStatus.Team[ CREATURE_TEAM ].bLastID )
ubSoldierID <= gTacticalStatus.Team[ CREATURE_TEAM ].bLastID )
{ //only enemies and creatures.
curr->pSoldier = MercPtrs[ ubSoldierID ];
}
@@ -2345,7 +2355,7 @@ void StripEnemyDetailedPlacementsIfSectorWasPlayerLiberated()
{
SECTORINFO *pSector;
SOLDIERINITNODE *curr;
if( !gfWorldLoaded || gbWorldSectorZ )
{ //No world loaded or underground. Underground sectors don't matter
//seeing enemies (not creatures) never rejuvenate underground.
@@ -2407,15 +2417,15 @@ void AddSoldierInitListMilitiaOnEdge( UINT8 ubStrategicInsertionCode, UINT8 ubNu
switch( ubStrategicInsertionCode )
{
case INSERTION_CODE_NORTH: bDesiredDirection = SOUTHEAST; break;
case INSERTION_CODE_EAST: bDesiredDirection = SOUTHWEST; break;
case INSERTION_CODE_SOUTH: bDesiredDirection = NORTHWEST; break;
case INSERTION_CODE_WEST: bDesiredDirection = NORTHEAST; break;
default: AssertMsg( 0, "Illegal direction passed to AddSoldierInitListMilitiaOnEdge()" ); break;
case INSERTION_CODE_NORTH: bDesiredDirection = SOUTHEAST; break;
case INSERTION_CODE_EAST: bDesiredDirection = SOUTHWEST; break;
case INSERTION_CODE_SOUTH: bDesiredDirection = NORTHWEST; break;
case INSERTION_CODE_WEST: bDesiredDirection = NORTHEAST; break;
default: AssertMsg( 0, "Illegal direction passed to AddSoldierInitListMilitiaOnEdge()" ); break;
}
#ifdef JA2TESTVERSION
ScreenMsg( FONT_RED, MSG_INTERFACE, L"Militia reinforcements have arrived! (%d admins, %d troops, %d elite)", ubNumGreen, ubNumReg, ubNumElites );
#endif
#ifdef JA2TESTVERSION
ScreenMsg( FONT_RED, MSG_INTERFACE, L"Militia reinforcements have arrived! (%d admins, %d troops, %d elite)", ubNumGreen, ubNumReg, ubNumElites );
#endif
ChooseMapEdgepoints( &MapEdgepointInfo, ubStrategicInsertionCode, (UINT8)(ubNumGreen + ubNumReg + ubNumElites) );
ubCurrSlot = 0;
@@ -2448,7 +2458,7 @@ void AddSoldierInitListMilitiaOnEdge( UINT8 ubStrategicInsertionCode, UINT8 ubNu
pSoldier->sNoiseGridno = (INT16)(CENTRAL_GRIDNO + ( Random( CENTRAL_RADIUS * 2 + 1 ) - CENTRAL_RADIUS ) + ( Random( CENTRAL_RADIUS * 2 + 1 ) - CENTRAL_RADIUS ) * WORLD_COLS);
pSoldier->ubNoiseVolume = MAX_MISC_NOISE_DURATION;
}
//Setup the position
if( ubCurrSlot < MapEdgepointInfo.ubNumPoints )
{ //using an edgepoint
@@ -2529,10 +2539,10 @@ void AddSoldierInitListMilitiaOnEdge( UINT8 ubStrategicInsertionCode, UINT8 ubNu
pSoldier->ubNoiseVolume = MAX_MISC_NOISE_DURATION;
}
// if ( GetTimeOfDayAmbientLightLevel() < NORMAL_LIGHTLEVEL_DAY + 2 )
// gTacticalStatus.Team[ ENEMY_TEAM ].bAwareOfOpposition = TRUE;
// gTacticalStatus.Team[ MILITIA_TEAM ].bAwareOfOpposition = TRUE;
// if ( GetTimeOfDayAmbientLightLevel() < NORMAL_LIGHTLEVEL_DAY + 2 )
// gTacticalStatus.Team[ ENEMY_TEAM ].bAwareOfOpposition = TRUE;
// gTacticalStatus.Team[ MILITIA_TEAM ].bAwareOfOpposition = TRUE;
//Setup the position
if( ubCurrSlot < MapEdgepointInfo.ubNumPoints )
{ //using an edgepoint
+5 -2
View File
@@ -53,6 +53,7 @@
#include "personnel.h"
#include "environment.h"
#include "Player Command.h"
#include "strategic.h"
#endif
#ifdef JA2EDITOR
@@ -1083,7 +1084,7 @@ BOOLEAN RecruitRPC( UINT8 ubCharNum )
}
}
// swap item to hand
SwapObjs( &(pNewSoldier->inv[ bSlot ]), &(pNewSoldier->inv[ HANDPOS ]) );
SwapObjs( pNewSoldier, bSlot, HANDPOS );
}
}
@@ -1211,8 +1212,10 @@ BOOLEAN UnRecruitEPC( UINT8 ubCharNum )
}
// how do we decide whether or not to set this?
gMercProfiles[ ubCharNum ].fUseProfileInsertionInfo = TRUE;
gMercProfiles[ ubCharNum ].ubMiscFlags3 |= PROFILE_MISC_FLAG3_PERMANENT_INSERTION_CODE;
gMercProfiles[ ubCharNum ].usStrategicInsertionData = pSoldier->sGridNo;
gMercProfiles[ ubCharNum ].fUseProfileInsertionInfo = TRUE;
gMercProfiles[ ubCharNum ].ubStrategicInsertionCode = INSERTION_CODE_GRIDNO;
// Add this guy to CIV team!
pNewSoldier = ChangeSoldierTeam( pSoldier, CIV_TEAM );
+9 -2
View File
@@ -150,7 +150,7 @@ void PickBurstLocations( SOLDIERTYPE *pSoldier )
ubShotsPerBurst = pSoldier->bDoAutofire;
}
else if ( gbNumBurstLocations > 0 )
ubShotsPerBurst = pSoldier->bDoAutofire / gbNumBurstLocations;
ubShotsPerBurst = pSoldier->bDoAutofire; // / gbNumBurstLocations;
}
else
@@ -163,8 +163,15 @@ void PickBurstLocations( SOLDIERTYPE *pSoldier )
ubShotsPerBurst = __min( ubShotsPerBurst, MAX_BURST_SPREAD_TARGETS);
if (ubShotsPerBurst == 1)
{
pSoldier->fDoSpread = FALSE;
return;
}
// Use # gridnos accululated and # burst shots to determine accululator
dStep = gbNumBurstLocations / (FLOAT)ubShotsPerBurst;
// Calculate it so that the actual last chosen shot location is the last spread point
dStep = (gbNumBurstLocations-1) / (FLOAT)(ubShotsPerBurst-1);
//Loop through our shots!
for ( cnt = 0; cnt < ubShotsPerBurst; cnt++ )
+1 -1
View File
@@ -1198,7 +1198,7 @@ BOOLEAN LoadCurrentSectorsInformationFromTempItemsFile()
}
//if the save is an older version, use theold way of oading it up
//if the save is an older version, use the old way of loading it up
if( guiSavedGameVersion < 57 )
{
if( DoesTempFileExistsForMap( SF_ENEMY_PRESERVED_TEMP_FILE_EXISTS, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) )
+4 -4
View File
@@ -556,7 +556,7 @@ void DisplayHiddenInterrupt( SOLDIERTYPE * pSoldier )
// Stop our guy....
AdjustNoAPToFinishMove( MercPtrs[ LATEST_INTERRUPT_GUY ], TRUE );
// Stop him from going to prone position if doing a turn while prone
MercPtrs[ LATEST_INTERRUPT_GUY ]->fTurningFromPronePosition = FALSE;
MercPtrs[ LATEST_INTERRUPT_GUY ]->bTurningFromPronePosition = TURNING_FROM_PRONE_OFF;
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"about to call AddTopMessage");
// get rid of any old overlay message
@@ -862,7 +862,7 @@ void StartInterrupt( void )
{
// Stop this guy....
AdjustNoAPToFinishMove( MercPtrs[ LATEST_INTERRUPT_GUY ], TRUE );
MercPtrs[ LATEST_INTERRUPT_GUY ]->fTurningFromPronePosition = FALSE;
MercPtrs[ LATEST_INTERRUPT_GUY ]->bTurningFromPronePosition = TURNING_FROM_PRONE_OFF;
}
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"StartInterrupt done");
@@ -1770,7 +1770,7 @@ void VerifyOutOfTurnOrderArray()
AdjustNoAPToFinishMove( MercPtrs[ gubOutOfTurnOrder[ ubNextIndex ] ], TRUE );
// If they were turning from prone, stop them
MercPtrs[ gubOutOfTurnOrder[ ubNextIndex ] ]->fTurningFromPronePosition = FALSE;
MercPtrs[ gubOutOfTurnOrder[ ubNextIndex ] ]->bTurningFromPronePosition = TURNING_FROM_PRONE_OFF;
DeleteFromIntList( ubNextIndex, FALSE );
}
@@ -1826,7 +1826,7 @@ void VerifyOutOfTurnOrderArray()
AdjustNoAPToFinishMove( MercPtrs[ gubOutOfTurnOrder[ ubLoop ] ], TRUE );
// If they were turning from prone, stop them
MercPtrs[ gubOutOfTurnOrder[ ubLoop ] ]->fTurningFromPronePosition = FALSE;
MercPtrs[ gubOutOfTurnOrder[ ubLoop ] ]->bTurningFromPronePosition = TURNING_FROM_PRONE_OFF;
DeleteFromIntList( ubLoop, FALSE );
+2 -2
View File
@@ -3110,7 +3110,7 @@ void GetKeyboardInput( UINT32 *puiNewEvent )
}
else if ( bSlot2 != ITEM_NOT_FOUND )
{
SwapObjs( &(pTeamSoldier->inv[bSlot1]), &(pTeamSoldier->inv[bSlot2] ) );
SwapObjs( pTeamSoldier, bSlot1, bSlot2 );
}
break;
}
@@ -3153,7 +3153,7 @@ void GetKeyboardInput( UINT32 *puiNewEvent )
}
else if ( bSlot2 != ITEM_NOT_FOUND )
{
SwapObjs( &(pTeamSoldier->inv[bSlot1]), &(pTeamSoldier->inv[bSlot2] ) );
SwapObjs( pTeamSoldier, bSlot1, bSlot2 );
}
break;
}
+3 -2
View File
@@ -201,7 +201,8 @@ UINT8 GetProperItemCursor( UINT8 ubSoldierID, UINT16 ubItemIndex, UINT16 usMapPo
if ( fRecalc && gfUIFullTargetFound )
{
// ATE: Check for ammo
if ( IsValidTargetMerc( (UINT8)gusUIFullTargetID ) && EnoughAmmo( pSoldier, FALSE, HANDPOS ) )
if ( IsValidTargetMerc( (UINT8)gusUIFullTargetID ) && EnoughAmmo( pSoldier, FALSE, HANDPOS ) &&
(!IsValidSecondHandShotForReloadingPurposes( pSoldier) || EnoughAmmo( pSoldier, FALSE, SECONDHANDPOS) ) )
{
// IF it's an ememy, goto confirm action mode
if ( ( guiUIFullTargetFlags & ENEMY_MERC ) && ( guiUIFullTargetFlags & VISIBLE_MERC ) && !( guiUIFullTargetFlags & DEAD_MERC ) && !gfCannotGetThrough )
@@ -972,7 +973,7 @@ UINT8 HandleNonActivatedTargetCursor( SOLDIERTYPE *pSoldier, UINT16 usMapPos , B
}
// Check for enough ammo...
if ( !EnoughAmmo( pSoldier, FALSE, HANDPOS ) )
if ( !EnoughAmmo( pSoldier, FALSE, HANDPOS ) || (IsValidSecondHandShotForReloadingPurposes( pSoldier) && !EnoughAmmo( pSoldier, FALSE, SECONDHANDPOS) ) )
{
// Check if ANY ammo exists.....
if ( FindAmmoToReload( pSoldier, HANDPOS, NO_SLOT ) == NO_SLOT )
+11 -7
View File
@@ -1300,7 +1300,7 @@ BOOLEAN FireWeapon( SOLDIERTYPE *pSoldier , INT16 sTargetGridNo )
// SET ATTACKER TO NOBODY, WILL GET SET EVENTUALLY
pSoldier->ubOppNum = NOBODY ;
UINT16 usItemClass = Item[ pSoldier->usAttackingWeapon ].usItemClass;
UINT32 usItemClass = Item[ pSoldier->usAttackingWeapon ].usItemClass;
if ( pSoldier->bWeaponMode == WM_ATTACHED_GL || pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST || pSoldier->bWeaponMode == WM_ATTACHED_GL_AUTO )
usItemClass = IC_LAUNCHER;
@@ -1316,15 +1316,19 @@ BOOLEAN FireWeapon( SOLDIERTYPE *pSoldier , INT16 sTargetGridNo )
// ATE: PAtch up - bookkeeping for spreading done out of whak
if ( pSoldier->fDoSpread)
{
if (pSoldier->bDoBurst )
{
pSoldier->fDoSpread = FALSE;
}
// 0verhaul: This check does not work! All auto-fire has bDoBurst turned on. And only allowing a spread
// for a single-shot mode is useless.
//if (pSoldier->bDoBurst )
//{
// pSoldier->fDoSpread = FALSE;
//}
//else
// 0verhaul: The original code seemed brain damaged: If the current spread target was 0 it would shoot at the
// non-spread target grid # instead. Also fDoSpread is used as a counter from 1 to MAX_BURST_SPREAD_TARGETS,
// but was actually reset before it got there. So the final spread target would never be shot at. Hopefully this
// will work better.
else if (pSoldier->fDoSpread > MAX_BURST_SPREAD_TARGETS ||
if (pSoldier->fDoSpread > MAX_BURST_SPREAD_TARGETS ||
pSoldier->sSpreadLocations[ pSoldier->fDoSpread - 1 ] == 0)
{
if (pSoldier->fDoSpread == 1)
@@ -1574,7 +1578,7 @@ BOOLEAN UseGun( SOLDIERTYPE *pSoldier , INT16 sTargetGridNo )
sprintf( zBurstString, gzBurstSndStrings[ Weapon[ usItemNum ].sBurstSound ], bShotsToFire );
INT8 volume = HIGHVOLUME;
if ( noisefactor < 100 ) volume = (volume * noisefactor) / 100;
if ( noisefactor < 100 ) volume = (INT8) ((volume * noisefactor) / 100);
// Try playing sound...
pSoldier->iBurstSoundID = PlayJA2SampleFromFile( zBurstString, RATE_11025, SoundVolume( (INT8) volume, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
}
+3 -4
View File
@@ -288,7 +288,8 @@ void ExamineSlantRoofFOVSlots( )
void RevealRoofsAndItems(SOLDIERTYPE *pSoldier, UINT32 itemsToo, BOOLEAN fShowLocators, UINT8 ubLevel, BOOLEAN fForce )
{
UINT32 maincnt,markercnt,marker,tilesLeftToSee,cnt,prevmarker;
UINT32 maincnt,markercnt,marker,tilesLeftToSee,prevmarker;
UINT8 cnt;
INT32 Inc[6],Dir[6];
INT8 itemVisible = FALSE;
INT8 Blocking,twoMoreTiles,markerDir;
@@ -371,9 +372,7 @@ void RevealRoofsAndItems(SOLDIERTYPE *pSoldier, UINT32 itemsToo, BOOLEAN fShowLo
BuildSightDir(dir,(UINT32 *)&Dir[0],(UINT32 *)&Dir[1],(UINT32 *)&Dir[2],(UINT32 *)&Dir[3],(UINT32 *)&Dir[4]);
for (cnt = 0; cnt < 5; cnt++)
{
Inc[cnt] = DirectionInc( Dir[cnt] );
}
Inc[cnt] = DirectionInc( (UINT8) Dir[cnt]);
// create gridno increment for NOVIEW - in other words, no increment!
Inc[5] = 0;
+2 -2
View File
@@ -4409,8 +4409,8 @@ void WriteQuantityAndAttachments( OBJECTTYPE *pObject, INT32 yp )
{ //ammo
if( pObject->ubNumberOfObjects > 1 )
{
CHAR16 str[50];
CHAR16 temp[5];
CHAR16 str[100];
CHAR16 temp[10];
UINT8 i;
swprintf( str, L"Clips: %d (%d", pObject->ubNumberOfObjects, pObject->ItemData.Generic.bStatus[0] );
for( i = 1; i < pObject->ubNumberOfObjects; i++ )