qtscript: Save AI group information in the savegame. This may subtly break existing savegames.

master
Per Inge Mathisen 2011-03-30 21:14:05 +02:00
parent 0ee8b860f8
commit 03618b8d2d
12 changed files with 53 additions and 79 deletions

View File

@ -85,10 +85,7 @@ void cmdDroidAddDroid(DROID *psCommander, DROID *psDroid)
if (psCommander->psGroup == NULL) if (psCommander->psGroup == NULL)
{ {
if (!grpCreate(&psGroup)) psGroup = grpCreate();
{
return;
}
psGroup->add(psCommander); psGroup->add(psCommander);
psDroid->group = UBYTE_MAX; psDroid->group = UBYTE_MAX;
} }

View File

@ -2247,16 +2247,9 @@ DROID *reallyBuildDroid(DROID_TEMPLATE *pTemplate, UDWORD x, UDWORD y, UDWORD pl
psDroid->pos.z = map_Height(psDroid->pos.x, psDroid->pos.y); psDroid->pos.z = map_Height(psDroid->pos.x, psDroid->pos.y);
} }
if ( (psDroid->droidType == DROID_TRANSPORTER) || if (psDroid->droidType == DROID_TRANSPORTER || psDroid->droidType == DROID_COMMAND)
(psDroid->droidType == DROID_COMMAND) )
{ {
if (!grpCreate(&psGrp)) psGrp = grpCreate();
{
debug(LOG_NEVER, "unit build: unable to create group");
ASSERT(!"unable to create group", "Can't create unit because can't create group");
delete psDroid;
return NULL;
}
psGrp->add(psDroid); psGrp->add(psDroid);
} }

View File

