Skip to content

Commit

Permalink
Store designed templates in a better way. Also, keep copy of designed…
Browse files Browse the repository at this point in the history
… templates in master list.

Adds some backwards compatibility code for beta1 that should be removed before final release.

Closes ticket:4372
  • Loading branch information
perim committed May 15, 2016
1 parent c0f41c4 commit 0556c63
Show file tree
Hide file tree
Showing 16 changed files with 239 additions and 253 deletions.
64 changes: 64 additions & 0 deletions lib/framework/wzconfig.cpp
Expand Up @@ -270,6 +270,70 @@ void WzConfig::endGroup()
}
}

bool WzConfig::beginArray(const QString &name)
{
ASSERT(mArray.isEmpty(), "beginArray() cannot be nested");
mObjNameStack.append(mName);
mObjStack.append(mObj);
mName = name;
if (mWarning == ReadAndWrite)
{
mObj = QJsonObject();
}
else
{
if (!contains(name)) // handled in this way for backwards compatibility
{
mName = mObjNameStack.takeLast();
mObj = mObjStack.takeLast();
return false;
}
QJsonValue value = mObj.value(name);
ASSERT(value.isArray(), "beginArray() on non-array key \"%s\"", name.toUtf8().constData());
mArray = value.toArray();
ASSERT(mArray.first().isObject(), "beginArray() on non-object array \"%s\"", name.toUtf8().constData());
mObj = mArray.first().toObject();
mArray.removeFirst();
}
return true;
}

void WzConfig::nextArrayItem()
{
if (mWarning == ReadAndWrite)
{
mArray.push_back(mObj);
mObj = QJsonObject();
}
else
{
mObj = mArray.first().toObject();
mArray.removeFirst();
}
}

int WzConfig::remainingArrayItems()
{
return mArray.size();
}

void WzConfig::endArray()
{
if (mWarning == ReadAndWrite)
{
mArray.push_back(mObj);
mObj = mObjStack.takeLast();
mObj[mName] = mArray;
mName = mObjNameStack.takeLast();
}
else
{
mName = mObjNameStack.takeLast();
mObj = mObjStack.takeLast();
}
mArray = QJsonArray();
}

