Fix template loading for the 8 human player case by storing static AI templates in a special

linked list for that purpose alone. These templates are not saved to savegames, and the ID
matching works only because load order is identical - the same way it is handled by campaign.
This means that MP templates.txt, like the campaign one, must never be reordered.
Patch reviewed by Zarel. Closes ticket:1486


git-svn-id: https://warzone2100.svn.sourceforge.net/svnroot/warzone2100/trunk@9606 4a71c877-e1ca-e34f-864e-861f7616d084
master
Per Inge Mathisen 2010-02-01 20:06:54 +00:00 committed by Git SVN Gateway
parent aa2e8fd0f5
commit 0cc7c315db
7 changed files with 87 additions and 86 deletions

View File

@ -94,6 +94,7 @@ extern DROID_TEMPLATE sDefaultDesignTemplate;
// Template storage
DROID_TEMPLATE *apsDroidTemplates[MAX_PLAYERS];
DROID_TEMPLATE *apsStaticTemplates; // for AIs and scripts
// store the experience of recently recycled droids
UWORD aDroidExperience[MAX_PLAYERS][MAX_RECYCLED_DROIDS];
@ -1834,15 +1835,18 @@ BOOL loadDroidTemplates(const char *pDroidData, UDWORD bufferSize)
{
int i;
// Give AI players all templates, and only those meant for humans (player 0)
// to human players.
// Give those meant for humans (player 0) to all human players.
for (i = 0; i < MAX_PLAYERS; i++)
{
if (!NetPlay.players[i].allocated || player == 0)
if (player == 0 && NetPlay.players[i].allocated) // human prototype template
{
addTemplate(i, pDroidDesign);
pDroidDesign->prefab = false;
addTemplateToList(pDroidDesign, &apsDroidTemplates[i]);
}
}
// Add all templates to static template list
pDroidDesign->prefab = true; // prefabricated templates referenced from VLOs
addTemplateToList(pDroidDesign, &apsStaticTemplates);
}
//increment the pointer to the start of the next record
@ -1871,6 +1875,13 @@ void initTemplatePoints(void)
pDroidDesign->powerPoints = calcTemplatePower(pDroidDesign);
}
}
for (pDroidDesign = apsStaticTemplates; pDroidDesign != NULL; pDroidDesign = pDroidDesign->psNext)
{
//calculate the total build points
pDroidDesign->buildPoints = calcTemplateBuild(pDroidDesign);
//calc the total power points
pDroidDesign->powerPoints = calcTemplatePower(pDroidDesign);
}
}
@ -2040,6 +2051,10 @@ BOOL loadDroidWeapons(const char *pWeaponData, UDWORD bufferSize)
pTemplate->aName);
pTemplate->storeCount++;
}
if (!isHumanPlayer(i))
{
break; // only one list to add to
}
}
//increment the pointer to the start of the next record
@ -2055,24 +2070,33 @@ BOOL loadDroidWeapons(const char *pWeaponData, UDWORD bufferSize)
BOOL droidTemplateShutDown(void)
{
unsigned int player;
DROID_TEMPLATE *pTemplate, *pNext;
for (player = 0; player < MAX_PLAYERS; player++)
{
DROID_TEMPLATE *pTemplate, *pNext;
for (pTemplate = apsDroidTemplates[player]; pTemplate != NULL; pTemplate = pNext)
{
pNext = pTemplate->psNext;
//FIX ME:
ASSERT(sDefaultDesignTemplate.pName != pTemplate->pName, "We'll soon be getting a double free()!!!");
if (pTemplate->pName != sDefaultDesignTemplate.pName)
if (pTemplate->pName != sDefaultDesignTemplate.pName) // sanity check probably no longer necessary
{
free(pTemplate->pName);
}
ASSERT(!pTemplate->prefab, "Static template %s in player template list!", pTemplate->aName);
free(pTemplate);
}
apsDroidTemplates[player] = NULL;
}
for (pTemplate = apsStaticTemplates; pTemplate != NULL; pTemplate = pNext)
{
pNext = pTemplate->psNext;
if (pTemplate->pName != sDefaultDesignTemplate.pName) // sanity check probably no longer necessary
{
free(pTemplate->pName);
}
ASSERT(pTemplate->prefab, "Player template %s in static template list!", pTemplate->aName);
free(pTemplate);
}
apsStaticTemplates = NULL;
free(sDefaultDesignTemplate.pName);
sDefaultDesignTemplate.pName = NULL;
@ -3056,8 +3080,14 @@ BOOL calcDroidMuzzleLocation(DROID *psDroid, Vector3f *muzzle, int weapon_slot)
DROID_TEMPLATE * getTemplateFromUniqueName(const char *pName, unsigned int player)
{
DROID_TEMPLATE *psCurr;
DROID_TEMPLATE *list = apsStaticTemplates; // assume AI
for (psCurr = apsDroidTemplates[player]; psCurr != NULL; psCurr = psCurr->psNext)
if (isHumanPlayer(player))
{
list = apsDroidTemplates[player]; // was human
}
for (psCurr = list; psCurr != NULL; psCurr = psCurr->psNext)
{
if (strcmp(psCurr->pName, pName) == 0)
{
@ -3069,63 +3099,42 @@ DROID_TEMPLATE * getTemplateFromUniqueName(const char *pName, unsigned int playe
}
/*!
* Gets a template from its name, irrespective of owner. This is really, really ugly, but
* when reading from a VLO file we do not know its future owner. We must never read templates
* from a human player, and we must never let AIs delete their templates, or this will break
* horribly.
* Get a static template from its name. This is used from scripts. These templates must
* never be changed or deleted.
* \param pName Template name
* \pre pName has to be the unique, untranslated name!
* \post pName will be translated via getDroidResourceName()!
*/
DROID_TEMPLATE *getTemplateFromTranslatedNameNoPlayer(char *pName)
{
int player;
const char *rName;
DROID_TEMPLATE *psCurr;
for (player = 0; player < MAX_PLAYERS; player++)
for (psCurr = apsStaticTemplates; psCurr != NULL; psCurr = psCurr->psNext)
{
DROID_TEMPLATE *psCurr;
for (psCurr = apsDroidTemplates[player]; psCurr != NULL; psCurr = psCurr->psNext)
rName = psCurr->pName ? psCurr->pName : psCurr->aName;
if (strcmp(rName, pName) == 0)
{
rName = psCurr->pName ? psCurr->pName : psCurr->aName;
if (!isHumanPlayer(player) && strcmp(rName, pName) == 0)
{
return psCurr;
}
return psCurr;
}
}
return NULL;
}
/*getTemplatefFromSinglePlayerID gets template for unique ID searching one players list */
DROID_TEMPLATE* getTemplateFromSinglePlayerID(UDWORD multiPlayerID, UDWORD player)
{
DROID_TEMPLATE *pDroidDesign;
for(pDroidDesign = apsDroidTemplates[player]; pDroidDesign != NULL; pDroidDesign = pDroidDesign->psNext)
{
if (pDroidDesign->multiPlayerID == multiPlayerID)
{
return pDroidDesign;
}
}
return NULL;
}
/*getTemplatefFromMultiPlayerID gets template for unique ID searching all lists */
DROID_TEMPLATE* getTemplateFromMultiPlayerID(UDWORD multiPlayerID)
{
UDWORD player;
UDWORD player;
DROID_TEMPLATE *pDroidDesign;
for (player=0; player < MAX_PLAYERS; player++)
for (player = 0; player < MAX_PLAYERS; player++)
{
pDroidDesign = getTemplateFromSinglePlayerID(multiPlayerID, player);
if (pDroidDesign != NULL)
for(pDroidDesign = apsDroidTemplates[player]; pDroidDesign != NULL; pDroidDesign = pDroidDesign->psNext)
{
return pDroidDesign;
if (pDroidDesign->multiPlayerID == multiPlayerID)
{
return pDroidDesign;
}
}
}
return NULL;

View File

@ -55,6 +55,8 @@ back when building is destroyed*/
//storage
extern DROID_TEMPLATE *apsDroidTemplates[MAX_PLAYERS];
extern DROID_TEMPLATE *apsStaticTemplates; // for AIs and scripts
extern bool runningMultiplayer(void);
//used to stop structures being built too near the edge and droids being placed down - pickATile
@ -227,8 +229,6 @@ extern BOOL calcDroidMuzzleLocation(DROID *psDroid, Vector3f *muzzle, int weapon
extern DROID_TEMPLATE * getTemplateFromUniqueName(const char *pName, unsigned int player);
/* gets a template from its name - relies on the name being unique */
extern DROID_TEMPLATE* getTemplateFromTranslatedNameNoPlayer(char *pName);
/*getTemplateFromSinglePlayerID gets template for unique ID searching one players list */
extern DROID_TEMPLATE* getTemplateFromSinglePlayerID(UDWORD multiPlayerID, UDWORD player);
/*getTemplateFromMultiPlayerID gets template for unique ID searching all lists */
extern DROID_TEMPLATE* getTemplateFromMultiPlayerID(UDWORD multiPlayerID);

View File

@ -124,6 +124,7 @@ typedef struct _droid_template
DROID_TYPE droidType; ///< The type of droid
UDWORD multiPlayerID; ///< multiplayer unique descriptor(cant use id's for templates). Used for save games as well now - AB 29/10/98
struct _droid_template* psNext; ///< Pointer to next template
bool prefab; ///< Not player designed, not saved, never delete or change
} WZ_DECL_MAY_ALIAS DROID_TEMPLATE;
typedef struct DROID

View File

@ -8928,7 +8928,7 @@ BOOL loadSaveTemplateV7(char *pFileData, UDWORD filesize, UDWORD numTemplates)
// ignore brains and programs for now
psTemplate->asParts[COMP_BRAIN] = 0;
psTemplate->prefab = false; // not AI template
//calculate the total build points
psTemplate->buildPoints = calcTemplateBuild(psTemplate);
@ -8937,9 +8937,6 @@ BOOL loadSaveTemplateV7(char *pFileData, UDWORD filesize, UDWORD numTemplates)
//store it in the apropriate player' list
psTemplate->psNext = apsDroidTemplates[psSaveTemplate->player];
apsDroidTemplates[psSaveTemplate->player] = psTemplate;
}
return true;
@ -9058,6 +9055,7 @@ BOOL loadSaveTemplateV14(char *pFileData, UDWORD filesize, UDWORD numTemplates)
// ignore brains and programs for now
psTemplate->asParts[COMP_BRAIN] = 0;
psTemplate->prefab = false; // not AI template
//calculate the total build points
psTemplate->buildPoints = calcTemplateBuild(psTemplate);
@ -9229,6 +9227,7 @@ BOOL loadSaveTemplateV(char *pFileData, UDWORD filesize, UDWORD numTemplates)
//no! put brains back in 10Feb //ignore brains and programs for now
//psTemplate->asParts[COMP_BRAIN] = 0;
psTemplate->prefab = false; // not AI template
//calculate the total build points
psTemplate->buildPoints = calcTemplateBuild(psTemplate);
@ -9259,10 +9258,6 @@ BOOL loadSaveTemplateV(char *pFileData, UDWORD filesize, UDWORD numTemplates)
psTemplate->psNext = apsDroidTemplates[psSaveTemplate->player];
apsDroidTemplates[psSaveTemplate->player] = psTemplate;
}
}
return true;

View File

@ -345,8 +345,8 @@ BOOL multiShutdown(void)
}
// ////////////////////////////////////////////////////////////////////////////
// copy tempates from one player to another.
BOOL addTemplate(UDWORD player, DROID_TEMPLATE *psNew)
// copy templates from one player to another.
BOOL addTemplateToList(DROID_TEMPLATE *psNew, DROID_TEMPLATE **ppList)
{
DROID_TEMPLATE *psTempl = malloc(sizeof(DROID_TEMPLATE));
@ -363,12 +363,19 @@ BOOL addTemplate(UDWORD player, DROID_TEMPLATE *psNew)
psTempl->pName = strdup(psNew->pName);
}
psTempl->psNext = apsDroidTemplates[player];
apsDroidTemplates[player] = psTempl;
psTempl->psNext = *ppList;
*ppList = psTempl;
return true;
}
// ////////////////////////////////////////////////////////////////////////////
// copy templates from one player to another.
BOOL addTemplate(UDWORD player, DROID_TEMPLATE *psNew)
{
return addTemplateToList(psNew, &apsDroidTemplates[player]);
}
// ////////////////////////////////////////////////////////////////////////////
// setup templates
BOOL multiTemplateSetup(void)

