New Feature: static fortifications can now be built by mercs (by Flugente)

- if the terrain allows it, an empty sandbag (item 1540) can be filled to a full sandbag (item 1541). You need to have a shovel (item 1015) in your second hand. You will notice the new hammer cursor
- by using a full sandbag, you can build a sandbag barrier
- by using a concertina stack, you can build a concertina wire barrier
- this only works if the current map has sandbags/concertina wire in its tileset
- with a shovel in your hand, you can remove a sandbag barrier
- changed the size of shovel so it can actually be put in inventories. It was also necessary to remove its ability to be used as a melee weapon.
- for further info, see this thread: http://www.bears-pit.com/board/ubbthreads.php/topics/305822.html#Post305822


git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5340 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Wanne
2012-06-11 08:32:07 +00:00
parent 56df9f8f69
commit 80509d2b61
25 changed files with 654 additions and 4 deletions
+3
View File
@@ -1346,6 +1346,7 @@ void LoadGameExternalOptions()
gGameExternalOptions.fZombieCanClimb = iniReader.ReadBoolean("Tactical Zombie Settings", "ZOMBIE_CAN_CLIMB", TRUE);
gGameExternalOptions.fZombieExplodingCivs = iniReader.ReadBoolean("Tactical Zombie Settings", "ZOMBIE_EXPLODING_CIVS", FALSE);
gGameExternalOptions.sEnemyZombieDamageResistance = iniReader.ReadInteger("Tactical Zombie Settings", "ZOMBIE_DAMAGE_RESISTANCE", 0, -50, 95);
gGameExternalOptions.sEnemyZombieBreathDamageResistance = iniReader.ReadInteger("Tactical Zombie Settings", "ZOMBIE_BREATH_DAMAGE_RESISTANCE", 0, -50, 95);
gGameExternalOptions.fZombieOnlyHeadshotsWork = iniReader.ReadBoolean("Tactical Zombie Settings", "ZOMBIE_ONLY_HEADSHOTS_WORK", FALSE);
gGameExternalOptions.sZombieDifficultyLevel = iniReader.ReadInteger("Tactical Zombie Settings", "ZOMBIE_DIFFICULTY_LEVEL", 2, 1, 4);
gGameExternalOptions.fZombieRiseWithArmour = iniReader.ReadBoolean("Tactical Zombie Settings", "ZOMBIE_RISE_WITH_ARMOUR", TRUE);
@@ -2283,6 +2284,8 @@ void LoadGameAPBPConstants()
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);
SetupMaxActionPointsAnimation();
#undef ReadInteger
}
+1
View File
@@ -372,6 +372,7 @@ typedef struct
BOOLEAN fZombieCanClimb;
BOOLEAN fZombieExplodingCivs;
INT8 sEnemyZombieDamageResistance;
INT8 sEnemyZombieBreathDamageResistance;
BOOLEAN fZombieOnlyHeadshotsWork;
INT8 sZombieDifficultyLevel;
BOOLEAN fZombieRiseWithArmour;
+1
View File
@@ -197,6 +197,7 @@ BP_JUMPOFFWALL,
BP_JUMPWALL,
AP_JUMPWALL,
AP_JUMPOFFWALL,
AP_FORTIFICATION,
TOTAL_APBP_VALUES
};
#endif
+285
View File
@@ -1120,6 +1120,80 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
}
}
// Flugente: sandbag stuff
if ( HasItemFlag(usHandItem, (EMPTY_SANDBAG|FULL_SANDBAG|SHOVEL|CONCERTINA)) )
{
// 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)) )
{
// check if we have a shovel in our second hand
OBJECTTYPE* pShovelObj = &(pSoldier->inv[SECONDHANDPOS]);
if ( !pShovelObj || !(pShovelObj->exists()) || !HasItemFlag(pSoldier->inv[ SECONDHANDPOS ].usItem, (SHOVEL)) )
{
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)) )
{
STRUCTURE* pStruct = FindStructure(sGridNo, STRUCTURE_GENERIC);
if ( !pStruct )
{
return( ITEM_HANDLE_REFUSAL );
}
}
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 ) )
{
// CHECK IF WE ARE AT THIS GRIDNO NOW
if ( pSoldier->sGridNo != sActionGridNo )
{
// SEND PENDING ACTION
pSoldier->aiData.ubPendingAction = MERC_BUILD_FORTIFICATION;
pSoldier->aiData.sPendingActionData2 = sAdjustedGridNo;
pSoldier->aiData.bPendingActionData3 = ubDirection;
pSoldier->aiData.ubPendingActionAnimCount = 0;
// WALK UP TO DEST FIRST
pSoldier->EVENT_InternalGetNewSoldierPath( sActionGridNo, pSoldier->usUIMovementMode, FALSE, TRUE );
}
else
{
pSoldier->EVENT_SoldierBuildStructure( sAdjustedGridNo, ubDirection );
}
// OK, set UI
SetUIBusy( pSoldier->ubID );
if ( fFromUI )
{
guiPendingOverrideEvent = A_CHANGE_TO_MOVE;
}
return( ITEM_HANDLE_OK );
}
else
{
return( ITEM_HANDLE_NOAPS );
}
}
else
{
return( ITEM_HANDLE_CANNOT_GETTO_LOCATION );
}
}
if ( Item[usHandItem].canandstring )
{
STRUCTURE *pStructure;
@@ -5907,3 +5981,214 @@ void SoldierStealItemFromSoldier( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent,
gsTempGridNo = sGridNo;
SetCustomizableTimerCallbackAndDelay( 1000, CheckForPickedOwnership, TRUE );
}
extern UINT8 NumEnemiesInAnySector( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ );
BOOLEAN BuildFortification( UINT32 flag )
{
INT32 sGridNo;
UINT32 fHeadType;
UINT16 usUseIndex;
UINT16 usUseObjIndex = 0;
INT32 iRandSelIndex = 1;
BOOLEAN fOkayToAdd;
UINT8 ubDirection;
if ( gusSelectedSoldier == NOBODY )
return FALSE;
if( (gTacticalStatus.uiFlags & INCOMBAT) && (gTacticalStatus.uiFlags & TURNBASED) )
{
return FALSE;
}
/* // comment this in to forbid building while enemies are around
if( gWorldSectorX != -1 && gWorldSectorY != -1 && gWorldSectorX != 0 && gWorldSectorY != 0 &&
NumEnemiesInAnySector( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) > 0 )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Cannot build while enemies are in this sector" );
return FALSE;
}*/
if( gbWorldSectorZ > 0 || gsInterfaceLevel > 0)
{
return FALSE;
}
GetMouseMapPos( &sGridNo );
if( InARoom( sGridNo, NULL ) )
return FALSE;
INT8 bOverTerrainType = GetTerrainType( sGridNo );
if( bOverTerrainType == MED_WATER || bOverTerrainType == DEEP_WATER || bOverTerrainType == LOW_WATER )
return FALSE;
UINT16 CurrentStruct = NO_TILE;
if ( sGridNo < 0x80000000 )
{
ubDirection = MercPtrs[ gusSelectedSoldier ]->ubDirection;
if ( (flag & CONCERTINA) != 0 )
{
// concertina wire
switch ( ubDirection )
{
case NORTH:
case SOUTH:
usUseIndex = 2 + 2*Random(2);
break;
case WEST:
case EAST:
usUseIndex = 3 + 2*Random(2);
break;
case NORTHEAST:
usUseIndex = 9;
break;
case SOUTHWEST:
usUseIndex = 8;
break;
case NORTHWEST:
usUseIndex = 7;
break;
case SOUTHEAST:
default:
usUseIndex = 6;
break;
}
}
else
{
// sandbags
switch ( ubDirection )
{
case NORTH:
case SOUTH:
usUseIndex = 3 + Random(2);
break;
case WEST:
case EAST:
usUseIndex = 8 + Random(2);
break;
case NORTHEAST:
case SOUTHWEST:
case NORTHWEST:
case SOUTHEAST:
default:
usUseIndex = 5;
break;
}
//usUseObjIndex = (UINT16)THIRDOSTRUCT;//SelOStructs2[ iRandSelIndex ].uiObject;
}
// search wether structure exists in the current tilesets. If not, well, too bad
UINT32 uiType = 0;
for(uiType = 0; uiType < giNumberOfTileTypes; ++uiType)
{
if( gTilesets[ giCurrentTilesetID ].TileSurfaceFilenames[ uiType ][0] )
{
if( (flag & CONCERTINA) != 0 )
{
if ( (_strnicmp(gTilesets[ giCurrentTilesetID ].TileSurfaceFilenames[ uiType ], "spot_1.sti", 10) == 0) )
{
usUseObjIndex = uiType;
break;
}
}
else if( (_strnicmp(gTilesets[ giCurrentTilesetID ].TileSurfaceFilenames[ uiType ], "sandbag.sti", 11) == 0) )
{
usUseObjIndex = uiType;
break;
}
}
}
if ( !usUseObjIndex )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"The selected barricade cannot be built in this sector" );
return FALSE;
}
// Check with Structure Database (aka ODB) if we can put the object here!
fOkayToAdd = OkayToAddStructureToWorld( sGridNo, 0, gTileDatabase[ (gTileTypeStartIndex[ usUseObjIndex ] + usUseIndex) ].pDBStructureRef, INVALID_STRUCTURE_ID );
if ( fOkayToAdd || (gTileDatabase[ (gTileTypeStartIndex[ usUseObjIndex ] + usUseIndex) ].pDBStructureRef == NULL) )
{
// Remove old graphic
ApplyMapChangesToMapTempFile( TRUE );
//dnl Remove existing structure before adding the same, seems to solve problem with stacking but still need test to be sure that is not removed something what should stay
RemoveStruct( sGridNo, (UINT16)(gTileTypeStartIndex[ usUseObjIndex ] + usUseIndex) );//dnl
// Actual structure info is added by the functions below
AddStructToHead( sGridNo, (UINT16)(gTileTypeStartIndex[ usUseObjIndex ] + usUseIndex) );
// For now, adjust to shadows by a hard-coded amount,
// Add mask if in long grass
GetLandHeadType( sGridNo, &fHeadType );
RecompileLocalMovementCosts(sGridNo);
// Turn off permanent changes....
ApplyMapChangesToMapTempFile( FALSE );
SetRenderFlags( RENDER_FLAG_FULL );
return TRUE;
}
}
else if ( CurrentStruct == ERASE_TILE && sGridNo < 0x80000000 )
{
RemoveAllStructsOfTypeRange( sGridNo, FIRSTOSTRUCT, LASTOSTRUCT );
RemoveAllShadowsOfTypeRange( sGridNo, FIRSTSHADOW, LASTSHADOW );
}
return FALSE;
}
BOOLEAN RemoveFortification( INT32 sGridNo )
{
STRUCTURE* pStruct = FindStructure(sGridNo, STRUCTURE_GENERIC);
if ( pStruct != NULL )
{
// Get LEVELNODE for struct and remove!
LEVELNODE* pNode = FindLevelNodeBasedOnStructure( pStruct->sGridNo, pStruct );
if ( pNode )
{
UINT32 uiTileType = 0;
if ( GetTileType( pNode->usIndex, &uiTileType ) )
{
UINT16 usIndex = pNode->usIndex;
// Check if we are a sandbag
if ( _strnicmp( gTilesets[ giCurrentTilesetID ].TileSurfaceFilenames[ uiTileType ], "sandbag.sti", 11) == 0 )
{
// Remove old graphic
ApplyMapChangesToMapTempFile( TRUE );
RemoveStruct( sGridNo, pNode->usIndex );
if ( !GridNoIndoors( sGridNo ) && gTileDatabase[ usIndex ].uiFlags & HAS_SHADOW_BUDDY && gTileDatabase[ usIndex ].sBuddyNum != -1 )
{
RemoveShadow( sGridNo, gTileDatabase[ usIndex ].sBuddyNum );
}
// Add mask if in long grass
UINT32 fHeadType = 0;
GetLandHeadType( sGridNo, &fHeadType );
RecompileLocalMovementCosts(sGridNo);
// Turn off permanent changes....
ApplyMapChangesToMapTempFile( FALSE );
SetRenderFlags( RENDER_FLAG_FULL );
return TRUE;
}
}
}
}
return FALSE;
}
+3
View File
@@ -175,6 +175,9 @@ 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 RemoveFortification( INT32 sGridNo );
extern ITEM_POOL *gpItemPool;//dnl ch26 210909
#endif
+57
View File
@@ -4117,6 +4117,24 @@ INT8 DrawUIMovementPath( SOLDIERTYPE *pSoldier, INT32 usMapPos, UINT32 uiFlags )
gsUIHandleShowMoveGridLocation = sActionGridNo;
}
}
else if ( uiFlags == MOVEUI_TARGET_FORTIFICATION )
{
sActionGridNo = FindAdjacentGridEx( pSoldier, usMapPos, &ubDirection, NULL, FALSE, TRUE );
if ( sActionGridNo == -1 )
{
sActionGridNo = usMapPos;
}
sAPCost = GetAPsToBuildFortification( pSoldier, sActionGridNo );
sAPCost += UIPlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints);
if ( sActionGridNo != pSoldier->sGridNo )
{
gfUIHandleShowMoveGrid = TRUE;
gsUIHandleShowMoveGridLocation = sActionGridNo;
}
}
else if ( uiFlags == MOVEUI_TARGET_MERCS )
{
INT32 sGotLocation = NOWHERE;
@@ -4423,6 +4441,45 @@ BOOLEAN UIMouseOnValidAttackLocation( SOLDIERTYPE *pSoldier )
}
}
if ( ubItemCursor == FORTICURS )
{
if ( gfUIFullTargetFound )
{
usMapPos = MercPtrs[ gusUIFullTargetID ]->sGridNo;
}
if ( pSoldier->pathing.bLevel == 0 )
{
if ( IsFortificationPossibleAtGridNo( usMapPos, NULL ) )
{
return( TRUE );
}
if ( HasItemFlag( (&(pSoldier->inv[HANDPOS]))->usItem, (EMPTY_SANDBAG)) )
{
// check if we have a shovel in our second hand
OBJECTTYPE* pShovelObj = &(pSoldier->inv[SECONDHANDPOS]);
if ( !pShovelObj || !(pShovelObj->exists()) || !HasItemFlag(pSoldier->inv[ SECONDHANDPOS ].usItem, (SHOVEL)) )
{
return( TRUE );
}
}
if ( HasItemFlag( (&(pSoldier->inv[HANDPOS]))->usItem, (SHOVEL)) )
{
STRUCTURE* pStruct = FindStructure(usMapPos, STRUCTURE_GENERIC);
if ( pStruct )
{
return( TRUE );
}
}
}
return( FALSE );
}
if ( ubItemCursor == BOMBCURS )
{
if ( usMapPos == pSoldier->sGridNo )
+1
View File
@@ -29,6 +29,7 @@
#define MOVEUI_TARGET_JAR 10
#define MOVEUI_TARGET_CAN 11
#define MOVEUI_TARGET_REFUEL 12
#define MOVEUI_TARGET_FORTIFICATION 13
#define MOVEUI_RETURN_ON_TARGET_MERC 1
+3
View File
@@ -212,6 +212,9 @@ UICursor gUICursors[ NUM_UI_CURSORS ] =
REFUEL_GREY_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_FUEL, 0,
REFUEL_RED_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_FUEL_RED, 0,
FORTIFICATION_GREY_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_FORTIFICATION, 0,
FORTIFICATION_RED_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_FORTIFICATION_RED, 0,
};
+3
View File
@@ -186,6 +186,9 @@ typedef enum
REFUEL_GREY_UICURSOR,
REFUEL_RED_UICURSOR,
FORTIFICATION_GREY_UICURSOR,
FORTIFICATION_RED_UICURSOR,
NUM_UI_CURSORS
} UICursorDefines;
+47
View File
@@ -173,6 +173,7 @@ typedef enum ATTACHMENT_SLOT{
#define JARCURS 21
#define TINCANCURS 22
#define REFUELCURS 23
#define FORTICURS 24
#define CAMERARANGE 10
@@ -708,6 +709,50 @@ extern OBJECTTYPE gTempObject;
#define PLAYER_NET_4_LVL_4 0x80000000 //2147483648
// ----------------------------------------------------------------
// -------- added by Flugente: various item flags --------
// flags used for various item properties (easier than adding 32 differently named variables). DO NOT CHANGE THEM, UNLESS YOU KNOW WHAT YOU ARE DOING!!!
// note that these should not be used to determine what kind of an attachment an item is, that is determined by attachmentclass and the AC_xxx flags above
#define EMPTY_SANDBAG 0x00000001 //1
#define FULL_SANDBAG 0x00000002 //2
#define SHOVEL 0x00000004 //4
#define CONCERTINA 0x00000008 //8
/*#define WH40K_POWER_ARMOR 0x00000010 //16
#define WH40K_POWER_PACK 0x00000020 //32
#define WH40K_JUMPPACK 0x00000040 //64
#define WH40K_DISPLACER 0x00000080 //128
#define WH40K_ROSARIUS 0x00000100 //256
#define WH40K_SEAL 0x00000200 //512
#define WH40K_POWER_WEAPON 0x00000400 //1024
#define ENEMY_NET_4_LVL_3 0x00000800 //2048
#define ENEMY_NET_1_LVL_4 0x00001000 //4096
#define ENEMY_NET_2_LVL_4 0x00002000 //8192
#define ENEMY_NET_3_LVL_4 0x00004000 //16384
#define ENEMY_NET_4_LVL_4 0x00008000 //32768
#define PLAYER_NET_1_LVL_1 0x00010000 //65536
#define PLAYER_NET_2_LVL_1 0x00020000 //131072
#define PLAYER_NET_3_LVL_1 0x00040000 //262144
#define PLAYER_NET_4_LVL_1 0x00080000 //524288
#define PLAYER_NET_1_LVL_2 0x00100000 //1048576
#define PLAYER_NET_2_LVL_2 0x00200000 //2097152
#define PLAYER_NET_3_LVL_2 0x00400000 //4194304
#define PLAYER_NET_4_LVL_2 0x00800000 //8388608
#define PLAYER_NET_1_LVL_3 0x01000000 //16777216
#define PLAYER_NET_2_LVL_3 0x02000000 //33554432
#define PLAYER_NET_3_LVL_3 0x04000000 //67108864
#define PLAYER_NET_4_LVL_3 0x08000000 //134217728
#define PLAYER_NET_1_LVL_4 0x10000000 //268435456
#define PLAYER_NET_2_LVL_4 0x20000000 //536870912
#define PLAYER_NET_3_LVL_4 0x40000000 //1073741824
#define PLAYER_NET_4_LVL_4 0x80000000 //2147483648*/
// ----------------------------------------------------------------
// replaces candamage
//#define ITEM_DAMAGEABLE 0x0001
//// replaces canrepair
@@ -962,6 +1007,8 @@ typedef struct
// Flugente poison system
INT16 bPoisonPercentage;
UINT32 usItemFlag; // bitflags to store various item properties (better than introducing 32 BOOLEAN values). If I only had thought of this earlier....
} INVTYPE;
// CHRISL: Added new structures to handle LBE gear and the two new XML files that will be needed to deal
+6
View File
@@ -13938,3 +13938,9 @@ void CheckBombSpecifics( OBJECTTYPE * pObj, INT8* detonatortype, INT8* setting,
*defusefrequency = (*pObj)[0]->data.bDefuseFrequency;
}
}
// Flugente: check for specific flags
BOOLEAN HasItemFlag( UINT16 usItem, UINT32 aFlag )
{
return( (Item[usItem].usItemFlag & aFlag) != 0 );
}
+3
View File
@@ -462,4 +462,7 @@ UINT64 GetAvailableAttachmentPoint ( OBJECTTYPE * pObject, UINT8 subObject );
// Flugente: check if and how a bomb has been set up
void CheckBombSpecifics( OBJECTTYPE * pObj, INT8* detonatortype, INT8* setting, INT8* defusefrequency );
// Flugente: check for specific flags
BOOLEAN HasItemFlag( UINT16 usItem, UINT32 aFlag );
#endif
+5
View File
@@ -1649,6 +1649,11 @@ BOOLEAN ExecuteOverhead( )
pSoldier->EVENT_SoldierBeginCutFence( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 );
pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION;
}
else if ( pSoldier->aiData.ubPendingAction == MERC_BUILD_FORTIFICATION )
{
pSoldier->EVENT_SoldierBuildStructure( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 );
pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION;
}
else if ( pSoldier->aiData.ubPendingAction == MERC_GIVEITEM )
{
pSoldier->EVENT_SoldierBeginGiveItem( );
+17
View File
@@ -3476,6 +3476,23 @@ 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 );
// If point cost is zero, return 0
if ( sAPCost != 0 )
{
// ADD APS TO PICKUP
sAPCost += APBPConstants[AP_FORTIFICATION];
}
return sAPCost;
}
INT16 GetAPsToJumpOver( SOLDIERTYPE *pSoldier )
{
+2
View File
@@ -356,6 +356,8 @@ 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 GetAPsToJumpOver( SOLDIERTYPE *pSoldier );
void GetAPChargeForShootOrStabWRTGunRaises( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTurningCost, BOOLEAN *pfChargeTurning, BOOLEAN *pfChargeRaise );
+2
View File
@@ -2143,6 +2143,8 @@ void RaiseZombies( void )
if ( zombieshaverisen )
{
SetRenderFlags( RENDER_FLAG_FULL );
#ifdef JA2TESTVERSION
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"A wave of zombies is created");
#endif
+103 -1
View File
@@ -13403,7 +13403,12 @@ INT32 SOLDIERTYPE::GetDamageResistance(BOOLEAN fAutoResolve, BOOLEAN fCalcBreath
else if (this->ubSoldierClass == SOLDIER_CLASS_ELITE && gGameExternalOptions.sEnemyEliteDamageResistance != 0)
resistance += gGameExternalOptions.sEnemyEliteDamageResistance;
else if (IsZombie())
resistance += gGameExternalOptions.sEnemyZombieDamageResistance;
{
if ( fCalcBreathLoss )
resistance += gGameExternalOptions.sEnemyZombieBreathDamageResistance;
else
resistance += gGameExternalOptions.sEnemyZombieDamageResistance;
}
}
//////////////////////////////////////////////////////////////////////////////////////
@@ -14370,6 +14375,103 @@ void SOLDIERTYPE::EVENT_SoldierBeginAttachCan( INT32 sGridNo, UINT8 ubDirection
}
void SOLDIERTYPE::EVENT_SoldierBuildStructure( INT32 sGridNo, UINT8 ubDirection )
{
BOOLEAN fSuccess = FALSE;
// do checks here...
OBJECTTYPE* pObj = &(this->inv[HANDPOS]);
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 );
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]) );
// we gain a bit of experience...
StatChange( this, STRAMT, 4, TRUE );
StatChange( this, HEALTHAMT, 2, TRUE );
fSuccess = TRUE;
}
}
else if ( HasItemFlag(this->inv[ HANDPOS ].usItem, (EMPTY_SANDBAG)) )
{
INT8 bOverTerrainType = GetTerrainType( sGridNo );
if( bOverTerrainType == FLAT_GROUND || bOverTerrainType == DIRT_ROAD || bOverTerrainType == LOW_GRASS )
{
// 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)) )
{
// test: does there an item that is a filled sandbag exist? (xmls might have changed)
UINT16 fullsandbagnr = 1541;
if ( HasItemFlag(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 );
fSuccess = TRUE;
}
}
}
}
else if ( HasItemFlag(this->inv[ HANDPOS ].usItem, (SHOVEL)) )
{
// Build the thing
if ( RemoveFortification( sGridNo ) )
{
// test: does there an item that is a filled sandbag exist? (xmls might have changed)
UINT16 fullsandbagnr = 1541;
if ( HasItemFlag(fullsandbagnr, FULL_SANDBAG) )
{
// Erase 'material' item from our hand - we 'used' it to build the structure
INT8 bObjSlot = HANDPOS;
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 );
fSuccess = TRUE;
}
}
}
}
if ( !fSuccess )
{
// Say NOTHING quote...
this->DoMercBattleSound( BATTLE_SOUND_NOTHING );
}
}
void SOLDIERTYPE::EVENT_SoldierBeginReloadRobot( INT32 sGridNo, UINT8 ubDirection, UINT8 ubMercSlot )
{
UINT8 ubPerson;
+3
View File
@@ -220,6 +220,7 @@ enum
MERC_TAKEBLOOD,
MERC_ATTACH_CAN,
MERC_FUEL_VEHICLE,
MERC_BUILD_FORTIFICATION,
};
// ENUMERATIONS FOR THROW ACTIONS
@@ -1240,6 +1241,8 @@ public:
void EVENT_SoldierBeginAttachCan( INT32 sGridNo, UINT8 ubDirection );
void EVENT_BeginMercTurn( BOOLEAN fFromRealTime, INT32 iRealTimeCounter );
void EVENT_SoldierBuildStructure( INT32 sGridNo, UINT8 ubDirection ); // added by Flugente
BOOLEAN EVENT_InternalGetNewSoldierPath( INT32 sDestGridNo, UINT16 usMovementAnim, BOOLEAN fFromUI, BOOLEAN fForceRestart );
void EVENT_InternalSetSoldierDestination( UINT16 usNewDirection, BOOLEAN fFromMove, UINT16 usAnimState );
void EVENT_InternalSetSoldierPosition( FLOAT dNewXPos, FLOAT dNewYPos ,BOOLEAN fUpdateDest, BOOLEAN fUpdateFinalDest, BOOLEAN fForceDelete );
+16
View File
@@ -564,6 +564,22 @@ BOOLEAN IsRefuelableStructAtGridNo( INT32 sGridNo, UINT8 *pubID )
}
// Flugente: determine wether a fortification can be built on this position
BOOLEAN IsFortificationPossibleAtGridNo( INT32 sGridNo, UINT8 *pubID )
{
GetMouseMapPos( &sGridNo );
INT8 bOverTerrainType = GetTerrainType( sGridNo );
if( bOverTerrainType == MED_WATER || bOverTerrainType == DEEP_WATER || bOverTerrainType == LOW_WATER )
return FALSE;
STRUCTURE * pStructure = NULL;
pStructure = FindStructure( sGridNo, (STRUCTURE_OBSTACLE) );
return( pStructure == NULL );
}
BOOLEAN IsCutWireFenceAtGridNo( INT32 sGridNo )
{
+1
View File
@@ -38,6 +38,7 @@ BOOLEAN IsCutWireFenceAtGridNo( INT32 sGridNo );
BOOLEAN IsRepairableStructAtGridNo( INT32 sGridNo, UINT8 *pubID );
BOOLEAN IsRefuelableStructAtGridNo( INT32 sGridNo, UINT8 *pubID );
BOOLEAN IsFortificationPossibleAtGridNo( INT32 sGridNo, UINT8 *pubID ); // added by Flugente
BOOLEAN IsRoofPresentAtGridNo( INT32 sGridNo );
+4 -1
View File
@@ -4440,7 +4440,10 @@ void GetKeyboardInput( UINT32 *puiNewEvent )
}
else
{
SetScopeMode();
INT32 sGridNo = 0;
GetMouseMapPos( &sGridNo );
RemoveFortification( sGridNo );
//SetScopeMode();
}
break;
+49
View File
@@ -53,6 +53,7 @@ UINT8 HandleRemoteCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, BOOLEAN fActivat
UINT8 HandleBombCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, BOOLEAN fActivated, UINT32 uiCursorFlags );
UINT8 HandleJarCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCursorFlags );
UINT8 HandleTinCanCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCursorFlags );
UINT8 HandleFortificationCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCursorFlags ); //added by Flugente
extern BOOLEAN HandleCheckForBadChangeToGetThrough( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pTargetSoldier, INT32 sTargetGridNo , INT8 bLevel );
@@ -298,6 +299,11 @@ UINT8 GetProperItemCursor( UINT8 ubSoldierID, UINT16 ubItemIndex, INT32 usMapPos
ubCursorID = HandleRefuelCursor( pSoldier, sTargetGridNo, uiCursorFlags );
break;
case FORTICURS:
ubCursorID = HandleFortificationCursor( pSoldier, sTargetGridNo, uiCursorFlags );
break;
case INVALIDCURS:
ubCursorID = INVALID_ACTION_UICURSOR;
@@ -2138,6 +2144,45 @@ UINT8 HandleBombCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, BOOLEAN fActivated
}
}
UINT8 HandleFortificationCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCursorFlags )
{
// DRAW PATH TO GUY
HandleUIMovementCursor( pSoldier, uiCursorFlags, sGridNo, MOVEUI_TARGET_FORTIFICATION );
if ( pSoldier->pathing.bLevel != 0 )
return( FORTIFICATION_RED_UICURSOR );
// 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( (&(pSoldier->inv[HANDPOS]))->usItem, (EMPTY_SANDBAG)) )
{
// check if we have a shovel in our second hand
OBJECTTYPE* pShovelObj = &(pSoldier->inv[SECONDHANDPOS]);
if ( !pShovelObj || !(pShovelObj->exists()) || !HasItemFlag(pSoldier->inv[ SECONDHANDPOS ].usItem, (SHOVEL)) )
{
return( FORTIFICATION_RED_UICURSOR );
}
}
if ( HasItemFlag( (&(pSoldier->inv[HANDPOS]))->usItem, (SHOVEL)) )
{
STRUCTURE* pStruct = FindStructure(sGridNo, STRUCTURE_GENERIC);
if ( pStruct )
{
return( FORTIFICATION_GREY_UICURSOR );
}
}
// can we build something here?
if ( IsFortificationPossibleAtGridNo( sGridNo, NULL ) && pSoldier->pathing.bLevel == 0 )
{
return( FORTIFICATION_GREY_UICURSOR );
}
return( FORTIFICATION_RED_UICURSOR );
}
void HandleEndConfirmCursor( SOLDIERTYPE *pSoldier )
@@ -2596,6 +2641,10 @@ UINT8 GetActionModeCursor( SOLDIERTYPE *pSoldier )
}
}
// Flugente: cursor for building fortifications
if ( HasItemFlag(usInHand, (EMPTY_SANDBAG|FULL_SANDBAG|SHOVEL|CONCERTINA)) )
ubCursor = FORTICURS;
// Now check our terrain to see if we cannot do the action now...
if ( WaterTooDeepForAttacks( pSoldier->sGridNo) )
{
+25
View File
@@ -118,6 +118,10 @@ CursorFileData CursorFileDatabase[] =
{ "CURSORS\\cur_swit.sti" , FALSE, 0, 0, 0, NULL },
{ "CURSORS\\bullseye.sti" , FALSE, 0, 0, 0, NULL },
{ "CURSORS\\deadleap.sti" , FALSE, 0, 0, 0, NULL },
{ "CURSORS\\hammer.sti" , FALSE, 0, ANIMATED_CURSOR, 3, NULL }, // Flugente: fortification stuff
{ "CURSORS\\hammer_r.sti" , FALSE, 0, ANIMATED_CURSOR, 3, NULL },
{ "CURSORS\\can_01.sti" , FALSE, 0, 0, 0, NULL },
{ "CURSORS\\can_02.sti" , FALSE, 0, 0, 0, NULL },
{ "CURSORS\\cur_tagr_ncth.sti" , FALSE, 0, ANIMATED_CURSOR, 7, NULL },
@@ -1178,6 +1182,27 @@ CursorData CursorDatabase[] =
0, 0, 0, 0, 0,
2, CENTER_CURSOR, CENTER_CURSOR , 0, 0 , 0, 0 },
/*{ C_TRINGS, 6, 0, HIDE_SUBCURSOR, HIDE_SUBCURSOR,
C_FORTIFICATION , 0, 0, CENTER_SUBCURSOR, CENTER_SUBCURSOR,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
2, CENTER_CURSOR, CENTER_CURSOR, 0, 0 , 0, 0 },*/
{ C_TRINGS, 6, 0, HIDE_SUBCURSOR, HIDE_SUBCURSOR,
C_FORTIFICATION , 0, 0, CENTER_SUBCURSOR, CENTER_SUBCURSOR,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
2, CENTER_CURSOR, CENTER_CURSOR, 0, 0 , 0, 0 },
{ C_TRINGS, 6, 0, HIDE_SUBCURSOR, HIDE_SUBCURSOR,
C_FORTIFICATION_RED , 0, 0, CENTER_SUBCURSOR, CENTER_SUBCURSOR,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
2, CENTER_CURSOR, CENTER_CURSOR, 0, 0 , 0, 0 },
{ C_TRINGS, 6, 0, HIDE_SUBCURSOR, HIDE_SUBCURSOR,
C_FUEL , 0, 0, CENTER_SUBCURSOR, CENTER_SUBCURSOR,
0, 0, 0, 0, 0,
+6
View File
@@ -152,6 +152,10 @@ typedef enum
CURSOR_STRATEGIC_BULLSEYE,
CURSOR_JUMP_OVER,
CURSOR_FORTIFICATION,
CURSOR_FORTIFICATION_RED,
CURSOR_FUEL,
CURSOR_FUEL_RED,
@@ -225,6 +229,8 @@ typedef enum
C_EXCHANGE,
C_BULLSEYE,
C_JUMPOVER,
C_FORTIFICATION,
C_FORTIFICATION_RED,
C_FUEL,
C_FUEL_RED,
C_ACTIONMODERED_NCTH,
+8 -2
View File
@@ -265,8 +265,8 @@ itemStartElementHandle(void *userData, const XML_Char *name, const XML_Char **at
strcmp(name, "Directional") == 0 ||
strcmp(name, "DrugType") == 0 ||
strcmp(name, "BlockIronSight") == 0 ||
// Flugente: poison system
strcmp(name, "PoisonPercentage") == 0 ||
strcmp(name, "ItemFlag") == 0 ||
strcmp(name, "fFlags") == 0 ))
{
@@ -1333,12 +1333,16 @@ itemEndElementHandle(void *userData, const XML_Char *name)
pData->curElement = ELEMENT;
pData->curItem.blockironsight = (BOOLEAN) atol(pData->szCharData);
}
// Flugente poison system
else if(strcmp(name, "PoisonPercentage") == 0)
{
pData->curElement = ELEMENT;
pData->curItem.bPoisonPercentage = (INT16) atol(pData->szCharData);
}
else if(strcmp(name, "ItemFlag") == 0)
{
pData->curElement = ELEMENT;
pData->curItem.usItemFlag = (UINT32) atol(pData->szCharData);
}
pData->maxReadDepth--;
@@ -1954,6 +1958,8 @@ BOOLEAN WriteItemStats()
FilePrintf(hFile,"\t\t<DrugType>%d</DrugType>\r\n", Item[cnt].drugtype );
FilePrintf(hFile,"\t\t<BlockIronSight>%d</BlockIronSight>\r\n", Item[cnt].blockironsight );
FilePrintf(hFile,"\t\t<ItemFlag>%d</ItemFlag>\r\n", Item[cnt].usItemFlag );
// Flugente poison system
FilePrintf(hFile,"\t\t<PoisonPercentage>%d</PoisonPercentage>\r\n", Item[cnt].bPoisonPercentage );