1
0

LUA functions added: GetSpellCaster(Spell) and GetCasterSpellLevel(Spell) the Spell field is optional if in a spell script

db additionally had field added:

alter table character_spell_effects add column caster_level smallint(5) unsigned not null default 0;
This commit is contained in:
Emagi 2025-01-18 09:16:35 -05:00
parent c300a5b066
commit dad7873dc5
7 changed files with 57 additions and 5 deletions

View File

@ -14298,6 +14298,46 @@ int EQ2Emu_lua_GetSpellInitialTarget(lua_State* state) {
return 0; return 0;
} }
int EQ2Emu_lua_GetSpellCaster(lua_State* state) {
LuaSpell* spell = lua_interface->GetSpell(state);
if(!spell) {
spell = lua_interface->GetCurrentSpell(state);
}
lua_interface->ResetFunctionStack(state);
if (spell) {
if(!spell->caster) {
lua_interface->LogError("%s: LUA GetSpellCaster command error, caster does not exist.", lua_interface->GetScriptName(state));
return 0;
}
lua_interface->SetSpawnValue(state, spell->caster);
return 1;
}
else {
lua_interface->LogError("%s: LUA GetSpellCaster command error, could not find spell.", lua_interface->GetScriptName(state));
}
return 0;
}
int EQ2Emu_lua_GetCasterSpellLevel(lua_State* state) {
LuaSpell* spell = lua_interface->GetSpell(state);
if(!spell) {
spell = lua_interface->GetCurrentSpell(state);
}
lua_interface->ResetFunctionStack(state);
if (spell) {
lua_interface->SetInt32Value(state, spell->initial_caster_level);
return 1;
}
else {
lua_interface->LogError("%s: LUA GetCasterSpellLevel command error, spell does not exist.", lua_interface->GetScriptName(state));
}
return 0;
}
int EQ2Emu_lua_GetSpellTargets(lua_State* state) { int EQ2Emu_lua_GetSpellTargets(lua_State* state) {
if (!lua_interface) if (!lua_interface)
return 0; return 0;

View File

@ -659,6 +659,8 @@ int EQ2Emu_lua_GetCharacterFlag(lua_State* state);
int EQ2Emu_lua_ToggleCharacterFlag(lua_State* state); int EQ2Emu_lua_ToggleCharacterFlag(lua_State* state);
int EQ2Emu_lua_GetSpellInitialTarget(lua_State* state); int EQ2Emu_lua_GetSpellInitialTarget(lua_State* state);
int EQ2Emu_lua_GetSpellCaster(lua_State* state);
int EQ2Emu_lua_GetCasterSpellLevel(lua_State* state);
int EQ2Emu_lua_GetSpellTargets(lua_State* state); int EQ2Emu_lua_GetSpellTargets(lua_State* state);
int EQ2Emu_lua_DespawnByLocationID(lua_State* state); int EQ2Emu_lua_DespawnByLocationID(lua_State* state);

View File

@ -1600,6 +1600,8 @@ void LuaInterface::RegisterFunctions(lua_State* state) {
lua_register(state, "ToggleCharacterFlag", EQ2Emu_lua_ToggleCharacterFlag); lua_register(state, "ToggleCharacterFlag", EQ2Emu_lua_ToggleCharacterFlag);
lua_register(state, "GetSpellInitialTarget", EQ2Emu_lua_GetSpellInitialTarget); lua_register(state, "GetSpellInitialTarget", EQ2Emu_lua_GetSpellInitialTarget);
lua_register(state, "GetSpellCaster", EQ2Emu_lua_GetSpellCaster);
lua_register(state, "GetCasterSpellLevel", EQ2Emu_lua_GetCasterSpellLevel);
lua_register(state, "GetSpellTargets", EQ2Emu_lua_GetSpellTargets); lua_register(state, "GetSpellTargets", EQ2Emu_lua_GetSpellTargets);
lua_register(state,"DespawnByLocationID", EQ2Emu_lua_DespawnByLocationID); lua_register(state,"DespawnByLocationID", EQ2Emu_lua_DespawnByLocationID);
@ -2114,6 +2116,7 @@ LuaSpell* LuaInterface::LoadSpellScript(const char* name) {
spell->initial_caster_char_id = 0; spell->initial_caster_char_id = 0;
spell->initial_target_char_id = 0; spell->initial_target_char_id = 0;
spell->zone = nullptr; spell->zone = nullptr;
spell->initial_caster_level = 0;
MSpells.lock(); MSpells.lock();
current_spells[spell->state] = spell; current_spells[spell->state] = spell;
@ -2413,6 +2416,7 @@ LuaSpell* LuaInterface::CreateSpellScript(const char* name, lua_State* existStat
new_spell->initial_caster_char_id = 0; new_spell->initial_caster_char_id = 0;
new_spell->initial_target_char_id = 0; new_spell->initial_target_char_id = 0;
new_spell->zone = nullptr; new_spell->zone = nullptr;
new_spell->initial_caster_level = 0;
current_spells[new_spell->state] = new_spell; current_spells[new_spell->state] = new_spell;
return new_spell; return new_spell;

View File

@ -104,6 +104,7 @@ struct LuaSpell{
bool restored; // restored spell cross zone bool restored; // restored spell cross zone
std::atomic<bool> has_proc; std::atomic<bool> has_proc;
ZoneServer* zone; ZoneServer* zone;
int16 initial_caster_level;
}; };
class LUAUserData{ class LUAUserData{

View File

@ -7245,13 +7245,13 @@ void Player::SaveSpellEffects()
continue; continue;
savedEffects.AddQueryAsync(GetCharacterID(), &database, Q_INSERT, savedEffects.AddQueryAsync(GetCharacterID(), &database, Q_INSERT,
"insert into character_spell_effects (name, caster_char_id, target_char_id, target_type, db_effect_type, spell_id, effect_slot, slot_pos, icon, icon_backdrop, conc_used, tier, total_time, expire_timestamp, lua_file, custom_spell, charid, damage_remaining, effect_bitmask, num_triggers, had_triggers, cancel_after_triggers, crit, last_spellattack_hit, interrupted, resisted, has_damaged, custom_function) values ('%s', %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %f, %u, '%s', %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, '%s')", "insert into character_spell_effects (name, caster_char_id, target_char_id, target_type, db_effect_type, spell_id, effect_slot, slot_pos, icon, icon_backdrop, conc_used, tier, total_time, expire_timestamp, lua_file, custom_spell, charid, damage_remaining, effect_bitmask, num_triggers, had_triggers, cancel_after_triggers, crit, last_spellattack_hit, interrupted, resisted, has_damaged, custom_function, caster_level) values ('%s', %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %f, %u, '%s', %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, '%s', %u)",
database.getSafeEscapeString(info->spell_effects[i].spell->spell->GetName()).c_str(), caster_char_id, database.getSafeEscapeString(info->spell_effects[i].spell->spell->GetName()).c_str(), caster_char_id,
target_char_id, 0 /*no target_type for spell_effects*/, DB_TYPE_SPELLEFFECTS /* db_effect_type for spell_effects */, info->spell_effects[i].spell->spell->IsCopiedSpell() ? info->spell_effects[i].spell->spell->GetSpellData()->inherited_spell_id : info->spell_effects[i].spell_id, i, info->spell_effects[i].spell->slot_pos, target_char_id, 0 /*no target_type for spell_effects*/, DB_TYPE_SPELLEFFECTS /* db_effect_type for spell_effects */, info->spell_effects[i].spell->spell->IsCopiedSpell() ? info->spell_effects[i].spell->spell->GetSpellData()->inherited_spell_id : info->spell_effects[i].spell_id, i, info->spell_effects[i].spell->slot_pos,
info->spell_effects[i].icon, info->spell_effects[i].icon_backdrop, 0 /* no conc_used for spell_effects */, info->spell_effects[i].tier, info->spell_effects[i].icon, info->spell_effects[i].icon_backdrop, 0 /* no conc_used for spell_effects */, info->spell_effects[i].tier,
info->spell_effects[i].total_time, timestamp, database.getSafeEscapeString(info->spell_effects[i].spell->file_name.c_str()).c_str(), info->spell_effects[i].spell->spell->IsCopiedSpell(), GetCharacterID(), info->spell_effects[i].total_time, timestamp, database.getSafeEscapeString(info->spell_effects[i].spell->file_name.c_str()).c_str(), info->spell_effects[i].spell->spell->IsCopiedSpell(), GetCharacterID(),
info->spell_effects[i].spell->damage_remaining, info->spell_effects[i].spell->effect_bitmask, info->spell_effects[i].spell->num_triggers, info->spell_effects[i].spell->had_triggers, info->spell_effects[i].spell->cancel_after_all_triggers, info->spell_effects[i].spell->damage_remaining, info->spell_effects[i].spell->effect_bitmask, info->spell_effects[i].spell->num_triggers, info->spell_effects[i].spell->had_triggers, info->spell_effects[i].spell->cancel_after_all_triggers,
info->spell_effects[i].spell->crit, info->spell_effects[i].spell->last_spellattack_hit, info->spell_effects[i].spell->interrupted, info->spell_effects[i].spell->resisted, info->spell_effects[i].spell->has_damaged, (info->maintained_effects[i].expire_timestamp) == 0xFFFFFFFF ? "" : database.getSafeEscapeString(spellProcess->SpellScriptTimerCustomFunction(info->spell_effects[i].spell).c_str()).c_str()); info->spell_effects[i].spell->crit, info->spell_effects[i].spell->last_spellattack_hit, info->spell_effects[i].spell->interrupted, info->spell_effects[i].spell->resisted, info->spell_effects[i].spell->has_damaged, (info->maintained_effects[i].expire_timestamp) == 0xFFFFFFFF ? "" : database.getSafeEscapeString(spellProcess->SpellScriptTimerCustomFunction(info->spell_effects[i].spell).c_str()).c_str(), info->spell_effects[i].spell->initial_caster_level);
} }
if (i < NUM_MAINTAINED_EFFECTS && info->maintained_effects[i].spell_id != 0xFFFFFFFF){ if (i < NUM_MAINTAINED_EFFECTS && info->maintained_effects[i].spell_id != 0xFFFFFFFF){
Spawn* spawn = GetZone()->GetSpawnByID(info->maintained_effects[i].spell->initial_target); Spawn* spawn = GetZone()->GetSpawnByID(info->maintained_effects[i].spell->initial_target);
@ -7273,12 +7273,12 @@ void Player::SaveSpellEffects()
if(info->maintained_effects[i].spell->spell->GetSpellData() && !info->maintained_effects[i].spell->spell->GetSpellData()->duration_until_cancel) if(info->maintained_effects[i].spell->spell->GetSpellData() && !info->maintained_effects[i].spell->spell->GetSpellData()->duration_until_cancel)
timestamp = info->maintained_effects[i].expire_timestamp - Timer::GetCurrentTime2(); timestamp = info->maintained_effects[i].expire_timestamp - Timer::GetCurrentTime2();
savedEffects.AddQueryAsync(GetCharacterID(), &database, Q_INSERT, savedEffects.AddQueryAsync(GetCharacterID(), &database, Q_INSERT,
"insert into character_spell_effects (name, caster_char_id, target_char_id, target_type, db_effect_type, spell_id, effect_slot, slot_pos, icon, icon_backdrop, conc_used, tier, total_time, expire_timestamp, lua_file, custom_spell, charid, damage_remaining, effect_bitmask, num_triggers, had_triggers, cancel_after_triggers, crit, last_spellattack_hit, interrupted, resisted, has_damaged, custom_function) values ('%s', %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %f, %u, '%s', %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, '%s')", "insert into character_spell_effects (name, caster_char_id, target_char_id, target_type, db_effect_type, spell_id, effect_slot, slot_pos, icon, icon_backdrop, conc_used, tier, total_time, expire_timestamp, lua_file, custom_spell, charid, damage_remaining, effect_bitmask, num_triggers, had_triggers, cancel_after_triggers, crit, last_spellattack_hit, interrupted, resisted, has_damaged, custom_function, caster_level) values ('%s', %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %f, %u, '%s', %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, '%s', %u)",
database.getSafeEscapeString(info->maintained_effects[i].name).c_str(), caster_char_id, target_char_id, info->maintained_effects[i].target_type, DB_TYPE_MAINTAINEDEFFECTS /* db_effect_type for maintained_effects */, info->maintained_effects[i].spell->spell->IsCopiedSpell() ? info->maintained_effects[i].spell->spell->GetSpellData()->inherited_spell_id : info->maintained_effects[i].spell_id, i, info->maintained_effects[i].slot_pos, database.getSafeEscapeString(info->maintained_effects[i].name).c_str(), caster_char_id, target_char_id, info->maintained_effects[i].target_type, DB_TYPE_MAINTAINEDEFFECTS /* db_effect_type for maintained_effects */, info->maintained_effects[i].spell->spell->IsCopiedSpell() ? info->maintained_effects[i].spell->spell->GetSpellData()->inherited_spell_id : info->maintained_effects[i].spell_id, i, info->maintained_effects[i].slot_pos,
info->maintained_effects[i].icon, info->maintained_effects[i].icon_backdrop, info->maintained_effects[i].conc_used, info->maintained_effects[i].tier, info->maintained_effects[i].icon, info->maintained_effects[i].icon_backdrop, info->maintained_effects[i].conc_used, info->maintained_effects[i].tier,
info->maintained_effects[i].total_time, timestamp, database.getSafeEscapeString(info->maintained_effects[i].spell->file_name.c_str()).c_str(), info->maintained_effects[i].spell->spell->IsCopiedSpell(), GetCharacterID(), info->maintained_effects[i].total_time, timestamp, database.getSafeEscapeString(info->maintained_effects[i].spell->file_name.c_str()).c_str(), info->maintained_effects[i].spell->spell->IsCopiedSpell(), GetCharacterID(),
info->maintained_effects[i].spell->damage_remaining, info->maintained_effects[i].spell->effect_bitmask, info->maintained_effects[i].spell->num_triggers, info->maintained_effects[i].spell->had_triggers, info->maintained_effects[i].spell->cancel_after_all_triggers, info->maintained_effects[i].spell->damage_remaining, info->maintained_effects[i].spell->effect_bitmask, info->maintained_effects[i].spell->num_triggers, info->maintained_effects[i].spell->had_triggers, info->maintained_effects[i].spell->cancel_after_all_triggers,
info->maintained_effects[i].spell->crit, info->maintained_effects[i].spell->last_spellattack_hit, info->maintained_effects[i].spell->interrupted, info->maintained_effects[i].spell->resisted, info->maintained_effects[i].spell->has_damaged, (info->maintained_effects[i].expire_timestamp) == 0xFFFFFFFF ? "" : database.getSafeEscapeString(spellProcess->SpellScriptTimerCustomFunction(info->maintained_effects[i].spell).c_str()).c_str()); info->maintained_effects[i].spell->crit, info->maintained_effects[i].spell->last_spellattack_hit, info->maintained_effects[i].spell->interrupted, info->maintained_effects[i].spell->resisted, info->maintained_effects[i].spell->has_damaged, (info->maintained_effects[i].expire_timestamp) == 0xFFFFFFFF ? "" : database.getSafeEscapeString(spellProcess->SpellScriptTimerCustomFunction(info->maintained_effects[i].spell).c_str()).c_str(), info->maintained_effects[i].spell->initial_caster_level);
info->maintained_effects[i].spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); info->maintained_effects[i].spell->MSpellTargets.readlock(__FUNCTION__, __LINE__);
std::string insertTargets = string("insert into character_spell_effect_targets (caster_char_id, target_char_id, target_type, db_effect_type, spell_id, effect_slot, slot_pos) values "); std::string insertTargets = string("insert into character_spell_effect_targets (caster_char_id, target_char_id, target_type, db_effect_type, spell_id, effect_slot, slot_pos) values ");

View File

@ -649,6 +649,7 @@ bool SpellProcess::CastInstant(Spell* spell, Entity* caster, Entity* target, boo
} }
lua_spell->caster = caster; lua_spell->caster = caster;
lua_spell->initial_caster_level = caster->GetInfoStruct()->get_effective_level() != 0 ? caster->GetInfoStruct()->get_effective_level() : caster->GetLevel();
lua_spell->zone = caster->GetZone(); lua_spell->zone = caster->GetZone();
lua_spell->initial_caster_char_id = (caster && caster->IsPlayer()) ? ((Player*)caster)->GetCharacterID() : 0; lua_spell->initial_caster_char_id = (caster && caster->IsPlayer()) ? ((Player*)caster)->GetCharacterID() : 0;
lua_spell->spell = spell; lua_spell->spell = spell;
@ -1069,6 +1070,7 @@ void SpellProcess::ProcessSpell(ZoneServer* zone, Spell* spell, Entity* caster,
int8 spell_type = spell->GetSpellData()->spell_type; int8 spell_type = spell->GetSpellData()->spell_type;
lua_spell->caster = caster; lua_spell->caster = caster;
lua_spell->initial_caster_level = caster->GetInfoStruct()->get_effective_level() != 0 ? caster->GetInfoStruct()->get_effective_level() : caster->GetLevel();
lua_spell->zone = caster->GetZone(); lua_spell->zone = caster->GetZone();
lua_spell->initial_caster_char_id = (caster && caster->IsPlayer()) ? ((Player*)caster)->GetCharacterID() : 0; lua_spell->initial_caster_char_id = (caster && caster->IsPlayer()) ? ((Player*)caster)->GetCharacterID() : 0;
lua_spell->spell = spell; lua_spell->spell = spell;
@ -1632,6 +1634,7 @@ void SpellProcess::ProcessSpell(ZoneServer* zone, Spell* spell, Entity* caster,
cast_timer->target_id = target ? target->GetID() : 0; cast_timer->target_id = target ? target->GetID() : 0;
cast_timer->spell = lua_spell; cast_timer->spell = lua_spell;
cast_timer->spell->caster = caster; cast_timer->spell->caster = caster;
cast_timer->spell->initial_caster_level = caster->GetInfoStruct()->get_effective_level() != 0 ? caster->GetInfoStruct()->get_effective_level() : caster->GetLevel();
cast_timer->spell->zone = caster->GetZone(); cast_timer->spell->zone = caster->GetZone();
cast_timer->delete_timer = false; cast_timer->delete_timer = false;
cast_timer->timer = new Timer(spell->GetSpellData()->cast_time * 10); cast_timer->timer = new Timer(spell->GetSpellData()->cast_time * 10);

View File

@ -7971,7 +7971,7 @@ void WorldDatabase::LoadCharacterSpellEffects(int32 char_id, Client* client, int
multimap<LuaSpell*, Entity*> restoreSpells; multimap<LuaSpell*, Entity*> restoreSpells;
// Use -1 on type and subtype to turn the enum into an int and make it a 0 index // Use -1 on type and subtype to turn the enum into an int and make it a 0 index
if (!database_new.Select(&result, "SELECT name, caster_char_id, target_char_id, target_type, spell_id, effect_slot, slot_pos, icon, icon_backdrop, conc_used, tier, total_time, expire_timestamp, lua_file, custom_spell, damage_remaining, effect_bitmask, num_triggers, had_triggers, cancel_after_triggers, crit, last_spellattack_hit, interrupted, resisted, has_damaged, custom_function FROM character_spell_effects WHERE charid = %u and db_effect_type = %u", char_id, db_spell_type)) { if (!database_new.Select(&result, "SELECT name, caster_char_id, target_char_id, target_type, spell_id, effect_slot, slot_pos, icon, icon_backdrop, conc_used, tier, total_time, expire_timestamp, lua_file, custom_spell, damage_remaining, effect_bitmask, num_triggers, had_triggers, cancel_after_triggers, crit, last_spellattack_hit, interrupted, resisted, has_damaged, custom_function, caster_level FROM character_spell_effects WHERE charid = %u and db_effect_type = %u", char_id, db_spell_type)) {
LogWrite(DATABASE__ERROR, 0, "DBNew", "MySQL Error %u: %s", database_new.GetError(), database_new.GetErrorMsg()); LogWrite(DATABASE__ERROR, 0, "DBNew", "MySQL Error %u: %s", database_new.GetError(), database_new.GetErrorMsg());
return; return;
} }
@ -8009,6 +8009,7 @@ void WorldDatabase::LoadCharacterSpellEffects(int32 char_id, Client* client, int
int8 resisted = result.GetInt32Str("resisted"); int8 resisted = result.GetInt32Str("resisted");
int8 has_damaged = result.GetInt32Str("has_damaged"); int8 has_damaged = result.GetInt32Str("has_damaged");
std::string custom_function = std::string(result.GetStringStr("custom_function")); std::string custom_function = std::string(result.GetStringStr("custom_function"));
int16 caster_level = result.GetInt16Str("caster_level");
LuaSpell* lua_spell = 0; LuaSpell* lua_spell = 0;
if(custom_spell) if(custom_spell)
{ {
@ -8133,6 +8134,7 @@ void WorldDatabase::LoadCharacterSpellEffects(int32 char_id, Client* client, int
lua_spell->num_triggers = num_triggers; lua_spell->num_triggers = num_triggers;
lua_spell->has_damaged = has_damaged; lua_spell->has_damaged = has_damaged;
lua_spell->is_damage_spell = has_damaged; lua_spell->is_damage_spell = has_damaged;
lua_spell->initial_caster_level = caster_level;
} }
if(lua_spell->initial_target == 0 && target_char_id == 0xFFFFFFFF && player->HasPet()) if(lua_spell->initial_target == 0 && target_char_id == 0xFFFFFFFF && player->HasPet())