Пример #1
0
// 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;
}
Пример #2
0
// 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;
}
Пример #3
0
/** 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;
}
Пример #4
0
// 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;
}
Пример #5
0
// 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;
}