[Quest API] Add EVENT_LOOT_ZONE to zone_controller (#1608)

* Add EVENT_LOOT_ZONE to zone_controller

* Fix porting event_loot_zone to lua API

* Remove extra spacing and remove forced message to allow for scripted responses.

* Allow all script parsing to fire before sending a failed lootitem, add corpse_id

* Only search for zone_controller once
This commit is contained in:
Natedog2012 2021-10-16 23:19:19 -05:00 committed by GitHub
parent 11c335a015
commit 7823ff5336
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 57 additions and 20 deletions

View File

@ -1283,21 +1283,24 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app)
} }
} }
char buf[88];
char q_corpse_name[64]; char q_corpse_name[64];
strcpy(q_corpse_name, corpse_name); strcpy(q_corpse_name, corpse_name);
snprintf(buf, 87, "%d %d %s", inst->GetItem()->ID, inst->GetCharges(), std::string buf = fmt::format("{} {} {} {}", inst->GetItem()->ID, inst->GetCharges(), EntityList::RemoveNumbers(q_corpse_name), GetID());
EntityList::RemoveNumbers(q_corpse_name));
buf[87] = '\0';
std::vector<EQ::Any> args; std::vector<EQ::Any> args;
args.push_back(inst); args.push_back(inst);
args.push_back(this); args.push_back(this);
if (parse->EventPlayer(EVENT_LOOT, client, buf, 0, &args) != 0) { bool prevent_loot = false;
lootitem->auto_loot = -1; if (RuleB(Zone, UseZoneController)) {
client->MessageString(Chat::Red, LOOT_NOT_ALLOWED, inst->GetItem()->Name); auto controller = entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID);
client->QueuePacket(app); if (controller){
delete inst; if (parse->EventNPC(EVENT_LOOT_ZONE, controller, client, buf.c_str(), 0, &args) != 0) {
return; prevent_loot = true;
}
}
}
if (parse->EventPlayer(EVENT_LOOT, client, buf.c_str(), 0, &args) != 0) {
prevent_loot = true;
} }
if (!IsPlayerCorpse()) if (!IsPlayerCorpse())
@ -1306,17 +1309,24 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app)
auto dz = zone->GetDynamicZone(); auto dz = zone->GetDynamicZone();
if (dz && !dz->CanClientLootCorpse(client, GetNPCTypeID(), GetID())) if (dz && !dz->CanClientLootCorpse(client, GetNPCTypeID(), GetID()))
{ {
prevent_loot = true;
// note on live this message is only sent once on the first loot attempt of an open corpse // note on live this message is only sent once on the first loot attempt of an open corpse
client->MessageString(Chat::Loot, LOOT_NOT_ALLOWED, inst->GetItem()->Name); client->MessageString(Chat::Loot, LOOT_NOT_ALLOWED, inst->GetItem()->Name);
lootitem->auto_loot = -1; // generates client eqstr 1370 "You may not loot that item from this corpse."
client->QueuePacket(app);
delete inst;
return;
} }
} }
// do we want this to have a fail option too? // do we want this to have a fail option too? Sure?
parse->EventItem(EVENT_LOOT, client, inst, this, buf, 0); if (parse->EventItem(EVENT_LOOT, client, inst, this, buf.c_str(), 0) != 0) {
prevent_loot = true;
}
if (prevent_loot) {
lootitem->auto_loot = -1;
client->QueuePacket(app);
safe_delete(inst);
return;
}
// safe to ACK now // safe to ACK now
client->QueuePacket(app); client->QueuePacket(app);

View File

@ -124,7 +124,8 @@ const char *QuestEventSubroutines[_LargestEventID] = {
"EVENT_TEST_BUFF", "EVENT_TEST_BUFF",
"EVENT_COMBINE", "EVENT_COMBINE",
"EVENT_CONSIDER", "EVENT_CONSIDER",
"EVENT_CONSIDER_CORPSE" "EVENT_CONSIDER_CORPSE",
"EVENT_LOOT_ZONE"
}; };
PerlembParser::PerlembParser() : perl(nullptr) PerlembParser::PerlembParser() : perl(nullptr)
@ -1411,12 +1412,14 @@ void PerlembParser::ExportEventVariables(
ExportVar(package_name.c_str(), "version", zone->GetInstanceVersion()); ExportVar(package_name.c_str(), "version", zone->GetInstanceVersion());
break; break;
} }
case EVENT_LOOT_ZONE:
case EVENT_LOOT: { case EVENT_LOOT: {
Seperator sep(data); Seperator sep(data);
ExportVar(package_name.c_str(), "looted_id", sep.arg[0]); ExportVar(package_name.c_str(), "looted_id", sep.arg[0]);
ExportVar(package_name.c_str(), "looted_charges", sep.arg[1]); ExportVar(package_name.c_str(), "looted_charges", sep.arg[1]);
ExportVar(package_name.c_str(), "corpse", sep.arg[2]); ExportVar(package_name.c_str(), "corpse", sep.arg[2]);
ExportVar(package_name.c_str(), "corpse_id", sep.arg[3]);
break; break;
} }

