Merged New Inventory Project into main branch

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@1871 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
lalien
2008-03-08 15:15:25 +00:00
parent e16d166277
commit 43ca24dda8
649 changed files with 93359 additions and 82507 deletions
+81 -81
View File
@@ -16,7 +16,7 @@
#include "editscreen.h"
#include "Editor Undo.h"
#include "Render Fun.h" //for access to gubWorldRoomInfo;
#include "Render Fun.h" //for access to gubWorldRoomInfo;
#include "Cursor Modes.h"
#include "Exit Grids.h"
#endif
@@ -24,35 +24,35 @@
/*
Kris -- Notes on how the undo code works:
At the bottom of the hierarchy, we need to determine the state of the undo command. The idea
is that we want to separate undo commands by separating them by new mouse clicks. By holding a mouse
down and painting various objects in the world would all constitute a single undo command. As soon as
the mouse is release, then a new undo command is setup. So, to automate this, there is a call every
At the bottom of the hierarchy, we need to determine the state of the undo command. The idea
is that we want to separate undo commands by separating them by new mouse clicks. By holding a mouse
down and painting various objects in the world would all constitute a single undo command. As soon as
the mouse is release, then a new undo command is setup. So, to automate this, there is a call every
frame to DetermineUndoState().
At the next level, there is a binary tree that keeps track of what map indices have been backup up in
the current undo command. The whole reason to maintain this list, is to avoid multiple map elements of
the same map index from being saved. In the outer code, everytime something is changed, a call to
At the next level, there is a binary tree that keeps track of what map indices have been backup up in
the current undo command. The whole reason to maintain this list, is to avoid multiple map elements of
the same map index from being saved. In the outer code, everytime something is changed, a call to
AddToUndoList() is called, so there are many cases (especially with building/terrain smoothing) that the
same mapindex is added to the undo list. This is also completely transparent, and doesn't need to be
same mapindex is added to the undo list. This is also completely transparent, and doesn't need to be
maintained.
In the outer code, there are several calls to AddToUndoList( iMapIndex ). This function basically looks
In the outer code, there are several calls to AddToUndoList( iMapIndex ). This function basically looks
in the binary tree for an existing entry, and if there isn't, then the entire mapelement is saved (with
the exception of the merc level ). Lights are also supported, but there is a totally different methodology
for accomplishing this. The equivalent function is AddLightToUndoList( iMapIndex ). In this case, only the
the exception of the merc level ). Lights are also supported, but there is a totally different methodology
for accomplishing this. The equivalent function is AddLightToUndoList( iMapIndex ). In this case, only the
light is saved, along with internal maintanance of several flags.
The actual mapelement copy code, is very complex. The mapelement is copied in parallel with a new one which
The actual mapelement copy code, is very complex. The mapelement is copied in parallel with a new one which
has to allocate several nodes of several types because a mapelement contains over a dozen separate lists, and
all of them need to be saved. The structure information of certain mapelements may be multitiled and must
also save the affected gridno's as well. This is also done internally. Basically, your call to
all of them need to be saved. The structure information of certain mapelements may be multitiled and must
also save the affected gridno's as well. This is also done internally. Basically, your call to
AddToUndoList() for any particular gridno, may actually save several entries (like for a car which could be 6+
tiles)
MERCS
Mercs are not supported in the undo code. Because they are so dynamic, and stats could change, they could
move, etc., it doesn't need to be in the undo code. The editor has its own way of dealing with mercs which
Mercs are not supported in the undo code. Because they are so dynamic, and stats could change, they could
move, etc., it doesn't need to be in the undo code. The editor has its own way of dealing with mercs which
doesn't use the undo methodology.
*/
@@ -71,13 +71,13 @@ void DisableUndo()
}
// undo node data element
typedef struct
typedef struct
{
INT32 iMapIndex;
MAP_ELEMENT *pMapTile;
BOOLEAN fLightSaved; //determines that a light has been saved
BOOLEAN fLightSaved; //determines that a light has been saved
UINT8 ubLightRadius; //the radius of the light to build if undo is called
UINT8 ubLightID; //only applies if a light was saved.
UINT8 ubLightID; //only applies if a light was saved.
UINT8 ubRoomNum;
} undo_struct;
@@ -108,27 +108,27 @@ BOOLEAN fNewUndoCmd = TRUE;
BOOLEAN gfIgnoreUndoCmdsForLights = FALSE;
//New pre-undo binary tree stuff
//With this, new undo commands will not duplicate saves in the same command. This will
//With this, new undo commands will not duplicate saves in the same command. This will
//increase speed, and save memory.
typedef struct MapIndexBinaryTree
{
struct MapIndexBinaryTree *left, *right;
UINT16 usMapIndex;
INT16 sMapIndex;
}MapIndexBinaryTree;
MapIndexBinaryTree *top = NULL;
void ClearUndoMapIndexTree();
BOOLEAN AddMapIndexToTree( UINT16 usMapIndex );
void CheckMapIndexForMultiTileStructures( UINT16 usMapIndex );
BOOLEAN AddMapIndexToTree( INT16 sMapIndex );
void CheckMapIndexForMultiTileStructures( INT16 sMapIndex );
void CheckForMultiTilesInTreeAndAddToUndoList( MapIndexBinaryTree *node );
//Recursively deletes all nodes below the node passed including itself.
void DeleteTreeNode( MapIndexBinaryTree **node )
{
if( (*node)->left )
if( (*node)->left )
DeleteTreeNode( &((*node)->left) );
if( (*node)->right )
if( (*node)->right )
DeleteTreeNode( &((*node)->right) );
MemFree( *node );
*node = NULL;
@@ -141,14 +141,14 @@ void ClearUndoMapIndexTree()
DeleteTreeNode( &top );
}
BOOLEAN AddMapIndexToTree( UINT16 usMapIndex )
BOOLEAN AddMapIndexToTree( INT16 sMapIndex )
{
MapIndexBinaryTree *curr, *parent;
if( !top )
{
top = (MapIndexBinaryTree*)MemAlloc( sizeof( MapIndexBinaryTree ) );
Assert( top );
top->usMapIndex = usMapIndex;
top->sMapIndex = sMapIndex;
top->left = NULL;
top->right = NULL;
return TRUE;
@@ -161,26 +161,26 @@ BOOLEAN AddMapIndexToTree( UINT16 usMapIndex )
while( curr )
{
parent = curr;
if( curr->usMapIndex == usMapIndex ) //found a match, so stop
if( curr->sMapIndex == sMapIndex ) //found a match, so stop
return FALSE;
//if the mapIndex is < node's mapIndex, then go left, else right
curr = ( usMapIndex < curr->usMapIndex ) ? curr->left : curr->right;
curr = ( sMapIndex < curr->sMapIndex ) ? curr->left : curr->right;
}
//if we made it this far, then curr is null and parent is pointing
//directly above.
//Create the new node and fill in the information.
curr = (MapIndexBinaryTree*)MemAlloc( sizeof( MapIndexBinaryTree ) );
Assert( curr );
curr->usMapIndex = usMapIndex;
curr->sMapIndex = sMapIndex;
curr->left = NULL;
curr->right = NULL;
//Now link the new node to the parent.
if( curr->usMapIndex < parent->usMapIndex )
if( curr->sMapIndex < parent->sMapIndex )
parent->left = curr;
else
parent->right = curr;
return TRUE;
}
}
//*************************************************************************
//
// Start of Undo code
@@ -236,7 +236,7 @@ BOOLEAN DeleteStackNodeContents( undo_stack *pCurrent )
pData = pCurrent->pData;
pMapTile = pData->pMapTile;
if( !pMapTile )
if( !pMapTile )
return TRUE; //light was saved -- mapelement wasn't saved.
// Free the memory associated with the map tile liked lists
@@ -309,14 +309,14 @@ BOOLEAN DeleteStackNodeContents( undo_stack *pCurrent )
{
pMapTile->pStructureHead = pStructureNode->pNext;
if( pStructureNode->usStructureID > INVALID_STRUCTURE_ID )
{ //Okay to delete the structure data -- otherwise, this would be
{ //Okay to delete the structure data -- otherwise, this would be
//merc structure data that we DON'T want to delete, because the merc node
//that hasn't been modified will still use this structure data!
MemFree( pStructureNode );
}
pStructureNode = pMapTile->pStructureHead;
}
// Free the map tile structure itself
MemFree( pMapTile );
@@ -356,23 +356,23 @@ void CropStackToMaxLength( INT32 iMaxCmds )
}
//We are adding a light to the undo list. We won't save the mapelement, nor will
//we validate the gridno in the binary tree. This works differently than a mapelement,
//because lights work on a different system. By setting the fLightSaved flag to TRUE,
//this will handle the way the undo command is handled. If there is no lightradius in
//We are adding a light to the undo list. We won't save the mapelement, nor will
//we validate the gridno in the binary tree. This works differently than a mapelement,
//because lights work on a different system. By setting the fLightSaved flag to TRUE,
//this will handle the way the undo command is handled. If there is no lightradius in
//our saved light, then we intend on erasing the light upon undo execution, otherwise, we
//save the light radius and light ID, so that we place it during undo execution.
void AddLightToUndoList( INT32 iMapIndex, INT32 iLightRadius, UINT8 ubLightID )
{
undo_stack *pNode;
undo_struct *pUndoInfo;
if( !gfUndoEnabled )
return;
//When executing an undo command (by adding a light or removing one), that command
//actually tries to add it to the undo list. So we wrap the execution of the undo
//actually tries to add it to the undo list. So we wrap the execution of the undo
//command by temporarily setting this flag, so it'll ignore, and not place a new undo
//command. When finished, the flag is cleared, and lights are again allowed to be saved
//command. When finished, the flag is cleared, and lights are again allowed to be saved
//in the undo list.
if( gfIgnoreUndoCmdsForLights )
return;
@@ -389,7 +389,7 @@ void AddLightToUndoList( INT32 iMapIndex, INT32 iLightRadius, UINT8 ubLightID )
}
pUndoInfo->fLightSaved = TRUE;
//if ubLightRadius is 0, then we don't need to save the light information because we
//if ubLightRadius is 0, then we don't need to save the light information because we
//will erase it when it comes time to execute the undo command.
pUndoInfo->ubLightRadius = (UINT8)iLightRadius;
pUndoInfo->ubLightID = ubLightID;
@@ -420,7 +420,7 @@ BOOLEAN AddToUndoList( INT32 iMapIndex )
//Check to see if the tile in question is even on the visible map, then
//if that is true, then check to make sure we don't already have the mapindex
//saved in the new binary tree (which only holds unique mapindex values).
if( GridNoOnVisibleWorldTile( (INT16)iMapIndex ) && AddMapIndexToTree( (UINT16)iMapIndex ) )
if( GridNoOnVisibleWorldTile( (INT16)iMapIndex ) && AddMapIndexToTree( (INT16)iMapIndex ) )
{
if( AddToUndoListCmd( iMapIndex, ++iCount ) )
@@ -439,7 +439,7 @@ BOOLEAN AddToUndoListCmd( INT32 iMapIndex, INT32 iCmdCount )
STRUCTURE *pStructure;
INT32 iCoveredMapIndex;
UINT8 ubLoop;
if ( (pNode = (undo_stack *)MemAlloc(sizeof( undo_stack )) ) == NULL )
{
return( FALSE );
@@ -482,7 +482,7 @@ BOOLEAN AddToUndoListCmd( INT32 iMapIndex, INT32 iCmdCount )
// copy the room number information (it's not in the mapelement structure)
pUndoInfo->ubRoomNum = gubWorldRoomInfo[ iMapIndex ];
pUndoInfo->fLightSaved = FALSE;
pUndoInfo->ubLightRadius = 0;
pUndoInfo->ubLightID = 0;
@@ -496,10 +496,10 @@ BOOLEAN AddToUndoListCmd( INT32 iMapIndex, INT32 iCmdCount )
// loop through pData->pStructureHead list
// for each structure
// find the base tile
// reference the db structure
// if number of tiles > 1
// add all covered tiles to undo list
// find the base tile
// reference the db structure
// if number of tiles > 1
// add all covered tiles to undo list
pStructure = pData->pStructureHead;
while (pStructure)
{
@@ -519,13 +519,13 @@ BOOLEAN AddToUndoListCmd( INT32 iMapIndex, INT32 iCmdCount )
}
void CheckMapIndexForMultiTileStructures( UINT16 usMapIndex )
void CheckMapIndexForMultiTileStructures( INT16 sMapIndex )
{
STRUCTURE * pStructure;
UINT8 ubLoop;
INT32 iCoveredMapIndex;
pStructure = gpWorldLevelData[usMapIndex].pStructureHead;
pStructure = gpWorldLevelData[sMapIndex].pStructureHead;
while (pStructure)
{
if (pStructure->pDBStructureRef->pDBStructure->ubNumberOfTiles > 1)
@@ -535,7 +535,7 @@ void CheckMapIndexForMultiTileStructures( UINT16 usMapIndex )
// for multi-tile structures we have to add, to the undo list, all the other tiles covered by the structure
if (pStructure->fFlags & STRUCTURE_BASE_TILE)
{
iCoveredMapIndex = usMapIndex + pStructure->pDBStructureRef->ppTile[ubLoop]->sPosRelToBase;
iCoveredMapIndex = sMapIndex + pStructure->pDBStructureRef->ppTile[ubLoop]->sPosRelToBase;
}
else
{
@@ -550,10 +550,10 @@ void CheckMapIndexForMultiTileStructures( UINT16 usMapIndex )
void CheckForMultiTilesInTreeAndAddToUndoList( MapIndexBinaryTree *node )
{
CheckMapIndexForMultiTileStructures( node->usMapIndex );
if( node->left )
CheckMapIndexForMultiTileStructures( node->sMapIndex );
if( node->left )
CheckForMultiTilesInTreeAndAddToUndoList( node->left );
if( node->right )
if( node->right )
CheckForMultiTilesInTreeAndAddToUndoList( node->right );
}
@@ -590,14 +590,14 @@ BOOLEAN ExecuteUndoList( void )
{
iUndoMapIndex = gpTileUndoStack->pData->iMapIndex;
fExitGrid = ExitGridAtGridNo( (UINT16)iUndoMapIndex );
fExitGrid = ExitGridAtGridNo( (INT16)iUndoMapIndex );
// Find which map tile we are to "undo"
if( gpTileUndoStack->pData->fLightSaved )
{ //We saved a light, so delete that light
INT16 sX, sY;
//Turn on this flag so that the following code, when executed, doesn't attempt to
//add lights to the undo list. That would cause problems...
//add lights to the undo list. That would cause problems...
gfIgnoreUndoCmdsForLights = TRUE;
ConvertGridNoToXY( (INT16)iUndoMapIndex, &sX, &sY );
if( !gpTileUndoStack->pData->ubLightRadius )
@@ -612,7 +612,7 @@ BOOLEAN ExecuteUndoList( void )
// of the undo's MAP_ELEMENT with the world's element.
SwapMapElementWithWorld( iUndoMapIndex, gpTileUndoStack->pData->pMapTile );
// copy the room number information back
// copy the room number information back
gubWorldRoomInfo[ iUndoMapIndex ] = gpTileUndoStack->pData->ubRoomNum;
// Now we smooth out the changes...
@@ -627,16 +627,16 @@ BOOLEAN ExecuteUndoList( void )
iCurCount++;
//Kris:
//The new cursor system is somehow interfering with the undo stuff. When
//an undo is called, the item is erased, but a cursor is added! I'm quickly
//The new cursor system is somehow interfering with the undo stuff. When
//an undo is called, the item is erased, but a cursor is added! I'm quickly
//hacking around this by erasing all cursors here.
RemoveAllTopmostsOfTypeRange( iUndoMapIndex, FIRSTPOINTERS, FIRSTPOINTERS );
if( fExitGrid && !ExitGridAtGridNo( (UINT16)iUndoMapIndex ) )
if( fExitGrid && !ExitGridAtGridNo( (INT16)iUndoMapIndex ) )
{ //An exitgrid has been removed, so get rid of the associated indicator.
RemoveTopmost( (UINT16)iUndoMapIndex, FIRSTPOINTERS8 );
}
else if( !fExitGrid && ExitGridAtGridNo( (UINT16)iUndoMapIndex ) )
else if( !fExitGrid && ExitGridAtGridNo( (INT16)iUndoMapIndex ) )
{ //An exitgrid has been added, so add the associated indicator
AddTopmostToTail( (UINT16)iUndoMapIndex, FIRSTPOINTERS8 );
}
@@ -669,7 +669,7 @@ void SmoothUndoMapTileTerrain( INT32 iWorldTile, MAP_ELEMENT *pUndoTile )
pLand = pLand->pNext;
}
}
else if ( gpWorldLevelData[ iWorldTile ].pLandHead == NULL )
else if ( gpWorldLevelData[ iWorldTile ].pLandHead == NULL )
{
// Nothing in world's tile, so smooth out the land in the old tile.
pLand = pUndoLand;
@@ -692,7 +692,7 @@ void SmoothUndoMapTileTerrain( INT32 iWorldTile, MAP_ELEMENT *pUndoTile )
while( pWLand != NULL && !fFound )
{
GetTileType( pWLand->usIndex, &uiWCheckType);
if ( uiCheckType == uiWCheckType )
fFound = TRUE;
@@ -715,7 +715,7 @@ void SmoothUndoMapTileTerrain( INT32 iWorldTile, MAP_ELEMENT *pUndoTile )
while( pLand != NULL && !fFound )
{
GetTileType( pLand->usIndex, &uiCheckType);
if ( uiCheckType == uiWCheckType )
fFound = TRUE;
@@ -731,7 +731,7 @@ void SmoothUndoMapTileTerrain( INT32 iWorldTile, MAP_ELEMENT *pUndoTile )
}
//Because of the potentially huge amounts of memory that can be allocated due to the inefficient
//undo methods coded by Bret, it is feasible that it could fail. Instead of using assertions to
//undo methods coded by Bret, it is feasible that it could fail. Instead of using assertions to
//terminate the program, destroy the memory allocated thusfar.
void DeleteMapElementContentsAfterCreationFail( MAP_ELEMENT *pNewMapElement )
{
@@ -762,7 +762,7 @@ void DeleteMapElementContentsAfterCreationFail( MAP_ELEMENT *pNewMapElement )
}
/*
union
union
{
struct TAG_level_node *pPrevNode; // FOR LAND, GOING BACKWARDS POINTER
ITEM_POOL *pItemPool; // ITEM POOLS
@@ -770,7 +770,7 @@ void DeleteMapElementContentsAfterCreationFail( MAP_ELEMENT *pNewMapElement )
INT32 iPhysicsObjectID; // ID FOR PHYSICS ITEM
INT32 uiAPCost; // FOR AP DISPLAY
}; // ( 4 byte union )
union
union
{
struct
{
@@ -787,7 +787,7 @@ BOOLEAN CopyMapElementFromWorld( MAP_ELEMENT *pNewMapElement, INT32 iMapIndex )
{
MAP_ELEMENT *pOldMapElement;
LEVELNODE *pOldLevelNode;
LEVELNODE *pLevelNode;
LEVELNODE *pLevelNode;
LEVELNODE *pNewLevelNode;
LEVELNODE *tail;
INT32 x;
@@ -832,7 +832,7 @@ BOOLEAN CopyMapElementFromWorld( MAP_ELEMENT *pNewMapElement, INT32 iMapIndex )
//place the new node inside of the new map element
if( !pNewStructure )
{
pNewMapElement->pStructureHead = pStructure;
pNewMapElement->pStructureHead = pStructure;
pNewStructure = pStructure;
}
else
@@ -886,7 +886,7 @@ BOOLEAN CopyMapElementFromWorld( MAP_ELEMENT *pNewMapElement, INT32 iMapIndex )
//place the new node inside of the new map element
if( !pNewLevelNode )
{
pNewMapElement->pLevelNodes[ x ] = pLevelNode;
pNewMapElement->pLevelNodes[ x ] = pLevelNode;
pNewLevelNode = pLevelNode;
}
else
@@ -916,7 +916,7 @@ BOOLEAN CopyMapElementFromWorld( MAP_ELEMENT *pNewMapElement, INT32 iMapIndex )
{ //make sure the structuredata pointer points to the parallel structure
STRUCTURE *pOld, *pNew;
//both lists are exactly the same size and contain the same information,
//but the addresses are different. We will traverse the old list until
//but the addresses are different. We will traverse the old list until
//we find the match, then
pOld = pOldMapElement->pStructureHead;
pNew = pNewMapElement->pStructureHead;
@@ -933,10 +933,10 @@ BOOLEAN CopyMapElementFromWorld( MAP_ELEMENT *pNewMapElement, INT32 iMapIndex )
}
//Kris:
//If this assert should fail, that means there is something wrong with
//the preservation of the structure data within the mapelement.
//the preservation of the structure data within the mapelement.
if( pOld != pOldLevelNode->pStructureData )
{
//OUCH!!! THIS IS HAPPENING. DISABLED IT FOR LINDA'S SAKE
//OUCH!!! THIS IS HAPPENING. DISABLED IT FOR LINDA'S SAKE
Assert( 1 );
}
}
@@ -968,11 +968,11 @@ BOOLEAN SwapMapElementWithWorld( INT32 iMapIndex, MAP_ELEMENT *pUndoMapElement )
pCurrentMapElement = &gpWorldLevelData[ iMapIndex ];
//Transfer the merc level node from the current world to the undo mapelement
//that will replace it. We do this, because mercs aren't associated with
//that will replace it. We do this, because mercs aren't associated with
//undo commands.
pUndoMapElement->pMercHead = gpWorldLevelData[ iMapIndex ].pMercHead;
gpWorldLevelData[ iMapIndex ].pMercHead = NULL;
//Swap the mapelements
TempMapElement = *pCurrentMapElement;
*pCurrentMapElement = *pUndoMapElement;
@@ -986,8 +986,8 @@ void DetermineUndoState()
// Reset the undo command mode if we released the left button.
if( !fNewUndoCmd )
{
if( !gfLeftButtonState && !gfCurrentSelectionWithRightButton ||
!gfRightButtonState && gfCurrentSelectionWithRightButton )
if( !gfLeftButtonState && !gfCurrentSelectionWithRightButton ||
!gfRightButtonState && gfCurrentSelectionWithRightButton )
{
//Clear the mapindex binary tree list, and set up flag for new undo command.
fNewUndoCmd = TRUE;
@@ -997,4 +997,4 @@ void DetermineUndoState()
}
#endif
#endif