bool CLuaRules::MoveCtrlNotify(const CUnit* unit, int data) { if (!haveMoveCtrlNotify) return false; // the call is not defined LUA_CALL_IN_CHECK(L, false); lua_checkstack(L, 6); static const LuaHashString cmdStr("MoveCtrlNotify"); if (!cmdStr.GetGlobalFunc(L)) return false; // the call is not defined // push the unit info lua_pushnumber(L, unit->id); lua_pushnumber(L, unit->unitDef->id); lua_pushnumber(L, unit->team); lua_pushnumber(L, data); // call the function if (!RunCallIn(cmdStr, 4, 1)) return false; // get the results if (!lua_isboolean(L, -1)) { LOG_L(L_WARNING, "%s() bad return value", cmdStr.GetString().c_str()); lua_pop(L, 1); return false; } const bool retval = !!lua_toboolean(L, -1); lua_pop(L, 1); return retval; }
int CLuaRules::AllowWeaponTargetCheck(unsigned int attackerID, unsigned int attackerWeaponNum, unsigned int attackerWeaponDefID) { if (!haveAllowWeaponTargetCheck) return -1; LUA_CALL_IN_CHECK(L, -1); lua_checkstack(L, 3 + 1); const int errfunc(SetupTraceback(L)); static const LuaHashString cmdStr("AllowWeaponTargetCheck"); int ret = -1; if (!cmdStr.GetGlobalFunc(L)) { if (errfunc) lua_pop(L, 1); return ret; } lua_pushnumber(L, attackerID); lua_pushnumber(L, attackerWeaponNum); lua_pushnumber(L, attackerWeaponDefID); const bool success = RunCallInTraceback(cmdStr, 3, 1, errfunc); if (!success) return ret; ret = (lua_isboolean(L, -1) && lua_toboolean(L, -1))? 1: 0; lua_pop(L, -1); return ret; }
bool CLuaRules::AllowDirectUnitControl(int playerID, const CUnit* unit) { if (!haveAllowDirectUnitControl) return true; // the call is not defined LUA_CALL_IN_CHECK(L, true); lua_checkstack(L, 6); static const LuaHashString cmdStr("AllowDirectUnitControl"); if (!cmdStr.GetGlobalFunc(L)) return true; // the call is not defined lua_pushnumber(L, unit->id); lua_pushnumber(L, unit->unitDef->id); lua_pushnumber(L, unit->team); lua_pushnumber(L, playerID); // call the function if (!RunCallIn(cmdStr, 4, 1)) return true; // get the results if (!lua_isboolean(L, -1)) { LOG_L(L_WARNING, "%s() bad return value", cmdStr.GetString().c_str()); lua_pop(L, 1); return true; } const bool retval = !!lua_toboolean(L, -1); lua_pop(L, 1); return retval; }
bool CLuaRules::AllowStartPosition(int playerID, const float3& pos) { if (!haveAllowStartPosition) return true; // the call is not defined LUA_CALL_IN_CHECK(L, true); lua_checkstack(L, 9); static const LuaHashString cmdStr("AllowStartPosition"); if (!cmdStr.GetGlobalFunc(L)) return true; // the call is not defined // push the start position and playerID lua_pushnumber(L, pos.x); lua_pushnumber(L, pos.y); lua_pushnumber(L, pos.z); lua_pushnumber(L, playerID); // call the function if (!RunCallIn(cmdStr, 4, 1)) return true; // get the results if (!lua_isboolean(L, -1)) { LOG_L(L_WARNING, "%s() bad return value", cmdStr.GetString().c_str()); lua_pop(L, 1); return true; } const bool retval = !!lua_toboolean(L, -1); lua_pop(L, 1); return retval; }
bool CLuaRules::AllowResourceLevel(int teamID, const string& type, float level) { if (!haveAllowResourceLevel) return true; // the call is not defined LUA_CALL_IN_CHECK(L, true); lua_checkstack(L, 5); static const LuaHashString cmdStr("AllowResourceLevel"); if (!cmdStr.GetGlobalFunc(L)) return true; // the call is not defined lua_pushnumber(L, teamID); lua_pushsstring(L, type); lua_pushnumber(L, level); // call the function if (!RunCallIn(cmdStr, 3, 1)) return true; // get the results if (!lua_isboolean(L, -1)) { LOG_L(L_WARNING, "%s() bad return value", cmdStr.GetString().c_str()); lua_pop(L, 1); return true; } const bool retval = !!lua_toboolean(L, -1); lua_pop(L, 1); return retval; }
bool CLuaRules::AllowResourceTransfer(int oldTeam, int newTeam, const string& type, float amount) { if (!haveAllowResourceTransfer) return true; // the call is not defined LUA_CALL_IN_CHECK(L, true); lua_checkstack(L, 6); static const LuaHashString cmdStr("AllowResourceTransfer"); if (!cmdStr.GetGlobalFunc(L)) return true; // the call is not defined lua_pushnumber(L, oldTeam); lua_pushnumber(L, newTeam); lua_pushsstring(L, type); lua_pushnumber(L, amount); // call the function if (!RunCallIn(cmdStr, 4, 1)) return true; // get the results if (!lua_isboolean(L, -1)) { LOG_L(L_WARNING, "%s() bad return value", cmdStr.GetString().c_str()); lua_pop(L, 1); return true; } const bool retval = !!lua_toboolean(L, -1); lua_pop(L, 1); return retval; }
bool CLuaRules::AllowFeatureCreation(const FeatureDef* featureDef, int teamID, const float3& pos) { if (!haveAllowFeatureCreation) return true; // the call is not defined LUA_CALL_IN_CHECK(L, true); lua_checkstack(L, 7); static const LuaHashString cmdStr("AllowFeatureCreation"); if (!cmdStr.GetGlobalFunc(L)) return true; // the call is not defined lua_pushnumber(L, featureDef->id); lua_pushnumber(L, teamID); lua_pushnumber(L, pos.x); lua_pushnumber(L, pos.y); lua_pushnumber(L, pos.z); // call the function if (!RunCallIn(cmdStr, 5, 1)) return true; // get the results if (!lua_isboolean(L, -1)) { LOG_L(L_WARNING, "%s() bad return value", cmdStr.GetString().c_str()); lua_pop(L, 1); return true; } const bool retval = !!lua_toboolean(L, -1); lua_pop(L, 1); return retval; }
bool CLuaRules::AllowFeatureBuildStep(const CUnit* builder, const CFeature* feature, float part) { if (!haveAllowFeatureBuildStep) return true; // the call is not defined LUA_CALL_IN_CHECK(L, true); lua_checkstack(L, 7); static const LuaHashString cmdStr("AllowFeatureBuildStep"); if (!cmdStr.GetGlobalFunc(L)) return true; // the call is not defined lua_pushnumber(L, builder->id); lua_pushnumber(L, builder->team); lua_pushnumber(L, feature->id); lua_pushnumber(L, feature->def->id); lua_pushnumber(L, part); // call the function if (!RunCallIn(cmdStr, 5, 1)) return true; // get the results if (!lua_isboolean(L, -1)) { LOG_L(L_WARNING, "%s() bad return value", cmdStr.GetString().c_str()); lua_pop(L, 1); return true; } const bool retval = !!lua_toboolean(L, -1); lua_pop(L, 1); return retval; }
bool CLuaRules::AllowCommand(const CUnit* unit, const Command& cmd, bool fromSynced) { if (!haveAllowCommand) return true; // the call is not defined LUA_CALL_IN_CHECK(L, true); lua_checkstack(L, 10); static const LuaHashString cmdStr("AllowCommand"); if (!cmdStr.GetGlobalFunc(L)) return true; // the call is not defined PushUnitAndCommand(L, unit, cmd); lua_pushboolean(L, fromSynced); // call the function if (!RunCallIn(cmdStr, 8, 1)) return true; // get the results if (!lua_isboolean(L, -1)) { LOG_L(L_WARNING, "%s() bad return value", cmdStr.GetString().c_str()); lua_pop(L, 1); return true; } const bool retval = !!lua_toboolean(L, -1); lua_pop(L, 1); return retval; }
bool CLuaRules::AllowUnitTransfer(const CUnit* unit, int newTeam, bool capture) { if (!haveAllowUnitTransfer) return true; // the call is not defined LUA_CALL_IN_CHECK(L, true); lua_checkstack(L, 7); static const LuaHashString cmdStr("AllowUnitTransfer"); if (!cmdStr.GetGlobalFunc(L)) return true; // the call is not defined lua_pushnumber(L, unit->id); lua_pushnumber(L, unit->unitDef->id); lua_pushnumber(L, unit->team); lua_pushnumber(L, newTeam); lua_pushboolean(L, capture); // call the function if (!RunCallIn(cmdStr, 5, 1)) return true; // get the results if (!lua_isboolean(L, -1)) { LOG_L(L_WARNING, "%s() bad return value", cmdStr.GetString().c_str()); lua_pop(L, 1); return true; } const bool retval = !!lua_toboolean(L, -1); lua_pop(L, 1); return retval; }
bool CLuaRules::CommandFallback(const CUnit* unit, const Command& cmd) { if (!haveCommandFallback) return true; // the call is not defined LUA_CALL_IN_CHECK(L, true); lua_checkstack(L, 9); static const LuaHashString cmdStr("CommandFallback"); if (!cmdStr.GetGlobalFunc(L)) return true; // the call is not defined PushUnitAndCommand(L, unit, cmd); // call the function if (!RunCallIn(cmdStr, 7, 1)) return true; // get the results if (!lua_isboolean(L, -1)) { LOG_L(L_WARNING, "%s() bad return value", cmdStr.GetString().c_str()); lua_pop(L, 1); return true; } const bool retval = !!lua_toboolean(L, -1); lua_pop(L, 1); // return 'true' to remove the command return retval; }
bool CLuaRules::CommandFallback(const CUnit* unit, const Command& cmd) { if (!haveCommandFallback) { return true; // the call is not defined } LUA_CALL_IN_CHECK(L); lua_checkstack(L, 9); static const LuaHashString cmdStr("CommandFallback"); if (!cmdStr.GetGlobalFunc(L)) { return true; // the call is not defined } // push the unit info lua_pushnumber(L, unit->id); lua_pushnumber(L, unit->unitDef->id); lua_pushnumber(L, unit->team); // push the command id lua_pushnumber(L, cmd.id); // push the params list lua_newtable(L); for (int p = 0; p < (int)cmd.params.size(); p++) { lua_pushnumber(L, p + 1); lua_pushnumber(L, cmd.params[p]); lua_rawset(L, -3); } HSTR_PUSH_NUMBER(L, "n", cmd.params.size()); // push the options table lua_newtable(L); HSTR_PUSH_NUMBER(L, "coded", cmd.options); HSTR_PUSH_BOOL(L, "alt", !!(cmd.options & ALT_KEY)); HSTR_PUSH_BOOL(L, "ctrl", !!(cmd.options & CONTROL_KEY)); HSTR_PUSH_BOOL(L, "shift", !!(cmd.options & SHIFT_KEY)); HSTR_PUSH_BOOL(L, "right", !!(cmd.options & RIGHT_MOUSE_KEY)); HSTR_PUSH_BOOL(L, "meta", !!(cmd.options & META_KEY)); // push the command tag lua_pushnumber(L, cmd.tag); // call the function if (!RunCallIn(cmdStr, 7, 1)) { return true; } // get the results if (!lua_isboolean(L, -1)) { logOutput.Print("%s() bad return value\n", cmdStr.GetString().c_str()); lua_pop(L, 1); return true; } const bool retval = !!lua_toboolean(L, -1); lua_pop(L, 1); // return 'true' to remove the command return retval; }
void CLuaHandleSynced::RecvFromSynced(lua_State *srcState, int args) { SELECT_UNSYNCED_LUA_STATE(); #if ((LUA_MT_OPT & LUA_STATE) && (LUA_MT_OPT & LUA_MUTEX)) if (!SingleState() && srcState != L) { // Sim thread sends to unsynced --> delay it DelayRecvFromSynced(srcState, args); return; } // Draw thread, delayed already, execute it #endif static const LuaHashString cmdStr("RecvFromSynced"); //LUA_CALL_IN_CHECK(L); -- not valid here if (!cmdStr.GetRegistryFunc(L)) return; // the call is not defined lua_insert(L, 1); // place the function // call the routine SetAllowChanges(false); SetHandleSynced(L, false); lua_State* L_Prev = ForceUnsyncedState(); RunCallIn(cmdStr, args, 0); RestoreState(L_Prev); SetHandleSynced(L, true); SetAllowChanges(true); }
string CLuaHandleSynced::GetSyncData() { string syncData; LUA_CALL_IN_CHECK(L, syncData); lua_checkstack(L, 2); static const LuaHashString cmdStr("GetSyncData"); if (!cmdStr.GetGlobalFunc(L)) { return syncData; } // call the routine if (!RunCallIn(cmdStr, 0, 1)) { return syncData; } // get the result if (!lua_isstring(L, -1)) { lua_pop(L, 1); return syncData; } const int len = lua_strlen(L, -1); const char* c = lua_tostring(L, -1); syncData.resize(len); for (int i = 0; i < len; i++) { syncData[i] = c[i]; } lua_pop(L, 1); return syncData; }
bool CLuaHandleSynced::Initialize(const string& syncData) { LUA_CALL_IN_CHECK(L, true); lua_checkstack(L, 3); static const LuaHashString cmdStr("Initialize"); if (!cmdStr.GetGlobalFunc(L)) { return true; } int errfunc = SetupTraceback(L) ? -2 : 0; LOG("Initialize errfunc=%d", errfunc); lua_pushsstring(L, syncData); // call the routine if (!RunCallInTraceback(cmdStr, 1, 1, errfunc)) { return false; } // get the results if (!lua_isboolean(L, -1)) { lua_pop(L, 1); return true; } const bool retval = !!lua_toboolean(L, -1); lua_pop(L, 1); return retval; }
/** * called after every damage modification (even HitByWeaponId) * but before the damage is applied * * expects two numbers returned by lua code: * 1st is stored under *newDamage if newDamage != NULL * 2nd is stored under *impulseMult if impulseMult != NULL */ bool CLuaRules::UnitPreDamaged(const CUnit* unit, const CUnit* attacker, float damage, int weaponID, bool paralyzer, float* newDamage, float* impulseMult) { if (!haveUnitPreDamaged) { return false; } LUA_CALL_IN_CHECK(L); lua_checkstack(L, 11); const int errfunc = SetupTraceback(); static const LuaHashString cmdStr("UnitPreDamaged"); if (!cmdStr.GetGlobalFunc(L)) { // remove error handler if (errfunc) { lua_pop(L, 1); } return false; // the call is not defined } int argCount = 5; lua_pushnumber(L, unit->id); lua_pushnumber(L, unit->unitDef->id); lua_pushnumber(L, unit->team); lua_pushnumber(L, damage); lua_pushboolean(L, paralyzer); if (fullRead) { lua_pushnumber(L, weaponID); argCount += 1; if (attacker != NULL) { lua_pushnumber(L, attacker->id); lua_pushnumber(L, attacker->unitDef->id); lua_pushnumber(L, attacker->team); argCount += 3; } } // call the routine RunCallInTraceback(cmdStr, argCount, 2, errfunc); if (newDamage && lua_isnumber(L, -2)) { *newDamage = lua_tonumber(L, -2); } else if (!lua_isnumber(L, -2) || lua_isnil(L, -2)) { // first value is obligatory, so may not be nil logOutput.Print("%s(): 1st value returned should be a number (newDamage)\n", cmdStr.GetString().c_str()); } if (impulseMult && lua_isnumber(L, -1)) { *impulseMult = lua_tonumber(L, -1); } else if (!lua_isnumber(L, -1) && !lua_isnil(L, -1)) { // second value is optional, so nils are OK logOutput.Print("%s(): 2nd value returned should be a number (impulseMult)\n", cmdStr.GetString().c_str()); } lua_pop(L, 2); return true; }
bool CLuaUI::HasLayoutButtons() { static const LuaHashString cmdStr("LayoutButtons"); if (!cmdStr.GetGlobalFunc(L)) { return false; // the call is not defined } lua_pop(L, 1); return true; }
inline bool CLuaHandle::PushUnsyncedCallIn(const LuaHashString& hs) { // LuaUI keeps these call-ins in the Global table, // the synced handles keep them in the Registry table if (userMode) { return hs.GetGlobalFunc(L); } else { return hs.GetRegistryFunc(L); } }
bool CLuaRules::AllowCommand(const CUnit* unit, const Command& cmd) { if (!haveAllowCommand) { return true; // the call is not defined } lua_settop(L, 0); static const LuaHashString cmdStr("AllowCommand"); if (!cmdStr.GetGlobalFunc(L)) { lua_settop(L, 0); return true; // the call is not defined } // push the unit info lua_pushnumber(L, unit->id); lua_pushnumber(L, unit->unitDef->id); lua_pushnumber(L, unit->team); // push the command id lua_pushnumber(L, cmd.id); // push the params list lua_newtable(L); for (int p = 0; p < (int)cmd.params.size(); p++) { lua_pushnumber(L, p + 1); lua_pushnumber(L, cmd.params[p]); lua_rawset(L, -3); } HSTR_PUSH_NUMBER(L, "n", cmd.params.size()); // push the options table lua_newtable(L); HSTR_PUSH_NUMBER(L, "coded", cmd.options); HSTR_PUSH_BOOL(L, "alt", !!(cmd.options & ALT_KEY)); HSTR_PUSH_BOOL(L, "ctrl", !!(cmd.options & CONTROL_KEY)); HSTR_PUSH_BOOL(L, "shift", !!(cmd.options & SHIFT_KEY)); HSTR_PUSH_BOOL(L, "right", !!(cmd.options & RIGHT_MOUSE_KEY)); // call the function if (!RunCallIn(cmdStr, 6, 1)) { return true; } // get the results const int args = lua_gettop(L); if ((args != 1) || !lua_isboolean(L, -1)) { logOutput.Print("%s() bad return value (%i)\n", cmdStr.GetString().c_str(), args); lua_settop(L, 0); return true; } return !!lua_toboolean(L, -1); }
void CLuaIntro::Shutdown() { LUA_CALL_IN_CHECK(L); lua_checkstack(L, 2); static const LuaHashString cmdStr("Shutdown"); if (!cmdStr.GetGlobalFunc(L)) { return; } // call the routine RunCallIn(cmdStr, 0, 0); }
void CLuaHandle::GameOver() { LUA_CALL_IN_CHECK(L); lua_checkstack(L, 2); static const LuaHashString cmdStr("GameOver"); if (!cmdStr.GetGlobalFunc(L)) { return; // the call is not defined } // call the routine RunCallIn(cmdStr, 0, 0); return; }
bool CLuaUI::HasLayoutButtons() { GML_RECMUTEX_LOCK(lua); // HasLayoutButtons lua_checkstack(L, 2); static const LuaHashString cmdStr("LayoutButtons"); if (!cmdStr.GetGlobalFunc(L)) { return false; // the call is not defined } lua_pop(L, 1); return true; }
void CLuaUI::ShockFront(const float3& pos, float power, float areaOfEffect, const float* distMod) { if (!haveShockFront) return; if (areaOfEffect < shockFrontMinArea && distMod == NULL) return; float3 gap = (camera->GetPos() - pos); #if defined(USE_GML) && GML_ENABLE_SIM // WTF? const float shockFrontDistMod = (GML::Enabled() && distMod != NULL)? *distMod : this->shockFrontDistAdj; #else const float shockFrontDistMod = this->shockFrontDistAdj; #endif float dist = gap.Length() + shockFrontDistMod; if ((power /= (dist * dist)) < shockFrontMinPower && distMod == NULL) return; LUA_UI_BATCH_PUSH(, UIShockFrontEvent(pos, power, areaOfEffect, shockFrontDistMod)) LUA_CALL_IN_CHECK(L); luaL_checkstack(L, 6, __FUNCTION__); static const LuaHashString cmdStr("ShockFront"); if (!cmdStr.GetGlobalFunc(L)) { haveShockFront = false; return; // the call is not defined } if (!gu->spectatingFullView && !losHandler->InLos(pos, gu->myAllyTeam)) { gap.x *= fuzzRand(0.25f); gap.y *= fuzzRand(0.25f); gap.z *= fuzzRand(0.25f); dist = gap.Length() + shockFrontDistMod; } const float3 dir = (gap / dist); // normalize lua_pushnumber(L, power); lua_pushnumber(L, dir.x); lua_pushnumber(L, dir.y); lua_pushnumber(L, dir.z); // call the routine if (!RunCallIn(cmdStr, 4, 0)) { return; } return; }
bool CLuaUI::HasLayoutButtons() { SELECT_LUA_STATE(); GML_DRCMUTEX_LOCK(lua); // HasLayoutButtons luaL_checkstack(L, 2, __FUNCTION__); static const LuaHashString cmdStr("LayoutButtons"); if (!cmdStr.GetGlobalFunc(L)) { return false; // the call is not defined } lua_pop(L, 1); return true; }
void CLuaUI::ShockFront(float power, const float3& pos, float areaOfEffect, float *distadj) { if (!haveShockFront) { return; } if (areaOfEffect < shockFrontMinArea && !distadj) { return; } #if defined(USE_GML) && GML_ENABLE_SIM float shockFrontDistAdj = distadj ? *distadj : this->shockFrontDistAdj; #endif float3 gap = (camera->pos - pos); float dist = gap.Length() + shockFrontDistAdj; power = power / (dist * dist); if (power < shockFrontMinPower && !distadj) { return; } LUA_UI_BATCH_PUSH(SHOCK_FRONT, power, pos, areaOfEffect, shockFrontDistAdj); LUA_CALL_IN_CHECK(L); lua_checkstack(L, 6); static const LuaHashString cmdStr("ShockFront"); if (!cmdStr.GetGlobalFunc(L)) { haveShockFront = false; return; // the call is not defined } if (!gu->spectatingFullView && !loshandler->InLos(pos, gu->myAllyTeam)) { const float fuzz = 0.25f; gap.x *= fuzzRand(fuzz); gap.y *= fuzzRand(fuzz); gap.z *= fuzzRand(fuzz); dist = gap.Length() + shockFrontDistAdj; } const float3 dir = (gap / dist); // normalize lua_pushnumber(L, power); lua_pushnumber(L, dir.x); lua_pushnumber(L, dir.y); lua_pushnumber(L, dir.z); // call the routine if (!RunCallIn(cmdStr, 4, 0)) { return; } return; }
void CLuaHandle::ProjectileDestroyed(const CProjectile* projectile) { LUA_CALL_IN_CHECK(L); lua_checkstack(L, 4); static const LuaHashString cmdStr("ProjectileDestroyed"); if (!cmdStr.GetGlobalFunc(L)) { return; // the call is not defined } lua_pushnumber(L, projectile->id); // call the routine RunCallIn(cmdStr, 1, 0); return; }
void CLuaHandle::PlayerChanged(int playerID) { LUA_CALL_IN_CHECK(L); lua_checkstack(L, 3); static const LuaHashString cmdStr("PlayerChanged"); if (!cmdStr.GetGlobalFunc(L)) { return; // the call is not defined } lua_pushnumber(L, playerID); // call the routine RunCallIn(cmdStr, 1, 0); return; }
void CLuaIntro::LoadProgress(const std::string& msg, const bool replace_lastline) { LUA_CALL_IN_CHECK(L); luaL_checkstack(L, 4, __FUNCTION__); static const LuaHashString cmdStr("LoadProgress"); if (!cmdStr.GetGlobalFunc(L)) { return; } lua_pushsstring(L, msg); lua_pushboolean(L, replace_lastline); // call the routine RunCallIn(L, cmdStr, 2, 0); }
void CLuaHandle::FeatureDestroyed(const CFeature* feature) { LUA_CALL_IN_CHECK(L); lua_checkstack(L, 4); static const LuaHashString cmdStr("FeatureDestroyed"); if (!cmdStr.GetGlobalFunc(L)) { return; // the call is not defined } lua_pushnumber(L, feature->id); lua_pushnumber(L, feature->allyteam); // call the routine RunCallIn(cmdStr, 2, 0); return; }
bool CLuaHandleSynced::LoadUnsyncedCode(const string& code, const string& debug) { lua_settop(L, 0); int error; error = luaL_loadbuffer(L, code.c_str(), code.size(), debug.c_str()); if (error != 0) { logOutput.Print("error = %i, %s, %s\n", error, debug.c_str(), lua_tostring(L, -1)); lua_settop(L, 0); return false; } unsyncedStr.GetRegistry(L); if (!lua_istable(L, -1)) { lua_settop(L, 0); return false; } lua_setfenv(L, -2); CLuaHandle* orig = activeHandle; SetActiveHandle(); error = lua_pcall(L, 0, 0, 0); SetActiveHandle(orig); if (error != 0) { logOutput.Print("error = %i, %s, %s\n", error, debug.c_str(), lua_tostring(L, -1)); lua_settop(L, 0); return false; } return true; }