void WzConfig::setValue(const QString &key, const QVariant &value)
{
mObj.insert(key, QJsonValue::fromVariant(value));
Expand Down
14 changes: 13 additions & 1 deletion lib/framework/wzconfig.h
Expand Up @@ -24,6 +24,7 @@
#include <QtCore/QVariant>
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonObject>
#include <QtCore/QJsonArray>
#include <physfs.h>
#include <stdbool.h>

Expand All @@ -39,6 +40,7 @@ class WzConfig

private:
QJsonObject mObj;
QJsonArray mArray;
QString mName;
QList<QJsonObject> mObjStack;
QStringList mObjNameStack;
Expand All @@ -63,21 +65,31 @@ class WzConfig
QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const;
QJsonValue json(const QString &key, const QJsonValue &defaultValue = QJsonValue()) const;

bool beginGroup(const QString &prefix);
bool beginArray(const QString &name);
void nextArrayItem();
void endArray();
int remainingArrayItems();

bool beginGroup(const QString &name);
void endGroup();

QString fileName() const
{
return mFilename;
}

bool isWritable() const
{
return mWarning == ReadAndWrite && mStatus;
}

void setValue(const QString &key, const QVariant &value);

QString group()
{
return mName;
}

bool status()
{
return mStatus;
Expand Down
2 changes: 2 additions & 0 deletions src/cheat.cpp
Expand Up @@ -32,6 +32,7 @@
#include "keymap.h"
#include "multiplay.h"
#include "qtscript.h"
#include "template.h"

struct CHEAT_ENTRY
{
Expand All @@ -42,6 +43,7 @@ struct CHEAT_ENTRY
bool Cheated = false;
static CHEAT_ENTRY cheatCodes[] =
{
{"templates", listTemplates}, // print templates
{"jsload", jsAutogame}, // load an AI script for selectedPlayer
{"jsdebug", jsShowDebug}, // show scripting states
{"clone wars", kf_CloneSelected}, // clone selected units
Expand Down
7 changes: 4 additions & 3 deletions src/design.cpp
Expand Up @@ -3988,7 +3988,7 @@ static void intDisplayDesignForm(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffse


/* save the current Template if valid. Return true if stored */
static bool saveTemplate(void)
static bool saveTemplate()
{
if (!intValidTemplate(&sCurrDesign, aCurrName, false, selectedPlayer))
{
Expand All @@ -4007,6 +4007,7 @@ static bool saveTemplate(void)
/* create empty template and point to that */
localTemplates.push_back(DROID_TEMPLATE());
psTempl = &localTemplates.back();
sCurrDesign.multiPlayerID = generateNewObjectId();
apsTemplateList.push_back(psTempl);

psTempl->ref = REF_TEMPLATE_START;
Expand Down Expand Up @@ -4037,8 +4038,8 @@ static bool saveTemplate(void)
widgDelete(psWScreen, IDDES_TEMPLBASE);
intAddTemplateForm(psTempl);

// Send template to in-game template list, since localTemplates/apsDroidTemplates is for UI use only.
psTempl->multiPlayerID = generateNewObjectId();
// Add template to in-game template list, since localTemplates/apsTemplateList is for UI use only.
copyTemplate(selectedPlayer, psTempl);

return true;
}
Expand Down
1 change: 0 additions & 1 deletion src/droiddef.h
Expand Up @@ -72,7 +72,6 @@ struct DROID_TEMPLATE : public BASE_STATS
uint8_t asWeaps[DROID_MAXWEAPS]; ///< weapon indices
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
DROID_TEMPLATE *psNext; ///< Pointer to next template
bool prefab; ///< Not player designed, not saved, never delete or change
bool stored; ///< Stored template
bool enabled; ///< Has been enabled
Expand Down
149 changes: 63 additions & 86 deletions src/game.cpp
Expand Up @@ -2072,37 +2072,18 @@ bool loadGame(const char *pGameToLoad, bool keepObjects, bool freeMem, bool User
//load up the Droid Templates BEFORE any structures are loaded
if (IsScenario == false)
{
if (bMultiPlayer)
{
DROID_TEMPLATE *pTemplate, *pNext;
for (pTemplate = apsDroidTemplates[0]; pTemplate != NULL;
pTemplate = pNext)
{
pNext = pTemplate->psNext;
delete pTemplate;
}
apsDroidTemplates[0] = NULL;
droidTemplateShutDown();
}

// In Multiplayer, clear templates out first.....
if (bMultiPlayer)
else
{
for (inc = 0; inc < MAX_PLAYERS; inc++)
{
while (apsDroidTemplates[inc]) // clear the old template out.
{
DROID_TEMPLATE *psTempl;
psTempl = apsDroidTemplates[inc]->psNext;
delete apsDroidTemplates[inc];
apsDroidTemplates[inc] = psTempl;
}
}
clearTemplates(0);
localTemplates.clear();
}
localTemplates.clear();

//load in the templates
aFileName[fileExten] = '\0';
strcat(aFileName, "templates.json");
//load the data into apsTemplates
if (!loadSaveTemplate(aFileName))
{
debug(LOG_ERROR, "Failed with: %s", aFileName);
Expand Down Expand Up @@ -5706,56 +5687,47 @@ bool loadSaveTemplate(const char *pFileName)
{
ini.beginGroup(list[i]);
int player = getPlayer(ini);
DROID_TEMPLATE *psTemplate = new DROID_TEMPLATE;
psTemplate->name = ini.value("name").toString();
psTemplate->ref = ini.value("ref").toInt();
psTemplate->droidType = (DROID_TYPE)ini.value("droidType").toInt();
psTemplate->multiPlayerID = ini.value("multiPlayerID").toInt();
psTemplate->asParts[COMP_BODY] = getCompFromName(COMP_BODY, ini.value("body", "ZNULLBODY").toString());
psTemplate->asParts[COMP_BRAIN] = getCompFromName(COMP_BRAIN, ini.value("brain", "ZNULLBRAIN").toString());
psTemplate->asParts[COMP_PROPULSION] = getCompFromName(COMP_PROPULSION, ini.value("propulsion", "ZNULLPROP").toString());
psTemplate->asParts[COMP_REPAIRUNIT] = getCompFromName(COMP_REPAIRUNIT, ini.value("repair", "ZNULLREPAIR").toString());
psTemplate->asParts[COMP_ECM] = getCompFromName(COMP_ECM, ini.value("ecm", "ZNULLECM").toString());
psTemplate->asParts[COMP_SENSOR] = getCompFromName(COMP_SENSOR, ini.value("sensor", "ZNULLSENSOR").toString());
psTemplate->asParts[COMP_CONSTRUCT] = getCompFromName(COMP_CONSTRUCT, ini.value("construct", "ZNULLCONSTRUCT").toString());
psTemplate->asWeaps[0] = getCompFromName(COMP_WEAPON, ini.value("weapon/1", "ZNULLWEAPON").toString());
psTemplate->asWeaps[1] = getCompFromName(COMP_WEAPON, ini.value("weapon/2", "ZNULLWEAPON").toString());
psTemplate->asWeaps[2] = getCompFromName(COMP_WEAPON, ini.value("weapon/3", "ZNULLWEAPON").toString());
psTemplate->numWeaps = ini.value("weapons").toInt();
psTemplate->enabled = ini.value("enabled").toBool();
psTemplate->prefab = false; // not AI template

//store it in the apropriate player' list
//if a template with the same multiplayerID exists overwrite it
//else add this template to the top of the list
DROID_TEMPLATE *psDestTemplate = apsDroidTemplates[player];
while (psDestTemplate != NULL)
{
if (psTemplate->multiPlayerID == psDestTemplate->multiPlayerID)
bool beta1_compat_hack = false; // TBD remove before release!
beta1_compat_hack = !ini.beginArray("templates");
while (ini.remainingArrayItems() > 0 || beta1_compat_hack)
{
DROID_TEMPLATE *psTemplate = new DROID_TEMPLATE;
psTemplate->name = ini.value("name").toString();
psTemplate->ref = ini.value("ref").toInt();
psTemplate->droidType = (DROID_TYPE)ini.value("droidType").toInt();
psTemplate->multiPlayerID = ini.value("multiPlayerID").toInt();
psTemplate->asParts[COMP_BODY] = getCompFromName(COMP_BODY, ini.value("body", "ZNULLBODY").toString());
psTemplate->asParts[COMP_BRAIN] = getCompFromName(COMP_BRAIN, ini.value("brain", "ZNULLBRAIN").toString());
psTemplate->asParts[COMP_PROPULSION] = getCompFromName(COMP_PROPULSION, ini.value("propulsion", "ZNULLPROP").toString());
psTemplate->asParts[COMP_REPAIRUNIT] = getCompFromName(COMP_REPAIRUNIT, ini.value("repair", "ZNULLREPAIR").toString());
psTemplate->asParts[COMP_ECM] = getCompFromName(COMP_ECM, ini.value("ecm", "ZNULLECM").toString());
psTemplate->asParts[COMP_SENSOR] = getCompFromName(COMP_SENSOR, ini.value("sensor", "ZNULLSENSOR").toString());
psTemplate->asParts[COMP_CONSTRUCT] = getCompFromName(COMP_CONSTRUCT, ini.value("construct", "ZNULLCONSTRUCT").toString());
psTemplate->asWeaps[0] = getCompFromName(COMP_WEAPON, ini.value("weapon/1", "ZNULLWEAPON").toString());
psTemplate->asWeaps[1] = getCompFromName(COMP_WEAPON, ini.value("weapon/2", "ZNULLWEAPON").toString());
psTemplate->asWeaps[2] = getCompFromName(COMP_WEAPON, ini.value("weapon/3", "ZNULLWEAPON").toString());
psTemplate->numWeaps = ini.value("weapons").toInt();
psTemplate->enabled = ini.value("enabled").toBool();
psTemplate->prefab = false; // not AI template
addTemplate(player, psTemplate);
if (beta1_compat_hack)
{
//whooh get rid of this one
break;
}
psDestTemplate = psDestTemplate->psNext;
}

if (psDestTemplate != NULL)
{
psTemplate->psNext = psDestTemplate->psNext;//preserve the list
*psDestTemplate = *psTemplate;
ini.nextArrayItem();
}
else
if (beta1_compat_hack)
{
//add it to the top of the list
psTemplate->psNext = apsDroidTemplates[player];
apsDroidTemplates[player] = psTemplate;
ini.endGroup();
continue;
}
ini.endArray();
ini.endGroup();
}

for (DROID_TEMPLATE *t = apsDroidTemplates[selectedPlayer]; t != NULL; t = t->psNext)
for (auto &keyvaluepair : droidTemplates[selectedPlayer])
{
localTemplates.push_front(*t);
localTemplates.push_back(*keyvaluepair.second);
}

return true;
Expand All @@ -5767,32 +5739,37 @@ bool writeTemplateFile(const char *pFileName)

for (int player = 0; player < MAX_PLAYERS; player++)
{
if (apsDroidLists[player] || apsStructLists[player]) // only write out templates of players that are still 'alive'
if (!apsDroidLists[player] && !apsStructLists[player]) // only write out templates of players that are still 'alive'
{
for (DROID_TEMPLATE *psCurr = apsDroidTemplates[player]; psCurr != NULL; psCurr = psCurr->psNext)
continue;
}
ini.beginGroup("player_" + QString::number(player));
setPlayer(ini, player);
ini.beginArray("templates");
for (auto &keyvaluepair : droidTemplates[player])
{
DROID_TEMPLATE *psCurr = keyvaluepair.second;
ini.setValue("name", psCurr->name);
ini.setValue("ref", psCurr->ref);
ini.setValue("droidType", psCurr->droidType);
ini.setValue("multiPlayerID", psCurr->multiPlayerID);
ini.setValue("body", (asBodyStats + psCurr->asParts[COMP_BODY])->id);
ini.setValue("propulsion", (asPropulsionStats + psCurr->asParts[COMP_PROPULSION])->id);
ini.setValue("brain", (asBrainStats + psCurr->asParts[COMP_BRAIN])->id);
ini.setValue("repair", (asRepairStats + psCurr->asParts[COMP_REPAIRUNIT])->id);
ini.setValue("ecm", (asECMStats + psCurr->asParts[COMP_ECM])->id);
ini.setValue("sensor", (asSensorStats + psCurr->asParts[COMP_SENSOR])->id);
ini.setValue("construct", (asConstructStats + psCurr->asParts[COMP_CONSTRUCT])->id);
ini.setValue("weapons", psCurr->numWeaps);
ini.setValue("enabled", psCurr->enabled);
for (int j = 0; j < psCurr->numWeaps; j++)
{
ini.beginGroup("template_" + QString::number(psCurr->multiPlayerID) + "_player" + QString::number(player));
ini.setValue("name", psCurr->name);
ini.setValue("ref", psCurr->ref);
ini.setValue("droidType", psCurr->droidType);
ini.setValue("multiPlayerID", psCurr->multiPlayerID);
setPlayer(ini, player);
ini.setValue("body", (asBodyStats + psCurr->asParts[COMP_BODY])->id);
ini.setValue("propulsion", (asPropulsionStats + psCurr->asParts[COMP_PROPULSION])->id);
ini.setValue("brain", (asBrainStats + psCurr->asParts[COMP_BRAIN])->id);
ini.setValue("repair", (asRepairStats + psCurr->asParts[COMP_REPAIRUNIT])->id);
ini.setValue("ecm", (asECMStats + psCurr->asParts[COMP_ECM])->id);
ini.setValue("sensor", (asSensorStats + psCurr->asParts[COMP_SENSOR])->id);
ini.setValue("construct", (asConstructStats + psCurr->asParts[COMP_CONSTRUCT])->id);
ini.setValue("weapons", psCurr->numWeaps);
ini.setValue("enabled", psCurr->enabled);
for (int j = 0; j < psCurr->numWeaps; j++)
{
ini.setValue("weapon/" + QString::number(j + 1), (asWeaponStats + psCurr->asWeaps[j])->id);
}
ini.endGroup();
ini.setValue("weapon/" + QString::number(j + 1), (asWeaponStats + psCurr->asWeaps[j])->id);
}
ini.nextArrayItem();
}
ini.endArray();
ini.endGroup();
}
return true;
}
Expand Down
6 changes: 3 additions & 3 deletions src/keybind.cpp
Expand Up @@ -396,11 +396,11 @@ void kf_CloneSelected(void)
{
if (psDroid->selected)
{
for (DROID_TEMPLATE *psTempl = apsDroidTemplates[selectedPlayer]; psTempl; psTempl = psTempl->psNext)
for (auto &keyvaluepair : droidTemplates[selectedPlayer])
{
if (psTempl->name.compare(psDroid->aName) == 0)
if (keyvaluepair.second->name.compare(psDroid->aName) == 0)
{
sTemplate = psTempl;
sTemplate = keyvaluepair.second;
break;
}
}
Expand Down

0 comments on commit 0556c63

Please sign in to comment.