@ -1636,7 +1636,7 @@ struct SAVE_DROID_V24
SAVE_MOVE_CONTROL sMove; \ SAVE_MOVE_CONTROL sMove; \
SWORD formationDir; \ SWORD formationDir; \
SDWORD formationX; \ SDWORD formationX; \
SDWORD formationY SDWORD aigroupidx
struct SAVE_DROID_V99 struct SAVE_DROID_V99
{ {
@ -5105,7 +5105,6 @@ static void SaveDroidMoveControl(SAVE_DROID * const psSaveDroid, DROID const * c
psSaveDroid->sMove.isInFormation = false; psSaveDroid->sMove.isInFormation = false;
psSaveDroid->formationDir = 0; psSaveDroid->formationDir = 0;
psSaveDroid->formationX = 0; psSaveDroid->formationX = 0;
psSaveDroid->formationY = 0;
} }
static void LoadDroidMoveControl(DROID * const psDroid, SAVE_DROID const * const psSaveDroid) static void LoadDroidMoveControl(DROID * const psDroid, SAVE_DROID const * const psSaveDroid)
@ -5334,6 +5333,14 @@ static DROID* buildDroidFromSaveDroid(SAVE_DROID* psSaveDroid, UDWORD version)
//rebuild the object pointer from the ID //rebuild the object pointer from the ID
FIXME_CAST_ASSIGN(UDWORD, psDroid->psBaseStruct, psSaveDroid->baseStructID); FIXME_CAST_ASSIGN(UDWORD, psDroid->psBaseStruct, psSaveDroid->baseStructID);
psDroid->group = psSaveDroid->group; psDroid->group = psSaveDroid->group;
if (psSaveDroid->aigroupidx >= 0)
{
psDroid->psGroup = grpFind(psSaveDroid->aigroupidx);
}
else
{
psDroid->psGroup = NULL;
}
psDroid->selected = psSaveDroid->selected; psDroid->selected = psSaveDroid->selected;
psDroid->died = psSaveDroid->died; psDroid->died = psSaveDroid->died;
psDroid->lastEmission = psSaveDroid->lastEmission; psDroid->lastEmission = psSaveDroid->lastEmission;
@ -5498,7 +5505,6 @@ static bool loadDroidSetPointers(void)
} }
} }
return true; return true;
} }
@ -5535,7 +5541,6 @@ bool loadSaveDroidV(char *pFileData, UDWORD filesize, UDWORD numDroids, UDWORD v
endian_sdword(&psSaveDroid->resistance); endian_sdword(&psSaveDroid->resistance);
endian_sword(&psSaveDroid->formationDir); endian_sword(&psSaveDroid->formationDir);
endian_sdword(&psSaveDroid->formationX); endian_sdword(&psSaveDroid->formationX);
endian_sdword(&psSaveDroid->formationY);
/* DROID_SAVE_V21 includes DROID_SAVE_V20 */ /* DROID_SAVE_V21 includes DROID_SAVE_V20 */
endian_udword(&psSaveDroid->commandId); endian_udword(&psSaveDroid->commandId);
/* DROID_SAVE_V20 includes OBJECT_SAVE_V20, SAVE_WEAPON */ /* DROID_SAVE_V20 includes OBJECT_SAVE_V20, SAVE_WEAPON */
@ -5752,6 +5757,7 @@ static bool buildSaveDroidFromDroid(SAVE_DROID* psSaveDroid, DROID* psCurr, DROI
} }
psSaveDroid->group = psCurr->group; psSaveDroid->group = psCurr->group;
psSaveDroid->aigroupidx = psCurr->psGroup ? psCurr->psGroup->id : -1;
psSaveDroid->selected = psCurr->selected; psSaveDroid->selected = psCurr->selected;
psSaveDroid->died = psCurr->died; psSaveDroid->died = psCurr->died;
psSaveDroid->lastEmission = psCurr->lastEmission; psSaveDroid->lastEmission = psCurr->lastEmission;
@ -5794,9 +5800,6 @@ static bool buildSaveDroidFromDroid(SAVE_DROID* psSaveDroid, DROID* psCurr, DROI
/* DROID_SAVE_V24 includes DROID_SAVE_V21 */ /* DROID_SAVE_V24 includes DROID_SAVE_V21 */
endian_sdword(&psSaveDroid->resistance); endian_sdword(&psSaveDroid->resistance);
// psSaveDroid->formationDir, psSaveDroid->formationX and psSaveDroid->formationY are set by SaveDroidMoveControl
// already, which also performs endian swapping, so we can (and should!) safely ignore those here.
/* DROID_SAVE_V21 includes DROID_SAVE_V20 */ /* DROID_SAVE_V21 includes DROID_SAVE_V20 */
endian_udword(&psSaveDroid->commandId); endian_udword(&psSaveDroid->commandId);
/* DROID_SAVE_V20 includes OBJECT_SAVE_V20 */ /* DROID_SAVE_V20 includes OBJECT_SAVE_V20 */

View File

@ -28,10 +28,10 @@
#include "lib/netplay/netplay.h" #include "lib/netplay/netplay.h"
#include "multiplay.h" #include "multiplay.h"
#include <QList> #include <QMap>
// Group system variables: grpGlobalManager enables to remove all the groups to Shutdown the system // Group system variables: grpGlobalManager enables to remove all the groups to Shutdown the system
static QList<DROID_GROUP *> grpGlobalManager; static QMap<int, DROID_GROUP *> grpGlobalManager;
static bool grpInitialized = false; static bool grpInitialized = false;
// initialise the group system // initialise the group system
@ -47,7 +47,7 @@ void grpShutDown(void)
{ {
/* Since we are not very diligent removing groups after we have /* Since we are not very diligent removing groups after we have
* created them; we need this hack to remove them on level end. */ * created them; we need this hack to remove them on level end. */
QList<DROID_GROUP *>::iterator iter; QMap<int, DROID_GROUP *>::iterator iter;
for(iter = grpGlobalManager.begin(); iter != grpGlobalManager.end(); iter++) for(iter = grpGlobalManager.begin(); iter != grpGlobalManager.end(); iter++)
{ {
@ -67,23 +67,33 @@ DROID_GROUP::DROID_GROUP()
} }
// create a new group // create a new group
bool grpCreate(DROID_GROUP **ppsGroup) DROID_GROUP *grpCreate(int id)
{ {
ASSERT(grpInitialized, "Group code not initialized yet"); ASSERT(grpInitialized, "Group code not initialized yet");
*ppsGroup = new DROID_GROUP; DROID_GROUP *psGroup = new DROID_GROUP;
ASSERT_OR_RETURN(false, *ppsGroup, "Out of memory"); if (id == -1)
(*ppsGroup)->id = grpGlobalManager.size(); {
grpGlobalManager.push_back(*ppsGroup); int i;
return true; for (i = 0; grpGlobalManager.contains(i); i++) {} // surly hack
psGroup->id = i;
}
else
{
ASSERT(!grpGlobalManager.contains(id), "Group %d is already created!", id);
psGroup->id = id;
}
grpGlobalManager.insert(psGroup->id, psGroup);
return psGroup;
} }
DROID_GROUP *grpFind(int id) DROID_GROUP *grpFind(int id)
{ {
if (id >= grpGlobalManager.size()) DROID_GROUP *psGroup = grpGlobalManager.value(id, NULL);
if (!psGroup)
{ {
return NULL; psGroup = grpCreate(id);
} }
return grpGlobalManager.at(id); return psGroup;
} }
// add a droid to a group // add a droid to a group
@ -200,7 +210,7 @@ void DROID_GROUP::remove(DROID *psDroid)
// free the group if necessary // free the group if necessary
if (refCount <= 0) if (refCount <= 0)
{ {
grpGlobalManager.removeOne(this); grpGlobalManager.remove(id);
delete this; delete this;
} }
} }

View File

@ -63,10 +63,10 @@ bool grpInitialise(void);
// shutdown the group system // shutdown the group system
void grpShutDown(void); void grpShutDown(void);
// create a new group /// create a new group, use -1 to generate a new ID. never use id != -1 unless loading from a savegame.
bool grpCreate(DROID_GROUP **ppsGroup); DROID_GROUP *grpCreate(int id = -1);
/// lookup group by its unique id /// lookup group by its unique id, or create it if not found
DROID_GROUP *grpFind(int id); DROID_GROUP *grpFind(int id);
#endif // __INCLUDED_SRC_GROUP_H__ #endif // __INCLUDED_SRC_GROUP_H__

View File

@ -1888,10 +1888,8 @@ void unloadTransporter(DROID *psTransporter, UDWORD x, UDWORD y, bool goingHome)
// a commander needs to get it's group back // a commander needs to get it's group back
if (psDroid->droidType == DROID_COMMAND) if (psDroid->droidType == DROID_COMMAND)
{ {
if (grpCreate(&psGroup)) psGroup = grpCreate();
{ psGroup->add(psDroid);
psGroup->add(psDroid);
}
clearCommandDroidFactory(psDroid); clearCommandDroidFactory(psDroid);
} }

View File

@ -392,11 +392,8 @@ void addDroid(DROID *psDroidToAdd, DROID *pList[MAX_PLAYERS])
// commanders have to get their group back // commanders have to get their group back
if (psDroidToAdd->droidType == DROID_COMMAND) if (psDroidToAdd->droidType == DROID_COMMAND)
{ {
grpCreate(&psGroup); psGroup = grpCreate();
if (psGroup) psGroup->add(psDroidToAdd);
{
psGroup->add(psDroidToAdd);
}
} }
} }
else if (pList[psDroidToAdd->player] == mission.apsDroidLists[psDroidToAdd->player]) else if (pList[psDroidToAdd->player] == mission.apsDroidLists[psDroidToAdd->player])

