// load a list of triggers static bool eventLoadTriggerList(WzConfig &ini, QString tname) { UDWORD event, offset, time; int numTriggers, context, type, trigger; SCRIPT_CONTEXT *psContext; numTriggers = ini.value("general/num" + tname).toInt(); for (int i = 0; i < numTriggers; i++) { ini.beginGroup(tname + "_" + QString::number(i)); time = ini.value("time").toInt(); context = ini.value("context").toInt(); if (!eventFindContext(context, &psContext)) { debug(LOG_FATAL, "could not find context"); return false; } type = ini.value("type").toInt(); trigger = ini.value("trigger").toInt(); event = ini.value("event").toInt(); offset = ini.value("offset").toInt(); if (!eventLoadTrigger(time, psContext, type, trigger, event, offset)) { debug(LOG_FATAL, "Failed to create trigger"); return false; } ini.endGroup(); } return true; }
// save a list of triggers static bool eventSaveTriggerList(ACTIVE_TRIGGER *psList, QString tname, WzConfig &ini) { int numTriggers = 0, context = 0; for (ACTIVE_TRIGGER *psCurr = psList; psCurr != NULL; psCurr = psCurr->psNext) { if (!eventGetContextIndex(psCurr->psContext, &context)) { debug(LOG_FATAL, "Could not find context"); return false; } ini.beginGroup(tname + "_" + QString::number(numTriggers)); ini.setValue("time", QVariant(psCurr->testTime)); ini.setValue("context", QVariant(context)); ini.setValue("type", QVariant(psCurr->type)); ini.setValue("trigger", QVariant(psCurr->trigger)); ini.setValue("event", QVariant(psCurr->event)); ini.setValue("offset", QVariant(psCurr->offset)); ini.endGroup(); numTriggers++; } ini.setValue("general/num" + tname, QVariant(numTriggers)); return true; }
DROID_TEMPLATE loadTemplateCommon(WzConfig &ini) { DROID_TEMPLATE design; QString droidType = ini.value("type").toString(); if (droidType == "ECM") { design.droidType = DROID_ECM; } else if (droidType == "SENSOR") { design.droidType = DROID_SENSOR; } else if (droidType == "CONSTRUCT") { design.droidType = DROID_CONSTRUCT; } else if (droidType == "WEAPON") { design.droidType = DROID_WEAPON; } else if (droidType == "PERSON") { design.droidType = DROID_PERSON; } else if (droidType == "CYBORG") { design.droidType = DROID_CYBORG; } else if (droidType == "CYBORG_SUPER") { design.droidType = DROID_CYBORG_SUPER; } else if (droidType == "CYBORG_CONSTRUCT") { design.droidType = DROID_CYBORG_CONSTRUCT; } else if (droidType == "CYBORG_REPAIR") { design.droidType = DROID_CYBORG_REPAIR; } else if (droidType == "TRANSPORTER") { design.droidType = DROID_TRANSPORTER; } else if (droidType == "SUPERTRANSPORTER") { design.droidType = DROID_SUPERTRANSPORTER; } else if (droidType == "DROID") { design.droidType = DROID_DEFAULT; } else if (droidType == "DROID_COMMAND") { design.droidType = DROID_COMMAND; } else if (droidType == "REPAIR") { design.droidType = DROID_REPAIR; } else { ASSERT(false, "No such droid type \"%s\" for %s", droidType.toUtf8().constData(), getID(&design)); } design.asParts[COMP_BODY] = getCompFromName(COMP_BODY, ini.value("body").toString()); design.asParts[COMP_BRAIN] = getCompFromName(COMP_BRAIN, ini.value("brain", QString("ZNULLBRAIN")).toString()); design.asParts[COMP_PROPULSION] = getCompFromName(COMP_PROPULSION, ini.value("propulsion", QString("ZNULLPROP")).toString()); design.asParts[COMP_REPAIRUNIT] = getCompFromName(COMP_REPAIRUNIT, ini.value("repair", QString("ZNULLREPAIR")).toString()); design.asParts[COMP_ECM] = getCompFromName(COMP_ECM, ini.value("ecm", QString("ZNULLECM")).toString()); design.asParts[COMP_SENSOR] = getCompFromName(COMP_SENSOR, ini.value("sensor", QString("ZNULLSENSOR")).toString()); design.asParts[COMP_CONSTRUCT] = getCompFromName(COMP_CONSTRUCT, ini.value("construct", QString("ZNULLCONSTRUCT")).toString()); QStringList weapons = ini.value("weapons").toStringList(); design.numWeaps = weapons.size(); design.asWeaps[0] = getCompFromName(COMP_WEAPON, weapons.value(0, QString("ZNULLWEAPON"))); design.asWeaps[1] = getCompFromName(COMP_WEAPON, weapons.value(1, QString("ZNULLWEAPON"))); design.asWeaps[2] = getCompFromName(COMP_WEAPON, weapons.value(2, QString("ZNULLWEAPON"))); return design; }
void saveTemplateCommon(WzConfig &ini, DROID_TEMPLATE *psCurr) { ini.setValue("name", psCurr->name); switch (psCurr->droidType) { case DROID_ECM: ini.setValue("type", "ECM"); break; case DROID_SENSOR: ini.setValue("type", "SENSOR"); break; case DROID_CONSTRUCT: ini.setValue("type", "CONSTRUCT"); break; case DROID_WEAPON: ini.setValue("type", "WEAPON"); break; case DROID_PERSON: ini.setValue("type", "PERSON"); break; case DROID_CYBORG: ini.setValue("type", "CYBORG"); break; case DROID_CYBORG_SUPER: ini.setValue("type", "CYBORG_SUPER"); break; case DROID_CYBORG_CONSTRUCT: ini.setValue("type", "CYBORG_CONSTRUCT"); break; case DROID_CYBORG_REPAIR: ini.setValue("type", "CYBORG_REPAIR"); break; case DROID_TRANSPORTER: ini.setValue("type", "TRANSPORTER"); break; case DROID_SUPERTRANSPORTER: ini.setValue("type", "SUPERTRANSPORTER"); break; case DROID_COMMAND: ini.setValue("type", "DROID_COMMAND"); break; case DROID_REPAIR: ini.setValue("type", "REPAIR"); break; case DROID_DEFAULT: ini.setValue("type", "DROID"); break; default: ASSERT(false, "No such droid type \"%d\" for %s", psCurr->droidType, psCurr->name.toUtf8().constData()); } ini.setValue("body", (asBodyStats + psCurr->asParts[COMP_BODY])->id); ini.setValue("propulsion", (asPropulsionStats + psCurr->asParts[COMP_PROPULSION])->id); if (psCurr->asParts[COMP_BRAIN] != 0) { ini.setValue("brain", (asBrainStats + psCurr->asParts[COMP_BRAIN])->id); } if ((asRepairStats + psCurr->asParts[COMP_REPAIRUNIT])->location == LOC_TURRET) // avoid auto-repair... { ini.setValue("repair", (asRepairStats + psCurr->asParts[COMP_REPAIRUNIT])->id); } if ((asECMStats + psCurr->asParts[COMP_ECM])->location == LOC_TURRET) { ini.setValue("ecm", (asECMStats + psCurr->asParts[COMP_ECM])->id); } if ((asSensorStats + psCurr->asParts[COMP_SENSOR])->location == LOC_TURRET) { ini.setValue("sensor", (asSensorStats + psCurr->asParts[COMP_SENSOR])->id); } if (psCurr->asParts[COMP_CONSTRUCT] != 0) { ini.setValue("construct", (asConstructStats + psCurr->asParts[COMP_CONSTRUCT])->id); } QStringList weapons; for (int j = 0; j < psCurr->numWeaps; j++) { weapons += (asWeaponStats + psCurr->asWeaps[j])->id; } if (weapons.size()) { ini.setValue("weapons", weapons); } }
/** Load the research stats */ bool loadResearch(WzConfig &ini) { ASSERT(ini.isAtDocumentRoot(), "WzConfig instance is in the middle of traversal"); std::vector<WzString> list = ini.childGroups(); PLAYER_RESEARCH dummy; memset(&dummy, 0, sizeof(dummy)); std::vector< std::vector<WzString> > preResearch; preResearch.resize(list.size()); for (size_t inc = 0; inc < list.size(); ++inc) { // HACK FIXME: the code assumes we have empty PLAYER_RESEARCH entries to throw around for (auto &j : asPlayerResList) { j.push_back(dummy); } ini.beginGroup(list[inc]); RESEARCH research; research.index = inc; research.name = ini.string("name"); research.id = list[inc]; //check the name hasn't been used already ASSERT_OR_RETURN(false, checkResearchName(&research, inc), "Research name '%s' used already", getName(&research)); research.ref = REF_RESEARCH_START + inc; research.results = ini.json("results", nlohmann::json::array()); //set subGroup icon WzString subGroup = ini.value("subgroupIconID", "").toWzString(); if (subGroup.compare("") != 0) { research.subGroup = setIconID(subGroup.toUtf8().c_str(), getName(&research)); } else { research.subGroup = NO_RESEARCH_ICON; } //set key topic unsigned int keyTopic = ini.value("keyTopic", 0).toUInt(); ASSERT(keyTopic <= 1, "Invalid keyTopic for research topic - '%s' ", getName(&research)); if (keyTopic <= 1) { research.keyTopic = ini.value("keyTopic", 0).toUInt(); } else { research.keyTopic = 0; } //set tech code UBYTE techCode = ini.value("techCode", 0).toUInt(); ASSERT(techCode <= 1, "Invalid tech code for research topic - '%s' ", getName(&research)); if (techCode == 0) { research.techCode = TC_MAJOR; } else { research.techCode = TC_MINOR; } //set the iconID WzString iconID = ini.value("iconID", "").toWzString(); if (iconID.compare("") != 0) { research.iconID = setIconID(iconID.toUtf8().c_str(), getName(&research)); } else { research.iconID = NO_RESEARCH_ICON; } //get the IMDs used in the interface WzString statID = ini.value("statID", "").toWzString(); research.psStat = nullptr; if (statID.compare("") != 0) { //try find the structure stat with given name research.psStat = getCompStatsFromName(statID); ASSERT_OR_RETURN(false, research.psStat, "Could not find stats for %s research %s", statID.toUtf8().c_str(), getName(&research)); } WzString imdName = ini.value("imdName", "").toWzString(); if (imdName.compare("") != 0) { research.pIMD = modelGet(imdName); ASSERT(research.pIMD != nullptr, "Cannot find the research PIE '%s' for record '%s'", imdName.toUtf8().data(), getName(&research)); } WzString imdName2 = ini.value("imdName2", "").toWzString(); if (imdName2.compare("") != 0) { research.pIMD2 = modelGet(imdName2); ASSERT(research.pIMD2 != nullptr, "Cannot find the 2nd research '%s' PIE for record '%s'", imdName2.toUtf8().data(), getName(&research)); } WzString msgName = ini.value("msgName", "").toWzString(); if (msgName.compare("") != 0) { //check its a major tech code ASSERT(research.techCode == TC_MAJOR, "This research should not have a message associated with it, '%s' the message will be ignored!", getName(&research)); if (research.techCode == TC_MAJOR) { research.pViewData = getViewData(msgName); } } //set the researchPoints unsigned int resPoints = ini.value("researchPoints", 0).toUInt(); ASSERT_OR_RETURN(false, resPoints <= UWORD_MAX, "Research Points too high for research topic - '%s' ", getName(&research)); research.researchPoints = resPoints; //set the research power unsigned int resPower = ini.value("researchPower", 0).toUInt(); ASSERT_OR_RETURN(false, resPower <= UWORD_MAX, "Research Power too high for research topic - '%s' ", getName(&research)); research.researchPower = resPower; //remember research pre-requisites for futher checking preResearch[inc] = ini.value("requiredResearch").toWzStringList(); //set components results std::vector<WzString> compResults = ini.value("resultComponents").toWzStringList(); for (size_t j = 0; j < compResults.size(); j++) { WzString compID = compResults[j].trimmed(); COMPONENT_STATS *pComp = getCompStatsFromName(compID); if (pComp != nullptr) { research.componentResults.push_back(pComp); } else { ASSERT(false, "Invalid item '%s' in list of result components of research '%s' ", compID.toUtf8().c_str(), getName(&research)); } } //set replaced components std::vector<WzString> replacedComp = ini.value("replacedComponents").toWzStringList(); for (size_t j = 0; j < replacedComp.size(); j++) { //read pair of components oldComponent:newComponent std::vector<WzString> pair = replacedComp[j].split(":"); ASSERT(pair.size() == 2, "Invalid item '%s' in list of replaced components of research '%s'. Required format: 'oldItem:newItem, item1:item2'", replacedComp[j].toUtf8().c_str(), getName(&research)); if (pair.size() != 2) { continue; //skip invalid entries } WzString oldCompID = pair[0].trimmed(); WzString newCompID = pair[1].trimmed(); COMPONENT_STATS *oldComp = getCompStatsFromName(oldCompID); if (oldComp == nullptr) { ASSERT(false, "Invalid item '%s' in list of replaced components of research '%s'. Wrong component code.", oldCompID.toUtf8().c_str(), getName(&research)); continue; } COMPONENT_STATS *newComp = getCompStatsFromName(newCompID); if (newComp == nullptr) { ASSERT(false, "Invalid item '%s' in list of replaced components of research '%s'. Wrong component code.", newCompID.toUtf8().c_str(), getName(&research)); continue; } RES_COMP_REPLACEMENT replItem; replItem.pOldComponent = oldComp; replItem.pNewComponent = newComp; research.componentReplacement.push_back(replItem); } //set redundant components std::vector<WzString> redComp = ini.value("redComponents").toWzStringList(); for (size_t j = 0; j < redComp.size(); j++) { WzString compID = redComp[j].trimmed(); COMPONENT_STATS *pComp = getCompStatsFromName(compID); if (pComp == nullptr) { ASSERT(false, "Invalid item '%s' in list of redundant components of research '%s' ", compID.toUtf8().c_str(), getName(&research)); } else { research.pRedArtefacts.push_back(pComp); } } //set result structures std::vector<WzString> resStruct = ini.value("resultStructures").toWzStringList(); for (size_t j = 0; j < resStruct.size(); j++) { WzString strucID = resStruct[j].trimmed(); int structIndex = getStructStatFromName(strucID); ASSERT(structIndex >= 0, "Invalid item '%s' in list of result structures of research '%s' ", strucID.toUtf8().c_str(), getName(&research)); if (structIndex >= 0) { research.pStructureResults.push_back(structIndex); } } //set required structures std::vector<WzString> reqStruct = ini.value("requiredStructures").toWzStringList(); for (size_t j = 0; j < reqStruct.size(); j++) { WzString strucID = reqStruct[j].trimmed(); int structIndex = getStructStatFromName(strucID.toUtf8().c_str()); ASSERT(structIndex >= 0, "Invalid item '%s' in list of required structures of research '%s' ", strucID.toUtf8().c_str(), getName(&research)); if (structIndex >= 0) { research.pStructList.push_back(structIndex); } } //set redundant structures std::vector<WzString> redStruct = ini.value("redStructures").toWzStringList(); for (size_t j = 0; j < redStruct.size(); j++) { WzString strucID = redStruct[j].trimmed(); int structIndex = getStructStatFromName(strucID.toUtf8().c_str()); ASSERT(structIndex >= 0, "Invalid item '%s' in list of redundant structures of research '%s' ", strucID.toUtf8().c_str(), getName(&research)); if (structIndex >= 0) { research.pRedStructs.push_back(structIndex); } } asResearch.push_back(research); ini.endGroup(); } //Load and check research pre-requisites (need do it AFTER loading research items) for (size_t inc = 0; inc < asResearch.size(); inc++) { std::vector<WzString> &preRes = preResearch[inc]; for (size_t j = 0; j < preRes.size(); j++) { WzString resID = preRes[j].trimmed(); RESEARCH *preResItem = getResearch(resID.toUtf8().c_str()); ASSERT(preResItem != nullptr, "Invalid item '%s' in list of pre-requisites of research '%s' ", resID.toUtf8().c_str(), getName(&asResearch[inc])); if (preResItem != nullptr) { asResearch[inc].pPRList.push_back(preResItem->index); } } } return true; }
/// default value load routine bool scrValDefLoad(INTERP_VAL *psVal, WzConfig &ini) { DROID *psCDroid; SDWORD index, members; UDWORD id; LEVEL_DATASET *psLevel; DROID_GROUP *psGroup = NULL; switch ((unsigned)psVal->type) // Unsigned cast to suppress compiler warnings due to enum abuse. { case ST_INTMESSAGE: if (ini.contains("data")) { psVal->v.oval = (void*)getViewData(ini.value("data").toString().toAscii().constData()); } else { psVal->v.oval = NULL; } break; case ST_BASEOBJECT: case ST_DROID: case ST_STRUCTURE: case ST_FEATURE: if (ini.contains("data")) { psVal->v.oval = (void*)getBaseObjFromId(ini.value("data").toInt()); } else { psVal->v.oval = NULL; } break; case ST_BASESTATS: case ST_COMPONENT: break; case ST_STRUCTURESTAT: index = 0; if (ini.contains("data")) { index = getStructStatFromName(ini.value("data").toString().toAscii().constData()); if (index == -1) { debug( LOG_FATAL, "Could not find stat"); index = 0; } } psVal->v.ival = index; break; case ST_FEATURESTAT: index = 0; if (ini.contains("data")) { index = getFeatureStatFromName(ini.value("data").toString().toAscii().constData()); if (index == -1) { debug( LOG_FATAL, "Could not find stat"); index = 0; } } psVal->v.ival = index; break; case ST_BODY: index = getCompFromResName(COMP_BODY, ini.value("data").toString().toAscii().constData()); if (index == -1) { debug(LOG_FATAL, "Could not find body component"); index = 0; } psVal->v.ival = index; break; case ST_PROPULSION: index = getCompFromResName(COMP_PROPULSION, ini.value("data").toString().toAscii().constData()); if (index == -1) { debug(LOG_FATAL, "Could not find propulsion component"); index = 0; } psVal->v.ival = index; break; case ST_ECM: index = getCompFromResName(COMP_ECM, ini.value("data").toString().toAscii().constData()); if (index == -1) { debug(LOG_FATAL, "Could not find ECM component"); index = 0; } psVal->v.ival = index; break; case ST_SENSOR: index = getCompFromResName(COMP_SENSOR, ini.value("data").toString().toAscii().constData()); if (index == -1) { debug(LOG_FATAL, "Could not find sensor component"); index = 0; } psVal->v.ival = index; break; case ST_CONSTRUCT: index = getCompFromResName(COMP_CONSTRUCT, ini.value("data").toString().toAscii().constData()); if (index == -1) { debug(LOG_FATAL, "Could not find constructor component"); index = 0; } psVal->v.ival = index; break; case ST_WEAPON: index = getCompFromResName(COMP_WEAPON, ini.value("data").toString().toAscii().constData()); if (index == -1) { debug(LOG_FATAL, "Could not find weapon"); index = 0; } psVal->v.ival = index; break; case ST_REPAIR: index = getCompFromResName(COMP_REPAIRUNIT, ini.value("data").toString().toAscii().constData()); if (index == -1) { debug(LOG_FATAL, "Could not find repair component"); index = 0; } psVal->v.ival = index; break; case ST_BRAIN: index = getCompFromResName(COMP_BRAIN, ini.value("data").toString().toAscii().constData()); if (index == -1) { debug(LOG_FATAL, "Could not find repair brain"); index = 0; } psVal->v.ival = index; break; case ST_TEMPLATE: psVal->v.oval = NULL; if (ini.contains("data")) { // FIXME: Ugh. Find a better way to show full template info psVal->v.oval = (void*)IdToTemplate(ini.value("data").toInt(), ANYPLAYER); if ((DROID_TEMPLATE*)(psVal->v.oval) == NULL) { debug(LOG_FATAL, "Could not find template %d", ini.value("data").toInt()); } } break; case ST_TEXTSTRING: psVal->v.sval = NULL; if (ini.contains("data")) { psVal->v.sval = strdup(ini.value("data").toString().toAscii().constData()); } break; case ST_LEVEL: psVal->v.sval = NULL; if (ini.contains("data")) { psLevel = levFindDataSet(ini.value("data").toString().toAscii().constData()); if (psLevel == NULL) { debug(LOG_FATAL, "Could not find level dataset"); } psVal->v.sval = psLevel->pName; } break; case ST_RESEARCH: psVal->v.oval = NULL; if (ini.contains("data")) { QString research = ini.value("data").toString(); if (!research.isEmpty()) { psVal->v.oval = (void*)getResearch(research.toUtf8().constData()); ASSERT_OR_RETURN(false, psVal->v.oval, "Could not find research %s", research.toUtf8().constData()); } } break; case ST_GROUP: if (psVal->v.oval == NULL) { DROID_GROUP *tmp = grpCreate(); tmp->add(NULL); psVal->v.oval = tmp; } psGroup = (DROID_GROUP *)(psVal->v.oval); members = ini.value("members", 0).toInt(); if (psGroup && members > 0) { QStringList droids = ini.value("data").toStringList(); // load the retreat data psGroup->sRunData.sPos = ini.vector2i("runpos"); psGroup->sRunData.forceLevel = ini.value("forceLevel").toInt(); psGroup->sRunData.leadership = ini.value("leadership").toInt(); psGroup->sRunData.healthLevel = ini.value("healthLevel").toInt(); // load the droids while (members > 0) { id = droids.takeLast().toInt(); psCDroid = (DROID *)getBaseObjFromId(id); if (!psCDroid) { debug(LOG_ERROR, "Could not find object id %d", id); } else { ((DROID_GROUP*)(psVal->v.oval))->add(psCDroid); } members--; } } break; case ST_SOUND: // find audio id // don't use sound if it's disabled if (audio_Disabled()) { psVal->v.ival = NO_SOUND; break; } index = audio_GetTrackID(ini.value("data").toString().toAscii().constData()); if (index == SAMPLE_NOT_FOUND) { // find empty id and set track vals QString soundname = ini.value("data").toString(); index = audio_SetTrackVals(soundname.toAscii().constData(), false, 100, 1800); if (!index) // this is a NON fatal error. { // We can't find filename of the sound for some reason. debug(LOG_ERROR, "Sound ID not available %s not found", soundname.toAscii().constData()); break; } } psVal->v.ival = index; break; case ST_STRUCTUREID: case ST_DROIDID: default: // just set the contents directly psVal->v.ival = ini.value("data").toInt(); break; } return true; }
// default value save routine //TODO: use union bool scrValDefSave(INTERP_VAL *psVal, WzConfig &ini) { VIEWDATA *psIntMessage; const char *pName; RESEARCH *psResearch; DROID *psCDroid; switch ((unsigned)psVal->type) // Unsigned cast to suppress compiler warnings due to enum abuse. { case ST_INTMESSAGE: // save the name psIntMessage = (VIEWDATA *)psVal->v.oval; if (psIntMessage != NULL) { ini.setValue("data", QString(psIntMessage->pName)); } break; case ST_BASEOBJECT: case ST_DROID: case ST_STRUCTURE: case ST_FEATURE: // just save the id if (psVal->v.oval && ((BASE_OBJECT *)psVal->v.oval)->died <= NOT_CURRENT_LIST) { ini.setValue("data", QVariant(((BASE_OBJECT *)psVal->v.oval)->id)); } break; case ST_BASESTATS: case ST_COMPONENT: case ST_FEATURESTAT: case ST_STRUCTURESTAT: case ST_BODY: case ST_PROPULSION: case ST_ECM: case ST_SENSOR: case ST_CONSTRUCT: case ST_WEAPON: case ST_REPAIR: case ST_BRAIN: pName = scrGetStatName(psVal->type, psVal->v.ival); if (pName) { ini.setValue("data", QString(pName)); } break; case ST_TEMPLATE: if (psVal->v.oval) { ini.setValue("data", ((DROID_TEMPLATE *)psVal->v.oval)->multiPlayerID); } break; case ST_TEXTSTRING: { const char *const idStr = psVal->v.sval ? strresGetIDfromString(psStringRes, psVal->v.sval) : NULL; if (idStr) { ini.setValue("data", QString(idStr)); } break; } case ST_LEVEL: if (psVal->v.sval) { ini.setValue("data", QString(psVal->v.sval)); } break; case ST_RESEARCH: psResearch = (RESEARCH *)psVal->v.oval; if (psResearch && psResearch->pName && psResearch->pName[0] != '\0') { ini.setValue("data", QString(psResearch->pName)); ASSERT(psResearch == getResearch(psResearch->pName), "Research %s not found!", psResearch->pName); } break; case ST_GROUP: { DROID_GROUP *const psGroup = (DROID_GROUP *)psVal->v.oval; if (psGroup) { const int members = psGroup->getNumMembers(); QStringList droids; for (psCDroid = psGroup->psList; psCDroid; psCDroid = psCDroid->psGrpNext) { checkValidId(psCDroid->id); droids.push_back(QString::number(psCDroid->id)); } ini.setValue("members", QVariant(members)); if (droids.size() > 0) { ini.setValue("data", droids); } ini.setVector2i("runpos", psGroup->sRunData.sPos); ini.setValue("forceLevel", QVariant(psGroup->sRunData.forceLevel)); ini.setValue("leadership", QVariant(psGroup->sRunData.leadership)); ini.setValue("healthLevel", QVariant(psGroup->sRunData.healthLevel)); } break; } case ST_SOUND: if(psVal->v.ival) { // can also return NULL pName = sound_GetTrackName((UDWORD)psVal->v.ival); } else { pName = NULL; } if (!pName) { debug(LOG_WARNING, "Could not get sound track name"); } if (pName) { ini.setValue("data", QString(pName)); } break; case ST_STRUCTUREID: case ST_DROIDID: ini.setValue("data", QVariant(psVal->v.ival)); break; default: ASSERT(false, "Unknown script variable type for save"); break; } return true; }
static void calcDataHash(const WzConfig &ini, uint32_t index) { std::string jsonDump = ini.compactStringRepresentation(); calcDataHash(reinterpret_cast<const uint8_t *>(jsonDump.data()), jsonDump.size(), index); }
// save the context information for the script system static bool eventSaveContext(WzConfig &ini) { int numVars, numContext = 0; UDWORD hashedName; // go through the context list for (SCRIPT_CONTEXT *psCCont = psContList; psCCont != NULL; psCCont = psCCont->psNext) { // save the context info if (!resGetHashfromData("SCRIPT", psCCont->psCode, &hashedName)) { debug(LOG_FATAL, "Could not find script resource id"); return false; } numVars = psCCont->psCode->numGlobals + psCCont->psCode->arraySize; ini.beginGroup("context_" + QString::number(numContext)); ini.setValue("context", hashedName); ini.setValue("numVars", numVars); ini.setValue("release", psCCont->release); ini.beginGroup("var"); // save the context variables int countVar = 0; for (VAL_CHUNK *psCVals = psCCont->psGlobals; psCVals != NULL; psCVals = psCVals->psNext) { for (int i = 0; i < CONTEXT_VALS; i++) { INTERP_VAL *psVal = psCVals->asVals + i; ASSERT(psVal->type < SWORD_MAX, "Variable type number %d too big", (int)psVal->type); ini.beginGroup(QString::number(countVar)); ini.setValue("type", QVariant(psVal->type)); ini.setValue("typename", QString(scriptTypeToString(psVal->type))); // for debugging // store the variable value if (psVal->type == VAL_STRING) { ini.setValue("data", QString(psVal->v.sval)); } else if (psVal->type == VAL_BOOL) { ini.setValue("data", QVariant((bool)psVal->v.bval)); } else if (psVal->type == VAL_FLOAT) { ini.setValue("data", QVariant((float)psVal->v.fval)); } else if (psVal->type == VAL_OBJ_GETSET || psVal->type == VAL_FUNC_EXTERN) { ini.setValue("data", QString("n/a")); } else if (psVal->type < VAL_USERTYPESTART) { ini.setValue("data", QVariant(psVal->v.ival)); } else { // user defined type SCR_VAL_SAVE saveFunc = asScrTypeTab[psVal->type - VAL_USERTYPESTART].saveFunc; ASSERT(saveFunc != NULL, "No save function for type %d", psVal->type); if (!saveFunc(psVal, ini)) { debug(LOG_FATAL, "Could not get user defined variable value"); return false; } } numVars -=1; countVar++; ini.endGroup(); if (numVars <= 0) { // done all the variables ASSERT(psCVals->psNext == NULL, "Number of context variables does not match the script code"); break; } } } ASSERT(numVars == 0, "Number of context variables does not match the script code (%d)", numVars); ini.endGroup(); ini.endGroup(); numContext++; } // actually store how many contexts have been saved ini.setValue("general/contexts", QVariant(numContext)); return true; }
// load the context information for the script system static bool eventLoadContext(WzConfig &ini) { SDWORD numVars, numContext; SCRIPT_CONTEXT *psCCont; SCR_VAL_LOAD loadFunc; UDWORD hashedName; SCRIPT_CODE *psCode; CONTEXT_RELEASE release; INTERP_VAL *psVal, data; // get the number of contexts in the save file numContext = ini.value("general/contexts", 0).toInt(); if (numContext == 0) { debug(LOG_FATAL, "No script contexts found -- failed to load script data"); return false; } // go through the contexts for (int context = 0; context < numContext; context++) { ini.beginGroup("context_" + QString::number(context)); hashedName = ini.value("context").toUInt(); numVars = ini.value("numVars").toInt(); release = (CONTEXT_RELEASE)ini.value("release").toInt(); psCode = (SCRIPT_CODE*)resGetDataFromHash("SCRIPT", hashedName); // create the context if (!eventNewContext(psCode, release, &psCCont)) { debug(LOG_FATAL, "Failed to create new context"); return false; } if (numVars != psCode->numGlobals + psCode->arraySize) { ASSERT(false, "Context %d of %d: Number of context variables (%d) does not match the script code (%d)", context, numContext, numVars, psCode->numGlobals + psCode->arraySize); return false; } // bit of a hack this - note the id of the context to link it to the triggers psContList->id = context; ini.beginGroup("var"); // set the context variables for (int i = 0; i < numVars; i++) { ini.beginGroup(QString::number(i)); // get the variable type INTERP_TYPE type = (INTERP_TYPE)ini.value("type").toInt(); // get the variable value if (type < VAL_USERTYPESTART) { data.type = type; switch (type) { case VAL_BOOL: data.v.bval = ini.value("data").toBool(); break; case VAL_FLOAT: data.v.fval = ini.value("data").toFloat(); break; case VAL_INT: case VAL_TRIGGER: case VAL_EVENT: case VAL_VOID: case VAL_OPCODE: case VAL_PKOPCODE: data.v.ival = ini.value("data").toInt(); break; case VAL_STRING: data.v.sval = (char*)malloc(MAXSTRLEN); strcpy(data.v.sval, ini.value("var/" + QString::number(i) + "/data").toString().toAscii().constData()); break; case VAL_OBJ_GETSET: case VAL_FUNC_EXTERN: // do nothing break; default: ASSERT(false, "Invalid internal type"); } // set the value in the context if (!eventSetContextVar(psCCont, i, &data)) { debug(LOG_FATAL, "Could not set variable value"); return false; } } else { // user defined type loadFunc = asScrTypeTab[type - VAL_USERTYPESTART].loadFunc; ASSERT(loadFunc, "No load function for type %d", type); // get the value pointer so that the loadFunc can write directly // into the variables data space. if (!eventGetContextVal(psCCont, i, &psVal)) { debug(LOG_FATAL, "Could not find variable %d in context %d", i, context); return false; } if (!loadFunc(psVal, ini)) { debug(LOG_FATAL, "Could not get variable value context %d, variable %d", context, i); return false; } } ini.endGroup(); } ini.endGroup(); ini.endGroup(); } return true; }