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:
Flugente
2020-07-23 22:11:23 +00:00
parent c8737017ff
commit 0c4997f6ec
33 changed files with 1021 additions and 85 deletions
+2 -2
View File
@@ -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
View File
@@ -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
+4
View File
@@ -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
View File
@@ -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);
+276
View File
@@ -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
+21
View File
@@ -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
View File
@@ -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 ////////////////////////////////////////////
/**
+1
View File
@@ -162,6 +162,7 @@ public:
void Setup( UINT32 aVal );
void Functions( UINT32 aVal );
void FunctionsGridNo( INT32 aVal );
private:
UINT32 usSkill;
+312 -31
View File
@@ -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
+5
View File
@@ -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
+4
View File
@@ -1260,6 +1260,10 @@
RelativePath=".\XML_StructureDeconstruct.cpp"
>
</File>
<File
RelativePath=".\XML_Structure_Move.cpp"
>
</File>
<File
RelativePath=".\XML_Taunts.cpp"
>
+4
View File
@@ -1262,6 +1262,10 @@
RelativePath=".\XML_StructureDeconstruct.cpp"
>
</File>
<File
RelativePath=".\XML_Structure_Move.cpp"
>
</File>
<File
RelativePath=".\XML_Taunts.cpp"
>
+1
View File
@@ -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" />
+3
View File
@@ -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>
+1
View File
@@ -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" />
+3
View File
@@ -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>
+1
View File
@@ -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" />
+3
View File
@@ -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>
+1
View File
@@ -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" />
+3
View File
@@ -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>
+6
View File
@@ -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();
+216
View File
@@ -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 );
}
+26 -26
View File
@@ -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
+42 -3
View File
@@ -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 )
{
+3
View File
@@ -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 );
+1 -1
View File
@@ -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",
+1 -1
View File
@@ -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",
+1 -1
View File
@@ -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",
+1 -1
View File
@@ -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",
+1 -1
View File
@@ -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",
+1 -1
View File
@@ -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",
+1 -1
View File
@@ -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",
+1 -1
View File
@@ -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",