View File

@ -93,6 +93,7 @@ typedef enum {
EVENT_COMBINE, EVENT_COMBINE,
EVENT_CONSIDER, EVENT_CONSIDER,
EVENT_CONSIDER_CORPSE, EVENT_CONSIDER_CORPSE,
EVENT_LOOT_ZONE,
_LargestEventID _LargestEventID
} QuestEventID; } QuestEventID;

View File

@ -4040,7 +4040,8 @@ luabind::scope lua_register_events() {
luabind::value("warp", static_cast<int>(EVENT_WARP)), luabind::value("warp", static_cast<int>(EVENT_WARP)),
luabind::value("test_buff", static_cast<int>(EVENT_TEST_BUFF)), luabind::value("test_buff", static_cast<int>(EVENT_TEST_BUFF)),
luabind::value("consider", static_cast<int>(EVENT_CONSIDER)), luabind::value("consider", static_cast<int>(EVENT_CONSIDER)),
luabind::value("consider_corpse", static_cast<int>(EVENT_CONSIDER_CORPSE)) luabind::value("consider_corpse", static_cast<int>(EVENT_CONSIDER_CORPSE)),
luabind::value("loot_zone", static_cast<int>(EVENT_LOOT_ZONE))
]; ];
} }

View File

@ -135,7 +135,8 @@ const char *LuaEvents[_LargestEventID] = {
"event_test_buff", "event_test_buff",
"event_combine", "event_combine",
"event_consider", "event_consider",
"event_consider_corpse" "event_consider_corpse",
"event_loot_zone"
}; };
extern Zone *zone; extern Zone *zone;
@ -185,6 +186,7 @@ LuaParser::LuaParser() {
NPCArgumentDispatch[EVENT_FEIGN_DEATH] = handle_npc_single_client; NPCArgumentDispatch[EVENT_FEIGN_DEATH] = handle_npc_single_client;
NPCArgumentDispatch[EVENT_ENTER_AREA] = handle_npc_area; NPCArgumentDispatch[EVENT_ENTER_AREA] = handle_npc_area;
NPCArgumentDispatch[EVENT_LEAVE_AREA] = handle_npc_area; NPCArgumentDispatch[EVENT_LEAVE_AREA] = handle_npc_area;
NPCArgumentDispatch[EVENT_LOOT_ZONE] = handle_npc_loot_zone;
PlayerArgumentDispatch[EVENT_SAY] = handle_player_say; PlayerArgumentDispatch[EVENT_SAY] = handle_player_say;
PlayerArgumentDispatch[EVENT_ENVIRONMENTAL_DAMAGE] = handle_player_environmental_damage; PlayerArgumentDispatch[EVENT_ENVIRONMENTAL_DAMAGE] = handle_player_environmental_damage;

View File

@ -237,6 +237,24 @@ void handle_npc_null(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, s
std::vector<EQ::Any> *extra_pointers) { std::vector<EQ::Any> *extra_pointers) {
} }
void handle_npc_loot_zone(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<EQ::Any> *extra_pointers) {
Lua_Client l_client(reinterpret_cast<Client*>(init));
luabind::adl::object l_client_o = luabind::adl::object(L, l_client);
l_client_o.push(L);
lua_setfield(L, -2, "other");
Lua_ItemInst l_item(EQ::any_cast<EQ::ItemInstance*>(extra_pointers->at(0)));
luabind::adl::object l_item_o = luabind::adl::object(L, l_item);
l_item_o.push(L);
lua_setfield(L, -2, "item");
Lua_Corpse l_corpse(EQ::any_cast<Corpse*>(extra_pointers->at(1)));
luabind::adl::object l_corpse_o = luabind::adl::object(L, l_corpse);
l_corpse_o.push(L);
lua_setfield(L, -2, "corpse");
}
//Player //Player
void handle_player_say(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, void handle_player_say(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<EQ::Any> *extra_pointers) { std::vector<EQ::Any> *extra_pointers) {

View File

@ -41,6 +41,8 @@ void handle_npc_area(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, s
std::vector<EQ::Any> *extra_pointers); std::vector<EQ::Any> *extra_pointers);
void handle_npc_null(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, void handle_npc_null(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<EQ::Any> *extra_pointers); std::vector<EQ::Any> *extra_pointers);
void handle_npc_loot_zone(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<EQ::Any> *extra_pointers);
//Player //Player
void handle_player_say(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, void handle_player_say(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,