mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 23:01:30 +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);
|
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()
|
void perl_register_quest()
|
||||||
{
|
{
|
||||||
perl::interpreter perl(PERL_GET_THX);
|
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))&Perl__gmsay);
|
||||||
package.add("gmsay", (void(*)(const char*, int, bool, int))&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("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("has_zone_flag", &Perl__has_zone_flag);
|
||||||
package.add("hasrecipelearned", &Perl__hasrecipelearned);
|
package.add("hasrecipelearned", &Perl__hasrecipelearned);
|
||||||
package.add("hastimer", &Perl__hastimer);
|
package.add("hastimer", &Perl__hastimer);
|
||||||
|
|||||||
@ -5642,6 +5642,31 @@ Lua_Zone lua_get_zone()
|
|||||||
return Lua_Zone(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 { \
|
#define LuaCreateNPCParse(name, c_type, default_value) do { \
|
||||||
cur = table[#name]; \
|
cur = table[#name]; \
|
||||||
if(luabind::type(cur) != LUA_TNIL) { \
|
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_circle", &lua_spawn_circle),
|
||||||
luabind::def("spawn_grid", &lua_spawn_grid),
|
luabind::def("spawn_grid", &lua_spawn_grid),
|
||||||
luabind::def("get_zone", &lua_get_zone),
|
luabind::def("get_zone", &lua_get_zone),
|
||||||
|
luabind::def("handin", &lua_handin),
|
||||||
/*
|
/*
|
||||||
Cross Zone
|
Cross Zone
|
||||||
*/
|
*/
|
||||||
|
|||||||
12
zone/npc.cpp
12
zone/npc.cpp
@ -4351,6 +4351,10 @@ bool NPC::CheckHandin(
|
|||||||
h = m_hand_in;
|
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 = {};
|
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
|
// 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
|
// multi-quest
|
||||||
if (IsMultiQuestEnabled()) {
|
if (IsMultiQuestEnabled()) {
|
||||||
for (auto &h_item: h.items) {
|
for (auto &h_item: m_hand_in.items) {
|
||||||
for (const auto &r_item: r.items) {
|
for (const auto &r_item: r.items) {
|
||||||
if (h_item.item_id == r_item.item_id && h_item.count == r_item.count) {
|
if (h_item.item_id == r_item.item_id && h_item.count == r_item.count) {
|
||||||
h_item.is_multiquest_item = true;
|
h_item.is_multiquest_item = true;
|
||||||
@ -4777,7 +4781,11 @@ NPC::Handin NPC::ReturnHandinItems(Client *c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
c->PushItemOnCursor(*i.item, true);
|
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;
|
returned_handin = true;
|
||||||
return true; // Mark this item for removal
|
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 botquest();
|
||||||
bool createBot(const char *name, const char *lastname, uint8 level, uint16 race, uint8 botclass, uint8 gender);
|
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:
|
private:
|
||||||
std::stack<running_quest> quests_running_;
|
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);
|
item_list.emplace_back(inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto handin_npc = tradingWith->CastToNPC();
|
||||||
|
|
||||||
m_external_handin_money_returned = {};
|
m_external_handin_money_returned = {};
|
||||||
m_external_handin_items_returned = {};
|
m_external_handin_items_returned = {};
|
||||||
bool has_aggro = tradingWith->CheckAggro(this);
|
bool has_aggro = tradingWith->CheckAggro(this);
|
||||||
if (parse->HasQuestSub(tradingWith->GetNPCTypeID(), EVENT_TRADE) && !has_aggro) {
|
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);
|
parse->EventNPC(EVENT_TRADE, tradingWith->CastToNPC(), this, "", 0, &item_list);
|
||||||
LogNpcHandinDetail("EVENT_TRADE triggered for NPC [{}]", tradingWith->GetNPCTypeID());
|
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
|
// 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
|
// 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
|
// 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