View File

@ -386,40 +386,29 @@ DROID_TEMPLATE *IdToTemplate(UDWORD tempId,UDWORD player)
{
DROID_TEMPLATE *psTempl = NULL;
UDWORD i;
if(player != ANYPLAYER)
// Check if we know which player this is from, in that case, assume it is a player template
if (player != ANYPLAYER)
{
for (psTempl = apsDroidTemplates[player]; // follow templates
(psTempl && (psTempl->multiPlayerID != tempId ));
psTempl = psTempl->psNext);
return psTempl;
}
else
// If not, first try static templates from AI control (could potentially also happen for currently human controlled players)
for (psTempl = apsStaticTemplates; psTempl && psTempl->multiPlayerID != tempId; psTempl = psTempl->psNext) ;
if (psTempl) return psTempl;
// We really have no idea, but it is not a static template, so search through every player template
for (i = 0; i < MAX_PLAYERS; i++)
{
// REALLY DANGEROUS!!! ID's are NOT assumed to be unique for TEMPLATES.
debug( LOG_NEVER, "Really Dodgy Check performed for a template" );
for(i=0;i<MAX_PLAYERS;i++)
{
for (psTempl = apsDroidTemplates[i]; // follow templates
(psTempl && (psTempl->multiPlayerID != tempId ));
psTempl = psTempl->psNext);
if(psTempl)
{
return psTempl;
}
}
for (psTempl = apsDroidTemplates[i]; psTempl && psTempl->multiPlayerID != tempId; psTempl = psTempl->psNext) ;
if (psTempl) return psTempl;
}
return psTempl;
}
// the same as above, but only checks names in similarity.
DROID_TEMPLATE *NameToTemplate(const char *sName,UDWORD player)
{
DROID_TEMPLATE *psTempl = NULL;
for (psTempl = apsDroidTemplates[player]; // follow templates
(psTempl && (strcmp(psTempl->aName,sName) != 0) );
psTempl = psTempl->psNext);
return psTempl;
return NULL;
}
/////////////////////////////////////////////////////////////////////////////////

