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); 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::AllowStartPosition(int playerID, const float3& pos) { if (!haveAllowStartPosition) { return true; // the call is not defined } LUA_CALL_IN_CHECK(L); 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)) { 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 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); 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_pushstring(L, type.c_str()); lua_pushnumber(L, amount); // call the function if (!RunCallIn(cmdStr, 4, 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 retval; }
bool CLuaRules::AllowDirectUnitControl(int playerID, const CUnit* unit) { if (!haveAllowDirectUnitControl) { return true; // the call is not defined } LUA_CALL_IN_CHECK(L); 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)) { 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 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); 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_pushstring(L, type.c_str()); lua_pushnumber(L, level); // call the function if (!RunCallIn(cmdStr, 3, 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 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); 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)) { 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 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; }
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 } 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::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); }
bool CLuaHandle::RunCallInTraceback(const LuaHashString& hs, int inArgs, int outArgs, int errfuncIndex) { std::string traceback; const int error = RunCallInTraceback(inArgs, outArgs, errfuncIndex, traceback); if (error != 0) { logOutput.Print("%s::RunCallIn: error = %i, %s, %s\n", GetName().c_str(), error, hs.GetString().c_str(), traceback.c_str()); return false; } return true; }
bool CLuaHandle::RunCallIn(const LuaHashString& hs, int inArgs, int outArgs) { CLuaHandle* orig = activeHandle; SetActiveHandle(); const int error = lua_pcall(L, inArgs, outArgs, 0); SetActiveHandle(orig); if (error != 0) { logOutput.Print("%s::RunCallIn: error = %i, %s, %s\n", GetName().c_str(), error, hs.GetString().c_str(), lua_tostring(L, -1)); lua_pop(L, 1); // log only errors that lead to a crash callinErrors += (error == 2); return false; } return true; }
bool CLuaRules::TerraformComplete(const CUnit* unit, const CUnit* build) { if (!haveTerraformComplete) { return false; // the call is not defined } LUA_CALL_IN_CHECK(L); lua_checkstack(L, 8); static const LuaHashString cmdStr("TerraformComplete"); 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); // push the construction info lua_pushnumber(L, build->id); lua_pushnumber(L, build->unitDef->id); lua_pushnumber(L, build->team); // call the function if (!RunCallIn(cmdStr, 6, 1)) { return false; } // get the results if (!lua_isboolean(L, -1)) { logOutput.Print("%s() bad return value\n", cmdStr.GetString().c_str()); lua_pop(L, 1); return false; } const bool retval = !!lua_toboolean(L, -1); lua_pop(L, 1); // return 'true' to remove the command return retval; }
bool CLuaRules::AllowUnitCreation(const UnitDef* unitDef, const CUnit* builder, const float3* pos) { if (!haveAllowUnitCreation) { return true; // the call is not defined } lua_settop(L, 0); static const LuaHashString cmdStr("AllowUnitCreation"); if (!cmdStr.GetGlobalFunc(L)) { lua_settop(L, 0); return true; // the call is not defined } lua_pushnumber(L, unitDef->id); lua_pushnumber(L, builder->id); lua_pushnumber(L, builder->team); if (pos) { lua_pushnumber(L, pos->x); lua_pushnumber(L, pos->y); lua_pushnumber(L, pos->z); } // call the function if (!RunCallIn(cmdStr, pos ? 6 : 4, 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); }
bool CLuaRules::AllowUnitCreation(const UnitDef* unitDef, const CUnit* builder, const float3* pos) { if (!haveAllowUnitCreation) { return true; // the call is not defined } LUA_CALL_IN_CHECK(L); lua_checkstack(L, 8); static const LuaHashString cmdStr("AllowUnitCreation"); if (!cmdStr.GetGlobalFunc(L)) { return true; // the call is not defined } lua_pushnumber(L, unitDef->id); lua_pushnumber(L, builder->id); lua_pushnumber(L, builder->team); if (pos) { lua_pushnumber(L, pos->x); lua_pushnumber(L, pos->y); lua_pushnumber(L, pos->z); } // call the function if (!RunCallIn(cmdStr, pos ? 6 : 3, 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 retval; }
bool CLuaHandle::Explosion(int weaponID, const float3& pos, const CUnit* owner) { if ((weaponID >= (int)watchWeapons.size()) || (weaponID < 0)) { return false; } if (!watchWeapons[weaponID]) { return false; } LUA_CALL_IN_CHECK(L); lua_checkstack(L, 7); static const LuaHashString cmdStr("Explosion"); if (!cmdStr.GetGlobalFunc(L)) { return false; // the call is not defined } lua_pushnumber(L, weaponID); lua_pushnumber(L, pos.x); lua_pushnumber(L, pos.y); lua_pushnumber(L, pos.z); if (owner != NULL) { lua_pushnumber(L, owner->id); } // call the routine RunCallIn(cmdStr, (owner == NULL) ? 4 : 5, 1); // get the results if (!lua_isboolean(L, -1)) { logOutput.Print("%s() bad return value\n", cmdStr.GetString().c_str()); lua_pop(L, 1); return false; } 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_settop(L, 0); static const LuaHashString cmdStr("AllowFeatureCreation"); if (!cmdStr.GetGlobalFunc(L)) { lua_settop(L, 0); 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 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); }
bool CLuaRules::DrawUnit(int unitID) { if (!haveDrawUnit) { return false; } LUA_CALL_IN_CHECK(L); lua_checkstack(L, 4); static const LuaHashString cmdStr("DrawUnit"); if (!cmdStr.GetRegistryFunc(L)) { return false; } const bool oldGLState = LuaOpenGL::IsDrawingEnabled(); LuaOpenGL::SetDrawingEnabled(true); lua_pushnumber(L, unitID); lua_pushnumber(L, game->GetDrawMode()); const bool success = RunCallIn(cmdStr, 2, 1); LuaOpenGL::SetDrawingEnabled(oldGLState); if (!success) { return false; } if (!lua_isboolean(L, -1)) { logOutput.Print("%s() bad return value\n", cmdStr.GetString().c_str()); lua_pop(L, 1); return false; } const bool retval = !!lua_toboolean(L, -1); lua_pop(L, 1); return retval; }
bool CLuaRules::AllowUnitCreation(const UnitDef* unitDef, const CUnit* builder, const BuildInfo* buildInfo) { if (!haveAllowUnitCreation) return true; // the call is not defined LUA_CALL_IN_CHECK(L, true); lua_checkstack(L, 9); static const LuaHashString cmdStr("AllowUnitCreation"); if (!cmdStr.GetGlobalFunc(L)) return true; // the call is not defined lua_pushnumber(L, unitDef->id); lua_pushnumber(L, builder->id); lua_pushnumber(L, builder->team); if (buildInfo != NULL) { lua_pushnumber(L, buildInfo->pos.x); lua_pushnumber(L, buildInfo->pos.y); lua_pushnumber(L, buildInfo->pos.z); lua_pushnumber(L, buildInfo->buildFacing); } // call the function if (!RunCallIn(cmdStr, (buildInfo != NULL)? 7 : 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::AllowFeatureBuildStep(const CUnit* builder, const CFeature* feature, float part) { if (!haveAllowFeatureBuildStep) { return true; // the call is not defined } lua_settop(L, 0); static const LuaHashString cmdStr("AllowFeatureBuildStep"); if (!cmdStr.GetGlobalFunc(L)) { lua_settop(L, 0); 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 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); }
bool CLuaRules::AllowResourceTransfer(int oldTeam, int newTeam, const string& type, float amount) { if (!haveAllowResourceTransfer) { return true; // the call is not defined } lua_settop(L, 0); static const LuaHashString cmdStr("AllowResourceTransfer"); if (!cmdStr.GetGlobalFunc(L)) { lua_settop(L, 0); return true; // the call is not defined } lua_pushnumber(L, oldTeam); lua_pushnumber(L, newTeam); lua_pushstring(L, type.c_str()); lua_pushnumber(L, amount); // call the function if (!RunCallIn(cmdStr, 4, 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); }
bool CLuaRules::AllowUnitTransfer(const CUnit* unit, int newTeam, bool capture) { if (!haveAllowUnitTransfer) { return true; // the call is not defined } lua_settop(L, 0); static const LuaHashString cmdStr("AllowUnitTransfer"); if (!cmdStr.GetGlobalFunc(L)) { lua_settop(L, 0); 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 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); }
bool CLuaRules::MoveCtrlNotify(const CUnit* unit, int data) { if (!haveMoveCtrlNotify) { return false; // the call is not defined } LUA_CALL_IN_CHECK(L); 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)) { logOutput.Print("%s() bad return value\n", cmdStr.GetString().c_str()); lua_pop(L, 1); return false; } 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); 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)) { 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 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); 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)) { 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 retval; }
void CLuaCob::CallFunction(const LuaHashString& name, const CUnit* unit, int& argsCount, int args[MAX_LUA_COB_ARGS]) { static int callDepth = 0; if (callDepth >= 16) { logOutput.Print("CLuaCob::CallFunction() call overflow: %s\n", name.GetString().c_str()); args[0] = 0; // failure return; } lua_settop(L, 0); if (!name.GetGlobalFunc(L)) { lua_settop(L, 0); logOutput.Print("CLuaCob::CallFunction() missing function: %s\n", name.GetString().c_str()); args[0] = 0; // failure return; } lua_pushnumber(L, unit->id); lua_pushnumber(L, unit->unitDef->id); lua_pushnumber(L, unit->team); for (int a = 0; a < argsCount; a++) { lua_pushnumber(L, args[a]); } // call the routine callDepth++; const int* oldArgs = currentArgs; currentArgs = args; const bool error = !RunCallIn(name, 3 + argsCount, LUA_MULTRET); currentArgs = oldArgs; callDepth--; // bail on error if (error) { args[0] = 0; // failure return; } // get the results const int retArgs = min(lua_gettop(L), (MAX_LUA_COB_ARGS - 1)); for (int a = 1; a <= retArgs; a++) { if (lua_isnumber(L, a)) { args[a] = (int)lua_tonumber(L, a); } else if (lua_isboolean(L, a)) { args[a] = lua_toboolean(L, a) ? 1 : 0; } else if (lua_istable(L, a)) { lua_rawgeti(L, a, 1); lua_rawgeti(L, a, 2); if (lua_isnumber(L, -2) && lua_isnumber(L, -1)) { const int x = (int)lua_tonumber(L, -2); const int z = (int)lua_tonumber(L, -1); args[a] = PACKXZ(x, z); } else { args[a] = 0; } lua_pop(L, 2); } else { args[a] = 0; } } args[0] = 1; // success return; }
/** * 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 weaponDefID, int projectileID, bool paralyzer, float* newDamage, float* impulseMult) { if (!haveUnitPreDamaged) return false; LUA_CALL_IN_CHECK(L, false); lua_checkstack(L, 9 + 4); const int errfunc = SetupTraceback(L); static const LuaHashString cmdStr("UnitPreDamaged"); if (!cmdStr.GetGlobalFunc(L)) { if (errfunc) // remove error handler 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 (GetHandleFullRead(L)) { lua_pushnumber(L, weaponDefID); argCount += 1; lua_pushnumber(L, projectileID); 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 const bool success = RunCallInTraceback(cmdStr, argCount, 2, errfunc); if (!success) return false; 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 LOG_L(L_WARNING, "%s(): 1st value returned should be a number (newDamage)", 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 LOG_L(L_WARNING, "%s(): 2nd value returned should be a number (impulseMult)", cmdStr.GetString().c_str()); } lua_pop(L, 2); return true; }
void CLuaRules::Cob2Lua(const LuaHashString& name, const CUnit* unit, int& argsCount, int args[MAX_LUA_COB_ARGS]) { static int callDepth = 0; if (callDepth >= 16) { LOG_L(L_WARNING, "CLuaRules::Cob2Lua() call overflow: %s", name.GetString().c_str()); args[0] = 0; // failure return; } LUA_CALL_IN_CHECK(L); const int top = lua_gettop(L); if (!lua_checkstack(L, 1 + 3 + argsCount)) { LOG_L(L_WARNING, "CLuaRules::Cob2Lua() lua_checkstack() error: %s", name.GetString().c_str()); args[0] = 0; // failure lua_settop(L, top); return; } if (!name.GetGlobalFunc(L)) { LOG_L(L_WARNING, "CLuaRules::Cob2Lua() missing function: %s", name.GetString().c_str()); args[0] = 0; // failure lua_settop(L, top); return; } lua_pushnumber(L, unit->id); lua_pushnumber(L, unit->unitDef->id); lua_pushnumber(L, unit->team); for (int a = 0; a < argsCount; a++) { lua_pushnumber(L, args[a]); } // call the routine callDepth++; const int* oldArgs = currentCobArgs; currentCobArgs = args; const bool error = !RunCallIn(name, 3 + argsCount, LUA_MULTRET); currentCobArgs = oldArgs; callDepth--; // bail on error if (error) { args[0] = 0; // failure lua_settop(L, top); return; } // get the results const int retArgs = std::min(lua_gettop(L) - top, (MAX_LUA_COB_ARGS - 1)); for (int a = 1; a <= retArgs; a++) { const int index = (a + top); if (lua_isnumber(L, index)) { args[a] = lua_toint(L, index); } else if (lua_isboolean(L, index)) { args[a] = lua_toboolean(L, index) ? 1 : 0; } else if (lua_istable(L, index)) { lua_rawgeti(L, index, 1); lua_rawgeti(L, index, 2); if (lua_isnumber(L, -2) && lua_isnumber(L, -1)) { const int x = lua_toint(L, -2); const int z = lua_toint(L, -1); args[a] = PACKXZ(x, z); } else { args[a] = 0; } lua_pop(L, 2); } else { args[a] = 0; } } args[0] = 1; // success lua_settop(L, top); return; }