[Luamod] Add CalcSpellEffectValue_formula to luamods (#2721)

* [Luamod] Add CalcSpellEffectValue_formula to luamods with example code in utils/mods/spell_formula.lua

* Fix typo

* Change formula down to uint32, fix format issues and remove debug on lua file
This commit is contained in:
Natedog2012 2023-01-11 17:49:35 -06:00 committed by GitHub
parent 2587a7fed5
commit 3341c0b7ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 179 additions and 3 deletions

View File

@ -1312,7 +1312,7 @@ struct SPDat_Spell_Struct
// If it is a number between 1-4 it means components[number] is a focus and not to expend it
// If it is a valid itemid it means this item is a focus as well
// -- NOEXPENDREAGENT1 ... NOEXPENDREAGENT4
/* 070 */ uint16 formula[EFFECT_COUNT]; // Spell's value formula -- LEVELAFFECT1MOD ... LEVELAFFECT12MOD
/* 070 */ uint32 formula[EFFECT_COUNT]; // Spell's value formula -- LEVELAFFECT1MOD ... LEVELAFFECT12MOD
/* 082 */ //int LightType; // probaly another effecttype flag -- LIGHTTYPE
/* 083 */ int8 good_effect; //0=detrimental, 1=Beneficial, 2=Beneficial, Group Only -- BENEFICIAL
/* 084 */ int activated; // probably another effecttype flag -- ACTIVATED

View File

@ -0,0 +1,92 @@
function CalcSpellEffectValue_formula(e)
--THE FUNCTIONALITY OF THIS IS FOR ADDING CUSTOM SPELL FORMULAS WITHOUT INTERFERING WITH EXISTING FORMULAS
if (e.formula >= 100000) then
e.IgnoreDefault = true;
else
e.IgnoreDefault = false;
return e;
end
local result = 0
local updownsign = 1
local ubase = e.base_value
local formula = e.formula
local base_value = e.base_value
local max_value = e.max_value
local caster_level = e.caster_level
local spell_id = e.spell_id
local ticsremaining = e.ticsremaining
if (ubase < 0) then
ubase = 0 - ubase;
end
if (max_value < base_value and max_value ~= 0) then
--values are calculated down
updownsign = -1;
else
--values are calculated up
updownsign = 1;
end
--ADD FORMULAS HERE NO NEED TO TOUCH OTHER CODE UNLESS YOU KNOW WHAT YOU ARE DOING!!!
--FORMULA NUMBERS 100,000+++ are considered "custom" and other spells will use normal logic from source!!!
local switch = {
[100000] = function ()
result = updownsign * (ubase + (e.self:GetSTR()/2)); --Half strength added to damage!
end,
[100001] = function ()
result = (updownsign * (ubase + (caster_level * 2))) * math.random(1,caster_level); -- multiplies final damage randomly from 1 up to caster level!
end,
}
eq.log_spells(
string.format("[Mob::CalcSpellEffectValue_formula] spell [%i] formula [%i] base [%i] max [%i] lvl [%i] Up/Down [%i]",
e.spell_id,
e.formula,
e.base_value,
e.max_value,
e.caster_level,
updownsign
)
);
local f = switch[e.formula]
if (f) then
f()
else
result = ubase; --DEFAULT YOU MAY CHANGE THIS TO WHATEVER YOU WISH BUT WILL ONLY CHANGE CUSTOM FORMULAS above 100,000 THAT AREN'T IN THE TABLE ABOVE!
end
local oresult = result;
--now check result against the allowed maximum
if (max_value ~= 0) then
if (updownsign == 1) then
if (result > max_value) then
result = max_value;
end
else
if (result < max_value) then
result = max_value;
end
end
end
--if base is less than zero, then the result need to be negative too
if (base_value < 0 and result > 0) then
result = result * -1;
end
eq.log_spells(
string.format("[Mob::CalcSpellEffectValue_formula] Result: [%i] (orig [%i]) cap [%i]",
result,
oresult,
max_value
)
);
e.ReturnValue = result;
return e;
end

View File

@ -1580,6 +1580,10 @@ void lua_log_combat(std::string message) {
Log(Logs::General, Logs::Combat, message.c_str());
}
void lua_log_spells(std::string message) {
Log(Logs::General, Logs::Spells, message.c_str());
}
void lua_update_zone_header(std::string type, std::string value) {
quest_manager.UpdateZoneHeader(type, value);
}
@ -4142,6 +4146,7 @@ luabind::scope lua_register_general() {
luabind::def("debug", (void(*)(std::string))&lua_debug),
luabind::def("debug", (void(*)(std::string, int))&lua_debug),
luabind::def("log_combat", (void(*)(std::string))&lua_log_combat),
luabind::def("log_spells", (void(*)(std::string))&lua_log_spells),
luabind::def("seconds_to_time", &lua_seconds_to_time),
luabind::def("time_to_seconds", &lua_time_to_seconds),
luabind::def("get_hex_color_code", &lua_get_hex_color_code),

View File

@ -45,6 +45,7 @@ void LuaMod::Init()
m_has_get_exp_for_level = parser_->HasFunction("GetEXPForLevel", package_name_);
m_has_get_experience_for_kill = parser_->HasFunction("GetExperienceForKill", package_name_);
m_has_common_outgoing_hit_success = parser_->HasFunction("CommonOutgoingHitSuccess", package_name_);
m_has_calc_spell_effect_value_formula = parser_->HasFunction("CalcSpellEffectValue_formula", package_name_);
}
void PutDamageHitInfo(lua_State *L, luabind::adl::object &e, DamageHitInfo &hit) {
@ -632,4 +633,59 @@ void LuaMod::GetExperienceForKill(Client *self, Mob *against, uint64 &returnValu
}
}
void LuaMod::CalcSpellEffectValue_formula(Mob *self, uint32 formula, int64 base_value, int64 max_value, int caster_level, uint16 spell_id, int ticsremaining, int64 &returnValue, bool &ignoreDefault)
{
int start = lua_gettop(L);
int64 retval = 0;
try {
if (!m_has_calc_spell_effect_value_formula) {
return;
}
lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str());
lua_getfield(L, -1, "CalcSpellEffectValue_formula");
Lua_Mob l_self(self);
luabind::adl::object e = luabind::newtable(L);
e["self"] = l_self;
e["formula"] = formula;
e["base_value"] = base_value;
e["max_value"] = max_value;
e["caster_level"] = caster_level;
e["spell_id"] = spell_id;
e["ticsremaining"] = ticsremaining;
e.push(L);
if (lua_pcall(L, 1, 1, 0)) {
std::string error = lua_tostring(L, -1);
parser_->AddError(error);
lua_pop(L, 2);
return;
}
if (lua_type(L, -1) == LUA_TTABLE) {
luabind::adl::object ret(luabind::from_stack(L, -1));
auto IgnoreDefaultObj = ret["IgnoreDefault"];
if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) {
ignoreDefault = ignoreDefault || luabind::object_cast<bool>(IgnoreDefaultObj);
}
auto returnValueObj = ret["ReturnValue"];
if (luabind::type(returnValueObj) == LUA_TNUMBER) {
returnValue = luabind::object_cast<int64>(returnValueObj);
}
}
}
catch (std::exception &ex) {
parser_->AddError(ex.what());
}
int end = lua_gettop(L);
int n = end - start;
if (n > 0) {
lua_pop(L, n);
}
}
#endif

