mirror of
https://github.com/1dot13/source.git
synced 2026-08-05 14:00:23 +02:00
Improved feature: structures can be dragged. Which ones is defined in a new xml.
For more info, see http://thepit.ja-galaxy-forum.com/index.php?t=msg&goto=360672&#msg_360672 Requires GameDir >= r2558 git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8870 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
+2
-2
@@ -55,8 +55,8 @@
|
||||
|
||||
#endif
|
||||
|
||||
CHAR8 czVersionNumber[16] = { "Build 20.07.17" }; //YY.MM.DD
|
||||
CHAR8 czVersionNumber[16] = { "Build 20.07.24" }; //YY.MM.DD
|
||||
CHAR16 zTrackingNumber[16] = { L"Z" };
|
||||
CHAR16 zRevisionNumber[16] = { L"Revision 8868" };
|
||||
CHAR16 zRevisionNumber[16] = { L"Revision 8870" };
|
||||
|
||||
// SAVE_GAME_VERSION is defined in header, change it there
|
||||
|
||||
+2
-1
@@ -22,6 +22,7 @@ extern CHAR16 zRevisionNumber[16];
|
||||
// Keeps track of the saved game version. Increment the saved game version whenever
|
||||
// you will invalidate the saved game file
|
||||
|
||||
#define DRAGSTRUCTURE 182 // Flugente: we can drag structures behind us
|
||||
#define DISABILITYFLAGMASK 181 // Flugente: disabilities get a flagmask
|
||||
#define PROFILETYPE_STORED 180 // Flugente: the type of each profile is stored in the savegame
|
||||
#define CORPSE_DISPOSAL 179 // Flugente: corpses can be removed by assignment
|
||||
@@ -101,7 +102,7 @@ extern CHAR16 zRevisionNumber[16];
|
||||
#define AP100_SAVEGAME_DATATYPE_CHANGE 105 // Before this, we didn't have the 100AP structure changes
|
||||
#define NIV_SAVEGAME_DATATYPE_CHANGE 102 // Before this, we used the old structure system
|
||||
|
||||
#define SAVE_GAME_VERSION DISABILITYFLAGMASK
|
||||
#define SAVE_GAME_VERSION DRAGSTRUCTURE
|
||||
|
||||
//#define RUSSIANGOLD
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -395,6 +395,10 @@ BOOLEAN LoadExternalGameplayData(STR directoryName, BOOLEAN isMultiplayer)
|
||||
strcat( fileName, INTERACTIVEACTIONSFILENAME );
|
||||
SGP_THROW_IFFALSE( ReadInInteractiveActionsStats( fileName ), INTERACTIVEACTIONSFILENAME );
|
||||
|
||||
strcpy( fileName, directoryName );
|
||||
strcat( fileName, STRUCTUREMOVEFILENAME );
|
||||
SGP_THROW_IFFALSE( ReadInStructureMoveStats( fileName ), STRUCTUREMOVEFILENAME );
|
||||
|
||||
strcpy(fileName, directoryName);
|
||||
strcat(fileName, MERCHANTSFILENAME);
|
||||
SGP_THROW_IFFALSE(ReadInMerchantStats(fileName),MERCHANTSFILENAME);
|
||||
|
||||
+24
-12
@@ -2436,18 +2436,6 @@ BOOLEAN SOLDIERTYPE::Load(HWFILE hFile)
|
||||
if ( guiCurrentSaveGameVersion >= SNITCH_TRAIT_EXTENDED )
|
||||
{
|
||||
numBytesRead = ReadFieldByField(hFile, &this->usSoldierFlagMask2, sizeof(usSoldierFlagMask2), sizeof(UINT32), numBytesRead);
|
||||
|
||||
if ( guiCurrentSaveGameVersion >= INDIVIDUAL_MILITIA )
|
||||
{
|
||||
numBytesRead = ReadFieldByField( hFile, &this->usIndividualMilitiaID, sizeof(usIndividualMilitiaID), sizeof(UINT32), numBytesRead );
|
||||
}
|
||||
else
|
||||
{
|
||||
this->usIndividualMilitiaID = 0;
|
||||
|
||||
for ( int i = 0; i < sizeof(usIndividualMilitiaID); ++i )
|
||||
buffer++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2457,6 +2445,18 @@ BOOLEAN SOLDIERTYPE::Load(HWFILE hFile)
|
||||
buffer++;
|
||||
}
|
||||
|
||||
if ( guiCurrentSaveGameVersion >= INDIVIDUAL_MILITIA )
|
||||
{
|
||||
numBytesRead = ReadFieldByField( hFile, &this->usIndividualMilitiaID, sizeof( usIndividualMilitiaID ), sizeof( UINT32 ), numBytesRead );
|
||||
}
|
||||
else
|
||||
{
|
||||
this->usIndividualMilitiaID = 0;
|
||||
|
||||
for ( int i = 0; i < sizeof( usIndividualMilitiaID ); ++i )
|
||||
buffer++;
|
||||
}
|
||||
|
||||
if ( guiCurrentSaveGameVersion >= DISABILITYFLAGMASK )
|
||||
{
|
||||
numBytesRead = ReadFieldByField( hFile, &this->usDisabilityFlagMask, sizeof( usDisabilityFlagMask ), sizeof( UINT32 ), numBytesRead );
|
||||
@@ -2469,6 +2469,18 @@ BOOLEAN SOLDIERTYPE::Load(HWFILE hFile)
|
||||
buffer++;
|
||||
}
|
||||
|
||||
if ( guiCurrentSaveGameVersion >= DRAGSTRUCTURE )
|
||||
{
|
||||
numBytesRead = ReadFieldByField( hFile, &this->sDragGridNo, sizeof( sDragGridNo ), sizeof( INT32 ), numBytesRead );
|
||||
}
|
||||
else
|
||||
{
|
||||
this->sDragGridNo = NOWHERE;
|
||||
|
||||
for ( int i = 0; i < sizeof( sDragGridNo ); ++i )
|
||||
buffer++;
|
||||
}
|
||||
|
||||
/*if ( guiCurrentSaveGameVersion >= FOOD_CHANGES )
|
||||
{
|
||||
numBytesRead = ReadFieldByField(hFile, &this->bFoodLevel, sizeof(bFoodLevel), sizeof(INT32), numBytesRead);
|
||||
|
||||
@@ -3997,6 +3997,46 @@ BOOLEAN MoveItemPools( INT32 sStartPos, INT32 sEndPos, INT8 bStartLevel, INT8 bE
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
BOOLEAN MoveItemPools_ForDragging( INT32 sStartPos, INT32 sEndPos, INT8 bStartLevel, INT8 bEndLevel )
|
||||
{
|
||||
// note, only works between locations on the ground
|
||||
ITEM_POOL* pItemPool;
|
||||
WORLDITEM TempWorldItem;
|
||||
|
||||
// loop over all items and note the ones we have to move. Move them afterwards, if we do it during the operation we risk pointer issues
|
||||
std::vector<INT32> itemindexestomove_vector;
|
||||
|
||||
if ( bStartLevel )
|
||||
GetItemPoolFromRoof( sStartPos, &pItemPool );
|
||||
else
|
||||
GetItemPoolFromGround( sStartPos, &pItemPool );
|
||||
|
||||
while ( pItemPool )
|
||||
{
|
||||
TempWorldItem = gWorldItems[pItemPool->iItemIndex];
|
||||
|
||||
// don't move an item if it's an armed bomb, an action item or if it isn't a fresh drop
|
||||
if ( TempWorldItem.object.usItem != ACTION_ITEM
|
||||
&& !( TempWorldItem.usFlags & WORLD_ITEM_ARMED_BOMB ) )
|
||||
{
|
||||
itemindexestomove_vector.push_back( pItemPool->iItemIndex );
|
||||
}
|
||||
|
||||
pItemPool = pItemPool->pNext;
|
||||
}
|
||||
|
||||
// now move the stuff
|
||||
for ( std::vector<INT32>::iterator it = itemindexestomove_vector.begin(), itend = itemindexestomove_vector.end(); it != itend; ++it )
|
||||
{
|
||||
TempWorldItem = gWorldItems[(*it)];
|
||||
|
||||
RemoveItemFromPool( sStartPos, ( *it ), bStartLevel );
|
||||
AddItemToPool( sEndPos, &( TempWorldItem.object ), 1, bEndLevel, TempWorldItem.usFlags, TempWorldItem.bRenderZHeightAboveLevel );
|
||||
}
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
BOOLEAN GetItemPool( INT32 usMapPos, ITEM_POOL **ppItemPool, UINT8 ubLevel )
|
||||
{
|
||||
LEVELNODE *pObject;
|
||||
@@ -4065,6 +4105,33 @@ BOOLEAN GetItemPoolFromGround( INT32 sMapPos, ITEM_POOL **ppItemPool )
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
BOOLEAN GetItemPoolFromRoof( INT32 sMapPos, ITEM_POOL **ppItemPool )
|
||||
{
|
||||
// Flugente: apparently the ...Ground version is called a lot, otherwise it would be smarter to just add an extra argument for level
|
||||
LEVELNODE *pObject = gpWorldLevelData[sMapPos].pOnRoofHead;
|
||||
|
||||
( *ppItemPool ) = NULL;
|
||||
|
||||
// LOOP THORUGH OBJECT LAYER
|
||||
while ( pObject != NULL )
|
||||
{
|
||||
if ( pObject->uiFlags & LEVELNODE_ITEM )
|
||||
{
|
||||
( *ppItemPool ) = pObject->pItemPool;
|
||||
|
||||
//DEF added the check because pObject->pItemPool was NULL which was causing problems
|
||||
if ( *ppItemPool )
|
||||
return( TRUE );
|
||||
else
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
pObject = pObject->pNext;
|
||||
}
|
||||
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
void NotifySoldiersToLookforItems( )
|
||||
{
|
||||
UINT32 cnt;
|
||||
@@ -7731,6 +7798,72 @@ UINT8 CheckBuildFortification( INT32 sGridNo, INT8 sLevel, UINT8 usIndex, UINT32
|
||||
return 1;
|
||||
}
|
||||
|
||||
UINT16 gusTempDragBuildSoldierID = NOBODY;
|
||||
|
||||
BOOLEAN BuildStructDrag( INT32 sGridNo, INT8 sLevel, UINT32 uiTileType, UINT8 usIndex, UINT16 usSoldierID )
|
||||
{
|
||||
// needs to be a valid location
|
||||
if ( TileIsOutOfBounds( sGridNo ) )
|
||||
return FALSE;
|
||||
|
||||
// if we want to build on a roof, a roof is required
|
||||
if ( sLevel && !FlatRoofAboveGridNo( sGridNo ) )
|
||||
return FALSE;
|
||||
|
||||
// don't build in water
|
||||
if ( TERRAIN_IS_WATER( GetTerrainType( sGridNo ) ) )
|
||||
return FALSE;
|
||||
|
||||
// do not build into people
|
||||
if ( NOBODY != WhoIsThere2( sGridNo, sLevel ) )
|
||||
return FALSE;
|
||||
|
||||
if ( uiTileType < 0 )
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szMTATextStr[STR_MTA_CANNOT_BUILD] );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gusTempDragBuildSoldierID = usSoldierID;
|
||||
|
||||
// Check with Structure Database (aka ODB) if we can put the object here!
|
||||
BOOLEAN fOkayToAdd = OkayToAddStructureToWorld( sGridNo, sLevel, gTileDatabase[( gTileTypeStartIndex[uiTileType] + usIndex )].pDBStructureRef, INVALID_STRUCTURE_ID );
|
||||
if ( fOkayToAdd || ( gTileDatabase[( gTileTypeStartIndex[uiTileType] + usIndex )].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
|
||||
// Actual structure info is added by the functions below
|
||||
if ( sLevel )
|
||||
{
|
||||
RemoveOnRoofStruct( sGridNo, (UINT16)( gTileTypeStartIndex[uiTileType] + usIndex ) );
|
||||
|
||||
AddOnRoofToTail( sGridNo, (UINT16)( gTileTypeStartIndex[uiTileType] + usIndex ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveStruct( sGridNo, (UINT16)( gTileTypeStartIndex[uiTileType] + usIndex ) );
|
||||
|
||||
AddStructToHead( sGridNo, (UINT16)( gTileTypeStartIndex[uiTileType] + usIndex ) );
|
||||
}
|
||||
|
||||
RecompileLocalMovementCosts( sGridNo );
|
||||
|
||||
// Turn off permanent changes....
|
||||
ApplyMapChangesToMapTempFile( FALSE );
|
||||
SetRenderFlags( RENDER_FLAG_FULL );
|
||||
|
||||
gusTempDragBuildSoldierID = NOBODY;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gusTempDragBuildSoldierID = NOBODY;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN BuildFortification( INT32 sGridNo, INT8 sLevel, UINT8 usIndex, UINT32 usStructureconstructindex )
|
||||
{
|
||||
INT16 sUseObjIndex = -1;
|
||||
@@ -7871,6 +8004,149 @@ BOOLEAN CanRemoveFortification( INT32 sGridNo, INT8 sLevel, UINT32 usStructureco
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN IsDragStructurePresent( INT32 sGridNo, INT8 sLevel, UINT32& arusTileType, UINT16& arusStructureNumber )
|
||||
{
|
||||
// needs to be a valid location
|
||||
if ( TileIsOutOfBounds( sGridNo ) )
|
||||
return FALSE;
|
||||
|
||||
STRUCTURE* pStruct = GetTallestStructureOnGridnoDrag( sGridNo, sLevel );
|
||||
|
||||
if ( pStruct != NULL )
|
||||
{
|
||||
// Get LEVELNODE for struct and remove!
|
||||
LEVELNODE* pNode = FindLevelNodeBasedOnStructure( pStruct->sGridNo, pStruct );
|
||||
|
||||
if ( pNode )
|
||||
{
|
||||
if ( GetTileType( pNode->usIndex, &arusTileType ) )
|
||||
{
|
||||
arusStructureNumber = pStruct->pDBStructureRef->pDBStructure->usStructureNumber;
|
||||
|
||||
// if tileset is from the current tileset, check that
|
||||
for ( int i = 0; i < STRUCTURE_MOVEPOSSIBLE_MAX; ++i )
|
||||
{
|
||||
// if tileset is from the current tileset, check that
|
||||
bool found = FALSE;
|
||||
if ( gTilesets[giCurrentTilesetID].TileSurfaceFilenames[arusTileType][0] )
|
||||
{
|
||||
if ( !_strnicmp( gTilesets[giCurrentTilesetID].TileSurfaceFilenames[arusTileType], gStructureMovePossible[i].szTileSetName, 11 ) )
|
||||
found = true;
|
||||
}
|
||||
// otherwise, check first tileset (GENERIC 1)
|
||||
else if ( gTilesets[0].TileSurfaceFilenames[arusTileType][0] )
|
||||
{
|
||||
if ( !_strnicmp( gTilesets[0].TileSurfaceFilenames[arusTileType], gStructureMovePossible[i].szTileSetName, 11 ) )
|
||||
found = true;
|
||||
}
|
||||
|
||||
if ( found )
|
||||
{
|
||||
for ( size_t j = 0, size = gStructureMovePossible[i].tilevector.size(); j < size; ++j )
|
||||
{
|
||||
if ( gStructureMovePossible[i].tilevector[j] == arusStructureNumber )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void GetDragStructureXmlEntry( UINT32 ausTileType, UINT16 ausStructureNumber, int& arXmlVectorEntry )
|
||||
{
|
||||
arXmlVectorEntry = -1;
|
||||
|
||||
// if tileset is from the current tileset, check that
|
||||
for ( int i = 0; i < STRUCTURE_MOVEPOSSIBLE_MAX; ++i )
|
||||
{
|
||||
// if tileset is from the current tileset, check that
|
||||
bool found = FALSE;
|
||||
if ( gTilesets[giCurrentTilesetID].TileSurfaceFilenames[ausTileType][0] )
|
||||
{
|
||||
if ( !_strnicmp( gTilesets[giCurrentTilesetID].TileSurfaceFilenames[ausTileType], gStructureMovePossible[i].szTileSetName, 11 ) )
|
||||
found = true;
|
||||
}
|
||||
// otherwise, check first tileset (GENERIC 1)
|
||||
else if ( gTilesets[0].TileSurfaceFilenames[ausTileType][0] )
|
||||
{
|
||||
if ( !_strnicmp( gTilesets[0].TileSurfaceFilenames[ausTileType], gStructureMovePossible[i].szTileSetName, 11 ) )
|
||||
found = true;
|
||||
}
|
||||
|
||||
if ( found )
|
||||
{
|
||||
for ( size_t j = 0, size = gStructureMovePossible[i].tilevector.size(); j < size; ++j )
|
||||
{
|
||||
if ( gStructureMovePossible[i].tilevector[j] == ausStructureNumber )
|
||||
{
|
||||
arXmlVectorEntry = i;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN RemoveStructDrag( INT32 sGridNo, INT8 sLevel, UINT32 uiTileType )
|
||||
{
|
||||
// needs to be a valid location
|
||||
if ( TileIsOutOfBounds( sGridNo ) )
|
||||
return FALSE;
|
||||
|
||||
STRUCTURE* pStruct = GetTallestStructureOnGridnoDrag( sGridNo, sLevel );
|
||||
|
||||
if ( pStruct != NULL )
|
||||
{
|
||||
// Get LEVELNODE for struct and remove!
|
||||
LEVELNODE* pNode = FindLevelNodeBasedOnStructure( pStruct->sGridNo, pStruct );
|
||||
|
||||
if ( pNode )
|
||||
{
|
||||
UINT16 usIndex = pNode->usIndex;
|
||||
|
||||
// Remove old graphic
|
||||
ApplyMapChangesToMapTempFile( TRUE );
|
||||
|
||||
if ( sLevel )
|
||||
{
|
||||
RemoveOnRoofStruct( sGridNo, usIndex );
|
||||
}
|
||||
|
||||
// if this is a wall, check wether the roof will collapse.
|
||||
// Yes, the player can damage himself by collapsing the roof of the house he is currently in. Such stupidity has to be punished.
|
||||
if ( pStruct->fFlags & STRUCTURE_WALL )
|
||||
{
|
||||
// this isn't an explosion, so the structural damage is moderate
|
||||
HandleRoofDestruction( sGridNo, 50 );
|
||||
}
|
||||
|
||||
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 );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN RemoveFortification( INT32 sGridNo, INT8 sLevel, UINT32 usStructureconstructindex )
|
||||
{
|
||||
// needs to be a valid location
|
||||
|
||||
@@ -159,6 +159,20 @@ typedef struct INTERACTIVE_STRUCTURE {
|
||||
extern INTERACTIVE_STRUCTURE gInteractiveStructure[INTERACTIVE_STRUCTURE_MAX];
|
||||
extern UINT32 gMaxInteractiveStructureRead;
|
||||
|
||||
// Flugente: we need to define what structures can be moved. Otherwise the player will drag around parts of the scenery.
|
||||
typedef struct STRUCTURE_MOVEPOSSIBLE {
|
||||
STRUCTURE_MOVEPOSSIBLE()
|
||||
: szTileSetDisplayName(), szTileSetName() {}
|
||||
|
||||
char szTileSetDisplayName[20]; // name of this structure to the player (tileset names are obscure)
|
||||
char szTileSetName[20]; // name of the tileset
|
||||
std::vector<UINT8> tilevector; // structures in the tileset that we can deconstruct
|
||||
} STRUCTURE_MOVEPOSSIBLE;
|
||||
|
||||
#define STRUCTURE_MOVEPOSSIBLE_MAX 200
|
||||
|
||||
extern STRUCTURE_MOVEPOSSIBLE gStructureMovePossible[STRUCTURE_MOVEPOSSIBLE_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 );
|
||||
@@ -186,10 +200,12 @@ OBJECTTYPE* InternalAddItemToPool( INT32 *psGridNo, OBJECTTYPE *pObject, INT8 bV
|
||||
INT32 AdjustGridNoForItemPlacement( SOLDIERTYPE *pSoldier, INT32 sGridNo );
|
||||
BOOLEAN GetItemPool( INT32 usMapPos, ITEM_POOL **ppItemPool, UINT8 ubLevel );
|
||||
BOOLEAN GetItemPoolFromGround( INT32 sMapPos, ITEM_POOL **ppItemPool );
|
||||
BOOLEAN GetItemPoolFromRoof( INT32 sMapPos, ITEM_POOL **ppItemPool );
|
||||
BOOLEAN DrawItemPoolList( ITEM_POOL *pItemPool, INT32 sGridNo, UINT8 bCommand, INT8 bZLevel, INT16 sXPos, INT16 sYPos );
|
||||
BOOLEAN RemoveItemFromPool( INT32 sGridNo, INT32 iItemIndex, UINT8 ubLevel );
|
||||
BOOLEAN ItemExistsAtLocation( INT32 sGridNo, INT32 iItemIndex, UINT8 ubLevel );
|
||||
BOOLEAN MoveItemPools( INT32 sStartPos, INT32 sEndPos, INT8 bStartLevel, INT8 bEndLevel );
|
||||
BOOLEAN MoveItemPools_ForDragging( INT32 sStartPos, INT32 sEndPos, INT8 bStartLevel, INT8 bEndLevel );
|
||||
|
||||
void SetItemPoolLocator( ITEM_POOL *pItemPool );
|
||||
void SetItemPoolLocatorWithCallback( ITEM_POOL *pItemPool, ITEM_POOL_LOCATOR_HOOK Callback );
|
||||
@@ -274,6 +290,11 @@ BOOLEAN BuildFortification( INT32 sGridNo, INT8 sLevel, UINT8 usIndex, UINT32 us
|
||||
BOOLEAN CanRemoveFortification( INT32 sGridNo, INT8 sLevel, UINT32 usStructureconstructindex );
|
||||
BOOLEAN RemoveFortification( INT32 sGridNo, INT8 sLevel, UINT32 usStructureconstructindex );
|
||||
|
||||
BOOLEAN IsDragStructurePresent( INT32 sGridNo, INT8 sLevel, UINT32& arusTileType, UINT16& arusStructureNumber );
|
||||
void GetDragStructureXmlEntry( UINT32 ausTileType, UINT16 ausStructureNumber, int& arXmlVectorEntry );
|
||||
BOOLEAN RemoveStructDrag( INT32 sGridNo, INT8 sLevel, UINT32 uiTileType );
|
||||
BOOLEAN BuildStructDrag( INT32 sGridNo, INT8 sLevel, UINT32 uiTileType, UINT8 usIndex, UINT16 usSoldierID );
|
||||
|
||||
void UpdateFortificationPossibleAmount();
|
||||
void HandleFortificationUpdate();
|
||||
|
||||
|
||||
+49
-2
@@ -15,6 +15,7 @@
|
||||
#include "Map Screen Interface.h"
|
||||
#include "Rotting Corpses.h"
|
||||
#include "Dialogue Control.h"
|
||||
#include "Handle Items.h"
|
||||
|
||||
extern void GetEquipmentTemplates( );
|
||||
|
||||
@@ -115,6 +116,7 @@ void Wrapper_Cancel_SoldierSelection( UINT32 aVal ) { gSoldierSelection.Cancel(
|
||||
DragSelection gDragSelection;
|
||||
|
||||
void Wrapper_Function_DragSelection( UINT32 aVal) { gDragSelection.Functions(aVal); }
|
||||
void Wrapper_Function_DragSelection_GridNo( INT32 aVal ){ gDragSelection.FunctionsGridNo( aVal ); }
|
||||
void Wrapper_Setup_DragSelection( UINT32 aVal ) { gDragSelection.Setup( aVal ); }
|
||||
void Wrapper_Cancel_DragSelection( UINT32 aVal ) { gDragSelection.Cancel( ); }
|
||||
/////////////////////////////// Drag Selection ////////////////////////////////////////////
|
||||
@@ -844,9 +846,34 @@ DragSelection::Setup( UINT32 aVal )
|
||||
GetPopup( )->addOption( *pOption );
|
||||
}
|
||||
|
||||
// gridno
|
||||
for ( int ubDirection = 0; ubDirection < NUM_WORLD_DIRECTIONS; ++ubDirection )
|
||||
{
|
||||
INT32 sTempGridNo = NewGridNo( pSoldier->sGridNo, DirectionInc( ubDirection ) );
|
||||
|
||||
UINT32 tiletype;
|
||||
UINT16 structurenumber;
|
||||
if ( pSoldier->CanDragStructure( sTempGridNo )
|
||||
&& IsDragStructurePresent( sTempGridNo, pSoldier->pathing.bLevel, tiletype, structurenumber ) )
|
||||
{
|
||||
int xmlentry;
|
||||
GetDragStructureXmlEntry( tiletype, structurenumber, xmlentry );
|
||||
|
||||
if ( xmlentry >= 0 )
|
||||
{
|
||||
swprintf( pStr, L"%hs %s", gStructureMovePossible[xmlentry].szTileSetDisplayName, FaceDirs[gOneCDirection[ubDirection]] );
|
||||
|
||||
// we have to use an offset of NOBODY in order to differentiate between person and corpse
|
||||
pOption = new POPUP_OPTION( &std::wstring( pStr ), new popupCallbackFunction<void, UINT32>( &Wrapper_Function_DragSelection_GridNo, sTempGridNo ) );
|
||||
|
||||
GetPopup()->addOption( *pOption );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// cancel option
|
||||
swprintf( pStr, pSkillMenuStrings[SKILLMENU_CANCEL] );
|
||||
pOption = new POPUP_OPTION( &std::wstring( pStr ), new popupCallbackFunction<void, UINT32>( &Wrapper_Cancel_SoldierSelection, 0 ) );
|
||||
pOption = new POPUP_OPTION( &std::wstring( pStr ), new popupCallbackFunction<void, UINT32>( &Wrapper_Cancel_DragSelection, 0 ) );
|
||||
GetPopup( )->addOption( *pOption );
|
||||
}
|
||||
|
||||
@@ -863,7 +890,7 @@ DragSelection::Functions( UINT32 aVal )
|
||||
|
||||
if ( pSoldier )
|
||||
{
|
||||
BOOLEAN result = pSoldier->UseSkill( usSkill, sTraitsMenuTargetGridNo, aVal );
|
||||
BOOLEAN result = pSoldier->UseSkill( usSkill, NOWHERE, aVal );
|
||||
|
||||
// additional dialogue
|
||||
AdditionalTacticalCharacterDialogue_CallsLua( pSoldier, ADE_SKILL_RESULT, usSkill, result );
|
||||
@@ -873,6 +900,26 @@ DragSelection::Functions( UINT32 aVal )
|
||||
gSkillSelection.Cancel();
|
||||
gTraitSelection.Cancel( );
|
||||
}
|
||||
|
||||
void
|
||||
DragSelection::FunctionsGridNo( INT32 aVal )
|
||||
{
|
||||
SOLDIERTYPE * pSoldier = NULL;
|
||||
|
||||
GetSoldier( &pSoldier, gusSelectedSoldier );
|
||||
|
||||
if ( pSoldier )
|
||||
{
|
||||
BOOLEAN result = pSoldier->UseSkill( usSkill, aVal, 0 );
|
||||
|
||||
// additional dialogue
|
||||
AdditionalTacticalCharacterDialogue_CallsLua( pSoldier, ADE_SKILL_RESULT, usSkill, result );
|
||||
}
|
||||
|
||||
Cancel();
|
||||
gSkillSelection.Cancel();
|
||||
gTraitSelection.Cancel();
|
||||
}
|
||||
/////////////////////////////// Drag Selection ////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
|
||||
@@ -162,6 +162,7 @@ public:
|
||||
|
||||
void Setup( UINT32 aVal );
|
||||
void Functions( UINT32 aVal );
|
||||
void FunctionsGridNo( INT32 aVal );
|
||||
|
||||
private:
|
||||
UINT32 usSkill;
|
||||
|
||||
+312
-31
@@ -1144,6 +1144,7 @@ void SOLDIERTYPE::initialize( )
|
||||
this->usQuickItemId = 0;
|
||||
this->ubQuickItemSlot = 0;
|
||||
this->usDisabilityFlagMask = 0;
|
||||
this->sDragGridNo = NOWHERE;
|
||||
}
|
||||
|
||||
bool SOLDIERTYPE::exists( )
|
||||
@@ -11705,34 +11706,7 @@ void SOLDIERTYPE::MoveMerc( FLOAT dMovementChange, FLOAT dAngle, BOOLEAN fCheckR
|
||||
// Flugente: drag people
|
||||
if ( currentlydragging )
|
||||
{
|
||||
// sevenfm: play sound while dragging
|
||||
if (!(this->usSoldierFlagMask2 & SOLDIER_DRAG_SOUND))
|
||||
{
|
||||
SGPFILENAME zFilename_Used;
|
||||
CHAR8 zFilename[512];
|
||||
// prepare drag sound
|
||||
if (gsDragSoundNum < 0)
|
||||
{
|
||||
gsDragSoundNum = 0;
|
||||
do
|
||||
{
|
||||
gsDragSoundNum++;
|
||||
sprintf(zFilename, "Sounds\\Misc\\DragBody%d", gsDragSoundNum);
|
||||
} while ( SoundFileExists( zFilename, zFilename_Used ) );
|
||||
gsDragSoundNum--;
|
||||
}
|
||||
|
||||
if (gsDragSoundNum > 0)
|
||||
{
|
||||
sprintf(zFilename, "Sounds\\Misc\\DragBody%d", Random(gsDragSoundNum) + 1);
|
||||
if ( SoundFileExists( zFilename, zFilename_Used ) )
|
||||
{
|
||||
PlayJA2SampleFromFile( zFilename_Used, RATE_11025, SoundVolume(MIDVOLUME, this->sGridNo), 1, SoundDir(this->sGridNo));
|
||||
}
|
||||
|
||||
this->usSoldierFlagMask2 |= SOLDIER_DRAG_SOUND;
|
||||
}
|
||||
}
|
||||
bool dragaborted = false;
|
||||
|
||||
if ( this->usDragPersonID != NOBODY )
|
||||
{
|
||||
@@ -11742,7 +11716,6 @@ void SOLDIERTYPE::MoveMerc( FLOAT dMovementChange, FLOAT dAngle, BOOLEAN fCheckR
|
||||
{
|
||||
// while it would be neat to take the opposite direction (which would make it look like we drag the other person by the legs),
|
||||
// this causes problems, as a prone person needs additional space for the legs. So just take the same direction
|
||||
//pSoldier->ubDirection = (this->ubDirection + 4 ) % NUM_WORLD_DIRECTIONS;
|
||||
pSoldier->ubDirection = this->ubDirection;
|
||||
|
||||
FLOAT dx = 0;
|
||||
@@ -11769,6 +11742,10 @@ void SOLDIERTYPE::MoveMerc( FLOAT dMovementChange, FLOAT dAngle, BOOLEAN fCheckR
|
||||
|
||||
pSoldier->EVENT_InternalSetSoldierPosition( base_x + dx, base_y + dy, FALSE, FALSE, FALSE );
|
||||
}
|
||||
else
|
||||
{
|
||||
dragaborted = true;
|
||||
}
|
||||
}
|
||||
else if ( this->sDragCorpseID >= 0 )
|
||||
{
|
||||
@@ -11776,6 +11753,10 @@ void SOLDIERTYPE::MoveMerc( FLOAT dMovementChange, FLOAT dAngle, BOOLEAN fCheckR
|
||||
|
||||
if ( pCorpse )
|
||||
{
|
||||
// move all enemy-dropped items along with the corpse, to make it look as if the items are still 'on' the body
|
||||
if ( sOldGridNo != this->sGridNo )
|
||||
MoveItemPools_ForDragging( pCorpse->def.sGridNo, sOldGridNo, this->pathing.bLevel, this->pathing.bLevel );
|
||||
|
||||
// move corpse to new location. We have to actually delete and recreate the corpse, otherwise direction changes will only be visible after saving the game
|
||||
ROTTING_CORPSE_DEFINITION CorpseDef;
|
||||
|
||||
@@ -11820,6 +11801,82 @@ void SOLDIERTYPE::MoveMerc( FLOAT dMovementChange, FLOAT dAngle, BOOLEAN fCheckR
|
||||
|
||||
this->sDragCorpseID = AddRottingCorpse(&CorpseDef);
|
||||
}
|
||||
else
|
||||
{
|
||||
dragaborted = true;
|
||||
}
|
||||
}
|
||||
else if ( sOldGridNo != this->sGridNo && this->sDragGridNo != NOWHERE )
|
||||
{
|
||||
bool success = false;
|
||||
UINT32 arusTileType;
|
||||
UINT16 arusStructureNumber;
|
||||
if ( IsDragStructurePresent( this->sDragGridNo, this->pathing.bLevel, arusTileType, arusStructureNumber ) )
|
||||
{
|
||||
// add
|
||||
if ( BuildStructDrag( sOldGridNo, gsInterfaceLevel, arusTileType, arusStructureNumber, this->ubID ) )
|
||||
{
|
||||
// remove
|
||||
RemoveStructDrag( this->sDragGridNo, gsInterfaceLevel, arusTileType );
|
||||
|
||||
// also move doors, this includes moving locks and traps
|
||||
DOOR* pDoor = FindDoorInfoAtGridNo( this->sDragGridNo );
|
||||
if ( pDoor )
|
||||
pDoor->sGridNo = sOldGridNo;
|
||||
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( success )
|
||||
{
|
||||
// move all items in/on the structure along
|
||||
MoveItemPools_ForDragging( this->sDragGridNo, sOldGridNo, this->pathing.bLevel, this->pathing.bLevel );
|
||||
|
||||
this->sDragGridNo = sOldGridNo;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->CancelDrag();
|
||||
|
||||
dragaborted = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !dragaborted )
|
||||
{
|
||||
// sevenfm: play sound while dragging
|
||||
if ( !( this->usSoldierFlagMask2 & SOLDIER_DRAG_SOUND ) )
|
||||
{
|
||||
SGPFILENAME zFilename_Used;
|
||||
CHAR8 zFilename[512];
|
||||
// prepare drag sound
|
||||
if ( gsDragSoundNum < 0 )
|
||||
{
|
||||
gsDragSoundNum = 0;
|
||||
do
|
||||
{
|
||||
gsDragSoundNum++;
|
||||
sprintf( zFilename, "Sounds\\Misc\\DragBody%d", gsDragSoundNum );
|
||||
} while ( SoundFileExists( zFilename, zFilename_Used ) );
|
||||
gsDragSoundNum--;
|
||||
}
|
||||
|
||||
if ( gsDragSoundNum > 0 )
|
||||
{
|
||||
sprintf( zFilename, "Sounds\\Misc\\DragBody%d", Random( gsDragSoundNum ) + 1 );
|
||||
if ( SoundFileExists( zFilename, zFilename_Used ) )
|
||||
{
|
||||
PlayJA2SampleFromFile( zFilename_Used, RATE_11025, SoundVolume( MIDVOLUME, this->sGridNo ), 1, SoundDir( this->sGridNo ) );
|
||||
}
|
||||
|
||||
this->usSoldierFlagMask2 |= SOLDIER_DRAG_SOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->CancelDrag();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18144,14 +18201,16 @@ BOOLEAN SOLDIERTYPE::UseSkill( UINT8 iSkill, INT32 usMapPos, UINT32 ID )
|
||||
|
||||
case SKILLS_CREATE_TURNCOAT:
|
||||
AttemptToCreateTurncoat ( ID );
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
case SKILLS_ACTIVATE_TURNCOATS:
|
||||
OrderTurnCoatToSwitchSides( ID );
|
||||
return OrderTurnCoatToSwitchSides( ID );
|
||||
break;
|
||||
|
||||
case SKILLS_ACTIVATE_TURNCOATS_ALL:
|
||||
OrderAllTurnCoatToSwitchSides();
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
case SKILLS_SPOTTER:
|
||||
@@ -18164,19 +18223,27 @@ BOOLEAN SOLDIERTYPE::UseSkill( UINT8 iSkill, INT32 usMapPos, UINT32 ID )
|
||||
{
|
||||
usSoldierFlagMask2 &= ~SOLDIER_TRAIT_FOCUS;
|
||||
sFocusGridNo = NOWHERE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
usSoldierFlagMask2 |= SOLDIER_TRAIT_FOCUS;
|
||||
sFocusGridNo = usMapPos;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case SKILLS_DRAG:
|
||||
if ( ID < NOBODY )
|
||||
if ( usMapPos != NOWHERE )
|
||||
SetDragOrderStructure( usMapPos );
|
||||
else if ( ID < NOBODY )
|
||||
SetDragOrderPerson( ID );
|
||||
else
|
||||
SetDragOrderCorpse( ID - NOBODY );
|
||||
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -20466,6 +20533,191 @@ BOOLEAN SOLDIERTYPE::CanDragCorpse( UINT16 usCorpseNum )
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN SOLDIERTYPE::CanDragStructure( INT32 sGridNo )
|
||||
{
|
||||
if ( !CanDragInPrinciple() )
|
||||
return FALSE;
|
||||
|
||||
if ( sGridNo == NOWHERE )
|
||||
return FALSE;
|
||||
|
||||
// not on the same tile
|
||||
if ( sGridNo == this->sGridNo )
|
||||
return FALSE;
|
||||
|
||||
// not in water
|
||||
if ( TERRAIN_IS_HIGH_WATER( sGridNo ) )
|
||||
return FALSE;
|
||||
|
||||
// must be near us
|
||||
if ( PythSpacesAway( sGridNo, this->sGridNo ) > 1 )
|
||||
return FALSE;
|
||||
|
||||
UINT32 tiletype;
|
||||
UINT16 structurenumber;
|
||||
if ( !IsDragStructurePresent( sGridNo, this->pathing.bLevel, tiletype, structurenumber ) )
|
||||
return FALSE;
|
||||
|
||||
// Now we need to check if there is not a wall between the two middle tiles
|
||||
UINT8 ubDragDirection = GetDirectionToGridNoFromGridNo( this->sGridNo, sGridNo );
|
||||
|
||||
{
|
||||
switch ( ubDragDirection )
|
||||
{
|
||||
case NORTH:
|
||||
if ( WallOrClosedDoorExistsOfTopLeftOrientation( sGridNo ) )
|
||||
return FALSE;
|
||||
break;
|
||||
case EAST:
|
||||
if ( WallOrClosedDoorExistsOfTopRightOrientation( this->sGridNo ) )
|
||||
return FALSE;
|
||||
break;
|
||||
case SOUTH:
|
||||
if ( WallOrClosedDoorExistsOfTopLeftOrientation( this->sGridNo ) )
|
||||
return FALSE;
|
||||
break;
|
||||
case WEST:
|
||||
if ( WallOrClosedDoorExistsOfTopRightOrientation( sGridNo ) )
|
||||
return FALSE;
|
||||
break;
|
||||
|
||||
case NORTHEAST:
|
||||
{
|
||||
bool successA = true;
|
||||
bool successB = true;
|
||||
|
||||
// two possibilities:
|
||||
// A) check whether there is no wall to our north, and no wall from there to the east
|
||||
{
|
||||
INT32 midpointgridno = NewGridNo( this->sGridNo, DirectionInc( NORTH ) );
|
||||
|
||||
if ( WallOrClosedDoorExistsOfTopLeftOrientation( midpointgridno )
|
||||
|| WallOrClosedDoorExistsOfTopRightOrientation( midpointgridno ) )
|
||||
{
|
||||
successA = false;
|
||||
}
|
||||
}
|
||||
|
||||
// B) check whether there is no wall to our east, and no wall from there to the north
|
||||
{
|
||||
INT32 midpointgridno = NewGridNo( this->sGridNo, DirectionInc( EAST ) );
|
||||
|
||||
if ( WallOrClosedDoorExistsOfTopRightOrientation( this->sGridNo )
|
||||
|| WallOrClosedDoorExistsOfTopLeftOrientation( sGridNo ) )
|
||||
{
|
||||
successB = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !successA && !successB )
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case SOUTHEAST:
|
||||
{
|
||||
bool successA = true;
|
||||
bool successB = true;
|
||||
|
||||
// two possibilities:
|
||||
// A) check whether there is no wall to our south, and no wall from there to the east
|
||||
{
|
||||
INT32 midpointgridno = NewGridNo( this->sGridNo, DirectionInc( SOUTH ) );
|
||||
|
||||
if ( WallOrClosedDoorExistsOfTopLeftOrientation( this->sGridNo )
|
||||
|| WallOrClosedDoorExistsOfTopRightOrientation( midpointgridno ) )
|
||||
{
|
||||
successA = false;
|
||||
}
|
||||
}
|
||||
|
||||
// B) check whether there is no wall to our east, and no wall from there to the south
|
||||
{
|
||||
INT32 midpointgridno = NewGridNo( this->sGridNo, DirectionInc( EAST ) );
|
||||
|
||||
if ( WallOrClosedDoorExistsOfTopRightOrientation( this->sGridNo )
|
||||
|| WallOrClosedDoorExistsOfTopLeftOrientation( midpointgridno ) )
|
||||
{
|
||||
successB = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !successA && !successB )
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case SOUTHWEST:
|
||||
{
|
||||
bool successA = true;
|
||||
bool successB = true;
|
||||
|
||||
// two possibilities:
|
||||
// A) check whether there is no wall to our south, and no wall from there to the west
|
||||
{
|
||||
INT32 midpointgridno = NewGridNo( this->sGridNo, DirectionInc( SOUTH ) );
|
||||
|
||||
if ( WallOrClosedDoorExistsOfTopLeftOrientation( this->sGridNo )
|
||||
|| WallOrClosedDoorExistsOfTopRightOrientation( sGridNo ) )
|
||||
{
|
||||
successA = false;
|
||||
}
|
||||
}
|
||||
|
||||
// B) check whether there is no wall to our west, and no wall from there to the south
|
||||
{
|
||||
INT32 midpointgridno = NewGridNo( this->sGridNo, DirectionInc( WEST ) );
|
||||
|
||||
if ( WallOrClosedDoorExistsOfTopRightOrientation( midpointgridno )
|
||||
|| WallOrClosedDoorExistsOfTopLeftOrientation( midpointgridno ) )
|
||||
{
|
||||
successB = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !successA && !successB )
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case NORTHWEST:
|
||||
{
|
||||
bool successA = true;
|
||||
bool successB = true;
|
||||
|
||||
// two possibilities:
|
||||
// A) check whether there is no wall to our north, and no wall from there to the west
|
||||
{
|
||||
INT32 midpointgridno = NewGridNo( this->sGridNo, DirectionInc( NORTH ) );
|
||||
|
||||
if ( WallOrClosedDoorExistsOfTopLeftOrientation( midpointgridno )
|
||||
|| WallOrClosedDoorExistsOfTopRightOrientation( sGridNo ) )
|
||||
{
|
||||
successA = false;
|
||||
}
|
||||
}
|
||||
|
||||
// B) check whether there is no wall to our west, and no wall from there to the north
|
||||
{
|
||||
INT32 midpointgridno = NewGridNo( this->sGridNo, DirectionInc( WEST ) );
|
||||
|
||||
if ( WallOrClosedDoorExistsOfTopRightOrientation( midpointgridno )
|
||||
|| WallOrClosedDoorExistsOfTopLeftOrientation( sGridNo ) )
|
||||
{
|
||||
successB = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !successA && !successB )
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN SOLDIERTYPE::IsDraggingSomeone( bool aStopIfConditionNotSatisfied )
|
||||
{
|
||||
if ( this->sDragCorpseID >= 0 )
|
||||
@@ -20482,6 +20734,13 @@ BOOLEAN SOLDIERTYPE::IsDraggingSomeone( bool aStopIfConditionNotSatisfied )
|
||||
else if ( aStopIfConditionNotSatisfied )
|
||||
CancelDrag();
|
||||
}
|
||||
else if ( this->sDragGridNo != NOWHERE )
|
||||
{
|
||||
if ( this->CanDragStructure( this->sDragGridNo ) )
|
||||
return TRUE;
|
||||
else if ( aStopIfConditionNotSatisfied )
|
||||
CancelDrag();
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@@ -20528,6 +20787,27 @@ void SOLDIERTYPE::SetDragOrderCorpse( UINT32 usID )
|
||||
}
|
||||
}
|
||||
|
||||
void SOLDIERTYPE::SetDragOrderStructure( INT32 sGridNo )
|
||||
{
|
||||
if ( CanDragStructure( sGridNo ) )
|
||||
{
|
||||
// sevenfm: if someone is dragging this corpse, cancel drag
|
||||
SOLDIERTYPE *pSoldier;
|
||||
for ( UINT32 uiLoop = 0; uiLoop < guiNumMercSlots; ++uiLoop )
|
||||
{
|
||||
pSoldier = MercPtrs[uiLoop];
|
||||
if ( pSoldier && pSoldier->sDragGridNo == sGridNo )
|
||||
{
|
||||
pSoldier->CancelDrag();
|
||||
}
|
||||
}
|
||||
|
||||
CancelDrag();
|
||||
|
||||
this->sDragGridNo = sGridNo;
|
||||
}
|
||||
}
|
||||
|
||||
void SOLDIERTYPE::CancelDrag()
|
||||
{
|
||||
// if we are dragging a person, set them to the center of their gridno, otherwise their position might be off
|
||||
@@ -20547,6 +20827,7 @@ void SOLDIERTYPE::CancelDrag()
|
||||
|
||||
this->usDragPersonID = NOBODY;
|
||||
this->sDragCorpseID = -1;
|
||||
this->sDragGridNo = NOWHERE;
|
||||
}
|
||||
|
||||
// Flugente: spy assignments
|
||||
|
||||
@@ -1585,6 +1585,9 @@ public:
|
||||
|
||||
// Flugente: store disabilities as a flagmask, so we can have multiple ones
|
||||
UINT32 usDisabilityFlagMask;
|
||||
|
||||
// Flugente: drag structures
|
||||
INT32 sDragGridNo;
|
||||
|
||||
#ifdef JA2UB
|
||||
//ja25
|
||||
@@ -2015,9 +2018,11 @@ public:
|
||||
BOOLEAN CanDragInPrinciple();
|
||||
BOOLEAN CanDragPerson( UINT16 usID );
|
||||
BOOLEAN CanDragCorpse( UINT16 usCorpseNum );
|
||||
BOOLEAN CanDragStructure( INT32 sGridNo );
|
||||
BOOLEAN IsDraggingSomeone(bool aStopIfConditionNotSatisfied = true);
|
||||
void SetDragOrderPerson( UINT16 usID );
|
||||
void SetDragOrderCorpse( UINT32 usID );
|
||||
void SetDragOrderStructure( INT32 sGridNo );
|
||||
void CancelDrag();
|
||||
|
||||
// Flugente: spy assignments
|
||||
|
||||
@@ -1260,6 +1260,10 @@
|
||||
RelativePath=".\XML_StructureDeconstruct.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_Structure_Move.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_Taunts.cpp"
|
||||
>
|
||||
|
||||
@@ -1262,6 +1262,10 @@
|
||||
RelativePath=".\XML_StructureDeconstruct.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_Structure_Move.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_Taunts.cpp"
|
||||
>
|
||||
|
||||
@@ -277,6 +277,7 @@
|
||||
<ClCompile Include="XML_SpreadPatterns.cpp" />
|
||||
<ClCompile Include="XML_StructureConstruct.cpp" />
|
||||
<ClCompile Include="XML_StructureDeconstruct.cpp" />
|
||||
<ClCompile Include="XML_Structure_Move.cpp" />
|
||||
<ClCompile Include="XML_Taunts.cpp" />
|
||||
<ClCompile Include="XML_AdditionalTileProperties.cpp" />
|
||||
<ClCompile Include="XML_TonyInventory.cpp" />
|
||||
|
||||
@@ -742,6 +742,9 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="XML_StructureDeconstruct.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XML_Structure_Move.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XML_StructureConstruct.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
|
||||
@@ -278,6 +278,7 @@
|
||||
<ClCompile Include="XML_SpreadPatterns.cpp" />
|
||||
<ClCompile Include="XML_StructureConstruct.cpp" />
|
||||
<ClCompile Include="XML_StructureDeconstruct.cpp" />
|
||||
<ClCompile Include="XML_Structure_Move.cpp" />
|
||||
<ClCompile Include="XML_Taunts.cpp" />
|
||||
<ClCompile Include="XML_AdditionalTileProperties.cpp" />
|
||||
<ClCompile Include="XML_TonyInventory.cpp" />
|
||||
|
||||
@@ -652,6 +652,9 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="XML_StructureDeconstruct.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XML_Structure_Move.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XML_TonyInventory.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
|
||||
@@ -278,6 +278,7 @@
|
||||
<ClCompile Include="XML_SpreadPatterns.cpp" />
|
||||
<ClCompile Include="XML_StructureConstruct.cpp" />
|
||||
<ClCompile Include="XML_StructureDeconstruct.cpp" />
|
||||
<ClCompile Include="XML_Structure_Move.cpp" />
|
||||
<ClCompile Include="XML_Taunts.cpp" />
|
||||
<ClCompile Include="XML_AdditionalTileProperties.cpp" />
|
||||
<ClCompile Include="XML_TonyInventory.cpp" />
|
||||
|
||||
@@ -653,6 +653,9 @@
|
||||
<ClCompile Include="XML_StructureDeconstruct.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XML_Structure_Move.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XML_TonyInventory.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -278,6 +278,7 @@
|
||||
<ClCompile Include="XML_SpreadPatterns.cpp" />
|
||||
<ClCompile Include="XML_StructureConstruct.cpp" />
|
||||
<ClCompile Include="XML_StructureDeconstruct.cpp" />
|
||||
<ClCompile Include="XML_Structure_Move.cpp" />
|
||||
<ClCompile Include="XML_Taunts.cpp" />
|
||||
<ClCompile Include="XML_AdditionalTileProperties.cpp" />
|
||||
<ClCompile Include="XML_TonyInventory.cpp" />
|
||||
|
||||
@@ -652,6 +652,9 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="XML_StructureDeconstruct.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XML_Structure_Move.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XML_TonyInventory.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
|
||||
@@ -78,6 +78,7 @@ typedef PARSE_STAGE;
|
||||
#define FOODOPINIONFILENAME "Items\\FoodOpinion.xml"
|
||||
#define STRUCTUREDECONSTRUCTFILENAME "Items\\StructureDeconstruct.xml"
|
||||
#define STRUCTURECONSTRUCTFILENAME "Items\\StructureConstruct.xml"
|
||||
#define STRUCTUREMOVEFILENAME "Items\\StructureMove.xml"
|
||||
#define CLOTHESFILENAME "Items\\Clothes.xml"
|
||||
#define RANDOMITEMFILENAME "Items\\RandomItem.xml"
|
||||
#define AMMOFILENAME "Items\\AmmoStrings.xml"
|
||||
@@ -335,6 +336,11 @@ extern BOOLEAN WriteStructureConstructStats();
|
||||
extern BOOLEAN ReadInInteractiveActionsStats( STR fileName );
|
||||
extern BOOLEAN WriteInteractiveActionsStats( );
|
||||
|
||||
// Flugente: structure move
|
||||
extern BOOLEAN ReadInStructureMoveStats( STR fileName );
|
||||
extern BOOLEAN WriteStructureMoveStats();
|
||||
|
||||
|
||||
// Flugente: merchants
|
||||
extern BOOLEAN ReadInMerchantStats(STR fileName);
|
||||
extern BOOLEAN WriteMerchantStats();
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
#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
|
||||
|
||||
STRUCTURE_MOVEPOSSIBLE gStructureMovePossible[STRUCTURE_MOVEPOSSIBLE_MAX];
|
||||
|
||||
struct
|
||||
{
|
||||
PARSE_STAGE curElement;
|
||||
|
||||
CHAR8 szCharData[MAX_CHAR_DATA_LENGTH + 1];
|
||||
STRUCTURE_MOVEPOSSIBLE* curArray;
|
||||
UINT32 maxArraySize;
|
||||
UINT32 curIndex;
|
||||
UINT32 currentDepth;
|
||||
UINT32 maxReadDepth;
|
||||
}
|
||||
typedef structuremoveParseData;
|
||||
|
||||
static void XMLCALL
|
||||
structuredemoveStartElementHandle( void *userData, const XML_Char *name, const XML_Char **atts )
|
||||
{
|
||||
structuremoveParseData * pData = (structuremoveParseData *)userData;
|
||||
|
||||
if ( pData->currentDepth <= pData->maxReadDepth ) //are we reading this element?
|
||||
{
|
||||
if ( strcmp( name, "STRUCTURESLIST" ) == 0 && pData->curElement == ELEMENT_NONE )
|
||||
{
|
||||
pData->curElement = ELEMENT_LIST;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if ( strcmp( name, "STRUCTURE" ) == 0 && pData->curElement == ELEMENT_LIST )
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if ( pData->curElement == ELEMENT &&
|
||||
( strcmp( name, "szTileSetDisplayName" ) == 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
|
||||
structuredemoveCharacterDataHandle( void *userData, const XML_Char *str, int len )
|
||||
{
|
||||
structuremoveParseData * pData = (structuremoveParseData *)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
|
||||
structuredemoveEndElementHandle( void *userData, const XML_Char *name )
|
||||
{
|
||||
static std::vector<UINT8> statictilevector;
|
||||
|
||||
structuremoveParseData * pData = (structuremoveParseData *)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 ( pData->curIndex < pData->maxArraySize )
|
||||
{
|
||||
// for whatever reasons the game crashes in VS2008 Release builds when copying over the tilevector
|
||||
// this seems odd, as this works just fine in VS2010 and VS2013, and also works in VS205 debug builds
|
||||
// for now, copy over the content by hand
|
||||
// check if the vector is empty because assigning an empty vector will crash VS2010 debug builds!
|
||||
if ( !statictilevector.empty() )
|
||||
{
|
||||
pData->curArray[pData->curIndex].tilevector = statictilevector;
|
||||
statictilevector.clear();
|
||||
}
|
||||
}
|
||||
|
||||
pData->curIndex++;
|
||||
}
|
||||
else if ( strcmp( name, "szTileSetDisplayName" ) == 0 )
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
strncpy( pData->curArray[pData->curIndex].szTileSetDisplayName, pData->szCharData, 20 );
|
||||
}
|
||||
else if ( strcmp( name, "szTileSetName" ) == 0 )
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
strncpy( pData->curArray[pData->curIndex].szTileSetName, pData->szCharData, 20 );
|
||||
}
|
||||
else if ( strcmp( name, "allowedtile" ) == 0 )
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
statictilevector.push_back( (UINT8)atol( pData->szCharData ) );
|
||||
}
|
||||
|
||||
pData->maxReadDepth--;
|
||||
}
|
||||
|
||||
pData->currentDepth--;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN ReadInStructureMoveStats( STR fileName )
|
||||
{
|
||||
HWFILE hFile;
|
||||
UINT32 uiBytesRead;
|
||||
UINT32 uiFSize;
|
||||
CHAR8 * lpcBuffer;
|
||||
XML_Parser parser = XML_ParserCreate( NULL );
|
||||
|
||||
structuremoveParseData pData;
|
||||
|
||||
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Loading StructureMove.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, structuredemoveStartElementHandle, structuredemoveEndElementHandle );
|
||||
XML_SetCharacterDataHandler( parser, structuredemoveCharacterDataHandle );
|
||||
|
||||
memset( &pData, 0, sizeof( pData ) );
|
||||
pData.curArray = gStructureMovePossible;
|
||||
pData.curIndex = 0;
|
||||
pData.maxArraySize = STRUCTURE_MOVEPOSSIBLE_MAX;
|
||||
|
||||
XML_SetUserData( parser, &pData );
|
||||
|
||||
if ( !XML_Parse( parser, lpcBuffer, uiFSize, TRUE ) )
|
||||
{
|
||||
CHAR8 errorBuf[511];
|
||||
|
||||
sprintf( errorBuf, "XML Parser Error in StructureMove.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 WriteStructureMoveStats()
|
||||
{
|
||||
//Debug code; make sure that what we got from the file is the same as what's there
|
||||
// Open a new file
|
||||
HWFILE hFile = FileOpen( "TABLEDATA\\StructureMove out.xml", FILE_ACCESS_WRITE | FILE_CREATE_ALWAYS, FALSE );
|
||||
if ( !hFile )
|
||||
return( FALSE );
|
||||
|
||||
{
|
||||
FilePrintf( hFile, "<STRUCTURESLIST>\r\n" );
|
||||
for ( UINT32 cnt = 0; cnt < STRUCTURE_MOVEPOSSIBLE_MAX; ++cnt )
|
||||
{
|
||||
FilePrintf( hFile, "\t<STRUCTURE>\r\n" );
|
||||
|
||||
FilePrintf( hFile, "\t\t<szTileSetDisplayName>%s</szTileSetDisplayName>\r\n", gStructureMovePossible[cnt].szTileSetDisplayName );
|
||||
FilePrintf( hFile, "\t\t<szTileSetName>%s</szTileSetName>\r\n", gStructureMovePossible[cnt].szTileSetName );
|
||||
|
||||
FilePrintf( hFile, "\t</STRUCTURE>\r\n" );
|
||||
}
|
||||
FilePrintf( hFile, "</STRUCTURESLIST>\r\n" );
|
||||
}
|
||||
FileClose( hFile );
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
@@ -65,60 +65,60 @@ extern UINT8 AtHeight[PROFILE_Z_SIZE];
|
||||
// how to handle explodable structures
|
||||
|
||||
// NOT used in DB structures!
|
||||
#define STRUCTURE_BASE_TILE 0x00000001
|
||||
#define STRUCTURE_BASE_TILE 0x00000001
|
||||
#define STRUCTURE_OPEN 0x00000002
|
||||
#define STRUCTURE_OPENABLE 0x00000004
|
||||
#define STRUCTURE_OPENABLE 0x00000004
|
||||
// synonyms for STRUCTURE_OPENABLE
|
||||
#define STRUCTURE_CLOSEABLE 0x00000004
|
||||
#define STRUCTURE_SEARCHABLE 0x00000004
|
||||
#define STRUCTURE_CLOSEABLE 0x00000004
|
||||
#define STRUCTURE_SEARCHABLE 0x00000004
|
||||
#define STRUCTURE_HIDDEN 0x00000008
|
||||
|
||||
#define STRUCTURE_MOBILE 0x00000010
|
||||
// STRUCTURE_PASSABLE is set for each structure instance where
|
||||
// the tile flag TILE_PASSABLE is set
|
||||
#define STRUCTURE_PASSABLE 0x00000020
|
||||
#define STRUCTURE_EXPLOSIVE 0x00000040
|
||||
#define STRUCTURE_TRANSPARENT 0x00000080
|
||||
#define STRUCTURE_PASSABLE 0x00000020
|
||||
#define STRUCTURE_EXPLOSIVE 0x00000040
|
||||
#define STRUCTURE_TRANSPARENT 0x00000080
|
||||
|
||||
#define STRUCTURE_GENERIC 0x00000100
|
||||
#define STRUCTURE_TREE 0x00000200
|
||||
#define STRUCTURE_FENCE 0x00000400
|
||||
#define STRUCTURE_WIREFENCE 0x00000800
|
||||
#define STRUCTURE_WIREFENCE 0x00000800
|
||||
|
||||
#define STRUCTURE_HASITEMONTOP 0x00001000 // ATE: HASITEM: struct has item on top of it
|
||||
#define STRUCTURE_HASITEMONTOP 0x00001000 // ATE: HASITEM: struct has item on top of it
|
||||
#define STRUCTURE_SPECIAL 0x00002000
|
||||
#define STRUCTURE_LIGHTSOURCE 0x00004000
|
||||
#define STRUCTURE_LIGHTSOURCE 0x00004000
|
||||
#define STRUCTURE_VEHICLE 0x00008000
|
||||
|
||||
#define STRUCTURE_WALL 0x00010000
|
||||
#define STRUCTURE_WALLNWINDOW 0x00020000
|
||||
#define STRUCTURE_SLIDINGDOOR 0x00040000
|
||||
#define STRUCTURE_WALLNWINDOW 0x00020000
|
||||
#define STRUCTURE_SLIDINGDOOR 0x00040000
|
||||
#define STRUCTURE_DOOR 0x00080000
|
||||
|
||||
// a "multi" structure (as opposed to multitiled) is composed of multiple graphics & structures
|
||||
#define STRUCTURE_MULTI 0x00100000
|
||||
#define STRUCTURE_CAVEWALL 0x00200000
|
||||
#define STRUCTURE_DDOOR_LEFT 0x00400000
|
||||
#define STRUCTURE_DDOOR_RIGHT 0x00800000
|
||||
#define STRUCTURE_CAVEWALL 0x00200000
|
||||
#define STRUCTURE_DDOOR_LEFT 0x00400000
|
||||
#define STRUCTURE_DDOOR_RIGHT 0x00800000
|
||||
|
||||
#define STRUCTURE_NORMAL_ROOF 0x01000000
|
||||
#define STRUCTURE_SLANTED_ROOF 0x02000000
|
||||
#define STRUCTURE_TALL_ROOF 0x04000000
|
||||
#define STRUCTURE_NORMAL_ROOF 0x01000000
|
||||
#define STRUCTURE_SLANTED_ROOF 0x02000000
|
||||
#define STRUCTURE_TALL_ROOF 0x04000000
|
||||
#define STRUCTURE_SWITCH 0x08000000
|
||||
|
||||
#define STRUCTURE_ON_LEFT_WALL 0x10000000
|
||||
#define STRUCTURE_ON_RIGHT_WALL 0x20000000
|
||||
#define STRUCTURE_ON_LEFT_WALL 0x10000000
|
||||
#define STRUCTURE_ON_RIGHT_WALL 0x20000000
|
||||
#define STRUCTURE_CORPSE 0x40000000
|
||||
#define STRUCTURE_PERSON 0x80000000
|
||||
|
||||
// COMBINATION FLAGS
|
||||
#define STRUCTURE_ANYFENCE 0x00000C00
|
||||
#define STRUCTURE_ANYFENCE 0x00000C00
|
||||
#define STRUCTURE_ANYDOOR 0x00CC0000
|
||||
#define STRUCTURE_OBSTACLE 0x00008F00
|
||||
#define STRUCTURE_WALLSTUFF 0x00CF0000
|
||||
#define STRUCTURE_BLOCKSMOVES 0x00208F00
|
||||
#define STRUCTURE_TYPE_DEFINED 0x8FEF8F00
|
||||
#define STRUCTURE_ROOF 0x07000000
|
||||
#define STRUCTURE_OBSTACLE 0x00008F00
|
||||
#define STRUCTURE_WALLSTUFF 0x00CF0000
|
||||
#define STRUCTURE_BLOCKSMOVES 0x00208F00
|
||||
#define STRUCTURE_TYPE_DEFINED 0x8FEF8F00
|
||||
#define STRUCTURE_ROOF 0x07000000
|
||||
|
||||
#define TILE_ON_ROOF 0x01
|
||||
#define TILE_PASSABLE 0x02
|
||||
|
||||
@@ -633,6 +633,8 @@ STRUCTURE * CreateStructureFromDB( DB_STRUCTURE_REF * pDBStructureRef, UINT8 ubT
|
||||
return( pStructure );
|
||||
}
|
||||
|
||||
extern UINT16 gusTempDragBuildSoldierID;
|
||||
|
||||
BOOLEAN OkayToAddStructureToTile( INT32 sBaseGridNo, INT16 sCubeOffset, DB_STRUCTURE_REF * pDBStructureRef, UINT8 ubTileIndex, INT16 sExclusionID, BOOLEAN fAddingForReal = FALSE, INT16 sSoldierID = NOBODY )
|
||||
{
|
||||
// Verifies whether a structure is blocked from being added to the map at a particular point
|
||||
@@ -953,7 +955,9 @@ BOOLEAN OkayToAddStructureToTile( INT32 sBaseGridNo, INT16 sCubeOffset, DB_STRUC
|
||||
|
||||
if ((pDBStructure->fFlags & STRUCTURE_OPENABLE))
|
||||
{
|
||||
if (pExistingStructure->fFlags & STRUCTURE_OPENABLE)
|
||||
// Flugente: we allow this if this structure is being dragged by a soldier, otherwise we can't move containers our of rooms (and are likely to unintenionally bar rooms)
|
||||
if (pExistingStructure->fFlags & STRUCTURE_OPENABLE
|
||||
&& !( gusTempDragBuildSoldierID != NOBODY && MercPtrs[gusTempDragBuildSoldierID]->sDragGridNo ) )
|
||||
{
|
||||
// don't allow two openable structures in the same tile or things will screw
|
||||
// up on an interface level
|
||||
@@ -2502,7 +2506,6 @@ BOOLEAN FiniStructureDB( void )
|
||||
|
||||
STRUCTURE* GetTallestStructureOnGridno( INT32 sGridNo, INT8 bLevel )
|
||||
{
|
||||
STRUCTURE* pCurrent = NULL;
|
||||
STRUCTURE* pStruct = NULL;
|
||||
INT8 bestheight = -1;
|
||||
INT16 sDesiredLevel = STRUCTURE_ON_GROUND;
|
||||
@@ -2510,7 +2513,7 @@ STRUCTURE* GetTallestStructureOnGridno( INT32 sGridNo, INT8 bLevel )
|
||||
if ( bLevel )
|
||||
sDesiredLevel = STRUCTURE_ON_ROOF;
|
||||
|
||||
pCurrent = gpWorldLevelData[sGridNo].pStructureHead;
|
||||
STRUCTURE* pCurrent = gpWorldLevelData[sGridNo].pStructureHead;
|
||||
|
||||
while ( pCurrent != NULL )
|
||||
{
|
||||
@@ -2538,6 +2541,42 @@ STRUCTURE* GetTallestStructureOnGridno( INT32 sGridNo, INT8 bLevel )
|
||||
return pStruct;
|
||||
}
|
||||
|
||||
STRUCTURE* GetTallestStructureOnGridnoDrag( INT32 sGridNo, INT8 bLevel )
|
||||
{
|
||||
STRUCTURE* pStruct = NULL;
|
||||
INT8 bestheight = -1;
|
||||
INT16 sDesiredLevel = STRUCTURE_ON_GROUND;
|
||||
|
||||
if ( bLevel )
|
||||
sDesiredLevel = STRUCTURE_ON_ROOF;
|
||||
|
||||
STRUCTURE* pCurrent = gpWorldLevelData[sGridNo].pStructureHead;
|
||||
|
||||
while ( pCurrent != NULL )
|
||||
{
|
||||
// Check level!
|
||||
if ( pCurrent->sCubeOffset == sDesiredLevel )
|
||||
{
|
||||
if ( pCurrent->fFlags & ( STRUCTURE_CORPSE | STRUCTURE_PERSON | STRUCTURE_ROOF | STRUCTURE_SWITCH | STRUCTURE_WALLSTUFF | STRUCTURE_MULTI | STRUCTURE_CAVEWALL | STRUCTURE_LIGHTSOURCE | STRUCTURE_VEHICLE | STRUCTURE_ANYFENCE | STRUCTURE_TREE ) )
|
||||
{
|
||||
pCurrent = pCurrent->pNext;
|
||||
continue;
|
||||
}
|
||||
|
||||
INT8 height = StructureHeight( pCurrent );
|
||||
if ( height > bestheight )
|
||||
{
|
||||
bestheight = height;
|
||||
pStruct = pCurrent;
|
||||
}
|
||||
}
|
||||
|
||||
pCurrent = pCurrent->pNext;
|
||||
}
|
||||
|
||||
return pStruct;
|
||||
}
|
||||
|
||||
|
||||
INT8 GetBlockingStructureInfo( INT32 sGridNo, INT8 bDir, INT8 bNextDir, INT8 bLevel, INT8 *pStructHeight, STRUCTURE ** ppTallestStructure, BOOLEAN fWallsBlock )
|
||||
{
|
||||
|
||||
@@ -85,6 +85,9 @@ BOOLEAN AddZStripInfoToVObject( HVOBJECT hVObject, STRUCTURE_FILE_REF * pStructu
|
||||
// Flugente: return the highest structure (no person, roof or corpse) on a gridno and level
|
||||
STRUCTURE* GetTallestStructureOnGridno( INT32 sGridNo, INT8 bLevel );
|
||||
|
||||
// Flugente: return the highest structure (no person, roof or corpse) on a gridno and level that we could possibly drag
|
||||
STRUCTURE* GetTallestStructureOnGridnoDrag( INT32 sGridNo, INT8 bLevel );
|
||||
|
||||
// FUNCTIONS FOR DETERMINING STUFF THAT BLOCKS VIEW FOR TILE_bASED LOS
|
||||
INT8 GetBlockingStructureInfo( INT32 sGridNo, INT8 bDir, INT8 bNextDir, INT8 bLevel, INT8 *pStructHeight, STRUCTURE ** ppTallestStructure, BOOLEAN fWallsBlock );
|
||||
|
||||
|
||||
@@ -2865,7 +2865,7 @@ STR16 pTraitSkillsDenialStrings[] =
|
||||
L" - 恶魔的财产\n", //L" - posession by a demon"
|
||||
L" - 与枪有关的技能(如自动武器)\n", //L" - a gun-related trait\n",
|
||||
L" - 举起枪(瞄准状态)\n", //L" - aimed gun\n",
|
||||
L" - 在佣兵旁边放下人或尸体\n", //L" - prone person or corpse next to merc\n",
|
||||
L" - prone person, corpse or structure next to merc\n", // TODO.Translate
|
||||
L" - 下蹲姿势\n", //L" - crouched position\n",
|
||||
L" - 清空主手装备\n", //L" - free main hand\n",
|
||||
L" - 潜伏技能\n", //L" - covert trait\n",
|
||||
|
||||
@@ -2864,7 +2864,7 @@ STR16 pTraitSkillsDenialStrings[] =
|
||||
L" - possession by a demon",
|
||||
L" - a gun-related trait\n", // TODO.Translate
|
||||
L" - aimed gun\n",
|
||||
L" - prone person or corpse next to merc\n", // TODO.Translate
|
||||
L" - prone person, corpse or structure next to merc\n",
|
||||
L" - crouched position\n",
|
||||
L" - free main hand\n",
|
||||
L" - covert trait\n",
|
||||
|
||||
@@ -2873,7 +2873,7 @@ STR16 pTraitSkillsDenialStrings[] =
|
||||
L" - possession by a demon\n",
|
||||
L" - a gun-related trait\n",
|
||||
L" - aimed gun\n",
|
||||
L" - prone person or corpse next to merc\n",
|
||||
L" - prone person, corpse or structure next to merc\n",
|
||||
L" - crouched position\n",
|
||||
L" - free main hand\n",
|
||||
L" - covert trait\n",
|
||||
|
||||
@@ -2873,7 +2873,7 @@ STR16 pTraitSkillsDenialStrings[] =
|
||||
L" - possession par un démon",
|
||||
L" - a gun-related trait\n", // TODO.Translate
|
||||
L" - aimed gun\n",
|
||||
L" - prone person or corpse next to merc\n", // TODO.Translate
|
||||
L" - prone person, corpse or structure next to merc\n",
|
||||
L" - crouched position\n",
|
||||
L" - free main hand\n",
|
||||
L" - covert trait\n",
|
||||
|
||||
@@ -2894,7 +2894,7 @@ STR16 pTraitSkillsDenialStrings[] =
|
||||
L" - besessen von einem Dämon",
|
||||
L" - a gun-related trait\n", // TODO.Translate
|
||||
L" - aimed gun\n",
|
||||
L" - prone person or corpse next to merc\n", // TODO.Translate
|
||||
L" - prone person, corpse or structure next to merc\n",
|
||||
L" - crouched position\n",
|
||||
L" - free main hand\n",
|
||||
L" - covert trait\n",
|
||||
|
||||
@@ -2859,7 +2859,7 @@ STR16 pTraitSkillsDenialStrings[] =
|
||||
L" - possession by a demon",
|
||||
L" - a gun-related trait\n", // TODO.Translate
|
||||
L" - aimed gun\n",
|
||||
L" - prone person or corpse next to merc\n", // TODO.Translate
|
||||
L" - prone person, corpse or structure next to merc\n",
|
||||
L" - crouched position\n",
|
||||
L" - free main hand\n",
|
||||
L" - covert trait\n",
|
||||
|
||||
@@ -2871,7 +2871,7 @@ STR16 pTraitSkillsDenialStrings[] =
|
||||
L" - possession by a demon",
|
||||
L" - a gun-related trait\n", // TODO.Translate
|
||||
L" - aimed gun\n",
|
||||
L" - prone person or corpse next to merc\n", // TODO.Translate
|
||||
L" - prone person, corpse or structure next to merc\n",
|
||||
L" - crouched position\n",
|
||||
L" - free main hand\n",
|
||||
L" - covert trait\n",
|
||||
|
||||
@@ -2865,7 +2865,7 @@ STR16 pTraitSkillsDenialStrings[] =
|
||||
L" - одержим бесами",
|
||||
L" - a gun-related trait\n", // TODO.Translate
|
||||
L" - aimed gun\n",
|
||||
L" - prone person or corpse next to merc\n", // TODO.Translate
|
||||
L" - prone person, corpse or structure next to merc\n",
|
||||
L" - crouched position\n",
|
||||
L" - free main hand\n",
|
||||
L" - covert trait\n",
|
||||
|
||||
Reference in New Issue
Block a user