mirror of
https://github.com/1dot13/source.git
synced 2026-08-19 14:20:30 +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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user