mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 16:51:29 +00:00
[Quest API] Implement eq.handin() and quest::handin() (#4718)
* [Quest API] Implement eq.handin() and quest::handin() * Fix MQ using new API style
This commit is contained in:
parent
875df8e64a
commit
425d24c1f4
@ -5973,6 +5973,28 @@ void Perl__SpawnGrid(uint32 npc_id, float x, float y, float z, float heading, fl
|
||||
quest_manager.SpawnGrid(npc_id, glm::vec4(x, y, z, heading), spacing, spawn_count);
|
||||
}
|
||||
|
||||
bool Perl__handin(perl::reference handin_ref)
|
||||
{
|
||||
perl::hash handin = handin_ref;
|
||||
|
||||
std::map<std::string, uint32> handin_map;
|
||||
|
||||
for (auto e: handin) {
|
||||
if (!e.first) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Strings::EqualFold(e.first, "0")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const uint32 count = static_cast<uint32>(handin.at(e.first));
|
||||
handin_map[e.first] = count;
|
||||
}
|
||||
|
||||
return quest_manager.handin(handin_map);
|
||||
}
|
||||
|
||||
void perl_register_quest()
|
||||
{
|
||||
perl::interpreter perl(PERL_GET_THX);
|
||||
@ -6698,6 +6720,7 @@ void perl_register_quest()
|
||||
package.add("gmsay", (void(*)(const char*, int, bool))&Perl__gmsay);
|
||||
package.add("gmsay", (void(*)(const char*, int, bool, int))&Perl__gmsay);
|
||||
package.add("gmsay", (void(*)(const char*, int, bool, int, int))&Perl__gmsay);
|
||||
package.add("handin", &Perl__handin);
|
||||
package.add("has_zone_flag", &Perl__has_zone_flag);
|
||||
package.add("hasrecipelearned", &Perl__hasrecipelearned);
|
||||
package.add("hastimer", &Perl__hastimer);
|
||||
|
||||
@ -5642,6 +5642,31 @@ Lua_Zone lua_get_zone()
|
||||
return Lua_Zone(zone);
|
||||
}
|
||||
|
||||
bool lua_handin(luabind::adl::object handin_table)
|
||||
{
|
||||
std::map<std::string, uint32> handin_map;
|
||||
|
||||
for (luabind::iterator i(handin_table), end; i != end; i++) {
|
||||
std::string key;
|
||||
if (luabind::type(i.key()) == LUA_TSTRING) {
|
||||
key = luabind::object_cast<std::string>(i.key());
|
||||
}
|
||||
else if (luabind::type(i.key()) == LUA_TNUMBER) {
|
||||
key = fmt::format("{}", luabind::object_cast<int>(i.key()));
|
||||
}
|
||||
else {
|
||||
LogError("Handin key type [{}] not supported", luabind::type(i.key()));
|
||||
}
|
||||
|
||||
if (!key.empty()) {
|
||||
handin_map[key] = luabind::object_cast<uint32>(handin_table[i.key()]);
|
||||
LogNpcHandinDetail("Handin key [{}] value [{}]", key, handin_map[key]);
|
||||
}
|
||||
}
|
||||
|
||||
return quest_manager.handin(handin_map);
|
||||
}
|
||||
|
||||
#define LuaCreateNPCParse(name, c_type, default_value) do { \
|
||||
cur = table[#name]; \
|
||||
if(luabind::type(cur) != LUA_TNIL) { \
|
||||
@ -6450,6 +6475,7 @@ luabind::scope lua_register_general() {
|
||||
luabind::def("spawn_circle", &lua_spawn_circle),
|
||||
luabind::def("spawn_grid", &lua_spawn_grid),
|
||||
luabind::def("get_zone", &lua_get_zone),
|
||||
luabind::def("handin", &lua_handin),
|
||||
/*
|
||||
Cross Zone
|
||||
*/
|
||||
|
||||
12
zone/npc.cpp
12
zone/npc.cpp
@ -4351,6 +4351,10 @@ bool NPC::CheckHandin(
|
||||
h = m_hand_in;
|
||||
}
|
||||
|
||||
if (IsMultiQuestEnabled()) {
|
||||
LogNpcHandin("{} Multi-Quest hand-in enabled", log_handin_prefix);
|
||||
}
|
||||
|
||||
std::vector<std::pair<const std::map<std::string, uint32>&, Handin&>> datasets = {};
|
||||
|
||||
// if we've already started the hand-in process, we don't want to re-process the hand-in data
|
||||
@ -4432,7 +4436,7 @@ bool NPC::CheckHandin(
|
||||
|
||||
// multi-quest
|
||||
if (IsMultiQuestEnabled()) {
|
||||
for (auto &h_item: h.items) {
|
||||
for (auto &h_item: m_hand_in.items) {
|
||||
for (const auto &r_item: r.items) {
|
||||
if (h_item.item_id == r_item.item_id && h_item.count == r_item.count) {
|
||||
h_item.is_multiquest_item = true;
|
||||
@ -4777,7 +4781,11 @@ NPC::Handin NPC::ReturnHandinItems(Client *c)
|
||||
}
|
||||
|
||||
c->PushItemOnCursor(*i.item, true);
|
||||
LogNpcHandin("Hand-in failed, returning item [{}]", i.item->GetItem()->Name);
|
||||
LogNpcHandin(
|
||||
"Hand-in failed, returning item [{}] i.is_multiquest_item [{}]",
|
||||
i.item->GetItem()->Name,
|
||||
i.is_multiquest_item
|
||||
);
|
||||
|
||||
returned_handin = true;
|
||||
return true; // Mark this item for removal
|
||||
|
||||
@ -4606,3 +4606,18 @@ void QuestManager::SpawnGrid(uint32 npc_id, glm::vec4 position, float spacing, u
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool QuestManager::handin(std::map<std::string, uint32> required) {
|
||||
QuestManagerCurrentQuestVars();
|
||||
if (!owner || !initiator) {
|
||||
LogQuests("QuestManager::handin called with nullptr owner. Probably syntax error in quest file");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (owner && !owner->IsNPC()) {
|
||||
LogQuests("QuestManager::handin called with non-NPC owner. Probably syntax error in quest file");
|
||||
return false;
|
||||
}
|
||||
|
||||
return owner->CastToNPC()->CheckHandin(initiator, {}, required, {});
|
||||
}
|
||||
|
||||
@ -376,6 +376,7 @@ public:
|
||||
bool botquest();
|
||||
bool createBot(const char *name, const char *lastname, uint8 level, uint16 race, uint8 botclass, uint8 gender);
|
||||
|
||||
bool handin(std::map<std::string, uint32> required);
|
||||
|
||||
private:
|
||||
std::stack<running_quest> quests_running_;
|
||||
|
||||
@ -618,16 +618,36 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st
|
||||
item_list.emplace_back(inst);
|
||||
}
|
||||
|
||||
auto handin_npc = tradingWith->CastToNPC();
|
||||
|
||||
m_external_handin_money_returned = {};
|
||||
m_external_handin_items_returned = {};
|
||||
bool has_aggro = tradingWith->CheckAggro(this);
|
||||
if (parse->HasQuestSub(tradingWith->GetNPCTypeID(), EVENT_TRADE) && !has_aggro) {
|
||||
// This CheckHandin call enables eq.handin and quest::handin to recognize the hand-in context.
|
||||
// It initializes the first hand-in bucket, which is then reused for the EVENT_TRADE subroutine.
|
||||
std::map<std::string, uint32> handin = {
|
||||
{"copper", trade->cp},
|
||||
{"silver", trade->sp},
|
||||
{"gold", trade->gp},
|
||||
{"platinum", trade->pp}
|
||||
};
|
||||
|
||||
for (EQ::ItemInstance *inst: items) {
|
||||
if (!inst || !inst->GetItem()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string item_id = fmt::format("{}", inst->GetItem()->ID);
|
||||
handin[item_id] += inst->GetCharges();
|
||||
}
|
||||
|
||||
handin_npc->CheckHandin(this, handin, {}, items);
|
||||
|
||||
parse->EventNPC(EVENT_TRADE, tradingWith->CastToNPC(), this, "", 0, &item_list);
|
||||
LogNpcHandinDetail("EVENT_TRADE triggered for NPC [{}]", tradingWith->GetNPCTypeID());
|
||||
}
|
||||
|
||||
auto handin_npc = tradingWith->CastToNPC();
|
||||
|
||||
// this is a catch-all return for items that weren't consumed by the EVENT_TRADE subroutine
|
||||
// it's possible we have a quest NPC that doesn't have an EVENT_TRADE subroutine
|
||||
// we can't double fire the ReturnHandinItems() event, so we need to check if it's already been processed from EVENT_TRADE
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user