View File

@ -129,7 +129,6 @@ extern WZ_DECL_WARN_UNUSED_RESULT STRUCTURE *IdToStruct(UDWORD id,UDWORD player
extern WZ_DECL_WARN_UNUSED_RESULT BOOL IdToDroid(UDWORD id, UDWORD player, DROID **psDroid);
extern WZ_DECL_WARN_UNUSED_RESULT FEATURE *IdToFeature(UDWORD id,UDWORD player);
extern WZ_DECL_WARN_UNUSED_RESULT DROID_TEMPLATE *IdToTemplate(UDWORD tempId,UDWORD player);
extern WZ_DECL_WARN_UNUSED_RESULT DROID_TEMPLATE *NameToTemplate(const char *sName,UDWORD player);
extern const char* getPlayerName(unsigned int player);
extern BOOL setPlayerName (UDWORD player, const char *sName);
@ -195,6 +194,7 @@ extern void playerResponding (void);
extern BOOL multiGameInit (void);
extern BOOL multiGameShutdown (void);
extern BOOL addTemplate (UDWORD player,DROID_TEMPLATE *psNew);
extern BOOL addTemplateToList(DROID_TEMPLATE *psNew, DROID_TEMPLATE **ppList);
// syncing.
extern BOOL sendCheck (void); //send/recv check info