View File

@ -95,16 +95,8 @@ static QScriptValue js_enumGroup(QScriptContext *context, QScriptEngine *engine)
static QScriptValue js_newGroup(QScriptContext *, QScriptEngine *) static QScriptValue js_newGroup(QScriptContext *, QScriptEngine *)
{ {
DROID_GROUP *newGrp = NULL; DROID_GROUP *newGrp = grpCreate();
if (grpCreate(&newGrp)) return QScriptValue(newGrp->id);
{
return QScriptValue(newGrp->id);
}
else
{
debug(LOG_ERROR, "Failed to create group");
return QScriptValue();
}
} }
static QScriptValue js_enumStruct(QScriptContext *context, QScriptEngine *engine) static QScriptValue js_enumStruct(QScriptContext *context, QScriptEngine *engine)

View File

@ -1261,13 +1261,7 @@ bool scrValDefLoad(SDWORD version, INTERP_VAL *psVal, char *pBuffer, UDWORD size
if (psVal->v.oval == NULL) if (psVal->v.oval == NULL)
{ {
DROID_GROUP *tmp; DROID_GROUP *tmp = grpCreate();
if (!grpCreate(&tmp))
{
debug( LOG_FATAL, "scrValDefLoad: out of memory" );
abort();
break;
}
tmp->add(NULL); tmp->add(NULL);
psVal->v.oval = tmp; psVal->v.oval = tmp;
} }

View File

@ -154,10 +154,7 @@ bool scrvNewGroup(INTERP_VAL *psVal)
{ {
DROID_GROUP *psGroup; DROID_GROUP *psGroup;
if (!grpCreate(&psGroup)) psGroup = grpCreate();
{
return false;
}
// increment the refcount so the group doesn't get automatically freed when empty // increment the refcount so the group doesn't get automatically freed when empty
psGroup->add(NULL); psGroup->add(NULL);

View File

@ -2052,15 +2052,10 @@ static bool setFunctionality(STRUCTURE *psBuilding, STRUCTURE_TYPE functionType)
psRepairFac->psObj = NULL; psRepairFac->psObj = NULL;
psRepairFac->droidQueue = 0; psRepairFac->droidQueue = 0;
if (!grpCreate(&((REPAIR_FACILITY*)psBuilding->pFunctionality)->psGroup)) psRepairFac->psGroup = grpCreate();
{
debug(LOG_NEVER, "couldn't create repair facility group"); // Add NULL droid to the group
} psRepairFac->psGroup->add(NULL);
else
{
// Add NULL droid to the group
psRepairFac->psGroup->add(NULL);
}
// Take advantage of upgrades // Take advantage of upgrades
structureRepairUpgrade(psBuilding); structureRepairUpgrade(psBuilding);

View File

@ -1354,10 +1354,8 @@ void transporterRemoveDroid(UDWORD id)
// check if it is a commander // check if it is a commander
if (psDroid->droidType == DROID_COMMAND) if (psDroid->droidType == DROID_COMMAND)
{ {
if (grpCreate(&psGroup)) psGroup = grpCreate();
{ psGroup->add(psDroid);
psGroup->add(psDroid);
}
} }
psDroid->selected = true; psDroid->selected = true;