mirror of
https://github.com/EQEmu/Server.git
synced 2026-06-02 19:30:25 +00:00
[Feature] Zone Scripting (#4908)
* [Feature] Add Zone Scripting Capabilities * Push * Update zone.cpp * Fix crashes * Lua * Add other events, finish Lua * Add EVENT_ENTER_ZONE * Final * Push * Push * [Feature] Add Zone Scripting Capabilities * Push * Update zone.cpp * Fix crashes * Add EVENT_ENTER_ZONE * Remove duplicates * Update embparser.cpp
This commit is contained in:
+256
-7
@@ -219,6 +219,7 @@ LuaParser::LuaParser() {
|
||||
SpellArgumentDispatch[i] = handle_spell_null;
|
||||
EncounterArgumentDispatch[i] = handle_encounter_null;
|
||||
BotArgumentDispatch[i] = handle_bot_null;
|
||||
ZoneArgumentDispatch[i] = handle_zone_null;
|
||||
}
|
||||
|
||||
NPCArgumentDispatch[EVENT_SAY] = handle_npc_event_say;
|
||||
@@ -409,6 +410,23 @@ LuaParser::LuaParser() {
|
||||
BotArgumentDispatch[EVENT_ENTITY_VARIABLE_SET] = handle_bot_entity_variable;
|
||||
BotArgumentDispatch[EVENT_ENTITY_VARIABLE_UPDATE] = handle_bot_entity_variable;
|
||||
BotArgumentDispatch[EVENT_SPELL_BLOCKED] = handle_bot_spell_blocked;
|
||||
|
||||
ZoneArgumentDispatch[EVENT_CLICK_DOOR] = handle_zone_click_door;
|
||||
ZoneArgumentDispatch[EVENT_CLICK_OBJECT] = handle_zone_click_object;
|
||||
ZoneArgumentDispatch[EVENT_DEATH_ZONE] = handle_zone_death;
|
||||
ZoneArgumentDispatch[EVENT_DESPAWN_ZONE] = handle_zone_despawn;
|
||||
ZoneArgumentDispatch[EVENT_ENTER_ZONE] = handle_zone_enter;
|
||||
ZoneArgumentDispatch[EVENT_LOOT_ZONE] = handle_zone_loot;
|
||||
ZoneArgumentDispatch[EVENT_PAYLOAD] = handle_zone_payload;
|
||||
ZoneArgumentDispatch[EVENT_PLAYER_PICKUP] = handle_zone_pickup;
|
||||
ZoneArgumentDispatch[EVENT_POPUP_RESPONSE] = handle_zone_popup;
|
||||
ZoneArgumentDispatch[EVENT_SIGNAL] = handle_zone_signal;
|
||||
ZoneArgumentDispatch[EVENT_SPAWN_ZONE] = handle_zone_spawn;
|
||||
ZoneArgumentDispatch[EVENT_TIMER] = handle_zone_timer;
|
||||
ZoneArgumentDispatch[EVENT_TIMER_PAUSE] = handle_zone_timer_pause_resume_start;
|
||||
ZoneArgumentDispatch[EVENT_TIMER_RESUME] = handle_zone_timer_pause_resume_start;
|
||||
ZoneArgumentDispatch[EVENT_TIMER_START] = handle_zone_timer_pause_resume_start;
|
||||
ZoneArgumentDispatch[EVENT_TIMER_STOP] = handle_zone_timer_stop;
|
||||
#endif
|
||||
|
||||
L = nullptr;
|
||||
@@ -489,7 +507,13 @@ int LuaParser::_EventNPC(std::string package_name, QuestEventID evt, NPC* npc, M
|
||||
arg_function(this, L, npc, init, data, extra_data, extra_pointers);
|
||||
Client *c = (init && init->IsClient()) ? init->CastToClient() : nullptr;
|
||||
|
||||
quest_manager.StartQuest(npc, c);
|
||||
RunningQuest q;
|
||||
|
||||
q.owner = npc;
|
||||
q.initiator = c;
|
||||
|
||||
quest_manager.StartQuest(q);
|
||||
|
||||
if(lua_pcall(L, 1, 1, start + 1)) {
|
||||
std::string error = lua_tostring(L, -1);
|
||||
AddError(error);
|
||||
@@ -582,7 +606,13 @@ int LuaParser::_EventPlayer(std::string package_name, QuestEventID evt, Client *
|
||||
auto arg_function = PlayerArgumentDispatch[evt];
|
||||
arg_function(this, L, client, data, extra_data, extra_pointers);
|
||||
|
||||
quest_manager.StartQuest(client, client);
|
||||
RunningQuest q;
|
||||
|
||||
q.owner = client;
|
||||
q.initiator = client;
|
||||
|
||||
quest_manager.StartQuest(q);
|
||||
|
||||
if(lua_pcall(L, 1, 1, start + 1)) {
|
||||
std::string error = lua_tostring(L, -1);
|
||||
AddError(error);
|
||||
@@ -666,7 +696,14 @@ int LuaParser::_EventItem(std::string package_name, QuestEventID evt, Client *cl
|
||||
auto arg_function = ItemArgumentDispatch[evt];
|
||||
arg_function(this, L, client, item, mob, data, extra_data, extra_pointers);
|
||||
|
||||
quest_manager.StartQuest(client, client, item);
|
||||
RunningQuest q;
|
||||
|
||||
q.owner = client;
|
||||
q.initiator = client;
|
||||
q.questitem = item;
|
||||
|
||||
quest_manager.StartQuest(q);
|
||||
|
||||
if(lua_pcall(L, 1, 1, start + 1)) {
|
||||
std::string error = lua_tostring(L, -1);
|
||||
AddError(error);
|
||||
@@ -748,7 +785,14 @@ int LuaParser::_EventSpell(std::string package_name, QuestEventID evt, Mob* mob,
|
||||
auto arg_function = SpellArgumentDispatch[evt];
|
||||
arg_function(this, L, mob, client, spell_id, data, extra_data, extra_pointers);
|
||||
|
||||
quest_manager.StartQuest(mob, client, nullptr, const_cast<SPDat_Spell_Struct*>(&spells[spell_id]));
|
||||
RunningQuest q;
|
||||
|
||||
q.owner = client;
|
||||
q.initiator = client;
|
||||
q.questspell = const_cast<SPDat_Spell_Struct*>(&spells[spell_id]);
|
||||
|
||||
quest_manager.StartQuest(q);
|
||||
|
||||
if(lua_pcall(L, 1, 1, start + 1)) {
|
||||
std::string error = lua_tostring(L, -1);
|
||||
AddError(error);
|
||||
@@ -814,7 +858,13 @@ int LuaParser::_EventEncounter(std::string package_name, QuestEventID evt, std::
|
||||
auto arg_function = EncounterArgumentDispatch[evt];
|
||||
arg_function(this, L, enc, data, extra_data, extra_pointers);
|
||||
|
||||
quest_manager.StartQuest(enc, nullptr, nullptr, nullptr, encounter_name);
|
||||
RunningQuest q;
|
||||
|
||||
q.owner = enc;
|
||||
q.encounter = encounter_name;
|
||||
|
||||
quest_manager.StartQuest(q);
|
||||
|
||||
if(lua_pcall(L, 1, 1, start + 1)) {
|
||||
std::string error = lua_tostring(L, -1);
|
||||
AddError(error);
|
||||
@@ -1757,7 +1807,13 @@ int LuaParser::_EventBot(
|
||||
arg_function(this, L, bot, init, data, extra_data, extra_pointers);
|
||||
auto* c = (init && init->IsClient()) ? init->CastToClient() : nullptr;
|
||||
|
||||
quest_manager.StartQuest(bot, c);
|
||||
RunningQuest q;
|
||||
|
||||
q.owner = bot;
|
||||
q.initiator = c;
|
||||
|
||||
quest_manager.StartQuest(q);
|
||||
|
||||
if(lua_pcall(L, 1, 1, start + 1)) {
|
||||
std::string error = lua_tostring(L, -1);
|
||||
AddError(error);
|
||||
@@ -1936,7 +1992,13 @@ int LuaParser::_EventMerc(
|
||||
arg_function(this, L, merc, init, data, extra_data, extra_pointers);
|
||||
auto* c = (init && init->IsClient()) ? init->CastToClient() : nullptr;
|
||||
|
||||
quest_manager.StartQuest(merc, c);
|
||||
RunningQuest q;
|
||||
|
||||
q.owner = merc;
|
||||
q.initiator = c;
|
||||
|
||||
quest_manager.StartQuest(q);
|
||||
|
||||
if(lua_pcall(L, 1, 1, start + 1)) {
|
||||
std::string error = lua_tostring(L, -1);
|
||||
AddError(error);
|
||||
@@ -2039,3 +2101,190 @@ void LuaParser::LoadMercScript(std::string filename) {
|
||||
void LuaParser::LoadGlobalMercScript(std::string filename) {
|
||||
LoadScript(filename, "global_merc");
|
||||
}
|
||||
|
||||
int LuaParser::EventZone(
|
||||
QuestEventID evt,
|
||||
Zone *zone,
|
||||
std::string data,
|
||||
uint32 extra_data,
|
||||
std::vector<std::any> *extra_pointers
|
||||
) {
|
||||
evt = ConvertLuaEvent(evt);
|
||||
if (evt >= _LargestEventID) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!zone) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ZoneHasQuestSub(evt)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _EventZone("zone", evt, zone, data, extra_data, extra_pointers);
|
||||
}
|
||||
|
||||
int LuaParser::EventGlobalZone(
|
||||
QuestEventID evt,
|
||||
Zone *zone,
|
||||
std::string data,
|
||||
uint32 extra_data,
|
||||
std::vector<std::any> *extra_pointers
|
||||
) {
|
||||
evt = ConvertLuaEvent(evt);
|
||||
if (evt >= _LargestEventID) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!zone) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!GlobalZoneHasQuestSub(evt)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _EventZone("global_zone", evt, zone, data, extra_data, extra_pointers);
|
||||
}
|
||||
|
||||
int LuaParser::_EventZone(
|
||||
std::string package_name,
|
||||
QuestEventID evt,
|
||||
Zone *zone,
|
||||
std::string data,
|
||||
uint32 extra_data,
|
||||
std::vector<std::any> *extra_pointers,
|
||||
luabind::adl::object *l_func
|
||||
) {
|
||||
const char *sub_name = LuaEvents[evt];
|
||||
int start = lua_gettop(L);
|
||||
|
||||
try {
|
||||
int npop = 2;
|
||||
PushErrorHandler(L);
|
||||
if(l_func != nullptr) {
|
||||
l_func->push(L);
|
||||
} else {
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, package_name.c_str());
|
||||
lua_getfield(L, -1, sub_name);
|
||||
npop = 3;
|
||||
}
|
||||
|
||||
lua_createtable(L, 0, 0);
|
||||
//push self
|
||||
Lua_Zone l_zone(zone);
|
||||
luabind::adl::object l_zone_o = luabind::adl::object(L, l_zone);
|
||||
l_zone_o.push(L);
|
||||
lua_setfield(L, -2, "self");
|
||||
|
||||
auto arg_function = ZoneArgumentDispatch[evt];
|
||||
arg_function(this, L, zone, data, extra_data, extra_pointers);
|
||||
|
||||
RunningQuest q;
|
||||
|
||||
q.zone = zone;
|
||||
|
||||
quest_manager.StartQuest(q);
|
||||
|
||||
if(lua_pcall(L, 1, 1, start + 1)) {
|
||||
std::string error = lua_tostring(L, -1);
|
||||
AddError(error);
|
||||
quest_manager.EndQuest();
|
||||
lua_pop(L, npop);
|
||||
return 0;
|
||||
}
|
||||
quest_manager.EndQuest();
|
||||
|
||||
if(lua_isnumber(L, -1)) {
|
||||
int ret = static_cast<int>(lua_tointeger(L, -1));
|
||||
lua_pop(L, npop);
|
||||
return ret;
|
||||
}
|
||||
|
||||
lua_pop(L, npop);
|
||||
} catch(std::exception &ex) {
|
||||
AddError(
|
||||
fmt::format(
|
||||
"Lua Exception | [{}] for Zone [{}] in [{}]: {}",
|
||||
sub_name,
|
||||
zone->GetShortName(),
|
||||
package_name,
|
||||
ex.what()
|
||||
)
|
||||
);
|
||||
|
||||
//Restore our stack to the best of our ability
|
||||
int end = lua_gettop(L);
|
||||
int n = end - start;
|
||||
if(n > 0) {
|
||||
lua_pop(L, n);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaParser::DispatchEventZone(
|
||||
QuestEventID evt,
|
||||
Zone *zone,
|
||||
std::string data,
|
||||
uint32 extra_data,
|
||||
std::vector<std::any> *extra_pointers
|
||||
) {
|
||||
evt = ConvertLuaEvent(evt);
|
||||
if (evt >= _LargestEventID) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string package_name = "zone";
|
||||
|
||||
auto iter = lua_encounter_events_registered.find(package_name);
|
||||
if (iter == lua_encounter_events_registered.end()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
auto riter = iter->second.begin();
|
||||
while (riter != iter->second.end()) {
|
||||
if (riter->event_id == evt) {
|
||||
package_name = fmt::format("encounter_{}", riter->encounter_name);
|
||||
int i = _EventZone(package_name, evt, zone, data, extra_data, extra_pointers, &riter->lua_reference);
|
||||
if (i != 0) {
|
||||
ret = i;
|
||||
}
|
||||
}
|
||||
|
||||
++riter;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool LuaParser::ZoneHasQuestSub(QuestEventID evt) {
|
||||
evt = ConvertLuaEvent(evt);
|
||||
if (evt >= _LargestEventID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *subname = LuaEvents[evt];
|
||||
return HasFunction(subname, "zone");
|
||||
}
|
||||
|
||||
bool LuaParser::GlobalZoneHasQuestSub(QuestEventID evt) {
|
||||
evt = ConvertLuaEvent(evt);
|
||||
if (evt >= _LargestEventID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *subname = LuaEvents[evt];
|
||||
return HasFunction(subname, "global_zone");
|
||||
}
|
||||
|
||||
void LuaParser::LoadZoneScript(std::string filename) {
|
||||
LoadScript(filename, "zone");
|
||||
}
|
||||
|
||||
void LuaParser::LoadGlobalZoneScript(std::string filename) {
|
||||
LoadScript(filename, "global_zone");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user