View File

@ -26,6 +26,7 @@ public:
void GetRequiredAAExperience(Client *self, uint32 &returnValue, bool &ignoreDefault);
void GetEXPForLevel(Client *self, uint16 level, uint32 &returnValue, bool &ignoreDefault);
void GetExperienceForKill(Client *self, Mob *against, uint64 &returnValue, bool &ignoreDefault);
void CalcSpellEffectValue_formula(Mob *self, uint32 formula, int64 base_value, int64 max_value, int caster_level, uint16 spell_id, int ticsremaining, int64 &returnValue, bool &ignoreDefault);
private:
LuaParser *parser_;
lua_State *L;
@ -40,4 +41,5 @@ private:
bool m_has_get_required_aa_experience;
bool m_has_get_exp_for_level;
bool m_has_get_experience_for_kill;
bool m_has_calc_spell_effect_value_formula;
};

View File

@ -1494,6 +1494,15 @@ uint64 LuaParser::GetExperienceForKill(Client *self, Mob *against, bool &ignoreD
return retval;
}
int64 LuaParser::CalcSpellEffectValue_formula(Mob *self, uint32 formula, int64 base_value, int64 max_value, int caster_level, uint16 spell_id, int ticsremaining, bool &ignoreDefault)
{
int64 retval = 0;
for (auto &mod : mods_) {
mod.CalcSpellEffectValue_formula(self, formula, base_value, max_value, caster_level, spell_id, ticsremaining, retval, ignoreDefault);
}
return retval;
}
#ifdef BOTS
int LuaParser::EventBot(
QuestEventID evt,

View File

@ -207,6 +207,7 @@ public:
uint32 GetRequiredAAExperience(Client *self, bool &ignoreDefault);
uint32 GetEXPForLevel(Client *self, uint16 level, bool &ignoreDefault);
uint64 GetExperienceForKill(Client *self, Mob *against, bool &ignoreDefault);
int64 CalcSpellEffectValue_formula(Mob *self, uint32 formula, int64 base_value, int64 max_value, int caster_level, uint16 spell_id, int ticsremaining, bool &ignoreDefault);
private:
LuaParser();

View File

@ -1244,7 +1244,7 @@ public:
//uint32 GetInstrumentMod(uint16 spell_id) const;
uint32 GetInstrumentMod(uint16 spell_id);
int64 CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level = 1, uint32 instrument_mod = 10, Mob *caster = nullptr, int ticsremaining = 0,uint16 casterid=0);
int64 CalcSpellEffectValue_formula(int64 formula, int64 base_value, int64 max_value, int caster_level, uint16 spell_id, int ticsremaining = 0);
int64 CalcSpellEffectValue_formula(uint32 formula, int64 base_value, int64 max_value, int caster_level, uint16 spell_id, int ticsremaining = 0);
virtual int CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, int caster_level2, Mob* caster1 = nullptr, Mob* caster2 = nullptr, int buffslot = -1);
uint32 GetCastedSpellInvSlot() const { return casting_spell_inventory_slot; }

View File

@ -28,6 +28,7 @@
#include "../common/misc_functions.h"
#include "quest_parser_collection.h"
#include "lua_parser.h"
#include "string_ids.h"
#include "worldserver.h"
@ -3408,8 +3409,18 @@ int64 Mob::CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level
}
// generic formula calculations
int64 Mob::CalcSpellEffectValue_formula(int64 formula, int64 base_value, int64 max_value, int caster_level, uint16 spell_id, int ticsremaining)
int64 Mob::CalcSpellEffectValue_formula(uint32 formula, int64 base_value, int64 max_value, int caster_level, uint16 spell_id, int ticsremaining)
{
#ifdef LUA_EQEMU
int64 lua_ret = 0;
bool ignoreDefault = false;
lua_ret = LuaParser::Instance()->CalcSpellEffectValue_formula(this, formula, base_value, max_value, caster_level, spell_id, ticsremaining, ignoreDefault);
if (ignoreDefault) {
return lua_ret;
}
#endif
/*
i need those formulas checked!!!!