[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];
strcpy(q_corpse_name, corpse_name);
snprintf(buf, 87, "%d %d %s", inst->GetItem()->ID, inst->GetCharges(),
EntityList::RemoveNumbers(q_corpse_name));
buf[87] = '\0';
std::string buf = fmt::format("{} {} {} {}", inst->GetItem()->ID, inst->GetCharges(), EntityList::RemoveNumbers(q_corpse_name), GetID());
std::vector<EQ::Any> args;
args.push_back(inst);
args.push_back(this);
if (parse->EventPlayer(EVENT_LOOT, client, buf, 0, &args) != 0) {
lootitem->auto_loot = -1;
client->MessageString(Chat::Red, LOOT_NOT_ALLOWED, inst->GetItem()->Name);
client->QueuePacket(app);
delete inst;
return;
bool prevent_loot = false;
if (RuleB(Zone, UseZoneController)) {
auto controller = entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID);
if (controller){
if (parse->EventNPC(EVENT_LOOT_ZONE, controller, client, buf.c_str(), 0, &args) != 0) {
prevent_loot = true;
}
}
}
if (parse->EventPlayer(EVENT_LOOT, client, buf.c_str(), 0, &args) != 0) {
prevent_loot = true;
}
if (!IsPlayerCorpse())
@ -1306,17 +1309,24 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app)
auto dz = zone->GetDynamicZone();
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
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?
parse->EventItem(EVENT_LOOT, client, inst, this, buf, 0);
// do we want this to have a fail option too? Sure?
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
client->QueuePacket(app);

View File

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

View File

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

View File

@ -4040,7 +4040,8 @@ luabind::scope lua_register_events() {
luabind::value("warp", static_cast<int>(EVENT_WARP)),
luabind::value("test_buff", static_cast<int>(EVENT_TEST_BUFF)),
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_combine",
"event_consider",
"event_consider_corpse"
"event_consider_corpse",
"event_loot_zone"
};
extern Zone *zone;
@ -185,6 +186,7 @@ LuaParser::LuaParser() {
NPCArgumentDispatch[EVENT_FEIGN_DEATH] = handle_npc_single_client;
NPCArgumentDispatch[EVENT_ENTER_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_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) {
}
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
void handle_player_say(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
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);
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);
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
void handle_player_say(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,