New Feature: Multi-turn actions allow mercs to perform actions intended on a specific gridno over multiple turns. Currently demonstrated on the adding/removing/filling of sandbags.

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5777 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Flugente
2013-01-06 03:51:09 +00:00
parent 153f55ace8
commit 9ea7ebf393
25 changed files with 462 additions and 124 deletions
+16 -13
View File
@@ -2415,6 +2415,16 @@ void LoadGameAPBPConstants()
APBPConstants[AP_INV_TO_BIG_POCKET] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_INV_TO_BIG_POCKET",4),4);
APBPConstants[AP_INV_TO_SMALL_POCKET] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_INV_TO_SMALL_POCKET",5),5);
APBPConstants[AP_INV_MAX_COST] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_INV_MAX_COST",25),25);
APBPConstants[AP_JUMPWALL] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_JUMPOFFWALL",40),40);
APBPConstants[AP_JUMPOFFWALL] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_JUMPWALL",24),24);
APBPConstants[AP_FORTIFICATION] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_FORTIFICATION", 250), 250);
APBPConstants[AP_REMOVE_FORTIFICATION] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_REMOVE_FORTIFICATION", 150), 150);
APBPConstants[AP_FILL_SANDBAG] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_FILL_SANDBAG", 200), 200);
APBPConstants[AP_EAT] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_EAT",80),80);
APBPConstants[AP_CLEANINGKIT] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_CLEANINGKIT",80),80);
APBPConstants[AP_INVENTORY_EXPLOSIVE_ACTIVATE] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_INVENTORY_EXPLOSIVE_ACTIVATE",20),20);
APBPConstants[AP_DISGUISE] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_DISGUISE",80),80);
APBPConstants[AP_HANDCUFF] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_HANDCUFF",50),50);
APBPConstants[DEFAULT_APS] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","DEFAULT_APS",80),80);
APBPConstants[DEFAULT_AIMSKILL] = iniReader.ReadInteger("APConstants","DEFAULT_AIMSKILL",80);
@@ -2465,21 +2475,14 @@ void LoadGameAPBPConstants()
APBPConstants[BP_JUMP_OVER] = iniReader.ReadInteger("BPConstants","BP_JUMP_OVER",250);
APBPConstants[BP_BACK_PACK] = iniReader.ReadInteger("APConstants","BP_JUMP_OVER",50);
APBPConstants[BP_WORK_ZIPPER] = iniReader.ReadInteger("APConstants","BP_WORK_ZIPPER",250);
APBPConstants[BP_UNJAM] = iniReader.ReadInteger("APConstants","BP_WORK_ZIPPER",0);
APBPConstants[BP_UNJAM] = iniReader.ReadInteger("APConstants","BP_WORK_ZIPPER",0);
APBPConstants[BP_JUMPOFFWALL] = iniReader.ReadInteger("BPConstants","BP_JUMPOFFWALL",250);
APBPConstants[BP_JUMPWALL] = iniReader.ReadInteger("BPConstants","BP_JUMPWALL",500);
APBPConstants[AP_JUMPWALL] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_JUMPOFFWALL",40),40);
APBPConstants[AP_JUMPOFFWALL] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_JUMPWALL",24),24);
APBPConstants[AP_FORTIFICATION] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_FORTIFICATION",80),80);
APBPConstants[AP_EAT] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_EAT",80),80);
APBPConstants[AP_CLEANINGKIT] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_CLEANINGKIT",80),80);
APBPConstants[AP_INVENTORY_EXPLOSIVE_ACTIVATE] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_INVENTORY_EXPLOSIVE_ACTIVATE",20),20);
APBPConstants[AP_DISGUISE] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_DISGUISE",80),80);
APBPConstants[AP_HANDCUFF] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_HANDCUFF",50),50);
APBPConstants[BP_FORTIFICATION] = iniReader.ReadInteger("BPConstants","BP_FORTIFICATION", 700);
APBPConstants[BP_REMOVE_FORTIFICATION] = iniReader.ReadInteger("BPConstants","BP_REMOVE_FORTIFICATION", 400);
APBPConstants[BP_FILL_SANDBAG] = iniReader.ReadInteger("BPConstants","BP_FILL_SANDBAG", 500);
APBPConstants[BP_HANDCUFF] = iniReader.ReadInteger("BPConstants","BP_HANDCUFF", 100);
SetupMaxActionPointsAnimation();
#undef ReadInteger
}
+2 -1
View File
@@ -20,8 +20,9 @@ extern CHAR16 zTrackingNumber[16];
//
// Keeps track of the saved game version. Increment the saved game version whenever
// you will invalidate the saved game file
#define SAVE_GAME_VERSION 137 // 134 // 133 // 132 //131 //125 //124 //114 //113 //112 //111 //110 //109 //108 //107 //106 //105 //104 //103 //102 //101 //100 // 99
#define SAVE_GAME_VERSION 138
#define MULTITURN_ACTIONS 138 // Flugente: multiturn actions
#define EXTERNALISED_MERCHANTS 137 // Flugente: increased the number of merchants and externalised their data
#define PRISON_SYSTEM 136 // Flugente: added var to the sector structure. Shouldn't break compatibility, but let's be safe
#define DUAL_BURST_ADDED 135
+14 -8
View File
@@ -143,6 +143,16 @@ AP_INV_TO_BIG_POCKET,
AP_INV_TO_SMALL_POCKET,
//Max inventory cost
AP_INV_MAX_COST,
AP_JUMPWALL,
AP_JUMPOFFWALL,
AP_FORTIFICATION,
AP_REMOVE_FORTIFICATION,
AP_FILL_SANDBAG,
AP_EAT,
AP_CLEANINGKIT,
AP_INVENTORY_EXPLOSIVE_ACTIVATE,
AP_DISGUISE,
AP_HANDCUFF,
DEFAULT_APS,
DEFAULT_AIMSKILL,
@@ -195,14 +205,10 @@ BP_WORK_ZIPPER,
BP_UNJAM,
BP_JUMPOFFWALL,
BP_JUMPWALL,
AP_JUMPWALL,
AP_JUMPOFFWALL,
AP_FORTIFICATION,
AP_EAT,
AP_CLEANINGKIT,
AP_INVENTORY_EXPLOSIVE_ACTIVATE,
AP_DISGUISE,
AP_HANDCUFF,
BP_FORTIFICATION,
BP_REMOVE_FORTIFICATION,
BP_FILL_SANDBAG,
BP_HANDCUFF,
TOTAL_APBP_VALUES
};
#endif
+21 -4
View File
@@ -2024,12 +2024,31 @@ BOOLEAN SOLDIERTYPE::Load(HWFILE hFile)
numBytesRead = ReadFieldByField(hFile, &this->usStarveDamageHealth, sizeof(usStarveDamageHealth), sizeof(UINT8), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->usStarveDamageStrength, sizeof(usStarveDamageStrength), sizeof(UINT8), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->ubFiller, sizeof(ubFiller), sizeof(UINT8), numBytesRead);
if ( guiCurrentSaveGameVersion >= MULTITURN_ACTIONS )
{
numBytesRead = ReadFieldByField(hFile, &this->bOverTurnAPS, sizeof(bOverTurnAPS), sizeof(INT16), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->sMTActionGridNo, sizeof(sMTActionGridNo), sizeof(INT32), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->usMultiTurnAction, sizeof(usMultiTurnAction), sizeof(UINT8), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->ubFiller, sizeof(ubFiller), sizeof(UINT8), numBytesRead);
}
else
{
this->bOverTurnAPS = 0;
this->sMTActionGridNo = NOWHERE;
this->usMultiTurnAction = 0;
// as we added new variables, fillersize was reduced, here we account for that. We have to also read the existing fillers that now do not exist anymore
const UINT8 tmp = sizeof(bOverTurnAPS) + sizeof(this->sMTActionGridNo) + sizeof(usMultiTurnAction);
UINT8 blarg[tmp];
numBytesRead = ReadFieldByField(hFile, &blarg, tmp, sizeof(UINT8), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->ubFiller, sizeof(ubFiller), sizeof(UINT8), numBytesRead);
}
}
else
{
//CHRISL: We have to make sure we add a buffer to account for the lack of ubInterruptCounter and that buffer needs to be a full DWORD in size
buffer = 0;
for(int i = 0; i < sizeof(bFoodLevel); ++i)
buffer++;
while((buffer%4) > 0)
@@ -2054,8 +2073,6 @@ BOOLEAN SOLDIERTYPE::Load(HWFILE hFile)
buffer++;
while((buffer%4) > 0)
buffer++;
numBytesRead += buffer;
}
#ifdef JA2UB
+7
View File
@@ -2327,6 +2327,13 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE
DoRightIcon( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons, 22 );
bNumRightIcons++;
}
// Flugente: add an icon if we are performing a multi-turn action
if ( MercPtrs[ pFace->ubSoldierID ]->GetMultiTurnAction() > MTA_NONE )
{
DoRightIcon( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons, 24 );
bNumRightIcons++;
}
}
switch( pSoldier->bAssignment )
+15 -11
View File
@@ -1140,6 +1140,8 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
// if we have an empty sandbag in our hands, we also need to have a shovel in our second hand, otherwise we can't fill it
if ( HasItemFlag(usHandItem, (EMPTY_SANDBAG)) )
{
sAPCost = APBPConstants[AP_FILL_SANDBAG];
// check if we have a shovel in our second hand
OBJECTTYPE* pShovelObj = &(pSoldier->inv[SECONDHANDPOS]);
@@ -1155,10 +1157,11 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
return( ITEM_HANDLE_REFUSAL );
}
}
// if we have a shovel in our hands, the targetted gridno must be a fortification (debris will do for this check)
if ( HasItemFlag(usHandItem, (SHOVEL)) )
// if we have a shovel in our hands, the targeted gridno must be a fortification (debris will do for this check)
else if ( HasItemFlag(usHandItem, (SHOVEL)) )
{
sAPCost = APBPConstants[AP_REMOVE_FORTIFICATION];
STRUCTURE* pStruct = FindStructure(sGridNo, STRUCTURE_GENERIC);
if ( !pStruct )
@@ -1166,16 +1169,20 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
return( ITEM_HANDLE_REFUSAL );
}
}
else
{
sAPCost = APBPConstants[AP_FORTIFICATION];
}
sActionGridNo = FindAdjacentGridEx( pSoldier, sGridNo, &ubDirection, &sAdjustedGridNo, TRUE, FALSE );
if ( sActionGridNo != -1 )
{
// Calculate AP costs...
sAPCost = GetAPsToBuildFortification( pSoldier, sActionGridNo );
sAPCost += PlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, FALSE, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints);
if ( EnoughPoints( pSoldier, sAPCost, 0, fFromUI ) )
//if ( EnoughPoints( pSoldier, sAPCost, 0, fFromUI ) )
if ( pSoldier->bActionPoints > 0 )
{
// CHECK IF WE ARE AT THIS GRIDNO NOW
if ( pSoldier->sGridNo != sActionGridNo )
@@ -6251,9 +6258,8 @@ void SoldierStealItemFromSoldier( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent,
SetCustomizableTimerCallbackAndDelay( 1000, CheckForPickedOwnership, TRUE );
}
BOOLEAN BuildFortification( UINT32 flag )
{
INT32 sGridNo;
BOOLEAN BuildFortification( INT32 sGridNo, UINT32 flag )
{
UINT32 fHeadType;
UINT16 usUseIndex;
UINT16 usUseObjIndex = 0;
@@ -6268,9 +6274,7 @@ BOOLEAN BuildFortification( UINT32 flag )
{
return FALSE;
}
GetMouseMapPos( &sGridNo );
if( InARoom( sGridNo, NULL ) )
return FALSE;
+1 -1
View File
@@ -180,7 +180,7 @@ UINT8 StealItems(SOLDIERTYPE* pSoldier,SOLDIERTYPE* pOpponent, UINT8* ubIndexRet
BOOLEAN MarblesExistAtLocation( INT32 sGridNo, UINT8 ubLevel, INT32 * piItemIndex );
BOOLEAN BuildFortification( UINT32 flag = FULL_SANDBAG ); // Flugente: build a structure, return true if sucessful
BOOLEAN BuildFortification( INT32 sGridNo , UINT32 flag = FULL_SANDBAG ); // Flugente: build a structure, return true if sucessful
BOOLEAN RemoveFortification( INT32 sGridNo );
extern ITEM_POOL *gpItemPool;//dnl ch26 210909
+1 -2
View File
@@ -4132,8 +4132,7 @@ INT8 DrawUIMovementPath( SOLDIERTYPE *pSoldier, INT32 usMapPos, UINT32 uiFlags )
sActionGridNo = usMapPos;
}
sAPCost = GetAPsToBuildFortification( pSoldier, sActionGridNo );
sAPCost = APBPConstants[AP_FORTIFICATION];
sAPCost += UIPlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints);
if ( sActionGridNo != pSoldier->sGridNo )
-11
View File
@@ -3681,17 +3681,6 @@ INT16 GetAPsToUseCan( SOLDIERTYPE *pSoldier, INT32 usMapPos )
}
INT16 GetAPsToBuildFortification( SOLDIERTYPE *pSoldier, INT32 usMapPos )
{
INT16 sAPCost = 0;
sAPCost = PlotPath( pSoldier, usMapPos, NO_COPYROUTE, NO_PLOT, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints );
sAPCost += APBPConstants[AP_FORTIFICATION];
return sAPCost;
}
INT16 GetAPsToHandcuff( SOLDIERTYPE *pSoldier, INT32 usMapPos )
{
INT16 sAPCost = 0;
-1
View File
@@ -356,7 +356,6 @@ INT16 GetAPsToUseJar( SOLDIERTYPE *pSoldier, INT32 usMapPos );
INT16 GetAPsToUseCan( SOLDIERTYPE *pSoldier, INT32 usMapPos );
INT16 GetBPsTouseJar( SOLDIERTYPE *pSoldier );
INT16 GetAPsToBuildFortification( SOLDIERTYPE *pSoldier, INT32 usMapPos ); // added by Flugente
INT16 GetAPsToHandcuff( SOLDIERTYPE *pSoldier, INT32 usMapPos ); // added by Flugente
INT16 GetAPsToJumpOver( SOLDIERTYPE *pSoldier );
+253 -69
View File
@@ -15474,6 +15474,240 @@ BOOLEAN SOLDIERTYPE::IsAssassin()
return FALSE;
}
UINT8 SOLDIERTYPE::GetMultiTurnAction()
{
return usMultiTurnAction;
}
void SOLDIERTYPE::StartMultiTurnAction(UINT8 usActionType)
{
// check wether we can perform any action at all
if ( !this->bActive || !this->bInSector || this->stats.bLife < OKLIFE || TileIsOutOfBounds(this->sGridNo) || this->pathing.bLevel != 0 || gAnimControl[ this->usAnimState ].ubEndHeight == ANIM_PRONE || gAnimControl[ this->usAnimState ].ubEndHeight == ANIM_STAND || this->bCollapsed )
return;
// if we already perform a multi-turn action, overwrite it
if ( GetMultiTurnAction() > MTA_NONE )
CancelMultiTurnAction(FALSE);
// set up the action and costs
usMultiTurnAction = usActionType;
// the action shall be performed on the gridno directly in front of us
sMTActionGridNo = NewGridNo( this->sGridNo, DirectionInc( this->ubDirection ) );
// for now, adding and removing a structure has the same AP cost - that might change in the future
switch( usMultiTurnAction )
{
case MTA_FORTIFY:
bOverTurnAPS = APBPConstants[AP_FORTIFICATION];
break;
case MTA_REMOVE_FORTIFY:
bOverTurnAPS = APBPConstants[AP_REMOVE_FORTIFICATION];
break;
case MTA_FILL_SANDBAG:
bOverTurnAPS = APBPConstants[AP_FILL_SANDBAG];
break;
}
// immediately starting the action would leave us without APs, thus removing the benefit of multi-turn actions (ability to do something else while performing a longer action)
// for this reason, we only do this when we are not in combat
if ( !( gTacticalStatus.uiFlags & TURNBASED && gTacticalStatus.uiFlags & INCOMBAT ) )
UpdateMultiTurnAction();
}
void SOLDIERTYPE::CancelMultiTurnAction(BOOLEAN fFinished)
{
// stop action
if ( !fFinished )
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szMTATextStr[STR_MTA_CANCEL], this->name, szMTATextStr[this->usMultiTurnAction] );
bOverTurnAPS = 0;
sMTActionGridNo = NOWHERE;
usMultiTurnAction = MTA_NONE;
}
// if we are doing any multiturn-action, remove our current APs from it, and if possible, perform the action and finish the process
BOOLEAN SOLDIERTYPE::UpdateMultiTurnAction()
{
// nothing to do here
if ( this->usMultiTurnAction == MTA_NONE )
return FALSE;
// check wether we can perform any action at all
if ( !this->bActive || !this->bInSector || this->stats.bLife < OKLIFE || TileIsOutOfBounds(this->sGridNo) || TileIsOutOfBounds(this->sMTActionGridNo) || this->pathing.bLevel != 0 || gAnimControl[ this->usAnimState ].ubEndHeight == ANIM_PRONE || gAnimControl[ this->usAnimState ].ubEndHeight == ANIM_STAND || this->bCollapsed )
{
CancelMultiTurnAction(FALSE);
return FALSE;
}
// check wether our selected action can still be performed
BOOLEAN fActionStillValid = TRUE;
// determine the gridno before us and the item we have in our main hand, this is enough for the current actions
OBJECTTYPE* pObj = &(this->inv[HANDPOS]);
if ( !pObj || !(pObj->exists()) )
fActionStillValid = FALSE;
// error if the gridno we started working on is not the gridno we are currently looking at
if ( this->sMTActionGridNo != NewGridNo( this->sGridNo, DirectionInc( this->ubDirection ) ) )
fActionStillValid = FALSE;
if ( !fActionStillValid )
{
CancelMultiTurnAction(FALSE);
return FALSE;
}
// a static variable that is the item number of sandbags. Hardcoding item numbers is bad, that's why we will search for it.
static UINT16 fullsandbagnr = 1541;
INT16 entireapcost = 0;
INT16 entirebpcost = 0;
switch( usMultiTurnAction )
{
case MTA_FORTIFY:
{
entireapcost = APBPConstants[AP_FORTIFICATION];
entirebpcost = APBPConstants[BP_FORTIFICATION];
if ( !IsFortificationPossibleAtGridNo( this->sMTActionGridNo ) )
fActionStillValid = FALSE;
}
break;
case MTA_REMOVE_FORTIFY:
{
entireapcost = APBPConstants[AP_REMOVE_FORTIFICATION];
entirebpcost = APBPConstants[BP_REMOVE_FORTIFICATION];
if ( !HasItemFlag(this->inv[ HANDPOS ].usItem, (SHOVEL)) )
fActionStillValid = FALSE;
}
break;
case MTA_FILL_SANDBAG:
{
entireapcost = APBPConstants[AP_FILL_SANDBAG];
entirebpcost = APBPConstants[BP_FILL_SANDBAG];
if ( !HasItemFlag(this->inv[ HANDPOS ].usItem, EMPTY_SANDBAG) )
fActionStillValid = FALSE;
else
{
INT8 bOverTerrainType = GetTerrainType( sGridNo );
if( bOverTerrainType != FLAT_GROUND && bOverTerrainType != DIRT_ROAD && bOverTerrainType != LOW_GRASS )
fActionStillValid = FALSE;
else
{
// check if we have a shovel in our second hand
OBJECTTYPE* pShovelObj = &(this->inv[SECONDHANDPOS]);
if ( !pShovelObj || !(pShovelObj->exists()) || !HasItemFlag(this->inv[ SECONDHANDPOS ].usItem, SHOVEL) )
fActionStillValid = FALSE;
}
}
}
break;
}
if ( !fActionStillValid )
{
CancelMultiTurnAction(FALSE);
return FALSE;
}
// if we are not in turnbased and no enemies are around, we reduce the number of necessary action points to 0. No need to keep waiting if there's nobody around anyway
if ( !( gTacticalStatus.uiFlags & TURNBASED && gTacticalStatus.uiFlags & INCOMBAT ) )
bOverTurnAPS = 0;
// otherwise this might take longer, so we refresh our animation
else
{
// refresh animations
if (!is_networked)
this->EVENT_InitNewSoldierAnim( CUTTING_FENCE, 0 , FALSE );
else
this->ChangeSoldierState( CUTTING_FENCE, 0, 0 );
// as setting the new animation costs APBPConstants[AP_USEWIRECUTTERS] APs every time, account for that
this->bActionPoints += APBPConstants[AP_USEWIRECUTTERS];
}
// if we can afford it, do it now
if ( bOverTurnAPS <= this->bActionPoints )
{
switch( usMultiTurnAction )
{
case MTA_FORTIFY:
{
// Build the thing
if ( BuildFortification( this->sMTActionGridNo, Item[ pObj->usItem ].usItemFlag ) )
{
// Erase 'material' item from our hand - we 'use' it to build the structure
DeleteObj( &(this->inv[HANDPOS]) );
// we gain a bit of experience...
StatChange( this, STRAMT, 4, TRUE );
StatChange( this, HEALTHAMT, 2, TRUE );
}
}
break;
case MTA_REMOVE_FORTIFY:
{
if ( RemoveFortification( this->sMTActionGridNo ) )
{
// eventually search for the number of a sandbag item
if ( HasItemFlag(fullsandbagnr, FULL_SANDBAG) || GetFirstItemWithFlag(&fullsandbagnr, FULL_SANDBAG) )
{
CreateItem( fullsandbagnr, 100, &gTempObject );
AddItemToPool( this->sMTActionGridNo, &gTempObject, 1, 0, 0, -1 );
// we gain a bit of experience...
StatChange( this, STRAMT, 3, TRUE );
StatChange( this, HEALTHAMT, 2, TRUE );
}
}
}
break;
case MTA_FILL_SANDBAG:
{
// eventually search for the number of a sandbag item
if ( HasItemFlag(fullsandbagnr, FULL_SANDBAG) || GetFirstItemWithFlag(&fullsandbagnr, FULL_SANDBAG) )
{
// Erase 'material' item from our hand - we 'used' it to build the structure
INT8 bObjSlot = HANDPOS;
CreateItem( fullsandbagnr, 100, &gTempObject );
SwapObjs( this, bObjSlot, &gTempObject, TRUE );
// we gain a bit of experience...
StatChange( this, STRAMT, 1, TRUE );
StatChange( this, HEALTHAMT, 1, TRUE );
}
}
break;
}
if ( entireapcost > 0 )
DeductPoints( this, bOverTurnAPS, (INT32)(entirebpcost * this->bOverTurnAPS / entireapcost), 0);
// we're done here!
CancelMultiTurnAction(TRUE);
}
// remove the costs as much as we can
else if ( this->bActionPoints > 0 )
{
INT16 oldAPs = this->bActionPoints;
if ( bOverTurnAPS > 0 )
DeductPoints( this, this->bActionPoints, (INT32)(entirebpcost * this->bActionPoints / entireapcost), 0);
bOverTurnAPS -= oldAPs;
}
return TRUE;
}
INT32 CheckBleeding( SOLDIERTYPE *pSoldier )
{
INT8 bBandaged; //,savedOurTurn;
@@ -16255,8 +16489,6 @@ extern UINT8 NumEnemiesInAnySector( INT16 sSectorX, INT16 sSectorY, INT16 sSecto
void SOLDIERTYPE::EVENT_SoldierBuildStructure( INT32 sGridNo, UINT8 ubDirection )
{
// a static variable that is the item number of sandbags. Hardcoding item numbers is bad, that's why we will search for it.
static UINT16 fullsandbagnr = 1541;
BOOLEAN fSuccess = FALSE;
// if specified by the ini, building/disassembling stuff is disabled while enemies are around
@@ -16275,36 +16507,12 @@ void SOLDIERTYPE::EVENT_SoldierBuildStructure( INT32 sGridNo, UINT8 ubDirection
if ( pObj && pObj->exists() && HasItemFlag(this->inv[ HANDPOS ].usItem, (EMPTY_SANDBAG|FULL_SANDBAG|SHOVEL|CONCERTINA)) )
{
// CHANGE DIRECTION AND GOTO ANIMATION NOW
this->EVENT_SetSoldierDesiredDirection( ubDirection );
this->EVENT_SetSoldierDirection( ubDirection );
if (!is_networked)
this->EVENT_InitNewSoldierAnim( CUTTING_FENCE, 0 , FALSE );
else
this->ChangeSoldierState( CUTTING_FENCE, 0, 0 );
// ugly, ugly hack: as e do not have a special animation for this action, we use the 'cut a fence' animations
// however, APs are directly deducted because of this. So we can't use the AP_FORTIFICATION costs
// for this reason, we deduct the APS still missing here
INT16 restAPs = max(0, APBPConstants[AP_FORTIFICATION] - APBPConstants[AP_USEWIRECUTTERS]);
if ( HasItemFlag(this->inv[ HANDPOS ].usItem, (FULL_SANDBAG|CONCERTINA)) )
{
// Build the thing
if ( BuildFortification( Item[ pObj->usItem ].usItemFlag ) )
{
// Erase 'material' item from our hand - we 'used' it to build the structure
DeleteObj( &(this->inv[HANDPOS]) );
this->StartMultiTurnAction( MTA_FORTIFY );
// we gain a bit of experience...
StatChange( this, STRAMT, 4, TRUE );
StatChange( this, HEALTHAMT, 2, TRUE );
DeductPoints( this, restAPs, 0, AFTERACTION_INTERRUPT );
fSuccess = TRUE;
}
fSuccess = TRUE;
}
else if ( HasItemFlag(this->inv[ HANDPOS ].usItem, (EMPTY_SANDBAG)) )
{
@@ -16316,52 +16524,17 @@ void SOLDIERTYPE::EVENT_SoldierBuildStructure( INT32 sGridNo, UINT8 ubDirection
if ( pShovelObj && pShovelObj->exists() && HasItemFlag(this->inv[ SECONDHANDPOS ].usItem, (SHOVEL)) )
{
// eventually search for the number of a sandbag item
if ( HasItemFlag(fullsandbagnr, FULL_SANDBAG) || GetFirstItemWithFlag(&fullsandbagnr, FULL_SANDBAG) )
{
// Erase 'material' item from our hand - we 'used' it to build the structure
INT8 bObjSlot = HANDPOS;
this->StartMultiTurnAction( MTA_FILL_SANDBAG );
CreateItem( fullsandbagnr, 100, &gTempObject );
SwapObjs( this, bObjSlot, &gTempObject, TRUE );
// we gain a bit of experience...
StatChange( this, STRAMT, 1, TRUE );
StatChange( this, HEALTHAMT, 1, TRUE );
DeductPoints( this, restAPs, 0, AFTERACTION_INTERRUPT );
fSuccess = TRUE;
}
fSuccess = TRUE;
}
}
}
else if ( HasItemFlag(this->inv[ HANDPOS ].usItem, (SHOVEL)) )
{
// Build the thing
if ( RemoveFortification( sGridNo ) )
{
// eventually search for the number of a sandbag item
if ( HasItemFlag(fullsandbagnr, FULL_SANDBAG) || GetFirstItemWithFlag(&fullsandbagnr, FULL_SANDBAG) )
{
// Erase 'material' item from our hand - we 'used' it to build the structure
INT8 bObjSlot = HANDPOS;
this->StartMultiTurnAction( MTA_REMOVE_FORTIFY );
CreateItem( fullsandbagnr, 100, &gTempObject );
// now add a tripwire item to the floor, simulating that activating tripwire deactivates it
AddItemToPool( sGridNo, &gTempObject, 1, 0, 0, -1 );
// we gain a bit of experience...
StatChange( this, STRAMT, 3, TRUE );
StatChange( this, HEALTHAMT, 2, TRUE );
DeductPoints( this, restAPs, 0, AFTERACTION_INTERRUPT );
fSuccess = TRUE;
}
}
fSuccess = TRUE;
}
}
@@ -16370,6 +16543,17 @@ void SOLDIERTYPE::EVENT_SoldierBuildStructure( INT32 sGridNo, UINT8 ubDirection
// Say NOTHING quote...
this->DoMercBattleSound( BATTLE_SOUND_NOTHING );
}
else
{
// CHANGE DIRECTION AND GOTO ANIMATION NOW
this->EVENT_SetSoldierDesiredDirection( ubDirection );
this->EVENT_SetSoldierDirection( ubDirection );
if (!is_networked)
this->EVENT_InitNewSoldierAnim( CUTTING_FENCE, 0 , FALSE );
else
this->ChangeSoldierState( CUTTING_FENCE, 0, 0 );
}
}
void SOLDIERTYPE::EVENT_SoldierHandcuffPerson( INT32 sGridNo, UINT8 ubDirection )
@@ -16474,7 +16658,7 @@ void SOLDIERTYPE::EVENT_SoldierHandcuffPerson( INT32 sGridNo, UINT8 ubDirection
StatChange( this, DEXTAMT, 3, TRUE );
StatChange( this, EXPERAMT, 2, TRUE );
DeductPoints( this, GetAPsToHandcuff( this, sGridNo ), 0, AFTERACTION_INTERRUPT );
DeductPoints( this, GetAPsToHandcuff( this, sGridNo ), APBPConstants[BP_HANDCUFF], AFTERACTION_INTERRUPT );
// this might have been the last guy...
CheckForEndOfBattle( FALSE );
@@ -16484,7 +16668,7 @@ void SOLDIERTYPE::EVENT_SoldierHandcuffPerson( INT32 sGridNo, UINT8 ubDirection
// we gain a bit of experience...
StatChange( this, DEXTAMT, 2, TRUE );
DeductPoints( this, GetAPsToHandcuff( this, sGridNo ), 0, AFTERACTION_INTERRUPT );
DeductPoints( this, GetAPsToHandcuff( this, sGridNo ), APBPConstants[BP_HANDCUFF], AFTERACTION_INTERRUPT );
// curses!
this->DoMercBattleSound( BATTLE_SOUND_CURSE1 );
+22 -1
View File
@@ -389,6 +389,16 @@ enum
#define WH40K_SOLDIER_KILLTHISTURN 0x80000000 //2147483648 // Soldier is on a kill streak*/
// ----------------------------------------------------------------
// Flugente: types of multi-turn actions
enum
{
MTA_NONE = 0,
MTA_FORTIFY,
MTA_REMOVE_FORTIFY,
MTA_FILL_SANDBAG,
NUM_MTA,
};
// enum of uniform pieces
typedef struct
{
@@ -1249,8 +1259,13 @@ public:
UINT8 usStarveDamageHealth; // damage to health due to starvation. Can be cured by surgery, but only if nutrition level is high enough again
UINT8 usStarveDamageStrength; // damage to strength due to starvation. Can be cured by surgery, but only if nutrition level is high enough again
// Flugente: multi-turn actions
INT16 bOverTurnAPS; // remaining AP cost for the next turns (allows actions to be performed for more than one turn)
INT32 sMTActionGridNo; // gridno on which we perfrom our multi-turn action
UINT8 usMultiTurnAction; // specifies which multi-turn action we are currently performing, 0: none
// Flugente: Decrease this filler by 1 for each new UINT8 / BOOLEAN variable, so we can maintain savegame compatibility!!
UINT8 ubFiller[20];
UINT8 ubFiller[13];
#ifdef JA2UB
//ja25
@@ -1512,6 +1527,12 @@ public:
// Flugente: are we an assassin?
BOOLEAN IsAssassin();
// Flugente: multi-turn actions
UINT8 GetMultiTurnAction();
void StartMultiTurnAction(UINT8 usActionType);
void CancelMultiTurnAction(BOOLEAN fFinished);
BOOLEAN UpdateMultiTurnAction();
//////////////////////////////////////////////////////////////////////////////
}; // SOLDIERTYPE;
+1 -1
View File
@@ -574,7 +574,7 @@ BOOLEAN IsFortificationPossibleAtGridNo( INT32 sGridNo )
STRUCTURE * pStructure = NULL;
pStructure = FindStructure( sGridNo, (STRUCTURE_OBSTACLE) );
pStructure = FindStructure( sGridNo, (STRUCTURE_OBSTACLE|STRUCTURE_PERSON) );
return( pStructure == NULL );
}
+3
View File
@@ -240,6 +240,9 @@ void HandleTacticalEndTurn( )
//{
//// UpdateStats( pSoldier );
//}
// Flugente: update multi-turn actions
pSoldier->UpdateMultiTurnAction();
}
}
+12 -1
View File
@@ -464,8 +464,19 @@ void EndTurnEvents( void )
DecaySmokeEffects( GetWorldTotalSeconds( ) );
DecayLightEffects( GetWorldTotalSeconds( ) );
SOLDIERTYPE* pSoldier = NULL;
UINT32 cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ++cnt, ++pSoldier)
{
if ( pSoldier->bActive && pSoldier->stats.bLife > 0 && !( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) && !( AM_A_ROBOT( pSoldier ) ) )
{
// Flugente: update multi-turn actions
pSoldier->UpdateMultiTurnAction();
}
}
// Flugente: Cool down/decay all items not in a soldier's inventory
CoolDownWorldItems();
CoolDownWorldItems( );
#ifdef ENABLE_ZOMBIES
// Flugente: raise zombies if in gamescreen and option set
+13
View File
@@ -748,6 +748,19 @@ enum
extern STR16 szPrisonerTextStr[];
enum
{
STR_MTA_NONE,
STR_MTA_FORTIFY,
STR_MTA_REMOVE_FORTIFY,
STR_TA_FILL_SANDBAG,
STR_MTA_CANCEL,
TEXT_NUM_MTA_STR
};
extern STR16 szMTATextStr[];
enum
{
AIR_RAID_TURN_STR,
+9
View File
@@ -7499,4 +7499,13 @@ STR16 szPrisonerTextStr[]=
L"这敌人丫宁死不从!",//L"The enemy refuses to surrender!",
};
STR16 szMTATextStr[]= // TODO.Translate
{
L"nothing",
L"building a fortification",
L"removing a fortification",
L"filling sandbags",
L"%s had to stop %s.",
};
#endif //CHINESE
+9
View File
@@ -7497,4 +7497,13 @@ STR16 szPrisonerTextStr[]=
L"The enemy refuses to surrender!",
};
STR16 szMTATextStr[]= // TODO.Translate
{
L"nothing",
L"building a fortification",
L"removing a fortification",
L"filling sandbags",
L"%s had to stop %s.",
};
#endif //DUTCH
+9
View File
@@ -7484,4 +7484,13 @@ STR16 szPrisonerTextStr[]=
L"The enemy refuses to surrender!",
};
STR16 szMTATextStr[]=
{
L"nothing",
L"building a fortification",
L"removing a fortification",
L"filling sandbags",
L"%s had to stop %s.",
};
#endif //ENGLISH
+9
View File
@@ -7471,4 +7471,13 @@ STR16 szPrisonerTextStr[]=
L"The enemy refuses to surrender!",
};
STR16 szMTATextStr[]= // TODO.Translate
{
L"nothing",
L"building a fortification",
L"removing a fortification",
L"filling sandbags",
L"%s had to stop %s.",
};
#endif //FRENCH
+9
View File
@@ -7311,4 +7311,13 @@ STR16 szPrisonerTextStr[]=
L"Der Gegner weigert sich aufzugeben!",
};
STR16 szMTATextStr[]= // TODO.Translate
{
L"nothing",
L"building a fortification",
L"removing a fortification",
L"filling sandbags",
L"%s had to stop %s.",
};
#endif //GERMAN
+9
View File
@@ -7484,4 +7484,13 @@ STR16 szPrisonerTextStr[]=
L"The enemy refuses to surrender!",
};
STR16 szMTATextStr[]= // TODO.Translate
{
L"nothing",
L"building a fortification",
L"removing a fortification",
L"filling sandbags",
L"%s had to stop %s.",
};
#endif //ITALIAN
+9
View File
@@ -7498,4 +7498,13 @@ STR16 szPrisonerTextStr[]=
L"The enemy refuses to surrender!",
};
STR16 szMTATextStr[]= // TODO.Translate
{
L"nothing",
L"building a fortification",
L"removing a fortification",
L"filling sandbags",
L"%s had to stop %s.",
};
#endif //POLISH
+9
View File
@@ -7450,4 +7450,13 @@ STR16 szPrisonerTextStr[]=
L"The enemy refuses to surrender!",
};
STR16 szMTATextStr[]= // TODO.Translate
{
L"nothing",
L"building a fortification",
L"removing a fortification",
L"filling sandbags",
L"%s had to stop %s.",
};
#endif //RUSSIAN
+9
View File
@@ -7501,4 +7501,13 @@ STR16 szPrisonerTextStr[]=
L"The enemy refuses to surrender!",
};
STR16 szMTATextStr[]= // TODO.Translate
{
L"nothing",
L"building a fortification",
L"removing a fortification",
L"filling sandbags",
L"%s had to stop %s.",
};
#endif //TAIWANESE