QScriptValue convStructure(STRUCTURE *psStruct, QScriptEngine *engine) { QScriptValue value = convObj(psStruct, engine); value.setProperty("status", (int)psStruct->status, QScriptValue::ReadOnly); value.setProperty("type", (int)OBJ_STRUCTURE, QScriptValue::ReadOnly); return value; }
static QScriptValue convDroid(QScriptEngine *engine) { QScriptValue value = convObj(engine); value.setProperty("action", 0, QScriptValue::ReadOnly); value.setProperty("order", 0, QScriptValue::ReadOnly); return value; }
static QScriptValue convFeature(QScriptEngine *engine) { QScriptValue value = convObj(engine); value.setProperty("type", OBJ_FEATURE, QScriptValue::ReadOnly); value.setProperty("health", 100, QScriptValue::ReadOnly); value.setProperty("damageable", true, QScriptValue::ReadOnly); return value; }
QScriptValue convDroid(DROID *psDroid, QScriptEngine *engine) { QScriptValue value = convObj(psDroid, engine); value.setProperty("action", (int)psDroid->action, QScriptValue::ReadOnly); value.setProperty("order", (int)psDroid->order, QScriptValue::ReadOnly); value.setProperty("type", (int)OBJ_DROID, QScriptValue::ReadOnly); return value; }
QScriptValue convMax(BASE_OBJECT *psObj, QScriptEngine *engine) { switch (psObj->type) { case OBJ_DROID: return convDroid((DROID *)psObj, engine); case OBJ_STRUCTURE: return convStructure((STRUCTURE *)psObj, engine); case OBJ_FEATURE: return convFeature((FEATURE *)psObj, engine); default: ASSERT(false, "No such supported object type"); return convObj(psObj, engine); } }
bool updateScripts() { // Update gameTime for (int i = 0; i < scripts.size(); ++i) { QScriptEngine *engine = scripts.at(i); engine->globalObject().setProperty("gameTime", gameTime, QScriptValue::ReadOnly | QScriptValue::Undeletable); } // Weed out dead timers for (int i = 0; i < timers.count(); ) { const timerNode node = timers.at(i); if (node.type == TIMER_ONESHOT_DONE || (node.baseobj > 0 && !IdToPointer(node.baseobj, node.player))) { timers.removeAt(i); } else { i++; } } // Check for timers, and run them if applicable. // TODO - load balancing QList<timerNode> runlist; // make a new list here, since we might trample all over the timer list during execution QList<timerNode>::iterator iter; // Weed out dead timers for (iter = timers.begin(); iter != timers.end(); iter++) { if (iter->frameTime <= gameTime) { iter->frameTime = iter->ms + gameTime; // update for next invokation if (iter->type == TIMER_ONESHOT_READY) { iter->type = TIMER_ONESHOT_DONE; // unless there is none } runlist.append(*iter); } } for (iter = runlist.begin(); iter != runlist.end(); iter++) { QScriptValueList args; if (iter->baseobj > 0) { args += convObj(IdToPointer(iter->baseobj, iter->player), iter->engine); } callFunction(iter->engine, iter->function, args, true); } return true; }
// These functions invent new imaginary objects static QScriptValue convStructure(QScriptEngine *engine) { QScriptValue value = convObj(engine); value.setProperty("type", OBJ_STRUCTURE, QScriptValue::ReadOnly); value.setProperty("status", (int)SS_BUILT, QScriptValue::ReadOnly); value.setProperty("isCB", false, QScriptValue::ReadOnly); value.setProperty("isSensor", false, QScriptValue::ReadOnly); value.setProperty("canHitAir", false, QScriptValue::ReadOnly); value.setProperty("canHitGround", true, QScriptValue::ReadOnly); value.setProperty("hasIndirect", false, QScriptValue::ReadOnly); value.setProperty("isRadarDetector", false, QScriptValue::ReadOnly); value.setProperty("range", 100, QScriptValue::ReadOnly); value.setProperty("health", 100, QScriptValue::ReadOnly); value.setProperty("cost", 100, QScriptValue::ReadOnly); value.setProperty("modules", QScriptValue::NullValue); return value; }
static QScriptValue convDroid(QScriptEngine *engine) { QScriptValue value = convObj(engine); value.setProperty("type", OBJ_DROID, QScriptValue::ReadOnly); value.setProperty("action", 0, QScriptValue::ReadOnly); value.setProperty("order", 0, QScriptValue::ReadOnly); value.setProperty("action", 0, QScriptValue::ReadOnly); value.setProperty("isCB", false, QScriptValue::ReadOnly); value.setProperty("isSensor", false, QScriptValue::ReadOnly); value.setProperty("canHitAir", false, QScriptValue::ReadOnly); value.setProperty("canHitGround", true, QScriptValue::ReadOnly); value.setProperty("hasIndirect", false, QScriptValue::ReadOnly); value.setProperty("isRadarDetector", false, QScriptValue::ReadOnly); value.setProperty("range", 100, QScriptValue::ReadOnly); value.setProperty("health", 100, QScriptValue::ReadOnly); value.setProperty("cost", 100, QScriptValue::ReadOnly); value.setProperty("experience", 1000, QScriptValue::ReadOnly); value.setProperty("group", QScriptValue::NullValue); value.setProperty("armed", QScriptValue::NullValue); return value; }
bool triggerStructureAttacked(STRUCTURE *psVictim, BASE_OBJECT *psAttacker) { if (!psAttacker) { // do not fire off this event if there is no attacker -- nothing do respond to // (FIXME -- consider this carefully) return false; } for (int i = 0; i < scripts.size(); ++i) { QScriptEngine *engine = scripts.at(i); int player = engine->globalObject().property("me").toInt32(); if (player == psVictim->player) { QScriptValueList args; args += convStructure(psVictim, engine); args += convObj(psAttacker, engine); callFunction(engine, "eventStructureAttacked", args); } } return true; }
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; }
QScriptValue convFeature(FEATURE *psFeature, QScriptEngine *engine) { QScriptValue value = convObj(psFeature, engine); value.setProperty("type", (int)OBJ_FEATURE, QScriptValue::ReadOnly); return value; }
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(); QScriptSyntaxCheckResult syntax = QScriptEngine::checkSyntax(source); if (syntax.state() != QScriptSyntaxCheckResult::Valid) { fprintf(stderr, "Syntax error in %s line %d: %s\n", path.toAscii().constData(), syntax.errorLineNumber(), syntax.errorMessage().toAscii().constData()); return false; } QScriptValue result = engine->evaluate(source, path); if (engine->hasUncaughtException()) { int line = engine->uncaughtExceptionLineNumber(); fprintf(stderr, "Uncaught exception at line %d, file %s: %s\n", line, path.toAscii().constData(), result.toString().toAscii().constData()); return false; } // 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)); // Special global variables engine->globalObject().setProperty("me", player, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("gameTime", 2, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("difficulty", difficulty, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("mapName", "Test", QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("baseType", CAMP_BASE, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("alliancesType", ALLIANCES_TEAMS, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("powerType", LEV_MED, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("maxPlayers", 4, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("scavengers", true, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("_", engine->newFunction(js_translate)); // 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("buildDroid", engine->newFunction(js_buildDroid)); engine->globalObject().setProperty("enumStruct", engine->newFunction(js_enumStruct)); engine->globalObject().setProperty("enumDroid", engine->newFunction(js_enumDroid)); engine->globalObject().setProperty("enumGroup", engine->newFunction(js_enumGroup)); 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)); // 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("addReticuleButton", engine->newFunction(js_addReticuleButton)); 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("allianceExistsBetween", engine->newFunction(js_allianceExistsBetween)); // Set some useful constants engine->globalObject().setProperty("DORDER_ATTACK", 0, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DORDER_MOVE", 0, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DORDER_SCOUT", 0, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DORDER_BUILD", 0, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("mapWidth", 64, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("mapHeight", 64, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("COMMAND", 0, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("OPTIONS", 0, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("BUILD", 0, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("MANUFACTURE", 0, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("RESEARCH", 0, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("INTELMAP", 0, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DESIGN", 0, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("CANCEL", 0, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("CAMP_CLEAN", CAMP_CLEAN, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("CAMP_BASE", CAMP_BASE, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("CAMP_WALLS", CAMP_WALLS, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("NO_ALLIANCES", NO_ALLIANCES, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("ALLIANCES", ALLIANCES, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("ALLIANCES_TEAMS", ALLIANCES_TEAMS, 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); // 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()); // 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); } // Now test timers // TODO -- implement object parameters QMutableListIterator<timerNode> iter(timers); while (iter.hasNext()) { timerNode node = iter.next(); callFunction(node.engine, node.function, QScriptValueList()); } // Clean up delete engine; timers.clear(); return true; }
// These functions invent new imaginary objects static QScriptValue convStructure(QScriptEngine *engine) { QScriptValue value = convObj(engine); value.setProperty("status", (int)SS_BUILT, QScriptValue::ReadOnly); return value; }