mirror of
https://github.com/1dot13/source.git
synced 2026-07-29 13:52:17 +02:00
Feature improvement:
- via StructureConstruct.xml and StructureDeconstruct.xml, one can now define which structures can be removed and created via items and the fortifications feature. For more information, see http://www.ja-galaxy-forum.com/ubbthreads.php/topics/335557#Post335557 does not break savegame compatibility. Requires GameDir >= r2140. git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@7491 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
@@ -373,6 +373,14 @@ BOOLEAN LoadExternalGameplayData(STR directoryName)
|
||||
strcat( fileName, DISEASEFILENAME );
|
||||
SGP_THROW_IFFALSE( ReadInDiseaseStats( fileName ), DISEASEFILENAME );
|
||||
|
||||
strcpy(fileName, directoryName);
|
||||
strcat(fileName, STRUCTUREDECONSTRUCTFILENAME);
|
||||
SGP_THROW_IFFALSE(ReadInStructureDeconstructStats(fileName),STRUCTUREDECONSTRUCTFILENAME);
|
||||
|
||||
strcpy(fileName, directoryName);
|
||||
strcat(fileName, STRUCTURECONSTRUCTFILENAME);
|
||||
SGP_THROW_IFFALSE(ReadInStructureConstructStats(fileName),STRUCTURECONSTRUCTFILENAME);
|
||||
|
||||
strcpy(fileName, directoryName);
|
||||
strcat(fileName, MERCHANTSFILENAME);
|
||||
SGP_THROW_IFFALSE(ReadInMerchantStats(fileName),MERCHANTSFILENAME);
|
||||
|
||||
+279
-158
@@ -86,6 +86,9 @@ UINT8 gubLastTripwire = 0;
|
||||
// set to TRUE if shift+click was pressed for planting bomb - will use for Improved Bomb Planting feature
|
||||
BOOLEAN gfShiftBombPlant = FALSE;
|
||||
|
||||
// Flugente: (de-)construct structures
|
||||
STRUCTURE_DECONSTRUCT gStructureDeconstruct[STRUCTURE_DECONSTRUCT_MAX];
|
||||
STRUCTURE_CONSTRUCT gStructureConstruct[STRUCTURE_CONSTRUCT_MAX];
|
||||
|
||||
LEVELNODE *AddItemGraphicToWorld( INVTYPE *pItem, INT32 sGridNo, UINT8 ubLevel );
|
||||
INT8 GetListMouseHotSpot( INT16 sLargestLineWidth, INT8 bNumItemsListed, INT16 sFontX, INT16 sFontY, INT8 bCurStart );
|
||||
@@ -1148,14 +1151,21 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
|
||||
}
|
||||
}
|
||||
|
||||
// Flugente: sandbag stuff
|
||||
if ( HasItemFlag(usHandItem, (EMPTY_SANDBAG|FULL_SANDBAG|SHOVEL|CONCERTINA)) )
|
||||
// Flugente: (de-)construct structures
|
||||
if ( HasItemFlag( usHandItem, EMPTY_SANDBAG ) || IsStructureDeconstructItem( usHandItem, sGridNo, pSoldier ) || IsStructureConstructItem( usHandItem, sGridNo, pSoldier ) )
|
||||
{
|
||||
// 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)) )
|
||||
if ( HasItemFlag(usHandItem, EMPTY_SANDBAG) )
|
||||
{
|
||||
sAPCost = GetAPsForMultiTurnAction( pSoldier, MTA_FILL_SANDBAG );
|
||||
|
||||
// we can only do this on certain terraintypes
|
||||
INT8 bOverTerrainType = GetTerrainType( sGridNo );
|
||||
if ( bOverTerrainType != FLAT_GROUND && bOverTerrainType != DIRT_ROAD && bOverTerrainType != LOW_GRASS )
|
||||
{
|
||||
return(ITEM_HANDLE_REFUSAL);
|
||||
}
|
||||
|
||||
// check if we have a shovel in our second hand
|
||||
OBJECTTYPE* pShovelObj = &(pSoldier->inv[SECONDHANDPOS]);
|
||||
|
||||
@@ -1163,39 +1173,40 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
|
||||
{
|
||||
return( ITEM_HANDLE_REFUSAL );
|
||||
}
|
||||
|
||||
// we can only do this on certain terraintypes
|
||||
INT8 bOverTerrainType = GetTerrainType( sGridNo );
|
||||
if( bOverTerrainType != FLAT_GROUND && bOverTerrainType != DIRT_ROAD && bOverTerrainType != LOW_GRASS )
|
||||
{
|
||||
return( ITEM_HANDLE_REFUSAL );
|
||||
}
|
||||
}
|
||||
// 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 = GetAPsForMultiTurnAction( pSoldier, MTA_REMOVE_FORTIFY );
|
||||
|
||||
STRUCTURE* pStruct = FindStructure(sGridNo, STRUCTURE_GENERIC);
|
||||
|
||||
if ( !pStruct )
|
||||
{
|
||||
return( ITEM_HANDLE_REFUSAL );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sAPCost = GetAPsForMultiTurnAction( pSoldier, MTA_FORTIFY );
|
||||
// if there is a structure, see if we can deconstruct it, if not, see if we can construct something
|
||||
STRUCTURE* pStruct = FindStructure( sGridNo, (STRUCTURE_GENERIC | STRUCTURE_WIREFENCE) );
|
||||
|
||||
if ( pStruct )
|
||||
{
|
||||
if ( !IsStructureDeconstructItem( usHandItem, sGridNo, pSoldier ) )
|
||||
return(ITEM_HANDLE_REFUSAL);
|
||||
|
||||
sAPCost = GetAPsForMultiTurnAction( pSoldier, MTA_REMOVE_FORTIFY );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !IsStructureConstructItem( usHandItem, sGridNo, pSoldier ) )
|
||||
return(ITEM_HANDLE_REFUSAL);
|
||||
|
||||
sAPCost = GetAPsForMultiTurnAction( pSoldier, MTA_FORTIFY );
|
||||
}
|
||||
}
|
||||
|
||||
sActionGridNo = FindAdjacentGridEx( pSoldier, sGridNo, &ubDirection, &sAdjustedGridNo, TRUE, FALSE );
|
||||
// we are at pSoldier->sGridNo and the action takes place at sGridNo
|
||||
// we need to find out in which direction we need to look
|
||||
// sActionGridNo is the gridno we are supposed to sit
|
||||
ubDirection = GetDirectionToGridNoFromGridNo( sGridNo, pSoldier->sGridNo );
|
||||
|
||||
sActionGridNo = FindAdjacentGridEx( pSoldier, sGridNo, &ubDirection, &sAdjustedGridNo, FALSE, FALSE );
|
||||
|
||||
if ( sActionGridNo != -1 )
|
||||
if ( !TileIsOutOfBounds( sActionGridNo ) )
|
||||
{
|
||||
// Calculate AP costs...
|
||||
sAPCost += PlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, FALSE, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints);
|
||||
sAPCost += PlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, FALSE, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints );
|
||||
|
||||
//if ( EnoughPoints( pSoldier, sAPCost, 0, fFromUI ) )
|
||||
if ( pSoldier->bActionPoints > 0 )
|
||||
{
|
||||
// CHECK IF WE ARE AT THIS GRIDNO NOW
|
||||
@@ -1203,7 +1214,7 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
|
||||
{
|
||||
// SEND PENDING ACTION
|
||||
pSoldier->aiData.ubPendingAction = MERC_BUILD_FORTIFICATION;
|
||||
pSoldier->aiData.sPendingActionData2 = sAdjustedGridNo;
|
||||
pSoldier->aiData.sPendingActionData2 = sGridNo;
|
||||
pSoldier->aiData.bPendingActionData3 = ubDirection;
|
||||
pSoldier->aiData.ubPendingActionAnimCount = 0;
|
||||
|
||||
@@ -1212,7 +1223,7 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
|
||||
}
|
||||
else
|
||||
{
|
||||
pSoldier->EVENT_SoldierBuildStructure( sAdjustedGridNo, ubDirection );
|
||||
pSoldier->EVENT_SoldierBuildStructure( sGridNo, ubDirection );
|
||||
}
|
||||
|
||||
// OK, set UI
|
||||
@@ -6693,7 +6704,37 @@ void SoldierStealItemFromSoldier( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent,
|
||||
SetCustomizableTimerCallbackAndDelay( 1000, CheckForPickedOwnership, TRUE );
|
||||
}
|
||||
|
||||
BOOLEAN BuildFortification( INT32 sGridNo, UINT32 flag )
|
||||
// can we construct a structure with this item?
|
||||
BOOLEAN IsStructureConstructItem(UINT16 usItem, INT32 sGridNo, SOLDIERTYPE* pSoldier)
|
||||
{
|
||||
if ( !usItem || TileIsOutOfBounds( sGridNo ) )
|
||||
return FALSE;
|
||||
|
||||
for ( UINT16 i = 0; i < STRUCTURE_CONSTRUCT_MAX; ++i )
|
||||
{
|
||||
if ( usItem == gStructureConstruct[i].usCreationItem )
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// can we remove a structure with this item?
|
||||
BOOLEAN IsStructureDeconstructItem( UINT16 usItem, INT32 sGridNo, SOLDIERTYPE* pSoldier )
|
||||
{
|
||||
if ( !usItem || TileIsOutOfBounds( sGridNo ) )
|
||||
return FALSE;
|
||||
|
||||
for ( UINT16 i = 0; i < STRUCTURE_DECONSTRUCT_MAX; ++i )
|
||||
{
|
||||
if ( usItem == gStructureDeconstruct[i].usDeconstructItem )
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN BuildFortification( INT32 sGridNo, SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj )
|
||||
{
|
||||
UINT32 fHeadType;
|
||||
UINT16 usUseIndex;
|
||||
@@ -6702,146 +6743,202 @@ BOOLEAN BuildFortification( INT32 sGridNo, UINT32 flag )
|
||||
BOOLEAN fOkayToAdd;
|
||||
UINT8 ubDirection;
|
||||
|
||||
if ( gusSelectedSoldier == NOBODY )
|
||||
// we need a valid soldier and a valid object
|
||||
if ( !pSoldier || !pObj )
|
||||
return FALSE;
|
||||
|
||||
if( gbWorldSectorZ > 0 || gsInterfaceLevel > 0)
|
||||
{
|
||||
// no building on roofs
|
||||
if( gsInterfaceLevel > 0 )
|
||||
return FALSE;
|
||||
|
||||
// needs to be a valid location
|
||||
if ( TileIsOutOfBounds( sGridNo ) )
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if( InARoom( sGridNo, NULL ) )
|
||||
return FALSE;
|
||||
//if( InARoom( sGridNo, NULL ) )
|
||||
//return FALSE;
|
||||
|
||||
// don't build in water
|
||||
INT8 bOverTerrainType = GetTerrainType( sGridNo );
|
||||
if( bOverTerrainType == MED_WATER || bOverTerrainType == DEEP_WATER || bOverTerrainType == LOW_WATER )
|
||||
return FALSE;
|
||||
|
||||
UINT16 CurrentStruct = NO_TILE;
|
||||
|
||||
if ( sGridNo < 0x80000000 )
|
||||
ubDirection = pSoldier->ubDirection;
|
||||
|
||||
// we'll check wether this item is in our index of known creation items
|
||||
BOOLEAN indexfound = FALSE;
|
||||
INT16 structureconstructindex = -1;
|
||||
for (UINT16 i = 0; i < STRUCTURE_DECONSTRUCT_MAX; ++i)
|
||||
{
|
||||
ubDirection = MercPtrs[ gusSelectedSoldier ]->ubDirection;
|
||||
if ( indexfound )
|
||||
break;
|
||||
|
||||
if ( (flag & CONCERTINA) != 0 )
|
||||
if ( pObj->usItem == gStructureConstruct[i].usCreationItem )
|
||||
{
|
||||
// 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 ( !gStructureConstruct[i].northtilevector.empty( ) )
|
||||
{
|
||||
if ( (_strnicmp(gTilesets[ giCurrentTilesetID ].TileSurfaceFilenames[ uiType ], "spot_1.sti", 10) == 0) )
|
||||
{
|
||||
usUseObjIndex = uiType;
|
||||
break;
|
||||
}
|
||||
usUseIndex = gStructureConstruct[i].northtilevector[Random( gStructureConstruct[i].northtilevector.size( ) )];
|
||||
structureconstructindex = i;
|
||||
indexfound = TRUE;
|
||||
}
|
||||
else if( (_strnicmp(gTilesets[ giCurrentTilesetID ].TileSurfaceFilenames[ uiType ], "sandbag.sti", 11) == 0) )
|
||||
break;
|
||||
case SOUTH:
|
||||
if ( !gStructureConstruct[i].southtilevector.empty( ) )
|
||||
{
|
||||
usUseIndex = gStructureConstruct[i].southtilevector[Random( gStructureConstruct[i].southtilevector.size( ) )];
|
||||
structureconstructindex = i;
|
||||
indexfound = TRUE;
|
||||
}
|
||||
break;
|
||||
case WEST:
|
||||
if ( !gStructureConstruct[i].westtilevector.empty( ) )
|
||||
{
|
||||
usUseIndex = gStructureConstruct[i].westtilevector[Random( gStructureConstruct[i].westtilevector.size( ) )];
|
||||
structureconstructindex = i;
|
||||
indexfound = TRUE;
|
||||
}
|
||||
break;
|
||||
case EAST:
|
||||
if ( !gStructureConstruct[i].easttilevector.empty( ) )
|
||||
{
|
||||
usUseIndex = gStructureConstruct[i].easttilevector[Random( gStructureConstruct[i].easttilevector.size( ) )];
|
||||
structureconstructindex = i;
|
||||
indexfound = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// for all other directions, just pick one tile, it doesn not matter from which direction
|
||||
if ( !gStructureConstruct[i].northtilevector.empty( ) )
|
||||
{
|
||||
usUseIndex = gStructureConstruct[i].northtilevector[Random( gStructureConstruct[i].northtilevector.size( ) )];
|
||||
structureconstructindex = i;
|
||||
indexfound = TRUE;
|
||||
}
|
||||
|
||||
if ( !indexfound && !gStructureConstruct[i].southtilevector.empty( ) )
|
||||
{
|
||||
usUseIndex = gStructureConstruct[i].southtilevector[Random( gStructureConstruct[i].southtilevector.size( ) )];
|
||||
structureconstructindex = i;
|
||||
indexfound = TRUE;
|
||||
}
|
||||
|
||||
if ( !indexfound && !gStructureConstruct[i].westtilevector.empty( ) )
|
||||
{
|
||||
usUseIndex = gStructureConstruct[i].westtilevector[Random( gStructureConstruct[i].westtilevector.size( ) )];
|
||||
structureconstructindex = i;
|
||||
indexfound = TRUE;
|
||||
}
|
||||
|
||||
if ( !indexfound && !gStructureConstruct[i].easttilevector.empty( ) )
|
||||
{
|
||||
usUseIndex = gStructureConstruct[i].easttilevector[Random( gStructureConstruct[i].easttilevector.size( ) )];
|
||||
structureconstructindex = i;
|
||||
indexfound = TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( structureconstructindex < 0 )
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szMTATextStr[STR_MTA_CANNOT_BUILD] );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// search wether structure exists in the current tilesets. If not, well, too bad
|
||||
for (UINT32 uiType = 0; uiType < giNumberOfTileTypes; ++uiType)
|
||||
{
|
||||
if( gTilesets[ giCurrentTilesetID ].TileSurfaceFilenames[ uiType ][0] )
|
||||
{
|
||||
if ( structureconstructindex >= 0 )
|
||||
{
|
||||
if ( !_strnicmp(gTilesets[ giCurrentTilesetID ].TileSurfaceFilenames[ uiType ], gStructureConstruct[structureconstructindex].szTileSetName, 10) )
|
||||
{
|
||||
usUseObjIndex = uiType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !usUseObjIndex )
|
||||
if ( !usUseObjIndex )
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szMTATextStr[ STR_MTA_CANNOT_BUILD ] );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// consumables are removed on creation
|
||||
if ( structureconstructindex >= 0 && gStructureConstruct[structureconstructindex].usItemStatusLoss )
|
||||
{
|
||||
if ( (*pObj)[0]->data.objectStatus <= gStructureConstruct[structureconstructindex].usItemStatusLoss )
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szMTATextStr[ STR_MTA_CANNOT_BUILD ] );
|
||||
return FALSE;
|
||||
UINT16 usItem = pObj->usItem;
|
||||
|
||||
// Erase 'material' item from our hand - we 'use' it to build the structure
|
||||
DeleteObj( &(pSoldier->inv[HANDPOS]) );
|
||||
|
||||
// sevenfm: auto-taking of items
|
||||
if ( !(gTacticalStatus.uiFlags & TURNBASED && gTacticalStatus.uiFlags & INCOMBAT) && gfShiftBombPlant )
|
||||
{
|
||||
pSoldier->TakeNewItemFromInventory( pObj->usItem );
|
||||
}
|
||||
}
|
||||
|
||||
// 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) )
|
||||
else
|
||||
{
|
||||
// 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;
|
||||
(*pObj)[0]->data.objectStatus -= gStructureConstruct[structureconstructindex].usItemStatusLoss;
|
||||
}
|
||||
}
|
||||
else if ( CurrentStruct == ERASE_TILE && sGridNo < 0x80000000 )
|
||||
|
||||
// TODO: if we create an earth pile, create a decal (signifiying the 'hole' we created at our position)
|
||||
|
||||
// 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) )
|
||||
{
|
||||
RemoveAllStructsOfTypeRange( sGridNo, FIRSTOSTRUCT, LASTOSTRUCT );
|
||||
RemoveAllShadowsOfTypeRange( sGridNo, FIRSTSHADOW, LASTSHADOW );
|
||||
// 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;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN RemoveFortification( INT32 sGridNo )
|
||||
BOOLEAN RemoveFortification( INT32 sGridNo, SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj )
|
||||
{
|
||||
STRUCTURE* pStruct = FindStructure(sGridNo, STRUCTURE_GENERIC);
|
||||
// we need a valid soldier and a valid object
|
||||
if ( !pSoldier || !pObj )
|
||||
return FALSE;
|
||||
|
||||
// not on roofs
|
||||
if ( gsInterfaceLevel > 0 )
|
||||
return FALSE;
|
||||
|
||||
// needs to be a valid location
|
||||
if ( TileIsOutOfBounds( sGridNo ) )
|
||||
return FALSE;
|
||||
|
||||
STRUCTURE* pStruct = FindStructure( sGridNo, (STRUCTURE_GENERIC | STRUCTURE_WIREFENCE) );
|
||||
|
||||
if ( pStruct != NULL )
|
||||
{
|
||||
@@ -6850,34 +6947,58 @@ BOOLEAN RemoveFortification( INT32 sGridNo )
|
||||
|
||||
if ( pNode )
|
||||
{
|
||||
UINT16 usIndex = pNode->usIndex;
|
||||
UINT32 uiTileType = 0;
|
||||
if ( GetTileType( pNode->usIndex, &uiTileType ) )
|
||||
if ( GetTileType( usIndex, &uiTileType ) )
|
||||
{
|
||||
UINT16 usIndex = pNode->usIndex;
|
||||
|
||||
// Check if we are a sandbag
|
||||
if ( _strnicmp( gTilesets[ giCurrentTilesetID ].TileSurfaceFilenames[ uiTileType ], "sandbag.sti", 11) == 0 )
|
||||
for (UINT16 i = 0; i < STRUCTURE_DECONSTRUCT_MAX; ++i)
|
||||
{
|
||||
// Remove old graphic
|
||||
ApplyMapChangesToMapTempFile( TRUE );
|
||||
|
||||
RemoveStruct( sGridNo, pNode->usIndex );
|
||||
if ( !GridNoIndoors( sGridNo ) && gTileDatabase[ usIndex ].uiFlags & HAS_SHADOW_BUDDY && gTileDatabase[ usIndex ].sBuddyNum != -1 )
|
||||
// item we have in our hand must be one with which we can deconstruct this
|
||||
if ( pObj->usItem == gStructureDeconstruct[i].usDeconstructItem )
|
||||
{
|
||||
RemoveShadow( sGridNo, gTileDatabase[ usIndex ].sBuddyNum );
|
||||
// Check if we are a sandbag or a earth pile
|
||||
if ( !_strnicmp( gTilesets[ giCurrentTilesetID ].TileSurfaceFilenames[ uiTileType ], gStructureDeconstruct[i].szTileSetName, 11) )
|
||||
{
|
||||
// we have to check wether this specific structure can be removed. Just checking the tileset name won't be enough.
|
||||
// For example, we could have a set consisting of crates and piles of earth, which we want to remove via applying a shovel on it.
|
||||
// We only want to do this on the earth piles, of course - flattening crates via a shovel would be odd :-)
|
||||
UINT8 numbertofind = (UINT8)(pStruct->pDBStructureRef->pDBStructure->usStructureNumber);
|
||||
|
||||
UINT8 size = gStructureDeconstruct[i].tilevector.size();
|
||||
for ( UINT8 j = 0; j < size; ++j)
|
||||
{
|
||||
if ( gStructureDeconstruct[i].tilevector[j] == numbertofind )
|
||||
{
|
||||
// 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 );
|
||||
}
|
||||
|
||||
RecompileLocalMovementCosts(sGridNo);
|
||||
|
||||
// Turn off permanent changes....
|
||||
ApplyMapChangesToMapTempFile( FALSE );
|
||||
SetRenderFlags( RENDER_FLAG_FULL );
|
||||
|
||||
// eventually create item
|
||||
if ( gStructureDeconstruct[i].usItemToCreate && gStructureDeconstruct[i].usCreatedItemStatus )
|
||||
{
|
||||
// when creating the object, make it have at least 1% status
|
||||
CreateItem( gStructureDeconstruct[i].usItemToCreate, max(1, gStructureDeconstruct[i].usCreatedItemStatus), &gTempObject );
|
||||
|
||||
AddItemToPool( sGridNo, &gTempObject, 1, 0, 0, -1 );
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+32
-2
@@ -79,6 +79,33 @@ typedef struct
|
||||
|
||||
} ITEM_POOL_LOCATOR;
|
||||
|
||||
// Flugente: we can construct and deconstruct map structures via items.
|
||||
typedef struct {
|
||||
UINT16 usDeconstructItem; // the item that has to be used to deconstruct the structure
|
||||
UINT16 usItemToCreate; // the item that will be created when we deconstruct a structure
|
||||
UINT8 usCreatedItemStatus; // status of the item to create
|
||||
char szTileSetName[20]; // name of the tileset
|
||||
std::vector<UINT8> tilevector; // structures in the tileset that we can deconstruct
|
||||
} STRUCTURE_DECONSTRUCT;
|
||||
|
||||
#define STRUCTURE_DECONSTRUCT_MAX 200
|
||||
|
||||
extern STRUCTURE_DECONSTRUCT gStructureDeconstruct[STRUCTURE_DECONSTRUCT_MAX];
|
||||
|
||||
typedef struct {
|
||||
UINT16 usCreationItem; // the item that will be consumed when creating the structure
|
||||
UINT8 usItemStatusLoss; // item will lose this number of status points
|
||||
char szTileSetName[20]; // name of the tileset
|
||||
std::vector<UINT8> northtilevector; // structures in the tileset we can create while facing north
|
||||
std::vector<UINT8> southtilevector; // structures in the tileset we can create while facing south
|
||||
std::vector<UINT8> easttilevector; // structures in the tileset we can create while facing east
|
||||
std::vector<UINT8> westtilevector; // structures in the tileset we can create while facing west
|
||||
} STRUCTURE_CONSTRUCT;
|
||||
|
||||
#define STRUCTURE_CONSTRUCT_MAX 200
|
||||
|
||||
extern STRUCTURE_CONSTRUCT gStructureConstruct[STRUCTURE_CONSTRUCT_MAX];
|
||||
|
||||
class SOLDIERTYPE;
|
||||
INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHandItem, BOOLEAN fFromUI );
|
||||
void SoldierPickupItem( SOLDIERTYPE *pSoldier, INT32 iItemIndex, INT32 sGridNo, INT8 bZLevel );
|
||||
@@ -180,8 +207,11 @@ UINT8 StealItems(SOLDIERTYPE* pSoldier,SOLDIERTYPE* pOpponent, UINT8* ubIndexRet
|
||||
|
||||
BOOLEAN MarblesExistAtLocation( INT32 sGridNo, UINT8 ubLevel, INT32 * piItemIndex );
|
||||
|
||||
BOOLEAN BuildFortification( INT32 sGridNo , UINT32 flag = FULL_SANDBAG ); // Flugente: build a structure, return true if sucessful
|
||||
BOOLEAN RemoveFortification( INT32 sGridNo );
|
||||
// Flugente: build an deconstruct structures
|
||||
BOOLEAN IsStructureConstructItem( UINT16 usItem, INT32 sGridNo, SOLDIERTYPE* pSoldier ); // can we construct a structure with this item?
|
||||
BOOLEAN IsStructureDeconstructItem( UINT16 usItem, INT32 sGridNo, SOLDIERTYPE* pSoldier ); // can we remove a structure with this item?
|
||||
BOOLEAN BuildFortification( INT32 sGridNo, SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj ); // build a structure, return true if sucessful
|
||||
BOOLEAN RemoveFortification( INT32 sGridNo, SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj ); // remove a structure, return true if sucessful
|
||||
|
||||
extern ITEM_POOL *gpItemPool;//dnl ch26 210909
|
||||
|
||||
|
||||
@@ -4512,7 +4512,7 @@ BOOLEAN UIMouseOnValidAttackLocation( SOLDIERTYPE *pSoldier )
|
||||
// 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)) )
|
||||
if ( pShovelObj && pShovelObj->exists() && HasItemFlag(pSoldier->inv[ SECONDHANDPOS ].usItem, (SHOVEL)) )
|
||||
{
|
||||
INT8 bOverTerrainType = GetTerrainType( usMapPos );
|
||||
if( bOverTerrainType == FLAT_GROUND || bOverTerrainType == DIRT_ROAD || bOverTerrainType == LOW_GRASS )
|
||||
@@ -4521,19 +4521,20 @@ BOOLEAN UIMouseOnValidAttackLocation( SOLDIERTYPE *pSoldier )
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( HasItemFlag( (&(pSoldier->inv[HANDPOS]))->usItem, (SHOVEL)) )
|
||||
|
||||
if ( IsFortificationPossibleAtGridNo( usMapPos ) && IsStructureConstructItem( pSoldier->inv[HANDPOS].usItem, usMapPos, pSoldier ) )
|
||||
{
|
||||
STRUCTURE* pStruct = FindStructure(usMapPos, STRUCTURE_GENERIC);
|
||||
return(TRUE);
|
||||
}
|
||||
else if ( IsStructureDeconstructItem( pSoldier->inv[HANDPOS].usItem, usMapPos, pSoldier ) )
|
||||
{
|
||||
STRUCTURE* pStruct = FindStructure( usMapPos, (STRUCTURE_GENERIC | STRUCTURE_WIREFENCE) );
|
||||
|
||||
if ( pStruct )
|
||||
{
|
||||
return( TRUE );
|
||||
return(TRUE);
|
||||
}
|
||||
}
|
||||
else if ( IsFortificationPossibleAtGridNo( usMapPos ) )
|
||||
{
|
||||
return( TRUE );
|
||||
}
|
||||
}
|
||||
|
||||
return( FALSE );
|
||||
|
||||
@@ -731,9 +731,9 @@ extern OBJECTTYPE gTempObject;
|
||||
// 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 FULL_SANDBAG 0x00000002 //2
|
||||
#define SHOVEL 0x00000004 //4 // a shovel is used for filling sandbags and other building-related tasks
|
||||
#define CONCERTINA 0x00000008 //8
|
||||
//#define CONCERTINA 0x00000008 //8
|
||||
|
||||
#define WATER_DRUM 0x00000010 //16 // water drums allow to refill canteens in the sector they are in
|
||||
#define MEAT_BLOODCAT 0x00000020 //32 // retrieve this by gutting a bloodcat
|
||||
@@ -765,7 +765,7 @@ extern OBJECTTYPE gTempObject;
|
||||
#define SIGNAL_SHELL 0x04000000 //67108864 // this is a signal shell that precedes artillery barrages
|
||||
#define POWER_PACK 0x08000000 //134217728 // item continously powers an item it is attached to
|
||||
|
||||
#define SPOTTERITEM 0x10000000 //268435456 // binocular
|
||||
//#define WOODENPLANK 0x10000000 //268435456 // wooden planks
|
||||
#define DISEASEPROTECTION_FACE 0x20000000 //536870912 // this item protects us from getting diseases by human contact if worn in a face slot
|
||||
#define DISEASEPROTECTION_HAND 0x40000000 //1073741824 // this item protects us from getting diseases by human contact if kept in inventory
|
||||
/*#define PLAYER_NET_4_LVL_4 0x80000000 //2147483648*/
|
||||
|
||||
@@ -3162,8 +3162,12 @@ BOOLEAN AdjustToNextAnimationFrame( SOLDIERTYPE *pSoldier )
|
||||
|
||||
case 766:
|
||||
|
||||
// Say COOL quote
|
||||
pSoldier->DoMercBattleSound( BATTLE_SOUND_COOL1 );
|
||||
// Flugente: if doing this action a lot, this gets annoying - only play sound sometimes
|
||||
if ( Chance(gGameExternalOptions.iChanceSayAnnoyingPhrase) )
|
||||
{
|
||||
// Say COOL quote
|
||||
pSoldier->DoMercBattleSound( BATTLE_SOUND_COOL1 );
|
||||
}
|
||||
break;
|
||||
|
||||
case 767:
|
||||
|
||||
+149
-151
@@ -16188,10 +16188,10 @@ UINT8 SOLDIERTYPE::GetMultiTurnAction( )
|
||||
return usMultiTurnAction;
|
||||
}
|
||||
|
||||
void SOLDIERTYPE::StartMultiTurnAction( UINT8 usActionType )
|
||||
void SOLDIERTYPE::StartMultiTurnAction( UINT8 usActionType, INT32 asGridNo )
|
||||
{
|
||||
// check wether we can perform any action at all
|
||||
if ( !this->bActive || !this->bInSector || this->stats.bLife < OKLIFE || TileIsOutOfBounds( this->sGridNo ) || this->bCollapsed )
|
||||
if ( !this->bActive || !this->bInSector || this->stats.bLife < OKLIFE || TileIsOutOfBounds( asGridNo ) || this->bCollapsed )
|
||||
return;
|
||||
|
||||
// wether an action is possible or not depends on action itself (there are actions without a gridno)
|
||||
@@ -16200,7 +16200,7 @@ void SOLDIERTYPE::StartMultiTurnAction( UINT8 usActionType )
|
||||
case MTA_FORTIFY:
|
||||
case MTA_REMOVE_FORTIFY:
|
||||
case MTA_FILL_SANDBAG:
|
||||
if ( this->pathing.bLevel != 0 || gAnimControl[this->usAnimState].ubEndHeight == ANIM_PRONE || gAnimControl[this->usAnimState].ubEndHeight == ANIM_STAND )
|
||||
if ( this->pathing.bLevel != 0 )
|
||||
return;
|
||||
break;
|
||||
}
|
||||
@@ -16213,8 +16213,8 @@ void SOLDIERTYPE::StartMultiTurnAction( UINT8 usActionType )
|
||||
usMultiTurnAction = usActionType;
|
||||
|
||||
// the action shall be performed on the gridno directly in front of us
|
||||
sMTActionGridNo = NewGridNo( this->sGridNo, DirectionInc( this->ubDirection ) );
|
||||
|
||||
sMTActionGridNo = asGridNo;
|
||||
|
||||
// for now, adding and removing a structure has the same AP cost - that might change in the future
|
||||
bOverTurnAPS = GetAPsForMultiTurnAction( this, usMultiTurnAction );
|
||||
|
||||
@@ -16248,24 +16248,31 @@ BOOLEAN SOLDIERTYPE::UpdateMultiTurnAction( )
|
||||
CancelMultiTurnAction( FALSE );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
// wether an action is possible or not depends on action itself (there are actions without a gridno)
|
||||
switch ( usMultiTurnAction )
|
||||
{
|
||||
case MTA_FORTIFY:
|
||||
case MTA_REMOVE_FORTIFY:
|
||||
case MTA_FILL_SANDBAG:
|
||||
if ( this->pathing.bLevel != 0 || gAnimControl[this->usAnimState].ubEndHeight == ANIM_PRONE || gAnimControl[this->usAnimState].ubEndHeight == ANIM_STAND )
|
||||
// building on a roof is forbidden! stopt his!
|
||||
if ( this->pathing.bLevel != 0 )
|
||||
{
|
||||
CancelMultiTurnAction( FALSE );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// we have to be crouched, get out of here, set us to be crouched first
|
||||
if ( gAnimControl[this->usAnimState].ubEndHeight != ANIM_CROUCH )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
default: // default: exit
|
||||
{
|
||||
CancelMultiTurnAction( FALSE );
|
||||
return FALSE;
|
||||
}
|
||||
{
|
||||
CancelMultiTurnAction( FALSE );
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -16289,56 +16296,54 @@ BOOLEAN SOLDIERTYPE::UpdateMultiTurnAction( )
|
||||
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 = GetAPsForMultiTurnAction( this, MTA_FORTIFY );
|
||||
entirebpcost = APBPConstants[BP_FORTIFICATION];
|
||||
case MTA_FORTIFY:
|
||||
{
|
||||
entireapcost = GetAPsForMultiTurnAction( this, MTA_FORTIFY );
|
||||
entirebpcost = APBPConstants[BP_FORTIFICATION];
|
||||
|
||||
if ( !IsFortificationPossibleAtGridNo( this->sMTActionGridNo ) )
|
||||
fActionStillValid = FALSE;
|
||||
else if ( !HasItemFlag( this->inv[HANDPOS].usItem, (FULL_SANDBAG | CONCERTINA) ) )
|
||||
fActionStillValid = FALSE;
|
||||
}
|
||||
break;
|
||||
case MTA_REMOVE_FORTIFY:
|
||||
{
|
||||
entireapcost = GetAPsForMultiTurnAction( this, MTA_REMOVE_FORTIFY );
|
||||
entirebpcost = APBPConstants[BP_REMOVE_FORTIFICATION];
|
||||
|
||||
if ( !HasItemFlag( this->inv[HANDPOS].usItem, (SHOVEL) ) )
|
||||
fActionStillValid = FALSE;
|
||||
}
|
||||
if ( !IsFortificationPossibleAtGridNo( this->sMTActionGridNo ) )
|
||||
fActionStillValid = FALSE;
|
||||
else if ( !IsStructureConstructItem( this->inv[HANDPOS].usItem, this->sMTActionGridNo, this ) )
|
||||
fActionStillValid = FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case MTA_FILL_SANDBAG:
|
||||
{
|
||||
entireapcost = GetAPsForMultiTurnAction( this, MTA_FILL_SANDBAG );
|
||||
entirebpcost = APBPConstants[BP_FILL_SANDBAG];
|
||||
case MTA_REMOVE_FORTIFY:
|
||||
{
|
||||
entireapcost = GetAPsForMultiTurnAction( this, MTA_REMOVE_FORTIFY );
|
||||
entirebpcost = APBPConstants[BP_REMOVE_FORTIFICATION];
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( !IsStructureDeconstructItem( this->inv[HANDPOS].usItem, this->sMTActionGridNo, this ) )
|
||||
fActionStillValid = FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case MTA_FILL_SANDBAG:
|
||||
{
|
||||
entireapcost = GetAPsForMultiTurnAction( this, MTA_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;
|
||||
}
|
||||
|
||||
@@ -16351,25 +16356,25 @@ BOOLEAN SOLDIERTYPE::UpdateMultiTurnAction( )
|
||||
// refresh animations
|
||||
switch ( usMultiTurnAction )
|
||||
{
|
||||
case MTA_FORTIFY:
|
||||
case MTA_REMOVE_FORTIFY:
|
||||
case MTA_FILL_SANDBAG:
|
||||
{
|
||||
// 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
|
||||
{
|
||||
if ( !is_networked )
|
||||
this->EVENT_InitNewSoldierAnim( CUTTING_FENCE, 0, FALSE );
|
||||
else
|
||||
this->ChangeSoldierState( CUTTING_FENCE, 0, 0 );
|
||||
case MTA_FORTIFY:
|
||||
case MTA_REMOVE_FORTIFY:
|
||||
case MTA_FILL_SANDBAG:
|
||||
{
|
||||
// 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
|
||||
{
|
||||
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];
|
||||
}
|
||||
}
|
||||
// as setting the new animation costs APBPConstants[AP_USEWIRECUTTERS] APs every time, account for that
|
||||
this->bActionPoints += APBPConstants[AP_USEWIRECUTTERS];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -16378,73 +16383,59 @@ BOOLEAN SOLDIERTYPE::UpdateMultiTurnAction( )
|
||||
{
|
||||
switch ( usMultiTurnAction )
|
||||
{
|
||||
case MTA_FORTIFY:
|
||||
{
|
||||
// Build the thing
|
||||
if ( BuildFortification( this->sMTActionGridNo, Item[pObj->usItem].usItemFlag ) )
|
||||
{
|
||||
UINT16 usItem = pObj->usItem;
|
||||
// Erase 'material' item from our hand - we 'use' it to build the structure
|
||||
DeleteObj( &(this->inv[HANDPOS]) );
|
||||
// sevenfm: auto-taking of items
|
||||
if ( !(gTacticalStatus.uiFlags & TURNBASED && gTacticalStatus.uiFlags & INCOMBAT) && gfShiftBombPlant )
|
||||
{
|
||||
TakeNewItemFromInventory( usItem );
|
||||
}
|
||||
case MTA_FORTIFY:
|
||||
{
|
||||
// Build the thing
|
||||
if ( BuildFortification( this->sMTActionGridNo, this, pObj ) )
|
||||
{
|
||||
// we gain a bit of experience...
|
||||
StatChange( this, STRAMT, 4, TRUE );
|
||||
StatChange( this, HEALTHAMT, 2, TRUE );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// 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, this, pObj ) )
|
||||
{
|
||||
// we gain a bit of experience...
|
||||
StatChange( this, STRAMT, 3, 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 );
|
||||
case MTA_FILL_SANDBAG:
|
||||
{
|
||||
// eventually search for the number of a sandbag item
|
||||
UINT16 fullsandbagnr = Item[this->inv[HANDPOS].usItem].usBuddyItem;
|
||||
if ( fullsandbagnr )
|
||||
{
|
||||
INT8 bObjSlot = HANDPOS;
|
||||
UINT16 usItem = pObj->usItem;
|
||||
|
||||
AddItemToPool( this->sMTActionGridNo, &gTempObject, 1, 0, 0, -1 );
|
||||
CreateItem( fullsandbagnr, 100, &gTempObject );
|
||||
if ( !(gTacticalStatus.uiFlags & TURNBASED && gTacticalStatus.uiFlags & INCOMBAT) && gfShiftBombPlant )
|
||||
{
|
||||
// sevenfm: drop filled sandbag to the ground and take new empty from inventory
|
||||
AddItemToPool( this->sGridNo, &gTempObject, 1, 0, 0, -1 );
|
||||
DeleteObj( &(this->inv[HANDPOS]) );
|
||||
TakeNewItemFromInventory( usItem );
|
||||
}
|
||||
else
|
||||
{
|
||||
SwapObjs( this, bObjSlot, &gTempObject, TRUE );
|
||||
}
|
||||
|
||||
// we gain a bit of experience...
|
||||
StatChange( this, STRAMT, 3, TRUE );
|
||||
StatChange( this, HEALTHAMT, 2, TRUE );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
// sevenfm: added this to correctly update interface
|
||||
DirtyMercPanelInterface( this, DIRTYLEVEL2 );
|
||||
|
||||
case MTA_FILL_SANDBAG:
|
||||
{
|
||||
// eventually search for the number of a sandbag item
|
||||
if ( HasItemFlag( fullsandbagnr, FULL_SANDBAG ) || GetFirstItemWithFlag( &fullsandbagnr, FULL_SANDBAG ) )
|
||||
{
|
||||
INT8 bObjSlot = HANDPOS;
|
||||
UINT16 usItem = pObj->usItem;
|
||||
|
||||
CreateItem( fullsandbagnr, 100, &gTempObject );
|
||||
if ( !(gTacticalStatus.uiFlags & TURNBASED && gTacticalStatus.uiFlags & INCOMBAT) && gfShiftBombPlant )
|
||||
{ // sevenfm: drop filled sandbag to the ground and take new empty from inventory
|
||||
AddItemToPool( this->sGridNo, &gTempObject, 1, 0, 0, -1 );
|
||||
DeleteObj( &(this->inv[HANDPOS]) );
|
||||
TakeNewItemFromInventory( usItem );
|
||||
}
|
||||
else
|
||||
{
|
||||
SwapObjs( this, bObjSlot, &gTempObject, TRUE );
|
||||
}
|
||||
// sevenfm: added this to correctly update interface
|
||||
DirtyMercPanelInterface( this, DIRTYLEVEL2 );
|
||||
|
||||
// we gain a bit of experience...
|
||||
StatChange( this, STRAMT, 1, TRUE );
|
||||
StatChange( this, HEALTHAMT, 1, TRUE );
|
||||
}
|
||||
}
|
||||
// we gain a bit of experience...
|
||||
StatChange( this, STRAMT, 1, TRUE );
|
||||
StatChange( this, HEALTHAMT, 1, TRUE );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -19742,19 +19733,16 @@ void SOLDIERTYPE::EVENT_SoldierBuildStructure( INT32 sGridNo, UINT8 ubDirection
|
||||
}
|
||||
}
|
||||
|
||||
// CHANGE DIRECTION AND GOTO ANIMATION NOW
|
||||
this->EVENT_SetSoldierDesiredDirection( ubDirection );
|
||||
this->EVENT_SetSoldierDirection( ubDirection );
|
||||
|
||||
// do checks here...
|
||||
OBJECTTYPE* pObj = &(this->inv[HANDPOS]);
|
||||
|
||||
if ( pObj && pObj->exists( ) && HasItemFlag( this->inv[HANDPOS].usItem, (EMPTY_SANDBAG | FULL_SANDBAG | SHOVEL | CONCERTINA) ) )
|
||||
if ( pObj && pObj->exists( ) && (HasItemFlag( this->inv[HANDPOS].usItem, EMPTY_SANDBAG ) || IsStructureConstructItem( this->inv[HANDPOS].usItem, sGridNo, this ) || IsStructureDeconstructItem( this->inv[HANDPOS].usItem, sGridNo, this ) ) )
|
||||
{
|
||||
if ( HasItemFlag( this->inv[HANDPOS].usItem, (FULL_SANDBAG | CONCERTINA) ) )
|
||||
{
|
||||
// Build the thing
|
||||
this->StartMultiTurnAction( MTA_FORTIFY );
|
||||
|
||||
fSuccess = TRUE;
|
||||
}
|
||||
else if ( HasItemFlag( this->inv[HANDPOS].usItem, (EMPTY_SANDBAG) ) )
|
||||
if ( HasItemFlag( this->inv[HANDPOS].usItem, EMPTY_SANDBAG ) )
|
||||
{
|
||||
INT8 bOverTerrainType = GetTerrainType( sGridNo );
|
||||
if ( bOverTerrainType == FLAT_GROUND || bOverTerrainType == DIRT_ROAD || bOverTerrainType == LOW_GRASS )
|
||||
@@ -19762,19 +19750,33 @@ void SOLDIERTYPE::EVENT_SoldierBuildStructure( INT32 sGridNo, UINT8 ubDirection
|
||||
// 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) ) )
|
||||
if ( pShovelObj && pShovelObj->exists( ) && HasItemFlag( this->inv[SECONDHANDPOS].usItem, SHOVEL ) )
|
||||
{
|
||||
this->StartMultiTurnAction( MTA_FILL_SANDBAG );
|
||||
this->StartMultiTurnAction( MTA_FILL_SANDBAG, sGridNo );
|
||||
|
||||
fSuccess = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( HasItemFlag( this->inv[HANDPOS].usItem, (SHOVEL) ) )
|
||||
else
|
||||
{
|
||||
this->StartMultiTurnAction( MTA_REMOVE_FORTIFY );
|
||||
// it is possible that an item is used in both constructing and deconstructing. We thus check wether a structure already exists at sGridNo to dedcut the players intention
|
||||
// if there is a structure, we will remove this fortification. If there isn't, then we will dig and create a earth pile
|
||||
STRUCTURE* pStruct = FindStructure( sGridNo, STRUCTURE_GENERIC );
|
||||
|
||||
fSuccess = TRUE;
|
||||
if ( !pStruct && IsStructureConstructItem( this->inv[HANDPOS].usItem, sGridNo, this ) )
|
||||
{
|
||||
// Build the thing
|
||||
this->StartMultiTurnAction( MTA_FORTIFY, sGridNo );
|
||||
|
||||
fSuccess = TRUE;
|
||||
}
|
||||
else if ( IsStructureDeconstructItem( this->inv[HANDPOS].usItem, sGridNo, this ) )
|
||||
{
|
||||
this->StartMultiTurnAction( MTA_REMOVE_FORTIFY, sGridNo );
|
||||
|
||||
fSuccess = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19785,10 +19787,6 @@ void SOLDIERTYPE::EVENT_SoldierBuildStructure( INT32 sGridNo, UINT8 ubDirection
|
||||
}
|
||||
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
|
||||
|
||||
@@ -1775,7 +1775,7 @@ public:
|
||||
|
||||
// Flugente: multi-turn actions
|
||||
UINT8 GetMultiTurnAction();
|
||||
void StartMultiTurnAction(UINT8 usActionType);
|
||||
void StartMultiTurnAction( UINT8 usActionType, INT32 asGridNo );
|
||||
void CancelMultiTurnAction(BOOLEAN fFinished);
|
||||
BOOLEAN UpdateMultiTurnAction();
|
||||
|
||||
|
||||
@@ -1240,6 +1240,14 @@
|
||||
RelativePath=".\XML_SpreadPatterns.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_StructureConstruct.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_StructureDeconstruct.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_Taunts.cpp"
|
||||
>
|
||||
|
||||
@@ -1242,6 +1242,14 @@
|
||||
RelativePath=".\XML_SpreadPatterns.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_StructureConstruct.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_StructureDeconstruct.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_Taunts.cpp"
|
||||
>
|
||||
|
||||
@@ -247,6 +247,8 @@
|
||||
<ClCompile Include="XML_SoundProfile.cpp" />
|
||||
<ClCompile Include="XML_Sounds.cpp" />
|
||||
<ClCompile Include="XML_SpreadPatterns.cpp" />
|
||||
<ClCompile Include="XML_StructureConstruct.cpp" />
|
||||
<ClCompile Include="XML_StructureDeconstruct.cpp" />
|
||||
<ClCompile Include="XML_Taunts.cpp" />
|
||||
<ClCompile Include="XML_AdditionalTileProperties.cpp" />
|
||||
<ClCompile Include="XML_TonyInventory.cpp" />
|
||||
|
||||
@@ -689,5 +689,11 @@
|
||||
<ClCompile Include="XML_FoodOpinions.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XML_StructureDeconstruct.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XML_StructureConstruct.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -248,6 +248,8 @@
|
||||
<ClCompile Include="XML_SoundProfile.cpp" />
|
||||
<ClCompile Include="XML_Sounds.cpp" />
|
||||
<ClCompile Include="XML_SpreadPatterns.cpp" />
|
||||
<ClCompile Include="XML_StructureConstruct.cpp" />
|
||||
<ClCompile Include="XML_StructureDeconstruct.cpp" />
|
||||
<ClCompile Include="XML_Taunts.cpp" />
|
||||
<ClCompile Include="XML_AdditionalTileProperties.cpp" />
|
||||
<ClCompile Include="XML_TonyInventory.cpp" />
|
||||
|
||||
@@ -601,6 +601,12 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="XML_SpreadPatterns.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XML_StructureConstruct.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XML_StructureDeconstruct.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XML_TonyInventory.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
|
||||
+16
-19
@@ -2209,12 +2209,12 @@ UINT8 HandleFortificationCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 ui
|
||||
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)) )
|
||||
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)) )
|
||||
if ( pShovelObj && (pShovelObj->exists()) && HasItemFlag(pSoldier->inv[ SECONDHANDPOS ].usItem, SHOVEL) )
|
||||
{
|
||||
INT8 bOverTerrainType = GetTerrainType( sGridNo );
|
||||
if( bOverTerrainType == FLAT_GROUND || bOverTerrainType == DIRT_ROAD || bOverTerrainType == LOW_GRASS )
|
||||
@@ -2225,23 +2225,19 @@ UINT8 HandleFortificationCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 ui
|
||||
|
||||
return( FORTIFICATION_RED_UICURSOR );
|
||||
}
|
||||
|
||||
if ( HasItemFlag( (&(pSoldier->inv[HANDPOS]))->usItem, (SHOVEL)) )
|
||||
|
||||
if ( IsFortificationPossibleAtGridNo( sGridNo ) && IsStructureConstructItem( pSoldier->inv[HANDPOS].usItem, sGridNo, pSoldier ) )
|
||||
{
|
||||
STRUCTURE* pStruct = FindStructure(sGridNo, STRUCTURE_GENERIC);
|
||||
return( FORTIFICATION_GREY_UICURSOR );
|
||||
}
|
||||
else if ( IsStructureDeconstructItem( pSoldier->inv[HANDPOS].usItem, sGridNo, pSoldier ) )
|
||||
{
|
||||
STRUCTURE* pStruct = FindStructure( sGridNo, (STRUCTURE_GENERIC | STRUCTURE_WIREFENCE));
|
||||
|
||||
if ( pStruct )
|
||||
{
|
||||
return( FORTIFICATION_GREY_UICURSOR );
|
||||
return(FORTIFICATION_GREY_UICURSOR);
|
||||
}
|
||||
else
|
||||
return( FORTIFICATION_RED_UICURSOR );
|
||||
}
|
||||
|
||||
// can we build something here?
|
||||
if ( IsFortificationPossibleAtGridNo( sGridNo ) )
|
||||
{
|
||||
return( FORTIFICATION_GREY_UICURSOR );
|
||||
}
|
||||
|
||||
return( FORTIFICATION_RED_UICURSOR );
|
||||
@@ -2741,7 +2737,7 @@ void HandleRightClickAdjustCursor( SOLDIERTYPE *pSoldier, INT32 usMapPos )
|
||||
|
||||
UINT8 GetActionModeCursor( SOLDIERTYPE *pSoldier )
|
||||
{
|
||||
UINT8 ubCursor;
|
||||
UINT8 ubCursor;
|
||||
UINT16 usInHand;
|
||||
|
||||
// If we are an EPC, do nothing....
|
||||
@@ -2772,7 +2768,6 @@ UINT8 GetActionModeCursor( SOLDIERTYPE *pSoldier )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( pSoldier->bWeaponMode == WM_ATTACHED_GL )
|
||||
{
|
||||
// Flugente: if using a rifle grenade, only allow firing if there is a bullet in the gun's magazine (required for firing)
|
||||
@@ -2787,6 +2782,7 @@ UINT8 GetActionModeCursor( SOLDIERTYPE *pSoldier )
|
||||
|
||||
return( TRAJECTORYCURS );
|
||||
}
|
||||
|
||||
if ( pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST || ( pSoldier->bWeaponMode == WM_BURST && Item[pSoldier->inv[HANDPOS].usItem].grenadelauncher ) )
|
||||
{
|
||||
if ( gGameSettings.fOptions [ TOPTION_GL_BURST_CURSOR ] )
|
||||
@@ -2824,8 +2820,9 @@ UINT8 GetActionModeCursor( SOLDIERTYPE *pSoldier )
|
||||
}
|
||||
}
|
||||
|
||||
// Flugente: cursor for building fortifications
|
||||
if ( HasItemFlag(usInHand, (EMPTY_SANDBAG|FULL_SANDBAG|SHOVEL|CONCERTINA)) )
|
||||
// Flugente: cursor for constructing/deconstructing
|
||||
// at the moment the gridno is not required in these functions, thus 1 suffices
|
||||
if ( HasItemFlag( usInHand, EMPTY_SANDBAG ) || IsStructureConstructItem( usInHand, 1, pSoldier ) || IsStructureDeconstructItem( usInHand, 1, pSoldier ) )
|
||||
ubCursor = FORTICURS;
|
||||
|
||||
// Flugente: cursor for handcuffs
|
||||
@@ -2836,7 +2833,7 @@ UINT8 GetActionModeCursor( SOLDIERTYPE *pSoldier )
|
||||
if ( ItemCanBeAppliedToOthers( usInHand ) )
|
||||
{
|
||||
// if item is a bomb, only allow apply if hovering over a soldier (otherwise we cannot mine anymore)
|
||||
if ( Item[ usInHand ].usItemClass == IC_BOMB )
|
||||
if ( Item[ usInHand ].usItemClass & IC_BOMB )
|
||||
{
|
||||
INT32 usMapPos = NOWHERE;
|
||||
if ( GetMouseMapPos( &usMapPos ) )
|
||||
|
||||
@@ -66,6 +66,8 @@ typedef PARSE_STAGE;
|
||||
#define DRUGSFILENAME "Items\\Drugs.xml"
|
||||
#define FOODFILENAME "Items\\Food.xml"
|
||||
#define FOODOPINIONFILENAME "Items\\FoodOpinion.xml"
|
||||
#define STRUCTUREDECONSTRUCTFILENAME "Items\\StructureDeconstruct.xml"
|
||||
#define STRUCTURECONSTRUCTFILENAME "Items\\StructureConstruct.xml"
|
||||
#define CLOTHESFILENAME "Items\\Clothes.xml"
|
||||
#define RANDOMITEMFILENAME "Items\\RandomItem.xml"
|
||||
#define AMMOFILENAME "Items\\AmmoStrings.xml"
|
||||
@@ -322,6 +324,13 @@ extern BOOLEAN WriteFoodOpinionStats();
|
||||
extern BOOLEAN ReadInDiseaseStats( STR fileName );
|
||||
extern BOOLEAN WriteDiseaseStats( );
|
||||
|
||||
// Flugente: structure (de-)construct
|
||||
extern BOOLEAN ReadInStructureDeconstructStats(STR fileName);
|
||||
extern BOOLEAN WriteStructureDeconstructStats();
|
||||
|
||||
extern BOOLEAN ReadInStructureConstructStats(STR fileName);
|
||||
extern BOOLEAN WriteStructureConstructStats();
|
||||
|
||||
// Flugente: merchants
|
||||
extern BOOLEAN ReadInMerchantStats(STR fileName);
|
||||
extern BOOLEAN WriteMerchantStats();
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
#ifdef PRECOMPILEDHEADERS
|
||||
#include "Tactical All.h"
|
||||
#else
|
||||
#include "sgp.h"
|
||||
#include "overhead.h"
|
||||
#include "Handle Items.h"
|
||||
#include "Debug Control.h"
|
||||
#include "expat.h"
|
||||
#include "XML.h"
|
||||
#endif
|
||||
|
||||
struct
|
||||
{
|
||||
PARSE_STAGE curElement;
|
||||
|
||||
CHAR8 szCharData[MAX_CHAR_DATA_LENGTH+1];
|
||||
STRUCTURE_CONSTRUCT curFood;
|
||||
STRUCTURE_CONSTRUCT * curArray;
|
||||
UINT32 maxArraySize;
|
||||
|
||||
UINT32 currentDepth;
|
||||
UINT32 maxReadDepth;
|
||||
}
|
||||
typedef structureconstructParseData;
|
||||
|
||||
UINT16 structureconstructcnt = 0;
|
||||
|
||||
static void XMLCALL
|
||||
structureconstructStartElementHandle(void *userData, const XML_Char *name, const XML_Char **atts)
|
||||
{
|
||||
structureconstructParseData * pData = (structureconstructParseData *)userData;
|
||||
|
||||
if(pData->currentDepth <= pData->maxReadDepth) //are we reading this element?
|
||||
{
|
||||
if(strcmp(name, "STRUCTURESLIST") == 0 && pData->curElement == ELEMENT_NONE)
|
||||
{
|
||||
pData->curElement = ELEMENT_LIST;
|
||||
|
||||
memset(pData->curArray,0,sizeof(STRUCTURE_CONSTRUCT)*pData->maxArraySize);
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(strcmp(name, "STRUCTURE") == 0 && pData->curElement == ELEMENT_LIST)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
memset(&pData->curFood,0,sizeof(STRUCTURE_CONSTRUCT));
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(pData->curElement == ELEMENT &&
|
||||
(strcmp(name, "usCreationItem") == 0 ||
|
||||
strcmp(name, "usItemStatusLoss") == 0 ||
|
||||
strcmp(name, "szTileSetName") == 0 ||
|
||||
strcmp(name, "northfacingtile") == 0 ||
|
||||
strcmp(name, "southfacingtile" ) == 0 ||
|
||||
strcmp(name, "eastfacingtile" ) == 0 ||
|
||||
strcmp(name, "westfacingtile") == 0 ))
|
||||
{
|
||||
pData->curElement = ELEMENT_PROPERTY;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
|
||||
pData->szCharData[0] = '\0';
|
||||
}
|
||||
|
||||
pData->currentDepth++;
|
||||
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
structureconstructCharacterDataHandle(void *userData, const XML_Char *str, int len)
|
||||
{
|
||||
structureconstructParseData * pData = (structureconstructParseData *)userData;
|
||||
|
||||
if( (pData->currentDepth <= pData->maxReadDepth) &&
|
||||
(strlen(pData->szCharData) < MAX_CHAR_DATA_LENGTH)
|
||||
){
|
||||
strncat(pData->szCharData,str,__min((unsigned int)len,MAX_CHAR_DATA_LENGTH-strlen(pData->szCharData)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void XMLCALL
|
||||
structureconstructEndElementHandle(void *userData, const XML_Char *name)
|
||||
{
|
||||
structureconstructParseData * pData = (structureconstructParseData *)userData;
|
||||
|
||||
if(pData->currentDepth <= pData->maxReadDepth) //we're at the end of an element that we've been reading
|
||||
{
|
||||
if(strcmp(name, "STRUCTURESLIST") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT_NONE;
|
||||
}
|
||||
else if(strcmp(name, "STRUCTURE") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT_LIST;
|
||||
|
||||
// we do NOT want to read the first entry -> move stuff by 1
|
||||
if(structureconstructcnt < pData->maxArraySize)
|
||||
{
|
||||
pData->curArray[structureconstructcnt] = pData->curFood; //write the data into the table
|
||||
}
|
||||
|
||||
++structureconstructcnt;
|
||||
}
|
||||
else if(strcmp(name, "usCreationItem") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curFood.usCreationItem = (UINT16) atol(pData->szCharData);
|
||||
}
|
||||
else if(strcmp(name, "usItemStatusLoss") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curFood.usItemStatusLoss = (UINT8) atol(pData->szCharData);
|
||||
}
|
||||
else if(strcmp(name, "szTileSetName") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
strncpy(pData->curFood.szTileSetName, pData->szCharData, 20);
|
||||
}
|
||||
else if(strcmp(name, "northfacingtile") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curFood.northtilevector.push_back( (UINT8) atol(pData->szCharData) );
|
||||
}
|
||||
else if(strcmp(name, "southfacingtile") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curFood.southtilevector.push_back( (UINT8) atol(pData->szCharData) );
|
||||
}
|
||||
else if ( strcmp( name, "eastfacingtile" ) == 0 )
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curFood.easttilevector.push_back( (UINT8)atol( pData->szCharData ) );
|
||||
}
|
||||
else if ( strcmp( name, "westfacingtile" ) == 0 )
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curFood.westtilevector.push_back( (UINT8)atol( pData->szCharData ) );
|
||||
}
|
||||
|
||||
pData->maxReadDepth--;
|
||||
}
|
||||
|
||||
pData->currentDepth--;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
BOOLEAN ReadInStructureConstructStats(STR fileName)
|
||||
{
|
||||
HWFILE hFile;
|
||||
UINT32 uiBytesRead;
|
||||
UINT32 uiFSize;
|
||||
CHAR8 * lpcBuffer;
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
|
||||
structureconstructParseData pData;
|
||||
|
||||
DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "Loading StructureConstruct.xml" );
|
||||
|
||||
// Open foods file
|
||||
hFile = FileOpen( fileName, FILE_ACCESS_READ, FALSE );
|
||||
if ( !hFile )
|
||||
return( FALSE );
|
||||
|
||||
uiFSize = FileGetSize(hFile);
|
||||
lpcBuffer = (CHAR8 *) MemAlloc(uiFSize+1);
|
||||
|
||||
//Read in block
|
||||
if ( !FileRead( hFile, lpcBuffer, uiFSize, &uiBytesRead ) )
|
||||
{
|
||||
MemFree(lpcBuffer);
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
lpcBuffer[uiFSize] = 0; //add a null terminator
|
||||
|
||||
FileClose( hFile );
|
||||
|
||||
XML_SetElementHandler(parser, structureconstructStartElementHandle, structureconstructEndElementHandle);
|
||||
XML_SetCharacterDataHandler(parser, structureconstructCharacterDataHandle);
|
||||
|
||||
memset(&pData,0,sizeof(pData));
|
||||
pData.curArray = gStructureConstruct;
|
||||
pData.maxArraySize = STRUCTURE_CONSTRUCT_MAX;
|
||||
|
||||
XML_SetUserData(parser, &pData);
|
||||
|
||||
if(!XML_Parse(parser, lpcBuffer, uiFSize, TRUE))
|
||||
{
|
||||
CHAR8 errorBuf[511];
|
||||
|
||||
sprintf(errorBuf, "XML Parser Error in StructureConstruct.xml: %s at line %d", XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser));
|
||||
LiveMessage(errorBuf);
|
||||
|
||||
MemFree(lpcBuffer);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
MemFree(lpcBuffer);
|
||||
|
||||
XML_ParserFree(parser);
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
BOOLEAN WriteStructureConstructStats()
|
||||
{
|
||||
//DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"writefoodsstats");
|
||||
HWFILE hFile;
|
||||
|
||||
//Debug code; make sure that what we got from the file is the same as what's there
|
||||
// Open a new file
|
||||
hFile = FileOpen( "TABLEDATA\\StructureConstruct out.xml", FILE_ACCESS_WRITE | FILE_CREATE_ALWAYS, FALSE );
|
||||
if ( !hFile )
|
||||
return( FALSE );
|
||||
|
||||
{
|
||||
UINT32 cnt;
|
||||
|
||||
FilePrintf(hFile,"<STRUCTURESLIST>\r\n");
|
||||
for(cnt = 0; cnt < STRUCTURE_CONSTRUCT_MAX; ++cnt)
|
||||
{
|
||||
FilePrintf(hFile,"\t<STRUCTURE>\r\n");
|
||||
|
||||
FilePrintf(hFile,"\t\t<usCreationItem>%d</usCreationItem>\r\n", gStructureConstruct[cnt].usCreationItem );
|
||||
FilePrintf(hFile,"\t\t<usItemStatusLoss>%d</usItemStatusLoss>\r\n", gStructureConstruct[cnt].usItemStatusLoss );
|
||||
FilePrintf(hFile,"\t\t<szTileSetName>%s</szTileSetName>\r\n", gStructureConstruct[cnt].szTileSetName );
|
||||
|
||||
FilePrintf(hFile,"\t</STRUCTURE>\r\n");
|
||||
}
|
||||
FilePrintf(hFile,"</STRUCTURESLIST>\r\n");
|
||||
}
|
||||
FileClose( hFile );
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
#ifdef PRECOMPILEDHEADERS
|
||||
#include "Tactical All.h"
|
||||
#else
|
||||
#include "sgp.h"
|
||||
#include "overhead.h"
|
||||
#include "Handle Items.h"
|
||||
#include "Debug Control.h"
|
||||
#include "expat.h"
|
||||
#include "XML.h"
|
||||
#endif
|
||||
|
||||
struct
|
||||
{
|
||||
PARSE_STAGE curElement;
|
||||
|
||||
CHAR8 szCharData[MAX_CHAR_DATA_LENGTH+1];
|
||||
STRUCTURE_DECONSTRUCT curFood;
|
||||
STRUCTURE_DECONSTRUCT * curArray;
|
||||
UINT32 maxArraySize;
|
||||
|
||||
UINT32 currentDepth;
|
||||
UINT32 maxReadDepth;
|
||||
}
|
||||
typedef structuredeconstructParseData;
|
||||
|
||||
UINT16 structuredeconstructcnt = 0;
|
||||
|
||||
static void XMLCALL
|
||||
structuredeconstructStartElementHandle(void *userData, const XML_Char *name, const XML_Char **atts)
|
||||
{
|
||||
structuredeconstructParseData * pData = (structuredeconstructParseData *)userData;
|
||||
|
||||
if(pData->currentDepth <= pData->maxReadDepth) //are we reading this element?
|
||||
{
|
||||
if(strcmp(name, "STRUCTURESLIST") == 0 && pData->curElement == ELEMENT_NONE)
|
||||
{
|
||||
pData->curElement = ELEMENT_LIST;
|
||||
|
||||
memset(pData->curArray,0,sizeof(STRUCTURE_DECONSTRUCT)*pData->maxArraySize);
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(strcmp(name, "STRUCTURE") == 0 && pData->curElement == ELEMENT_LIST)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
memset(&pData->curFood,0,sizeof(STRUCTURE_DECONSTRUCT));
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(pData->curElement == ELEMENT &&
|
||||
(strcmp(name, "usDeconstructItem") == 0 ||
|
||||
strcmp( name, "usItemToCreate" ) == 0 ||
|
||||
strcmp( name, "usCreatedItemStatus" ) == 0 ||
|
||||
strcmp(name, "szTileSetName") == 0 ||
|
||||
strcmp(name, "allowedtile") == 0 ))
|
||||
{
|
||||
pData->curElement = ELEMENT_PROPERTY;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
|
||||
pData->szCharData[0] = '\0';
|
||||
}
|
||||
|
||||
pData->currentDepth++;
|
||||
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
structuredeconstructCharacterDataHandle(void *userData, const XML_Char *str, int len)
|
||||
{
|
||||
structuredeconstructParseData * pData = (structuredeconstructParseData *)userData;
|
||||
|
||||
if( (pData->currentDepth <= pData->maxReadDepth) &&
|
||||
(strlen(pData->szCharData) < MAX_CHAR_DATA_LENGTH)
|
||||
){
|
||||
strncat(pData->szCharData,str,__min((unsigned int)len,MAX_CHAR_DATA_LENGTH-strlen(pData->szCharData)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void XMLCALL
|
||||
structuredeconstructEndElementHandle(void *userData, const XML_Char *name)
|
||||
{
|
||||
structuredeconstructParseData * pData = (structuredeconstructParseData *)userData;
|
||||
|
||||
if(pData->currentDepth <= pData->maxReadDepth) //we're at the end of an element that we've been reading
|
||||
{
|
||||
if(strcmp(name, "STRUCTURESLIST") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT_NONE;
|
||||
}
|
||||
else if(strcmp(name, "STRUCTURE") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT_LIST;
|
||||
|
||||
if(structuredeconstructcnt < pData->maxArraySize)
|
||||
{
|
||||
pData->curArray[structuredeconstructcnt] = pData->curFood; //write the data into the table
|
||||
}
|
||||
|
||||
++structuredeconstructcnt;
|
||||
}
|
||||
else if ( strcmp( name, "usDeconstructItem" ) == 0 )
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curFood.usDeconstructItem = (UINT16)atol( pData->szCharData );
|
||||
}
|
||||
else if(strcmp(name, "usItemToCreate") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curFood.usItemToCreate = (UINT16) atol(pData->szCharData);
|
||||
}
|
||||
else if ( strcmp( name, "usCreatedItemStatus" ) == 0 )
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curFood.usCreatedItemStatus = (UINT8)atol( pData->szCharData );
|
||||
}
|
||||
else if(strcmp(name, "szTileSetName") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
strncpy(pData->curFood.szTileSetName, pData->szCharData, 20);
|
||||
}
|
||||
else if(strcmp(name, "allowedtile") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curFood.tilevector.push_back( (UINT8) atol(pData->szCharData) );
|
||||
}
|
||||
|
||||
pData->maxReadDepth--;
|
||||
}
|
||||
|
||||
pData->currentDepth--;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
BOOLEAN ReadInStructureDeconstructStats(STR fileName)
|
||||
{
|
||||
HWFILE hFile;
|
||||
UINT32 uiBytesRead;
|
||||
UINT32 uiFSize;
|
||||
CHAR8 * lpcBuffer;
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
|
||||
structuredeconstructParseData pData;
|
||||
|
||||
DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "Loading StructureDeconstruct.xml" );
|
||||
|
||||
// Open foods file
|
||||
hFile = FileOpen( fileName, FILE_ACCESS_READ, FALSE );
|
||||
if ( !hFile )
|
||||
return( FALSE );
|
||||
|
||||
uiFSize = FileGetSize(hFile);
|
||||
lpcBuffer = (CHAR8 *) MemAlloc(uiFSize+1);
|
||||
|
||||
//Read in block
|
||||
if ( !FileRead( hFile, lpcBuffer, uiFSize, &uiBytesRead ) )
|
||||
{
|
||||
MemFree(lpcBuffer);
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
lpcBuffer[uiFSize] = 0; //add a null terminator
|
||||
|
||||
FileClose( hFile );
|
||||
|
||||
|
||||
XML_SetElementHandler(parser, structuredeconstructStartElementHandle, structuredeconstructEndElementHandle);
|
||||
XML_SetCharacterDataHandler(parser, structuredeconstructCharacterDataHandle);
|
||||
|
||||
|
||||
memset(&pData,0,sizeof(pData));
|
||||
pData.curArray = gStructureDeconstruct;
|
||||
pData.maxArraySize = STRUCTURE_DECONSTRUCT_MAX;
|
||||
|
||||
XML_SetUserData(parser, &pData);
|
||||
|
||||
|
||||
if(!XML_Parse(parser, lpcBuffer, uiFSize, TRUE))
|
||||
{
|
||||
CHAR8 errorBuf[511];
|
||||
|
||||
sprintf(errorBuf, "XML Parser Error in StructureDeconstruct.xml: %s at line %d", XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser));
|
||||
LiveMessage(errorBuf);
|
||||
|
||||
MemFree(lpcBuffer);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
MemFree(lpcBuffer);
|
||||
|
||||
|
||||
XML_ParserFree(parser);
|
||||
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
BOOLEAN WriteStructureDeconstructStats()
|
||||
{
|
||||
//DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"writefoodsstats");
|
||||
HWFILE hFile;
|
||||
|
||||
//Debug code; make sure that what we got from the file is the same as what's there
|
||||
// Open a new file
|
||||
hFile = FileOpen( "TABLEDATA\\StructureDeconstruct out.xml", FILE_ACCESS_WRITE | FILE_CREATE_ALWAYS, FALSE );
|
||||
if ( !hFile )
|
||||
return( FALSE );
|
||||
|
||||
{
|
||||
UINT32 cnt;
|
||||
|
||||
FilePrintf(hFile,"<STRUCTURESLIST>\r\n");
|
||||
for(cnt = 0; cnt < STRUCTURE_DECONSTRUCT_MAX; ++cnt)
|
||||
{
|
||||
FilePrintf(hFile,"\t<STRUCTURE>\r\n");
|
||||
|
||||
FilePrintf(hFile,"\t\t<usDeconstructItem>%d</usDeconstructItem>\r\n", gStructureDeconstruct[cnt].usDeconstructItem );
|
||||
FilePrintf(hFile,"\t\t<usItemToCreate>%d</usItemToCreate>\r\n", gStructureDeconstruct[cnt].usItemToCreate );
|
||||
FilePrintf(hFile,"\t\t<usCreatedItemStatus>%d</usCreatedItemStatus>\r\n", gStructureDeconstruct[cnt].usCreatedItemStatus );
|
||||
FilePrintf(hFile,"\t\t<szTileSetName>%s</szTileSetName>\r\n", gStructureDeconstruct[cnt].szTileSetName );
|
||||
|
||||
FilePrintf(hFile,"\t</STRUCTURE>\r\n");
|
||||
}
|
||||
FilePrintf(hFile,"</STRUCTURESLIST>\r\n");
|
||||
}
|
||||
FileClose( hFile );
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
Reference in New Issue
Block a user