//__ \subsection{eventResearched(research[, structure])} //__ An event that is run whenever a new research is available. The structure //__ parameter is set if the research comes from a research lab owned by the //__ current player. If an ally does the research, the structure parameter will //__ be set to null. bool triggerEventResearched(RESEARCH *psResearch, STRUCTURE *psStruct, int player) { for (int i = 0; i < scripts.size() && psStruct; ++i) { QScriptEngine *engine = scripts.at(i); int me = engine->globalObject().property("me").toInt32(); if (me == player) { QScriptValueList args; args += convResearch(psResearch, engine, player); if (psStruct) { args += convStructure(psStruct, engine); } callFunction(engine, "eventResearched", args); } } return true; }
static QScriptValue js_enumResearch(QScriptContext *context, QScriptEngine *engine) { QScriptValue result = engine->newArray(1); result.setProperty(0, convResearch(engine)); return result; }
bool testPlayerScript(QString path, int player, int difficulty) { QScriptEngine *engine = new QScriptEngine(); QFile input(path); input.open(QIODevice::ReadOnly); QString source(QString::fromUtf8(input.readAll())); input.close(); // Special functions engine->globalObject().setProperty("setTimer", engine->newFunction(js_setTimer)); engine->globalObject().setProperty("queue", engine->newFunction(js_queue)); engine->globalObject().setProperty("removeTimer", engine->newFunction(js_removeTimer)); engine->globalObject().setProperty("include", engine->newFunction(js_include)); engine->globalObject().setProperty("bind", engine->newFunction(js_bind)); // Special global variables engine->globalObject().setProperty("version", 1, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("selectedPlayer", 0, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("gameTime", 2, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("difficulty", 1, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("mapName", "TEST", QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("baseType", 1, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("alliancesType", 2, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("powerType", 1, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("maxPlayers", CUR_PLAYERS, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("scavengers", true, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("mapWidth", 80, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("mapHeight", 80, QScriptValue::ReadOnly | QScriptValue::Undeletable); // Most special global engine->globalObject().setProperty("me", player, QScriptValue::ReadOnly | QScriptValue::Undeletable); // Register functions to the script engine here engine->globalObject().setProperty("_", engine->newFunction(js_translate)); engine->globalObject().setProperty("label", engine->newFunction(js_label)); engine->globalObject().setProperty("enumLabels", engine->newFunction(js_enumLabels)); engine->globalObject().setProperty("enumGateways", engine->newFunction(js_enumGateways)); // horrible hacks follow -- do not rely on these being present! engine->globalObject().setProperty("hackNetOff", engine->newFunction(js_hackNetOff)); engine->globalObject().setProperty("hackNetOn", engine->newFunction(js_hackNetOn)); engine->globalObject().setProperty("objFromId", engine->newFunction(js_objFromId)); // General functions -- geared for use in AI scripts engine->globalObject().setProperty("debug", engine->newFunction(js_debug)); engine->globalObject().setProperty("console", engine->newFunction(js_console)); engine->globalObject().setProperty("structureIdle", engine->newFunction(js_structureIdle)); engine->globalObject().setProperty("enumStruct", engine->newFunction(js_enumStruct)); engine->globalObject().setProperty("enumStructOffWorld", engine->newFunction(js_enumStructOffWorld)); engine->globalObject().setProperty("enumDroid", engine->newFunction(js_enumDroid)); engine->globalObject().setProperty("enumGroup", engine->newFunction(js_enumGroup)); engine->globalObject().setProperty("enumFeature", engine->newFunction(js_enumFeature)); engine->globalObject().setProperty("enumBlips", engine->newFunction(js_enumBlips)); engine->globalObject().setProperty("enumResearch", engine->newFunction(js_enumResearch)); engine->globalObject().setProperty("getResearch", engine->newFunction(js_getResearch)); engine->globalObject().setProperty("pursueResearch", engine->newFunction(js_pursueResearch)); engine->globalObject().setProperty("distBetweenTwoPoints", engine->newFunction(js_distBetweenTwoPoints)); engine->globalObject().setProperty("newGroup", engine->newFunction(js_newGroup)); engine->globalObject().setProperty("groupAddArea", engine->newFunction(js_groupAddArea)); engine->globalObject().setProperty("groupAddDroid", engine->newFunction(js_groupAddDroid)); engine->globalObject().setProperty("groupSize", engine->newFunction(js_groupSize)); engine->globalObject().setProperty("orderDroidLoc", engine->newFunction(js_orderDroidLoc)); engine->globalObject().setProperty("playerPower", engine->newFunction(js_playerPower)); engine->globalObject().setProperty("isStructureAvailable", engine->newFunction(js_isStructureAvailable)); engine->globalObject().setProperty("pickStructLocation", engine->newFunction(js_pickStructLocation)); engine->globalObject().setProperty("droidCanReach", engine->newFunction(js_droidCanReach)); engine->globalObject().setProperty("orderDroidStatsLoc", engine->newFunction(js_orderDroidBuild)); // deprecated engine->globalObject().setProperty("orderDroidBuild", engine->newFunction(js_orderDroidBuild)); engine->globalObject().setProperty("orderDroidObj", engine->newFunction(js_orderDroidObj)); engine->globalObject().setProperty("orderDroid", engine->newFunction(js_orderDroid)); engine->globalObject().setProperty("buildDroid", engine->newFunction(js_buildDroid)); engine->globalObject().setProperty("addDroid", engine->newFunction(js_addDroid)); engine->globalObject().setProperty("addFeature", engine->newFunction(js_addFeature)); engine->globalObject().setProperty("componentAvailable", engine->newFunction(js_componentAvailable)); engine->globalObject().setProperty("isVTOL", engine->newFunction(js_isVTOL)); engine->globalObject().setProperty("safeDest", engine->newFunction(js_safeDest)); engine->globalObject().setProperty("activateStructure", engine->newFunction(js_activateStructure)); engine->globalObject().setProperty("chat", engine->newFunction(js_chat)); // Functions that operate on the current player only engine->globalObject().setProperty("centreView", engine->newFunction(js_centreView)); engine->globalObject().setProperty("playSound", engine->newFunction(js_playSound)); engine->globalObject().setProperty("gameOverMessage", engine->newFunction(js_gameOverMessage)); // Global state manipulation -- not for use with skirmish AI (unless you want it to cheat, obviously) engine->globalObject().setProperty("setStructureLimits", engine->newFunction(js_setStructureLimits)); engine->globalObject().setProperty("applyLimitSet", engine->newFunction(js_applyLimitSet)); engine->globalObject().setProperty("setMissionTime", engine->newFunction(js_setMissionTime)); engine->globalObject().setProperty("setReinforcementTime", engine->newFunction(js_setReinforcementTime)); engine->globalObject().setProperty("completeResearch", engine->newFunction(js_completeResearch)); engine->globalObject().setProperty("enableResearch", engine->newFunction(js_enableResearch)); engine->globalObject().setProperty("setPower", engine->newFunction(js_setPower)); engine->globalObject().setProperty("setTutorialMode", engine->newFunction(js_setTutorialMode)); engine->globalObject().setProperty("setDesign", engine->newFunction(js_setDesign)); engine->globalObject().setProperty("setMiniMap", engine->newFunction(js_setMiniMap)); engine->globalObject().setProperty("addReticuleButton", engine->newFunction(js_addReticuleButton)); engine->globalObject().setProperty("removeReticuleButton", engine->newFunction(js_removeReticuleButton)); engine->globalObject().setProperty("enableStructure", engine->newFunction(js_enableStructure)); engine->globalObject().setProperty("makeComponentAvailable", engine->newFunction(js_makeComponentAvailable)); engine->globalObject().setProperty("enableComponent", engine->newFunction(js_enableComponent)); engine->globalObject().setProperty("enableTemplate", engine->newFunction(js_enableTemplate)); engine->globalObject().setProperty("allianceExistsBetween", engine->newFunction(js_allianceExistsBetween)); engine->globalObject().setProperty("removeStruct", engine->newFunction(js_removeStruct)); engine->globalObject().setProperty("removeObject", engine->newFunction(js_removeObject)); engine->globalObject().setProperty("setScrollParams", engine->newFunction(js_setScrollParams)); engine->globalObject().setProperty("addStructure", engine->newFunction(js_addStructure)); engine->globalObject().setProperty("loadLevel", engine->newFunction(js_loadLevel)); engine->globalObject().setProperty("setDroidExperience", engine->newFunction(js_setDroidExperience)); engine->globalObject().setProperty("setNoGoArea", engine->newFunction(js_setNoGoArea)); engine->globalObject().setProperty("setAlliance", engine->newFunction(js_setAlliance)); engine->globalObject().setProperty("setAssemblyPoint", engine->newFunction(js_setAssemblyPoint)); // Set some useful constants engine->globalObject().setProperty("DORDER_ATTACK", 0, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DORDER_MOVE", 1, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DORDER_SCOUT", 2, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DORDER_BUILD", 2, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DORDER_HELPBUILD", 3, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DORDER_LINEBUILD", 4, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DORDER_REPAIR", 5, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DORDER_RETREAT", 6, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DORDER_PATROL", 7, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DORDER_DEMOLISH", 8, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DORDER_EMBARK", 9, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DORDER_DISEMBARK", 10, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DORDER_FIRESUPPORT", 11, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DORDER_HOLD", 12, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DORDER_RTR", 13, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DORDER_RTB", 14, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DORDER_STOP", 15, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DORDER_REARM", 16, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("COMMAND", 0, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("BUILD", 1, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("MANUFACTURE", 2, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("RESEARCH", 3, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("INTELMAP", 4, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DESIGN", 5, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("CANCEL", 6, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("CAMP_CLEAN", 0, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("CAMP_BASE", 1, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("CAMP_WALLS", 2, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("NO_ALLIANCES", 0, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("ALLIANCES", 1, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("ALLIANCES_TEAMS", 2, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("BEING_BUILT", SS_BEING_BUILT, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("BUILT", SS_BUILT, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("BEING_DEMOLISHED", SS_BEING_DEMOLISHED, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DROID_CONSTRUCT", 0, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DROID_WEAPON", 1, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DROID_PERSON", 2, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DROID_REPAIR", 3, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DROID_SENSOR", 4, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DROID_ECM", 5, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DROID_CYBORG", 6, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DROID_TRANSPORTER", 7, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DROID_COMMAND", 8, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("HQ", 0, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("FACTORY", 1, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("POWER_GEN", 2, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("RESOURCE_EXTRACTOR", 3, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DEFENSE", 4, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("LASSAT", 5, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("WALL", 6, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("RESEARCH_LAB", 7, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("REPAIR_FACILITY", 8, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("CYBORG_FACTORY", 9, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("VTOL_FACTORY", 10, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("REARM_PAD", 11, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("SAT_UPLINK", 12, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("GATE", 13, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("COMMAND_CONTROL", 14, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("EASY", 0, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("MEDIUM", 1, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("HARD", 2, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("INSANE", 3, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("STRUCTURE", OBJ_STRUCTURE, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DROID", OBJ_DROID, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("FEATURE", OBJ_FEATURE, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("POSITION", POSITION, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("AREA", AREA, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("ALL_PLAYERS", -1, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("ALLIES", -2, QScriptValue::ReadOnly | QScriptValue::Undeletable); QScriptValue playerData = engine->newArray(CUR_PLAYERS); for (int i = 0; i < CUR_PLAYERS; i++) { QScriptValue vector = engine->newObject(); vector.setProperty("difficulty", 0, QScriptValue::ReadOnly | QScriptValue::Undeletable); vector.setProperty("colour", 0, QScriptValue::ReadOnly | QScriptValue::Undeletable); vector.setProperty("position", i, QScriptValue::ReadOnly | QScriptValue::Undeletable); vector.setProperty("team", i, QScriptValue::ReadOnly | QScriptValue::Undeletable); vector.setProperty("isAI", i != 0, QScriptValue::ReadOnly | QScriptValue::Undeletable); vector.setProperty("isHuman", i == 0, QScriptValue::ReadOnly | QScriptValue::Undeletable); playerData.setProperty(i, vector, QScriptValue::ReadOnly | QScriptValue::Undeletable); } engine->globalObject().setProperty("playerData", playerData, QScriptValue::ReadOnly | QScriptValue::Undeletable); // Static map knowledge about start positions //== \item[derrickPositions] An array of derrick starting positions on the current map. Each item in the array is an //== object containing the x and y variables for a derrick. //== \item[startPositions] An array of player start positions on the current map. Each item in the array is an //== object containing the x and y variables for a player start position. QScriptValue startPositions = engine->newArray(CUR_PLAYERS); for (int i = 0; i < CUR_PLAYERS; i++) { QScriptValue vector = engine->newObject(); vector.setProperty("x", 40, QScriptValue::ReadOnly | QScriptValue::Undeletable); vector.setProperty("y", 40, QScriptValue::ReadOnly | QScriptValue::Undeletable); startPositions.setProperty(i, vector, QScriptValue::ReadOnly | QScriptValue::Undeletable); } QScriptValue derrickPositions = engine->newArray(6); for (int i = 0; i < 6; i++) { QScriptValue vector = engine->newObject(); vector.setProperty("x", 40, QScriptValue::ReadOnly | QScriptValue::Undeletable); vector.setProperty("y", 40, QScriptValue::ReadOnly | QScriptValue::Undeletable); derrickPositions.setProperty(i, vector, QScriptValue::ReadOnly | QScriptValue::Undeletable); } engine->globalObject().setProperty("derrickPositions", derrickPositions, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("startPositions", startPositions, QScriptValue::ReadOnly | QScriptValue::Undeletable); QScriptSyntaxCheckResult syntax = QScriptEngine::checkSyntax(source); if (syntax.state() != QScriptSyntaxCheckResult::Valid) { qFatal("Syntax error in %s line %d: %s", path.toUtf8().constData(), syntax.errorLineNumber(), syntax.errorMessage().toUtf8().constData()); return false; } QScriptValue result = engine->evaluate(source, path); if (engine->hasUncaughtException()) { int line = engine->uncaughtExceptionLineNumber(); qFatal("Uncaught exception at line %d, file %s: %s", line, path.toUtf8().constData(), result.toString().toUtf8().constData()); return false; } // Call init callFunction(engine, "eventGameInit", QScriptValueList()); // Now set gameTime to something proper engine->globalObject().setProperty("gameTime", 10101, QScriptValue::ReadOnly | QScriptValue::Undeletable); callFunction(engine, "eventStartLevel", QScriptValueList()); callFunction(engine, "eventLaunchTransporter", QScriptValueList()); callFunction(engine, "eventReinforcementsArrived", QScriptValueList()); callFunction(engine, "eventMissionTimeout", QScriptValueList()); callFunction(engine, "eventVideoDone", QScriptValueList()); // Call other events { QScriptValueList args; args += convDroid(engine); args += convStructure(engine); callFunction(engine, "eventDroidBuilt", args); } { QScriptValueList args; args += convStructure(engine); args += convObj(engine); callFunction(engine, "eventStructureAttacked", args); } { QScriptValueList args; args += convResearch(engine); args += convStructure(engine); callFunction(engine, "eventResearched", args); } { QScriptValueList args; args += convObj(engine); args += convObj(engine); callFunction(engine, "eventAttacked", args); } { QScriptValueList args; args += convStructure(engine); args += convDroid(engine); callFunction(engine, "eventStructureBuilt", args); } { QScriptValueList args; args += convDroid(engine); callFunction(engine, "eventDroidIdle", args); } { QScriptValueList args; args += QScriptValue(0); args += QScriptValue(1); args += QScriptValue("message"); callFunction(engine, "eventChat", args); } { QScriptValueList args; args += convObj(engine); args += convObj(engine); callFunction(engine, "eventObjectSeen", args); } // Now test timers // TODO -- implement object parameters for (int i = 0; i < timers.size(); ++i) { timerNode node = timers.at(i); callFunction(node.engine, node.function, QScriptValueList(), true); } // Clean up delete engine; timers.clear(); return true; }
static QScriptValue js_getResearch(QScriptContext *context, QScriptEngine *engine) { ARG_COUNT_EXACT(1); return convResearch(engine); }