From efab0c4b6bfce37c8563cf4fd57b73fc5b20c371 Mon Sep 17 00:00:00 2001 From: Kinglykrab <89047260+Kinglykrab@users.noreply.github.com> Date: Wed, 20 Oct 2021 15:11:14 -0400 Subject: [PATCH] [Quest API] Add remove LDoN Win/Loss to Perl and Lua. (#1611) * [Quest API] Add remove LDoN Win/Loss to Perl and Lua. - Add $client->RemoveLDoNLoss(theme_id) to Perl. - Add $client->RemoveLDoNWin(theme_id) to Perl. - Add quest::removeldonloss(theme_id) to Perl. - Add quest::removeldonwin(theme_id) to Perl. - Add quest::crosszoneremoveldonlossbycharid(character_id, theme_id) to Perl. - Add quest::crosszoneremoveldonlossbygroupid(group_id, theme_id) to Perl. - Add quest::crosszoneremoveldonlossbyraidid(raid_id, theme_id) to Perl. - Add quest::crosszoneremoveldonlossbyguildid(guild_id, theme_id) to Perl. - Add quest::crosszoneremoveldonlossbyexpeditionid(expedition_id, theme_id) to Perl. - Add quest::crosszoneremoveldonlossbyclientname(client_name, theme_id) to Perl. - Add quest::crosszoneremoveldonwinbycharid(character_id, theme_id) to Perl. - Add quest::crosszoneremoveldonwinbygroupid(group_id, theme_id) to Perl. - Add quest::crosszoneremoveldonwinbyraidid(raid_id, theme_id) to Perl. - Add quest::crosszoneremoveldonwinbyguildid(guild_id, theme_id) to Perl. - Add quest::crosszoneremoveldonwinbyexpeditionid(expedition_id, theme_id) to Perl. - Add quest::crosszoneremoveldonwinbyclientname(client_name, theme_id) to Perl. - Add quest::worldwideaddldonloss(theme_id, min_status, max_status) to Perl. - Add quest::worldwideaddldonwin(theme_id, min_status, max_status) to Perl. - Add client:RemoveLDoNLoss(theme_id) to Lua. - Add client:RemoveLDoNWin(theme_id) to Lua. - Add eq.remove_ldon_loss(theme_id) to Lua. - Add eq.remove_ldon_win(theme_id) to Lua. - Add eq.cross_zone_remove_ldon_loss_by_char_id(character_id, theme_id) to Lua. - Add eq.cross_zone_remove_ldon_loss_by_group_id(group_id, theme_id) to Lua. - Add eq.cross_zone_remove_ldon_loss_by_raid_id(raid_id, theme_id) to Lua. - Add eq.cross_zone_remove_ldon_loss_by_guild_id(guild_id, theme_id) to Lua. - Add eq.cross_zone_remove_ldon_loss_by_expedition_id(expedition_id, theme_id) to Lua. - Add eq.cross_zone_remove_ldon_loss_by_client_name(client_name, theme_id) to Lua. - Add eq.cross_zone_remove_ldon_win_by_char_id(character_id, theme_id) to Lua. - Add eq.cross_zone_remove_ldon_win_by_group_id(group_id, theme_id) to Lua. - Add eq.cross_zone_remove_ldon_win_by_raid_id(raid_id, theme_id) to Lua. - Add eq.cross_zone_remove_ldon_win_by_guild_id(guild_id, theme_id) to Lua. - Add eq.cross_zone_remove_ldon_win_by_expedition_id(expedition_id, theme_id) to Lua. - Add eq.cross_zone_remove_ldon_win_by_client_name(client_name, theme_id) to Lua. - Add eq.world_wide_add_ldon_loss(theme_id, min_status, max_status) to Lua. - Add eq.world_wide_add_ldon_win(theme_id, min_status, max_status) to Lua. Adds enum for LDoN Themes and Theme Bitmasks so we're not using magic numbers. Adds item links to item messages and augment messages on rejection/restriction/Lore. * Update client_packet.cpp * Update client_packet.cpp * Update servertalk.h Alphabetical. --- common/database.cpp | 56 +- common/database.h | 2 +- common/eq_constants.h | 18 + .../base/base_adventure_template_repository.h | 2 +- .../repositories/base/base_items_repository.h | 2 +- common/servertalk.h | 16 +- zone/client.cpp | 151 ++-- zone/client.h | 3 +- zone/client_packet.cpp | 242 +++---- zone/embparser_api.cpp | 416 ++++++++--- zone/inventory.cpp | 684 ++++++++++++------ zone/lua_client.cpp | 18 +- zone/lua_client.h | 2 + zone/lua_general.cpp | 184 ++++- zone/perl_client.cpp | 34 +- zone/questmgr.cpp | 24 +- zone/questmgr.h | 2 + zone/worldserver.cpp | 116 ++- 18 files changed, 1337 insertions(+), 635 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index e694e7801..9a0ea375d 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2042,62 +2042,64 @@ void Database::ClearRaidLeader(uint32 gid, uint32 rid) QueryDatabase(query); } -void Database::UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win) +void Database::UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win, bool remove) { - std::string field; - - switch(theme) - { - case 1: - { + switch(theme) { + case LDoNThemes::GUK: { field = "guk_"; break; } - case 2: - { + case LDoNThemes::MIR: { field = "mir_"; break; } - case 3: - { + case LDoNThemes::MMC: { field = "mmc_"; break; } - case 4: - { + case LDoNThemes::RUJ: { field = "ruj_"; break; } - case 5: - { + case LDoNThemes::TAK: { field = "tak_"; break; } - default: - { + default: { return; } } - if (win) - field += "wins"; - else - field += "losses"; + field += win ? "wins" : "losses"; + std::string field_operation = remove ? "-" : "+"; - std::string query = StringFormat("UPDATE `adventure_stats` SET %s=%s+1 WHERE player_id=%u",field.c_str(), field.c_str(), char_id); + std::string query = fmt::format( + "UPDATE `adventure_stats` SET {} = {} {} 1 WHERE player_id = {}", + field, + field, + field_operation, + char_id + ); auto results = QueryDatabase(query); - if (results.RowsAffected() != 0) + if (results.RowsAffected() != 0) { return; + } - query = StringFormat("INSERT INTO `adventure_stats` SET %s=1, player_id=%u", field.c_str(), char_id); - QueryDatabase(query); + if (!remove) { + query = fmt::format( + "INSERT INTO `adventure_stats` SET {} = 1, player_id = {}", + field, + char_id + ); + QueryDatabase(query); + } } bool Database::GetAdventureStats(uint32 char_id, AdventureStats_Struct *as) { - std::string query = StringFormat( + std::string query = fmt::format( "SELECT " "`guk_wins`, " "`mir_wins`, " @@ -2112,7 +2114,7 @@ bool Database::GetAdventureStats(uint32 char_id, AdventureStats_Struct *as) "FROM " "`adventure_stats` " "WHERE " - "player_id = %u ", + "player_id = {}", char_id ); auto results = QueryDatabase(query); diff --git a/common/database.h b/common/database.h index 16506dfae..64856ef80 100644 --- a/common/database.h +++ b/common/database.h @@ -176,7 +176,7 @@ public: /* Adventure related. */ - void UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win); + void UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win = false, bool remove = false); bool GetAdventureStats(uint32 char_id, AdventureStats_Struct *as); /* Account Related */ diff --git a/common/eq_constants.h b/common/eq_constants.h index fb6f0c557..6321b2d9b 100644 --- a/common/eq_constants.h +++ b/common/eq_constants.h @@ -974,4 +974,22 @@ enum class DynamicZoneMemberStatus : uint8_t LinkDead }; +enum LDoNThemes { + Unused = 0, + GUK, + MIR, + MMC, + RUJ, + TAK +}; + +enum LDoNThemeBits { + UnusedBit = 0, + GUKBit = 1, + MIRBit = 2, + MMCBit = 4, + RUJBit = 8, + TAKBit = 16 +}; + #endif /*COMMON_EQ_CONSTANTS_H*/ diff --git a/common/repositories/base/base_adventure_template_repository.h b/common/repositories/base/base_adventure_template_repository.h index 4509268ad..b54e4fa89 100644 --- a/common/repositories/base/base_adventure_template_repository.h +++ b/common/repositories/base/base_adventure_template_repository.h @@ -148,7 +148,7 @@ public: entry.zone_in_time = 1800; entry.win_points = 0; entry.lose_points = 0; - entry.theme = 1; + entry.theme = LDoNThemes::GUK; entry.zone_in_zone_id = 0; entry.zone_in_x = 0; entry.zone_in_y = 0; diff --git a/common/repositories/base/base_items_repository.h b/common/repositories/base/base_items_repository.h index 06a7797b8..8bbbd979e 100644 --- a/common/repositories/base/base_items_repository.h +++ b/common/repositories/base/base_items_repository.h @@ -717,7 +717,7 @@ public: entry.itemclass = 0; entry.itemtype = 0; entry.ldonprice = 0; - entry.ldontheme = 0; + entry.ldontheme = LDoNThemes::Unused; entry.ldonsold = 0; entry.light = 0; entry.lore = ""; diff --git a/common/servertalk.h b/common/servertalk.h index fd91f591e..86d4b08a6 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -271,9 +271,11 @@ enum { }; enum { - CZLDoNUpdateSubtype_Loss, - CZLDoNUpdateSubtype_Points, - CZLDoNUpdateSubtype_Win + CZLDoNUpdateSubtype_AddLoss, + CZLDoNUpdateSubtype_AddPoints, + CZLDoNUpdateSubtype_AddWin, + CZLDoNUpdateSubtype_RemoveLoss, + CZLDoNUpdateSubtype_RemoveWin, }; enum { @@ -297,9 +299,11 @@ enum { }; enum { - WWLDoNUpdateType_Loss, - WWLDoNUpdateType_Points, - WWLDoNUpdateType_Win + WWLDoNUpdateType_AddLoss, + WWLDoNUpdateType_AddPoints, + WWLDoNUpdateType_AddWin, + WWLDoNUpdateType_RemoveLoss, + WWLDoNUpdateType_RemoveWin }; enum { diff --git a/zone/client.cpp b/zone/client.cpp index 215ba2480..aceb82b20 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -318,7 +318,7 @@ Client::Client(EQStreamInterface* ieqs) adventure_stats_timer = nullptr; adventure_leaderboard_timer = nullptr; adv_data = nullptr; - adv_requested_theme = 0; + adv_requested_theme = LDoNThemes::Unused; adv_requested_id = 0; adv_requested_member_count = 0; @@ -1375,9 +1375,8 @@ bool Client::UpdateLDoNPoints(uint32 theme_id, int points) { return false; } - switch (theme_id) - { - case 0: { // No theme, so distribute evenly across all + switch (theme_id) { + case LDoNThemes::Unused: { // No theme, so distribute evenly across all int split_points = (points / 5); int guk_points = (split_points + (points % 5)); int mir_points = split_points; @@ -1421,47 +1420,52 @@ bool Client::UpdateLDoNPoints(uint32 theme_id, int points) { m_pp.ldon_points_ruj += ruj_points; m_pp.ldon_points_tak += tak_points; points -= split_points; - if (split_points != 0) // if anything left, recursively loop thru again + if (split_points != 0) { // if anything left, recursively loop thru again UpdateLDoNPoints(0, split_points); - + } break; } - case 1: { + case LDoNThemes::GUK: { if(points < 0) { - if(m_pp.ldon_points_guk < (0 - points)) + if(m_pp.ldon_points_guk < (0 - points)) { return false; + } } m_pp.ldon_points_guk += points; break; } - case 2: { + case LDoNThemes::MIR: { if(points < 0) { - if(m_pp.ldon_points_mir < (0 - points)) + if(m_pp.ldon_points_mir < (0 - points)) { return false; + } } m_pp.ldon_points_mir += points; break; } - case 3: { + case LDoNThemes::MMC: { if(points < 0) { - if(m_pp.ldon_points_mmc < (0 - points)) + if(m_pp.ldon_points_mmc < (0 - points)) { return false; + } } m_pp.ldon_points_mmc += points; break; } - case 4: { + case LDoNThemes::RUJ: { if(points < 0) { - if(m_pp.ldon_points_ruj < (0 - points)) + if(m_pp.ldon_points_ruj < (0 - points)) { return false; + } } m_pp.ldon_points_ruj += points; break; } - case 5: { + case LDoNThemes::TAK: { if(points < 0) { - if(m_pp.ldon_points_tak < (0 - points)) + if(m_pp.ldon_points_tak < (0 - points)) { return false; + } } m_pp.ldon_points_tak += points; break; @@ -5490,15 +5494,15 @@ uint32 Client::GetLDoNPointsTheme(uint32 t) { switch(t) { - case 1: + case LDoNThemes::GUK: return m_pp.ldon_points_guk; - case 2: + case LDoNThemes::MIR: return m_pp.ldon_points_mir; - case 3: + case LDoNThemes::MMC: return m_pp.ldon_points_mmc; - case 4: + case LDoNThemes::RUJ: return m_pp.ldon_points_ruj; - case 5: + case LDoNThemes::TAK: return m_pp.ldon_points_tak; default: return 0; @@ -5509,15 +5513,15 @@ uint32 Client::GetLDoNWinsTheme(uint32 t) { switch(t) { - case 1: + case LDoNThemes::GUK: return m_pp.ldon_wins_guk; - case 2: + case LDoNThemes::MIR: return m_pp.ldon_wins_mir; - case 3: + case LDoNThemes::MMC: return m_pp.ldon_wins_mmc; - case 4: + case LDoNThemes::RUJ: return m_pp.ldon_wins_ruj; - case 5: + case LDoNThemes::TAK: return m_pp.ldon_wins_tak; default: return 0; @@ -5528,77 +5532,62 @@ uint32 Client::GetLDoNLossesTheme(uint32 t) { switch(t) { - case 1: + case LDoNThemes::GUK: return m_pp.ldon_losses_guk; - case 2: + case LDoNThemes::MIR: return m_pp.ldon_losses_mir; - case 3: + case LDoNThemes::MMC: return m_pp.ldon_losses_mmc; - case 4: + case LDoNThemes::RUJ: return m_pp.ldon_losses_ruj; - case 5: + case LDoNThemes::TAK: return m_pp.ldon_losses_tak; default: return 0; } } -void Client::AddLDoNLoss(uint32 theme_id) -{ - switch (theme_id) - { - case 1: - m_pp.ldon_losses_guk += 1; - database.UpdateAdventureStatsEntry(CharacterID(), theme_id, false); +void Client::UpdateLDoNWinLoss(uint32 theme_id, bool win, bool remove) { + switch (theme_id) { + case LDoNThemes::GUK: + if (win) { + m_pp.ldon_wins_guk += (remove ? -1 : 1); + } else { + m_pp.ldon_losses_guk += (remove ? -1 : 1); + } break; - case 2: - m_pp.ldon_losses_mir += 1; - database.UpdateAdventureStatsEntry(CharacterID(), theme_id, false); + case LDoNThemes::MIR: + if (win) { + m_pp.ldon_wins_mir += (remove ? -1 : 1); + } else { + m_pp.ldon_losses_mir += (remove ? -1 : 1); + } break; - case 3: - m_pp.ldon_losses_mmc += 1; - database.UpdateAdventureStatsEntry(CharacterID(), theme_id, false); + case LDoNThemes::MMC: + if (win) { + m_pp.ldon_wins_mmc += (remove ? -1 : 1); + } else { + m_pp.ldon_losses_mmc += (remove ? -1 : 1); + } break; - case 4: - m_pp.ldon_losses_ruj += 1; - database.UpdateAdventureStatsEntry(CharacterID(), theme_id, false); + case LDoNThemes::RUJ: + if (win) { + m_pp.ldon_wins_ruj += (remove ? -1 : 1); + } else { + m_pp.ldon_losses_ruj += (remove ? -1 : 1); + } break; - case 5: - m_pp.ldon_losses_tak += 1; - database.UpdateAdventureStatsEntry(CharacterID(), theme_id, false); + case LDoNThemes::TAK: + if (win) { + m_pp.ldon_wins_tak += (remove ? -1 : 1); + } else { + m_pp.ldon_losses_tak += (remove ? -1 : 1); + } break; default: return; - } -} - -void Client::AddLDoNWin(uint32 theme_id) -{ - switch (theme_id) - { - case 1: - m_pp.ldon_wins_guk += 1; - database.UpdateAdventureStatsEntry(CharacterID(), theme_id, true); - break; - case 2: - m_pp.ldon_wins_mir += 1; - database.UpdateAdventureStatsEntry(CharacterID(), theme_id, true); - break; - case 3: - m_pp.ldon_wins_mmc += 1; - database.UpdateAdventureStatsEntry(CharacterID(), theme_id, true); - break; - case 4: - m_pp.ldon_wins_ruj += 1; - database.UpdateAdventureStatsEntry(CharacterID(), theme_id, true); - break; - case 5: - m_pp.ldon_wins_tak += 1; - database.UpdateAdventureStatsEntry(CharacterID(), theme_id, true); - break; - default: - return; - } + } + database.UpdateAdventureStatsEntry(CharacterID(), theme_id, win, remove); } @@ -5981,7 +5970,7 @@ void Client::NewAdventure(int id, int theme, const char *text, int member_count, void Client::ClearPendingAdventureData() { adv_requested_id = 0; - adv_requested_theme = 0; + adv_requested_theme = LDoNThemes::Unused; safe_delete_array(adv_requested_data); adv_requested_member_count = 0; } diff --git a/zone/client.h b/zone/client.h index da77e2b25..550be9620 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1323,8 +1323,7 @@ public: uint32 GetLDoNWinsTheme(uint32 t); uint32 GetLDoNLossesTheme(uint32 t); uint32 GetLDoNPointsTheme(uint32 t); - void AddLDoNWin(uint32 theme_id); - void AddLDoNLoss(uint32 theme_id); + void UpdateLDoNWinLoss(uint32 theme_id, bool win = false, bool remove = false); void CheckLDoNHail(Mob *target); void CheckEmoteHail(Mob *target, const char* message); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 73802cac4..f1c47a4d1 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1979,136 +1979,136 @@ void Client::Handle_OP_AdventureMerchantPurchase(const EQApplicationPacket *app) const EQ::ItemData* item = nullptr; bool found = false; - std::list merlist = zone->merchanttable[merchantid]; - std::list::const_iterator itr; - - for (itr = merlist.begin(); itr != merlist.end(); ++itr) { - MerchantList ml = *itr; - if (GetLevel() < ml.level_required) { + std::list merchantlists = zone->merchanttable[merchantid]; + for (auto merchantlist : merchantlists) { + if (GetLevel() < merchantlist.level_required) { continue; } - int32 fac = tmp->GetPrimaryFaction(); - if (fac != 0 && GetModCharacterFactionLevel(fac) < ml.faction_required) { + int faction_id = tmp->GetPrimaryFaction(); + if (faction_id != 0 && GetModCharacterFactionLevel(faction_id) < merchantlist.faction_required) { continue; } - item = database.GetItem(ml.item); - if (!item) + item = database.GetItem(merchantlist.item); + if (!item) { continue; + } + if (item->ID == aps->itemid) { //This check to make sure that the item is actually on the NPC, people attempt to inject packets to get items summoned... found = true; break; } } + if (!item || !found) { Message(Chat::Red, "Error: The item you purchased does not exist!"); return; } - if (aps->Type == LDoNMerchant) - { - if (m_pp.ldon_points_available < int32(item->LDoNPrice)) { + auto item_cost = item->LDoNPrice; + bool cannot_afford = false; + std::string merchant_type; + if (item_cost < 0) { + Message(Chat::Red, "This item cannot be bought."); + return; + } + + if (aps->Type == LDoNMerchant) { + if (m_pp.ldon_points_available < item_cost) { Message(Chat::Red, "You cannot afford that item."); return; } - if (item->LDoNTheme <= 16) - { - if (item->LDoNTheme & 16) - { - if (m_pp.ldon_points_tak < int32(item->LDoNPrice)) - { - Message(Chat::Red, "You need at least %u points in tak to purchase this item.", int32(item->LDoNPrice)); - return; - } - } - else if (item->LDoNTheme & 8) - { - if (m_pp.ldon_points_ruj < int32(item->LDoNPrice)) - { - Message(Chat::Red, "You need at least %u points in ruj to purchase this item.", int32(item->LDoNPrice)); - return; - } - } - else if (item->LDoNTheme & 4) - { - if (m_pp.ldon_points_mmc < int32(item->LDoNPrice)) - { - Message(Chat::Red, "You need at least %u points in mmc to purchase this item.", int32(item->LDoNPrice)); - return; - } - } - else if (item->LDoNTheme & 2) - { - if (m_pp.ldon_points_mir < int32(item->LDoNPrice)) - { - Message(Chat::Red, "You need at least %u points in mir to purchase this item.", int32(item->LDoNPrice)); - return; - } - } - else if (item->LDoNTheme & 1) - { - if (m_pp.ldon_points_guk < int32(item->LDoNPrice)) - { - Message(Chat::Red, "You need at least %u points in guk to purchase this item.", int32(item->LDoNPrice)); - return; + if (item->LDoNTheme <= LDoNThemeBits::TAKBit) { + if (item->LDoNTheme & LDoNThemeBits::TAKBit) { + if (m_pp.ldon_points_tak < item_cost) { + cannot_afford = true; + merchant_type = fmt::format("Deepest Guk Point{}", item_cost != 1 ? "s" : ""); + } + } else if (item->LDoNTheme & LDoNThemeBits::RUJBit) { + if (m_pp.ldon_points_ruj < item_cost) { + cannot_afford = true; + merchant_type = fmt::format("Miragul's Menagerie Point{}", item_cost != 1 ? "s" : ""); + } + } else if (item->LDoNTheme & LDoNThemeBits::MMCBit) { + if (m_pp.ldon_points_mmc < item_cost) { + cannot_afford = true; + merchant_type = fmt::format("Mistmoore Catacombs Point{}", item_cost != 1 ? "s" : ""); + } + } else if (item->LDoNTheme & LDoNThemeBits::MIRBit) { + if (m_pp.ldon_points_mir < item_cost) { + cannot_afford = true; + merchant_type = fmt::format("Rujarkian Hills Point{}", item_cost != 1 ? "s" : ""); + } + } else if (item->LDoNTheme & LDoNThemeBits::GUKBit) { + if (m_pp.ldon_points_guk < item_cost) { + cannot_afford = true; + merchant_type = fmt::format("Takish-Hiz Point{}", item_cost != 1 ? "s" : ""); } } + + + } + } else if (aps->Type == DiscordMerchant) { + if (GetPVPPoints() < item_cost) { + cannot_afford = true; + merchant_type = fmt::format("PVP Point{}", item_cost != 1 ? "s" : ""); + } + } else if (aps->Type == NorrathsKeepersMerchant) { + if (GetRadiantCrystals() < item_cost) { + cannot_afford = true; + merchant_type = database.CreateItemLink(RuleI(Zone, RadiantCrystalItemID)); + } + } else if (aps->Type == DarkReignMerchant) { + if (GetEbonCrystals() < item_cost) { + cannot_afford = true; + merchant_type = database.CreateItemLink(RuleI(Zone, EbonCrystalItemID)); + } + } else { + Message(Chat::Red, "Unknown Adventure Merchant Type."); + return; + } + + if (cannot_afford && !merchant_type.empty()) { + Message( + Chat::Red, + fmt::format( + "You need at least {} {} to purchase this item.", + item_cost, + merchant_type + ).c_str() + ); + } + + + if (CheckLoreConflict(item)) { + Message( + Chat::Yellow, + fmt::format( + "You already have a lore {} ({}) in your inventory.", + database.CreateItemLink(item->ID), + item->ID + ).c_str() + ); + return; + } + + if (aps->Type == LDoNMerchant) { + int required_points = item_cost * -1; + + if (!UpdateLDoNPoints(6, required_points)) { + return; } } else if (aps->Type == DiscordMerchant) { - if (GetPVPPoints() < item->LDoNPrice) - { - Message(Chat::Red, "You need at least %u PVP points to purchase this item.", int32(item->LDoNPrice)); - return; - } - } - else if (aps->Type == NorrathsKeepersMerchant) - { - if (GetRadiantCrystals() < item->LDoNPrice) - { - Message(Chat::Red, "You need at least %u Radiant Crystals to purchase this item.", int32(item->LDoNPrice)); - return; - } - } - else if (aps->Type == DarkReignMerchant) - { - if (GetEbonCrystals() < item->LDoNPrice) - { - Message(Chat::Red, "You need at least %u Ebon Crystals to purchase this item.", int32(item->LDoNPrice)); - return; - } - } - else - { - Message(Chat::Red, "Unknown Adventure Merchant type."); - return; - } - - - if (CheckLoreConflict(item)) - { - Message(Chat::Yellow, "You can only have one of a lore item."); - return; - } - - if (aps->Type == LDoNMerchant) - { - int32 requiredpts = (int32)item->LDoNPrice*-1; - - if (!UpdateLDoNPoints(6, requiredpts)) - return; - } - else if (aps->Type == DiscordMerchant) - { - SetPVPPoints(GetPVPPoints() - (int32)item->LDoNPrice); + SetPVPPoints(GetPVPPoints() - item_cost); SendPVPStats(); } else if (aps->Type == NorrathsKeepersMerchant) { - SetRadiantCrystals(GetRadiantCrystals() - (int32)item->LDoNPrice); + SetRadiantCrystals(GetRadiantCrystals() - item_cost); } else if (aps->Type == DarkReignMerchant) { @@ -2165,36 +2165,20 @@ void Client::Handle_OP_AdventureMerchantRequest(const EQApplicationPacket *app) } item = database.GetItem(ml.item); - if (item) - { - uint32 theme; - if (item->LDoNTheme > 16) - { - theme = 0; - } - else if (item->LDoNTheme & 16) - { - theme = 5; - } - else if (item->LDoNTheme & 8) - { - theme = 4; - } - else if (item->LDoNTheme & 4) - { - theme = 3; - } - else if (item->LDoNTheme & 2) - { - theme = 2; - } - else if (item->LDoNTheme & 1) - { - theme = 1; - } - else - { - theme = 0; + if (item) { + uint32 theme = LDoNThemes::Unused; + if (item->LDoNTheme > LDoNThemeBits::TAKBit) { + theme = LDoNThemes::Unused; + } else if (item->LDoNTheme & LDoNThemeBits::TAKBit) { + theme = LDoNThemes::TAK; + } else if (item->LDoNTheme & LDoNThemeBits::RUJBit) { + theme = LDoNThemes::RUJ; + } else if (item->LDoNTheme & LDoNThemeBits::MMCBit) { + theme = LDoNThemes::MMC; + } else if (item->LDoNTheme & LDoNThemeBits::RUJBit) { + theme = LDoNThemes::MIR; + } else if (item->LDoNTheme & LDoNThemeBits::GUKBit) { + theme = LDoNThemes::GUK; } ss << "^" << item->Name << "|"; ss << item->ID << "|"; diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 98e061c8c..fda5cd9b1 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -5314,7 +5314,7 @@ XS(XS__crosszoneaddldonlossbycharid) { Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonlossbycharid(int character_id, uint32 theme_id)"); { uint8 update_type = CZUpdateType_Character; - uint8 update_subtype = CZLDoNUpdateSubtype_Loss; + uint8 update_subtype = CZLDoNUpdateSubtype_AddLoss; int character_id = (int) SvIV(ST(0)); uint32 theme_id = (uint32) SvUV(ST(1)); quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, character_id, theme_id); @@ -5329,7 +5329,7 @@ XS(XS__crosszoneaddldonlossbygroupid) { Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonlossbygroupid(int group_id, uint32 theme_id)"); { uint8 update_type = CZUpdateType_Group; - uint8 update_subtype = CZLDoNUpdateSubtype_Loss; + uint8 update_subtype = CZLDoNUpdateSubtype_AddLoss; int group_id = (int) SvIV(ST(0)); uint32 theme_id = (uint32) SvUV(ST(1)); quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, group_id, theme_id); @@ -5344,7 +5344,7 @@ XS(XS__crosszoneaddldonlossbyraidid) { Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonlossbyraidid(int raid_id, uint32 theme_id)"); { uint8 update_type = CZUpdateType_Raid; - uint8 update_subtype = CZLDoNUpdateSubtype_Loss; + uint8 update_subtype = CZLDoNUpdateSubtype_AddLoss; int raid_id = (int) SvIV(ST(0)); uint32 theme_id = (uint32) SvUV(ST(1)); quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, raid_id, theme_id); @@ -5359,7 +5359,7 @@ XS(XS__crosszoneaddldonlossbyguildid) { Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonlossbyguildid(int guild_id, uint32 theme_id)"); { uint8 update_type = CZUpdateType_Guild; - uint8 update_subtype = CZLDoNUpdateSubtype_Loss; + uint8 update_subtype = CZLDoNUpdateSubtype_AddLoss; int guild_id = (int) SvIV(ST(0)); uint32 theme_id = (uint32) SvUV(ST(1)); quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, guild_id, theme_id); @@ -5374,7 +5374,7 @@ XS(XS__crosszoneaddldonlossbyexpeditionid) { Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonlossbyexpeditionid(uint32 expedition_id, uint32 theme_id)"); { uint8 update_type = CZUpdateType_Expedition; - uint8 update_subtype = CZLDoNUpdateSubtype_Loss; + uint8 update_subtype = CZLDoNUpdateSubtype_AddLoss; uint32 expedition_id = (uint32) SvUV(ST(0)); uint32 theme_id = (uint32) SvUV(ST(1)); quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, expedition_id, theme_id); @@ -5389,7 +5389,7 @@ XS(XS__crosszoneaddldonlossbyclientname) { Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonlossbyclientname(const char* client_name, uint32 theme_id)"); { uint8 update_type = CZUpdateType_ClientName; - uint8 update_subtype = CZLDoNUpdateSubtype_Loss; + uint8 update_subtype = CZLDoNUpdateSubtype_AddLoss; int update_identifier = 0; int points = 1; const char* client_name = (const char*) SvPV_nolen(ST(0)); @@ -5406,7 +5406,7 @@ XS(XS__crosszoneaddldonpointsbycharid) { Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonpointsbycharid(int character_id, uint32 theme_id, int points)"); { uint8 update_type = CZUpdateType_Character; - uint8 update_subtype = CZLDoNUpdateSubtype_Points; + uint8 update_subtype = CZLDoNUpdateSubtype_AddPoints; int character_id = (int) SvIV(ST(0)); uint32 theme_id = (uint32) SvUV(ST(1)); int points = (int) SvIV(ST(2)); @@ -5422,7 +5422,7 @@ XS(XS__crosszoneaddldonpointsbygroupid) { Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonpointsbygroupid(int group_id, uint32 theme_id, int points)"); { uint8 update_type = CZUpdateType_Group; - uint8 update_subtype = CZLDoNUpdateSubtype_Points; + uint8 update_subtype = CZLDoNUpdateSubtype_AddPoints; int group_id = (int) SvIV(ST(0)); uint32 theme_id = (uint32) SvUV(ST(1)); int points = (int) SvIV(ST(2)); @@ -5438,7 +5438,7 @@ XS(XS__crosszoneaddldonpointsbyraidid) { Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonpointsbyraidid(int raid_id, uint32 theme_id, int points)"); { uint8 update_type = CZUpdateType_Raid; - uint8 update_subtype = CZLDoNUpdateSubtype_Points; + uint8 update_subtype = CZLDoNUpdateSubtype_AddPoints; int raid_id = (int) SvIV(ST(0)); uint32 theme_id = (uint32) SvUV(ST(1)); int points = (int) SvIV(ST(2)); @@ -5454,7 +5454,7 @@ XS(XS__crosszoneaddldonpointsbyguildid) { Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonpointsbyguildid(int guild_id, uint32 theme_id, int points)"); { uint8 update_type = CZUpdateType_Guild; - uint8 update_subtype = CZLDoNUpdateSubtype_Points; + uint8 update_subtype = CZLDoNUpdateSubtype_AddPoints; int guild_id = (int) SvIV(ST(0)); uint32 theme_id = (uint32) SvUV(ST(1)); int points = (int) SvIV(ST(2)); @@ -5470,7 +5470,7 @@ XS(XS__crosszoneaddldonpointsbyexpeditionid) { Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonpointsbyexpeditionid(uint32 expedition_id, uint32 theme_id, int points)"); { uint8 update_type = CZUpdateType_Expedition; - uint8 update_subtype = CZLDoNUpdateSubtype_Points; + uint8 update_subtype = CZLDoNUpdateSubtype_AddPoints; uint32 expedition_id = (uint32) SvUV(ST(0)); uint32 theme_id = (uint32) SvUV(ST(1)); int points = (int) SvIV(ST(2)); @@ -5486,7 +5486,7 @@ XS(XS__crosszoneaddldonpointsbyclientname) { Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonpointsbyclientname(const char* client_name, uint32 theme_id, int points)"); { uint8 update_type = CZUpdateType_ClientName; - uint8 update_subtype = CZLDoNUpdateSubtype_Points; + uint8 update_subtype = CZLDoNUpdateSubtype_AddPoints; int update_identifier = 0; const char* client_name = (const char*) SvPV_nolen(ST(0)); uint32 theme_id = (uint32) SvUV(ST(1)); @@ -5503,7 +5503,7 @@ XS(XS__crosszoneaddldonwinbycharid) { Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonwinbycharid(int character_id, uint32 theme_id)"); { uint8 update_type = CZUpdateType_Character; - uint8 update_subtype = CZLDoNUpdateSubtype_Win; + uint8 update_subtype = CZLDoNUpdateSubtype_AddWin; int character_id = (int) SvIV(ST(0)); uint32 theme_id = (uint32) SvUV(ST(1)); quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, character_id, theme_id); @@ -5518,7 +5518,7 @@ XS(XS__crosszoneaddldonwinbygroupid) { Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonwinbygroupid(int group_id, uint32 theme_id)"); { uint8 update_type = CZUpdateType_Group; - uint8 update_subtype = CZLDoNUpdateSubtype_Win; + uint8 update_subtype = CZLDoNUpdateSubtype_AddWin; int group_id = (int) SvIV(ST(0)); uint32 theme_id = (uint32) SvUV(ST(1)); quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, group_id, theme_id); @@ -5533,7 +5533,7 @@ XS(XS__crosszoneaddldonwinbyraidid) { Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonwinbyraidid(int raid_id, uint32 theme_id)"); { uint8 update_type = CZUpdateType_Raid; - uint8 update_subtype = CZLDoNUpdateSubtype_Win; + uint8 update_subtype = CZLDoNUpdateSubtype_AddWin; int raid_id = (int) SvIV(ST(0)); uint32 theme_id = (uint32) SvUV(ST(1)); quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, raid_id, theme_id); @@ -5548,7 +5548,7 @@ XS(XS__crosszoneaddldonwinbyguildid) { Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonwinbyguildid(int guild_id, uint32 theme_id)"); { uint8 update_type = CZUpdateType_Guild; - uint8 update_subtype = CZLDoNUpdateSubtype_Win; + uint8 update_subtype = CZLDoNUpdateSubtype_AddWin; int guild_id = (int) SvIV(ST(0)); uint32 theme_id = (uint32) SvUV(ST(1)); quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, guild_id, theme_id); @@ -5563,7 +5563,7 @@ XS(XS__crosszoneaddldonwinbyexpeditionid) { Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonwinbyexpeditionid(uint32 expedition_id, uint32 theme_id)"); { uint8 update_type = CZUpdateType_Expedition; - uint8 update_subtype = CZLDoNUpdateSubtype_Win; + uint8 update_subtype = CZLDoNUpdateSubtype_AddWin; uint32 expedition_id = (uint32) SvUV(ST(0)); uint32 theme_id = (uint32) SvUV(ST(1)); quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, expedition_id, theme_id); @@ -5578,7 +5578,7 @@ XS(XS__crosszoneaddldonwinbyclientname) { Perl_croak(aTHX_ "Usage: quest::crosszoneaddldonwinbyclientname(const char* client_name, uint32 theme_id)"); { uint8 update_type = CZUpdateType_ClientName; - uint8 update_subtype = CZLDoNUpdateSubtype_Win; + uint8 update_subtype = CZLDoNUpdateSubtype_AddWin; int update_identifier = 0; int points = 1; const char* client_name = (const char*) SvPV_nolen(ST(0)); @@ -6618,6 +6618,190 @@ XS(XS__crosszonemoveinstancebyclientname) { XSRETURN_EMPTY; } +XS(XS__crosszoneremoveldonlossbycharid); +XS(XS__crosszoneremoveldonlossbycharid) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: quest::crosszoneremoveldonlossbycharid(int character_id, uint32 theme_id)"); + { + uint8 update_type = CZUpdateType_Character; + uint8 update_subtype = CZLDoNUpdateSubtype_RemoveLoss; + int character_id = (int) SvIV(ST(0)); + uint32 theme_id = (uint32) SvUV(ST(1)); + quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, character_id, theme_id); + } + XSRETURN_EMPTY; +} + +XS(XS__crosszoneremoveldonlossbygroupid); +XS(XS__crosszoneremoveldonlossbygroupid) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: quest::crosszoneremoveldonlossbygroupid(int group_id, uint32 theme_id)"); + { + uint8 update_type = CZUpdateType_Group; + uint8 update_subtype = CZLDoNUpdateSubtype_RemoveLoss; + int group_id = (int) SvIV(ST(0)); + uint32 theme_id = (uint32) SvUV(ST(1)); + quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, group_id, theme_id); + } + XSRETURN_EMPTY; +} + +XS(XS__crosszoneremoveldonlossbyraidid); +XS(XS__crosszoneremoveldonlossbyraidid) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: quest::crosszoneremoveldonlossbyraidid(int raid_id, uint32 theme_id)"); + { + uint8 update_type = CZUpdateType_Raid; + uint8 update_subtype = CZLDoNUpdateSubtype_RemoveLoss; + int raid_id = (int) SvIV(ST(0)); + uint32 theme_id = (uint32) SvUV(ST(1)); + quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, raid_id, theme_id); + } + XSRETURN_EMPTY; +} + +XS(XS__crosszoneremoveldonlossbyguildid); +XS(XS__crosszoneremoveldonlossbyguildid) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: quest::crosszoneremoveldonlossbyguildid(int guild_id, uint32 theme_id)"); + { + uint8 update_type = CZUpdateType_Guild; + uint8 update_subtype = CZLDoNUpdateSubtype_RemoveLoss; + int guild_id = (int) SvIV(ST(0)); + uint32 theme_id = (uint32) SvUV(ST(1)); + quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, guild_id, theme_id); + } + XSRETURN_EMPTY; +} + +XS(XS__crosszoneremoveldonlossbyexpeditionid); +XS(XS__crosszoneremoveldonlossbyexpeditionid) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: quest::crosszoneremoveldonlossbyexpeditionid(uint32 expedition_id, uint32 theme_id)"); + { + uint8 update_type = CZUpdateType_Expedition; + uint8 update_subtype = CZLDoNUpdateSubtype_RemoveLoss; + uint32 expedition_id = (uint32) SvUV(ST(0)); + uint32 theme_id = (uint32) SvUV(ST(1)); + quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, expedition_id, theme_id); + } + XSRETURN_EMPTY; +} + +XS(XS__crosszoneremoveldonlossbyclientname); +XS(XS__crosszoneremoveldonlossbyclientname) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: quest::crosszoneremoveldonlossbyclientname(const char* client_name, uint32 theme_id)"); + { + uint8 update_type = CZUpdateType_ClientName; + uint8 update_subtype = CZLDoNUpdateSubtype_RemoveLoss; + int update_identifier = 0; + int points = 1; + const char* client_name = (const char*) SvPV_nolen(ST(0)); + uint32 theme_id = (uint32) SvUV(ST(1)); + quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, update_identifier, theme_id, points, client_name); + } + XSRETURN_EMPTY; +} + +XS(XS__crosszoneremoveldonwinbycharid); +XS(XS__crosszoneremoveldonwinbycharid) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: quest::crosszoneremoveldonwinbycharid(int character_id, uint32 theme_id)"); + { + uint8 update_type = CZUpdateType_Character; + uint8 update_subtype = CZLDoNUpdateSubtype_RemoveWin; + int character_id = (int) SvIV(ST(0)); + uint32 theme_id = (uint32) SvUV(ST(1)); + quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, character_id, theme_id); + } + XSRETURN_EMPTY; +} + +XS(XS__crosszoneremoveldonwinbygroupid); +XS(XS__crosszoneremoveldonwinbygroupid) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: quest::crosszoneremoveldonwinbygroupid(int group_id, uint32 theme_id)"); + { + uint8 update_type = CZUpdateType_Group; + uint8 update_subtype = CZLDoNUpdateSubtype_RemoveWin; + int group_id = (int) SvIV(ST(0)); + uint32 theme_id = (uint32) SvUV(ST(1)); + quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, group_id, theme_id); + } + XSRETURN_EMPTY; +} + +XS(XS__crosszoneremoveldonwinbyraidid); +XS(XS__crosszoneremoveldonwinbyraidid) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: quest::crosszoneremoveldonwinbyraidid(int raid_id, uint32 theme_id)"); + { + uint8 update_type = CZUpdateType_Raid; + uint8 update_subtype = CZLDoNUpdateSubtype_RemoveWin; + int raid_id = (int) SvIV(ST(0)); + uint32 theme_id = (uint32) SvUV(ST(1)); + quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, raid_id, theme_id); + } + XSRETURN_EMPTY; +} + +XS(XS__crosszoneremoveldonwinbyguildid); +XS(XS__crosszoneremoveldonwinbyguildid) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: quest::crosszoneremoveldonwinbyguildid(int guild_id, uint32 theme_id)"); + { + uint8 update_type = CZUpdateType_Guild; + uint8 update_subtype = CZLDoNUpdateSubtype_RemoveWin; + int guild_id = (int) SvIV(ST(0)); + uint32 theme_id = (uint32) SvUV(ST(1)); + quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, guild_id, theme_id); + } + XSRETURN_EMPTY; +} + +XS(XS__crosszoneremoveldonwinbyexpeditionid); +XS(XS__crosszoneremoveldonwinbyexpeditionid) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: quest::crosszoneremoveldonwinbyexpeditionid(uint32 expedition_id, uint32 theme_id)"); + { + uint8 update_type = CZUpdateType_Expedition; + uint8 update_subtype = CZLDoNUpdateSubtype_RemoveWin; + uint32 expedition_id = (uint32) SvUV(ST(0)); + uint32 theme_id = (uint32) SvUV(ST(1)); + quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, expedition_id, theme_id); + } + XSRETURN_EMPTY; +} + +XS(XS__crosszoneremoveldonwinbyclientname); +XS(XS__crosszoneremoveldonwinbyclientname) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: quest::crosszoneremoveldonwinbyclientname(const char* client_name, uint32 theme_id)"); + { + uint8 update_type = CZUpdateType_ClientName; + uint8 update_subtype = CZLDoNUpdateSubtype_RemoveWin; + int update_identifier = 0; + int points = 1; + const char* client_name = (const char*) SvPV_nolen(ST(0)); + uint32 theme_id = (uint32) SvUV(ST(1)); + quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, update_identifier, theme_id, points, client_name); + } + XSRETURN_EMPTY; +} + XS(XS__crosszoneremovespellbycharid); XS(XS__crosszoneremovespellbycharid) { dXSARGS; @@ -7265,6 +7449,75 @@ XS(XS__crosszoneupdateactivitybyclientname) { XSRETURN_EMPTY; } +XS(XS__worldwideaddldonloss); +XS(XS__worldwideaddldonloss) { + dXSARGS; + if (items < 1 || items > 3) + Perl_croak(aTHX_ "Usage: quest::worldwideaddldonloss(uint32 theme_id, [min_status = 0, max_status = 0])"); + { + uint8 update_type = CZLDoNUpdateSubtype_AddLoss; + uint32 theme_id = (uint32)SvUV(ST(0)); + int points = 1; + uint8 min_status = 0; + uint8 max_status = 0; + if (items == 2) + min_status = (uint8)SvUV(ST(1)); + + if (items == 3) + max_status = (uint8)SvUV(ST(2)); + + quest_manager.WorldWideLDoNUpdate(update_type, theme_id, points, min_status, max_status); + } + XSRETURN_EMPTY; +} + +XS(XS__worldwideaddldonpoints); +XS(XS__worldwideaddldonpoints) { + dXSARGS; + if (items < 1 || items > 4) + Perl_croak(aTHX_ "Usage: quest::worldwideaddldonpoints(uint32 theme_id. [int points = 1, min_status = 0, max_status = 0])"); + { + uint8 update_type = CZLDoNUpdateSubtype_AddPoints; + uint32 theme_id = (uint32)SvUV(ST(0)); + int points = 1; + uint8 min_status = 0; + uint8 max_status = 0; + if (items == 2) + points = (int)SvIV(ST(1)); + + if (items == 3) + min_status = (uint8)SvUV(ST(2)); + + if (items == 4) + max_status = (uint8)SvUV(ST(3)); + + quest_manager.WorldWideLDoNUpdate(update_type, theme_id, points, min_status, max_status); + } + XSRETURN_EMPTY; +} + +XS(XS__worldwideaddldonwin); +XS(XS__worldwideaddldonwin) { + dXSARGS; + if (items < 1 || items > 3) + Perl_croak(aTHX_ "Usage: quest::worldwideaddldonwin(uint32 theme_id, [min_status = 0, max_status = 0])"); + { + uint8 update_type = CZLDoNUpdateSubtype_AddWin; + uint32 theme_id = (uint32)SvUV(ST(0)); + int points = 1; + uint8 min_status = 0; + uint8 max_status = 0; + if (items == 2) + min_status = (uint8)SvUV(ST(1)); + + if (items == 3) + max_status = (uint8)SvUV(ST(2)); + + quest_manager.WorldWideLDoNUpdate(update_type, theme_id, points, min_status, max_status); + } + XSRETURN_EMPTY; +} + XS(XS__worldwideassigntask); XS(XS__worldwideassigntask) { dXSARGS; @@ -7492,6 +7745,50 @@ XS(XS__worldwidemoveinstance) { XSRETURN_EMPTY; } +XS(XS__worldwideremoveldonloss); +XS(XS__worldwideremoveldonloss) { + dXSARGS; + if (items < 1 || items > 3) + Perl_croak(aTHX_ "Usage: quest::worldwideremoveldonloss(uint32 theme_id, [min_status = 0, max_status = 0])"); + { + uint8 update_type = CZLDoNUpdateSubtype_RemoveLoss; + uint32 theme_id = (uint32)SvUV(ST(0)); + int points = 1; + uint8 min_status = 0; + uint8 max_status = 0; + if (items == 2) + min_status = (uint8)SvUV(ST(1)); + + if (items == 3) + max_status = (uint8)SvUV(ST(2)); + + quest_manager.WorldWideLDoNUpdate(update_type, theme_id, points, min_status, max_status); + } + XSRETURN_EMPTY; +} + +XS(XS__worldwideremoveldonwin); +XS(XS__worldwideremoveldonwin) { + dXSARGS; + if (items < 1 || items > 3) + Perl_croak(aTHX_ "Usage: quest::worldwideremoveldonwin(uint32 theme_id, [min_status = 0, max_status = 0])"); + { + uint8 update_type = CZLDoNUpdateSubtype_RemoveWin; + uint32 theme_id = (uint32)SvUV(ST(0)); + int points = 1; + uint8 min_status = 0; + uint8 max_status = 0; + if (items == 2) + min_status = (uint8)SvUV(ST(1)); + + if (items == 3) + max_status = (uint8)SvUV(ST(2)); + + quest_manager.WorldWideLDoNUpdate(update_type, theme_id, points, min_status, max_status); + } + XSRETURN_EMPTY; +} + XS(XS__worldwideremovespell); XS(XS__worldwideremovespell) { dXSARGS; @@ -7659,75 +7956,6 @@ XS(XS__worldwideupdateactivity) { XSRETURN_EMPTY; } -XS(XS__worldwideaddldonloss); -XS(XS__worldwideaddldonloss) { - dXSARGS; - if (items < 1 || items > 3) - Perl_croak(aTHX_ "Usage: quest::worldwideaddldonloss(uint32 theme_id, [min_status = 0, max_status = 0])"); - { - uint8 update_type = CZLDoNUpdateSubtype_Loss; - uint32 theme_id = (uint32) SvUV(ST(0)); - int points = 1; - uint8 min_status = 0; - uint8 max_status = 0; - if (items == 2) - min_status = (uint8) SvUV(ST(1)); - - if (items == 3) - max_status = (uint8) SvUV(ST(2)); - - quest_manager.WorldWideLDoNUpdate(update_type, theme_id, points, min_status, max_status); - } - XSRETURN_EMPTY; -} - -XS(XS__worldwideaddldonpoints); -XS(XS__worldwideaddldonpoints) { - dXSARGS; - if (items < 1 || items > 4) - Perl_croak(aTHX_ "Usage: quest::worldwideaddldonpoints(uint32 theme_id. [int points = 1, min_status = 0, max_status = 0])"); - { - uint8 update_type = CZLDoNUpdateSubtype_Points; - uint32 theme_id = (uint32) SvUV(ST(0)); - int points = 1; - uint8 min_status = 0; - uint8 max_status = 0; - if (items == 2) - points = (int) SvIV(ST(1)); - - if (items == 3) - min_status = (uint8) SvUV(ST(2)); - - if (items == 4) - max_status = (uint8) SvUV(ST(3)); - - quest_manager.WorldWideLDoNUpdate(update_type, theme_id, points, min_status, max_status); - } - XSRETURN_EMPTY; -} - -XS(XS__worldwideaddldonwin); -XS(XS__worldwideaddldonwin) { - dXSARGS; - if (items < 1 || items > 3) - Perl_croak(aTHX_ "Usage: quest::worldwideaddldonwin(uint32 theme_id, [min_status = 0, max_status = 0])"); - { - uint8 update_type = CZLDoNUpdateSubtype_Win; - uint32 theme_id = (uint32) SvUV(ST(0)); - int points = 1; - uint8 min_status = 0; - uint8 max_status = 0; - if (items == 2) - min_status = (uint8) SvUV(ST(1)); - - if (items == 3) - max_status = (uint8) SvUV(ST(2)); - - quest_manager.WorldWideLDoNUpdate(update_type, theme_id, points, min_status, max_status); - } - XSRETURN_EMPTY; -} - XS(XS__isnpcspawned); XS(XS__isnpcspawned) { dXSARGS; @@ -7944,6 +8172,18 @@ EXTERN_C XS(boot_quest) { newXS(strcpy(buf, "crosszonemoveinstancebyguildid"), XS__crosszonemoveinstancebyguildid, file); newXS(strcpy(buf, "crosszonemoveinstancebyexpeditionid"), XS__crosszonemoveinstancebyexpeditionid, file); newXS(strcpy(buf, "crosszonemoveinstancebyclientname"), XS__crosszonemoveinstancebyclientname, file); + newXS(strcpy(buf, "crosszoneremoveldonlossbycharid"), XS__crosszoneremoveldonlossbycharid, file); + newXS(strcpy(buf, "crosszoneremoveldonlossbygroupid"), XS__crosszoneremoveldonlossbygroupid, file); + newXS(strcpy(buf, "crosszoneremoveldonlossbyraidid"), XS__crosszoneremoveldonlossbyraidid, file); + newXS(strcpy(buf, "crosszoneremoveldonlossbyguildid"), XS__crosszoneremoveldonlossbyguildid, file); + newXS(strcpy(buf, "crosszoneremoveldonlossbyexpeditionid"), XS__crosszoneremoveldonlossbyexpeditionid, file); + newXS(strcpy(buf, "crosszoneremoveldonlossbyclientname"), XS__crosszoneremoveldonlossbyclientname, file); + newXS(strcpy(buf, "crosszoneremoveldonwinbycharid"), XS__crosszoneremoveldonwinbycharid, file); + newXS(strcpy(buf, "crosszoneremoveldonwinbygroupid"), XS__crosszoneremoveldonwinbygroupid, file); + newXS(strcpy(buf, "crosszoneremoveldonwinbyraidid"), XS__crosszoneremoveldonwinbyraidid, file); + newXS(strcpy(buf, "crosszoneremoveldonwinbyguildid"), XS__crosszoneremoveldonwinbyguildid, file); + newXS(strcpy(buf, "crosszoneremoveldonwinbyexpeditionid"), XS__crosszoneremoveldonwinbyexpeditionid, file); + newXS(strcpy(buf, "crosszoneremoveldonwinbyclientname"), XS__crosszoneremoveldonwinbyclientname, file); newXS(strcpy(buf, "crosszoneremovespellbycharid"), XS__crosszoneremovespellbycharid, file); newXS(strcpy(buf, "crosszoneremovespellbygroupid"), XS__crosszoneremovespellbygroupid, file); newXS(strcpy(buf, "crosszoneremovespellbyraidid"), XS__crosszoneremovespellbyraidid, file); @@ -7994,6 +8234,8 @@ EXTERN_C XS(boot_quest) { newXS(strcpy(buf, "worldwidemessage"), XS__worldwidemessage, file); newXS(strcpy(buf, "worldwidemove"), XS__worldwidemove, file); newXS(strcpy(buf, "worldwidemoveinstance"), XS__worldwidemoveinstance, file); + newXS(strcpy(buf, "worldwideremoveldonloss"), XS__worldwideremoveldonloss, file); + newXS(strcpy(buf, "worldwideremoveldonwin"), XS__worldwideremoveldonwin, file); newXS(strcpy(buf, "worldwideremovespell"), XS__worldwideremovespell, file); newXS(strcpy(buf, "worldwideremovetask"), XS__worldwideremovetask, file); newXS(strcpy(buf, "worldwideresetactivity"), XS__worldwideresetactivity, file); diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 0a805ad07..d6c3c5e79 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -186,25 +186,57 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, // make sure the item exists if(item == nullptr) { - Message(Chat::Red, "Item %u does not exist.", item_id); - LogInventory("Player [{}] on account [{}] attempted to create an item with an invalid id.\n(Item: [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], Aug6: [{}])\n", - GetName(), account_name, item_id, aug1, aug2, aug3, aug4, aug5, aug6); - + Message( + Chat::Red, + fmt::format( + "Item {} does not exist.", + item_id + ).c_str() + ); + LogInventory( + "Player [{}] on account [{}] attempted to create an item with an invalid id.\n" + "Item [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], Aug6: [{}])\n", + GetName(), + account_name, + item_id, + aug1, + aug2, + aug3, + aug4, + aug5, + aug6 + ); return false; } // check that there is not a lore conflict between base item and existing inventory else if(CheckLoreConflict(item)) { // DuplicateLoreMessage(item_id); - Message(Chat::Red, "You already have a lore %s (%i) in your inventory.", item->Name, item_id); - + Message( + Chat::Red, + fmt::format( + "You already have a lore {} ({}) in your inventory.", + database.CreateItemLink(item_id), + item_id + ).c_str() + ); return false; } // check to make sure we are augmenting an augmentable item else if (((!item->IsClassCommon()) || (item->AugType > 0)) && (aug1 | aug2 | aug3 | aug4 | aug5 | aug6)) { Message(Chat::Red, "You can not augment an augment or a non-common class item."); - LogInventory("Player [{}] on account [{}] attempted to augment an augment or a non-common class item.\n(Item: [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], Aug5: [{}])\n", - GetName(), account_name, item->ID, aug1, aug2, aug3, aug4, aug5, aug6); - + LogInventory( + "Player [{}] on account [{}] attempted to augment an augment or a non-common class item.\n" + "Item [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], Aug5: [{}])\n", + GetName(), + account_name, + item->ID, + aug1, + aug2, + aug3, + aug4, + aug5, + aug6 + ); return false; } @@ -216,7 +248,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, /* else if(item->MinStatus && ((this->Admin() < item->MinStatus) || (this->Admin() < RuleI(GM, MinStatusToSummonItem)))) { Message(Chat::Red, "You are not a GM or do not have the status to summon this item."); - LogInventory("Player [{}] on account [{}] attempted to create a GM-only item with a status of [{}].\n(Item: [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], Aug6: [{}], MinStatus: [{}])\n", + LogInventory("Player [{}] on account [{}] attempted to create a GM-only item with a status of [{}].\n"Item [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], Aug6: [{}], MinStatus: [{}])\n", GetName(), account_name, this->Admin(), item->ID, aug1, aug2, aug3, aug4, aug5, aug6, item->MinStatus); return false; @@ -224,23 +256,39 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, */ uint32 augments[EQ::invaug::SOCKET_COUNT] = { aug1, aug2, aug3, aug4, aug5, aug6 }; - - uint32 classes = item->Classes; - uint32 races = item->Races; - uint32 slots = item->Slots; - - bool enforcewear = RuleB(Inventory, EnforceAugmentWear); - bool enforcerestr = RuleB(Inventory, EnforceAugmentRestriction); - bool enforceusable = RuleB(Inventory, EnforceAugmentUsability); - + uint32 classes = item->Classes; + uint32 races = item->Races; + uint32 slots = item->Slots; + bool enforce_wearable = RuleB(Inventory, EnforceAugmentWear); + bool enforce_restrictions = RuleB(Inventory, EnforceAugmentRestriction); + bool enforce_usable = RuleB(Inventory, EnforceAugmentUsability); for (int iter = EQ::invaug::SOCKET_BEGIN; iter <= EQ::invaug::SOCKET_END; ++iter) { + int augment_slot = iter + 1; const EQ::ItemData* augtest = database.GetItem(augments[iter]); - if(augtest == nullptr) { if(augments[iter]) { - Message(Chat::Red, "Augment %u (Aug%i) does not exist.", augments[iter], iter + 1); - LogInventory("Player [{}] on account [{}] attempted to create an augment (Aug[{}]) with an invalid id.\n(Item: [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], Aug6: [{}])\n", - GetName(), account_name, (iter + 1), item->ID, aug1, aug2, aug3, aug4, aug5, aug6); + Message( + Chat::Red, + fmt::format( + "Augment {} in Augment Slot {} does not exist.", + augments[iter], + augment_slot + ).c_str() + ); + LogInventory( + "Player [{}] on account [{}] attempted to create an augment (Aug[{}]) with an invalid id.\n" + "Item [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], Aug6: [{}])\n", + GetName(), + account_name, + augment_slot, + item->ID, + aug1, + aug2, + aug3, + aug4, + aug5, + aug6 + ); return false; } @@ -249,15 +297,42 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, // check that there is not a lore conflict between augment and existing inventory if(CheckLoreConflict(augtest)) { // DuplicateLoreMessage(augtest->ID); - Message(Chat::Red, "You already have a lore %s (%u) in your inventory.", augtest->Name, augtest->ID); + Message( + Chat::Red, + fmt::format( + "You already have a lore {} ({}) in your inventory.", + database.CreateItemLink(augtest->ID), + augtest->ID + ).c_str() + ); return false; } // check that augment is an actual augment else if(augtest->AugType == 0) { - Message(Chat::Red, "%s (%u) (Aug%i) is not an actual augment.", augtest->Name, augtest->ID, iter + 1); - LogInventory("Player [{}] on account [{}] attempted to use a non-augment item (Aug[{}]) as an augment.\n(Item: [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], Aug6: [{}])\n", - GetName(), account_name, item->ID, (iter + 1), aug1, aug2, aug3, aug4, aug5, aug6); + Message( + Chat::Red, + fmt::format( + "{} ({}) in Augment Slot {} is not an actual augment.", + database.CreateItemLink(augtest->ID), + augtest->ID, + augment_slot + ).c_str() + ); + LogInventory( + "Player [{}] on account [{}] attempted to use a non-augment item (Augment Slot [{}]) as an augment.\n" + "Item [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], Aug6: [{}])\n", + GetName(), + account_name, + item->ID, + augment_slot, + aug1, + aug2, + aug3, + aug4, + aug5, + aug6 + ); return false; } @@ -269,232 +344,352 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, else if(augtest->MinStatus && ((this->Admin() < augtest->MinStatus) || (this->Admin() < RuleI(GM, MinStatusToSummonItem)))) { Message(Chat::Red, "You are not a GM or do not have the status to summon this augment."); LogInventory("Player [{}] on account [{}] attempted to create a GM-only augment (Aug[{}]) with a status of [{}].\n(Item: [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], MinStatus: [{}])\n", - GetName(), account_name, (iter + 1), this->Admin(), item->ID, aug1, aug2, aug3, aug4, aug5, aug6, item->MinStatus); + GetName(), account_name, augment_slot, this->Admin(), item->ID, aug1, aug2, aug3, aug4, aug5, aug6, item->MinStatus); return false; } */ // check for augment type allowance - if(enforcewear) { + if(enforce_wearable) { if ((item->AugSlotType[iter] == EQ::item::AugTypeNone) || !(((uint32)1 << (item->AugSlotType[iter] - 1)) & augtest->AugType)) { - Message(Chat::Red, "Augment %u (Aug%i) is not acceptable wear on Item %u.", augments[iter], iter + 1, item->ID); - LogInventory("Player [{}] on account [{}] attempted to augment an item with an unacceptable augment type (Aug[{}]).\n(Item: [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], Aug6: [{}])\n", - GetName(), account_name, (iter + 1), item->ID, aug1, aug2, aug3, aug4, aug5, aug6); + Message( + Chat::Red, + fmt::format( + "Augment {} ({}) in Augment Slot {} is not capable of being socketed in to {} ({}).", + database.CreateItemLink(augments[iter]), + augments[iter], + augment_slot, + database.CreateItemLink(item->ID), + item->ID + ).c_str() + ); + LogInventory( + "Player [{}] on account [{}] attempted to augment an item with an unacceptable augment type (Aug[{}]).\n" + "Item [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], Aug6: [{}])\n", + GetName(), + account_name, + augment_slot, + item->ID, + aug1, + aug2, + aug3, + aug4, + aug5, + aug6 + ); return false; } if(item->AugSlotVisible[iter] == 0) { - Message(Chat::Red, "Item %u has not evolved enough to accept Augment %u (Aug%i).", item->ID, augments[iter], iter + 1); - LogInventory("Player [{}] on account [{}] attempted to augment an unevolved item with augment type (Aug[{}]).\n(Item: [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], Aug6: [{}])\n", - GetName(), account_name, (iter + 1), item->ID, aug1, aug2, aug3, aug4, aug5, aug6); + Message( + Chat::Red, + "{} ({}) has not evolved enough to accept {} ({}) in Augment Slot {}.", + database.CreateItemLink(item->ID), + item->ID, + database.CreateItemLink(augments[iter]), + augments[iter], + augment_slot + ); + LogInventory( + "Player [{}] on account [{}] attempted to augment an unevolved item with augment type (Aug[{}]).\n" + "Item [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], Aug6: [{}])\n", + GetName(), + account_name, + augment_slot, + item->ID, + aug1, + aug2, + aug3, + aug4, + aug5, + aug6 + ); return false; } } // check for augment to item restriction - if(enforcerestr) { - bool restrictfail = false; - uint8 it = item->ItemType; - - switch(augtest->AugRestrict) { - case EQ::item::AugRestrictionAny: - break; - case EQ::item::AugRestrictionArmor: - switch(it) { - case EQ::item::ItemTypeArmor: + if(enforce_restrictions) { + bool is_restricted = false; + uint8 item_type = item->ItemType; + switch (augtest->AugRestrict) { + case EQ::item::AugRestrictionAny: break; + case EQ::item::AugRestrictionArmor: + switch (item_type) { + case EQ::item::ItemTypeArmor: + break; + default: + is_restricted = true; + break; + } + break; + case EQ::item::AugRestrictionWeapons: + switch (item_type) { + case EQ::item::ItemType1HSlash: + case EQ::item::ItemType1HBlunt: + case EQ::item::ItemType1HPiercing: + case EQ::item::ItemTypeMartial: + case EQ::item::ItemType2HSlash: + case EQ::item::ItemType2HBlunt: + case EQ::item::ItemType2HPiercing: + case EQ::item::ItemTypeBow: + break; + default: + is_restricted = true; + break; + } + break; + case EQ::item::AugRestriction1HWeapons: + switch (item_type) { + case EQ::item::ItemType1HSlash: + case EQ::item::ItemType1HBlunt: + case EQ::item::ItemType1HPiercing: + case EQ::item::ItemTypeMartial: + break; + default: + is_restricted = true; + break; + } + break; + case EQ::item::AugRestriction2HWeapons: + switch (item_type) { + case EQ::item::ItemType2HSlash: + case EQ::item::ItemType2HBlunt: + case EQ::item::ItemType2HPiercing: + case EQ::item::ItemTypeBow: + break; + default: + is_restricted = true; + break; + } + break; + case EQ::item::AugRestriction1HSlash: + switch (item_type) { + case EQ::item::ItemType1HSlash: + break; + default: + is_restricted = true; + break; + } + break; + case EQ::item::AugRestriction1HBlunt: + switch (item_type) { + case EQ::item::ItemType1HBlunt: + break; + default: + is_restricted = true; + break; + } + break; + case EQ::item::AugRestrictionPiercing: + switch (item_type) { + case EQ::item::ItemType1HPiercing: + break; + default: + is_restricted = true; + break; + } + break; + case EQ::item::AugRestrictionHandToHand: + switch (item_type) { + case EQ::item::ItemTypeMartial: + break; + default: + is_restricted = true; + break; + } + break; + case EQ::item::AugRestriction2HSlash: + switch (item_type) { + case EQ::item::ItemType2HSlash: + break; + default: + is_restricted = true; + break; + } + break; + case EQ::item::AugRestriction2HBlunt: + switch (item_type) { + case EQ::item::ItemType2HBlunt: + break; + default: + is_restricted = true; + break; + } + break; + case EQ::item::AugRestriction2HPierce: + switch (item_type) { + case EQ::item::ItemType2HPiercing: + break; + default: + is_restricted = true; + break; + } + break; + case EQ::item::AugRestrictionBows: + switch (item_type) { + case EQ::item::ItemTypeBow: + break; + default: + is_restricted = true; + break; + } + break; + case EQ::item::AugRestrictionShields: + switch (item_type) { + case EQ::item::ItemTypeShield: + break; + default: + is_restricted = true; + break; + } + break; + case EQ::item::AugRestriction1HSlash1HBluntOrHandToHand: + switch (item_type) { + case EQ::item::ItemType1HSlash: + case EQ::item::ItemType1HBlunt: + case EQ::item::ItemTypeMartial: + break; + default: + is_restricted = true; + break; + } + break; + case EQ::item::AugRestriction1HBluntOrHandToHand: + switch (item_type) { + case EQ::item::ItemType1HBlunt: + case EQ::item::ItemTypeMartial: + break; + default: + is_restricted = true; + break; + } + break; + // These 3 are in-work + case EQ::item::AugRestrictionUnknown1: + case EQ::item::AugRestrictionUnknown2: + case EQ::item::AugRestrictionUnknown3: default: - restrictfail = true; + is_restricted = true; break; - } - break; - case EQ::item::AugRestrictionWeapons: - switch(it) { - case EQ::item::ItemType1HSlash: - case EQ::item::ItemType1HBlunt: - case EQ::item::ItemType1HPiercing: - case EQ::item::ItemTypeMartial: - case EQ::item::ItemType2HSlash: - case EQ::item::ItemType2HBlunt: - case EQ::item::ItemType2HPiercing: - case EQ::item::ItemTypeBow: - break; - default: - restrictfail = true; - break; - } - break; - case EQ::item::AugRestriction1HWeapons: - switch(it) { - case EQ::item::ItemType1HSlash: - case EQ::item::ItemType1HBlunt: - case EQ::item::ItemType1HPiercing: - case EQ::item::ItemTypeMartial: - break; - default: - restrictfail = true; - break; - } - break; - case EQ::item::AugRestriction2HWeapons: - switch(it) { - case EQ::item::ItemType2HSlash: - case EQ::item::ItemType2HBlunt: - case EQ::item::ItemType2HPiercing: - case EQ::item::ItemTypeBow: - break; - default: - restrictfail = true; - break; - } - break; - case EQ::item::AugRestriction1HSlash: - switch(it) { - case EQ::item::ItemType1HSlash: - break; - default: - restrictfail = true; - break; - } - break; - case EQ::item::AugRestriction1HBlunt: - switch(it) { - case EQ::item::ItemType1HBlunt: - break; - default: - restrictfail = true; - break; - } - break; - case EQ::item::AugRestrictionPiercing: - switch(it) { - case EQ::item::ItemType1HPiercing: - break; - default: - restrictfail = true; - break; - } - break; - case EQ::item::AugRestrictionHandToHand: - switch(it) { - case EQ::item::ItemTypeMartial: - break; - default: - restrictfail = true; - break; - } - break; - case EQ::item::AugRestriction2HSlash: - switch(it) { - case EQ::item::ItemType2HSlash: - break; - default: - restrictfail = true; - break; - } - break; - case EQ::item::AugRestriction2HBlunt: - switch(it) { - case EQ::item::ItemType2HBlunt: - break; - default: - restrictfail = true; - break; - } - break; - case EQ::item::AugRestriction2HPierce: - switch(it) { - case EQ::item::ItemType2HPiercing: - break; - default: - restrictfail = true; - break; - } - break; - case EQ::item::AugRestrictionBows: - switch(it) { - case EQ::item::ItemTypeBow: - break; - default: - restrictfail = true; - break; - } - break; - case EQ::item::AugRestrictionShields: - switch(it) { - case EQ::item::ItemTypeShield: - break; - default: - restrictfail = true; - break; - } - break; - case EQ::item::AugRestriction1HSlash1HBluntOrHandToHand: - switch(it) { - case EQ::item::ItemType1HSlash: - case EQ::item::ItemType1HBlunt: - case EQ::item::ItemTypeMartial: - break; - default: - restrictfail = true; - break; - } - break; - case EQ::item::AugRestriction1HBluntOrHandToHand: - switch(it) { - case EQ::item::ItemType1HBlunt: - case EQ::item::ItemTypeMartial: - break; - default: - restrictfail = true; - break; - } - break; - // These 3 are in-work - case EQ::item::AugRestrictionUnknown1: - case EQ::item::AugRestrictionUnknown2: - case EQ::item::AugRestrictionUnknown3: - default: - restrictfail = true; - break; } - if(restrictfail) { - Message(Chat::Red, "Augment %u (Aug%i) is restricted from wear on Item %u.", augments[iter], (iter + 1), item->ID); - LogInventory("Player [{}] on account [{}] attempted to augment an item with a restricted augment (Aug[{}]).\n(Item: [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], Aug6: [{}])\n", - GetName(), account_name, (iter + 1), item->ID, aug1, aug2, aug3, aug4, aug5, aug6); + if(is_restricted) { + Message( + Chat::Red, + fmt::format( + "{} ({}) in Augment Slot {} is restricted from being augmented in to {} ({}).", + database.CreateItemLink(augments[iter]), + augments[iter], + augment_slot, + database.CreateItemLink(item->ID), + item->ID + ).c_str() + ); + LogInventory( + "Player [{}] on account [{}] attempted to augment an item with a restricted augment (Aug[{}]).\n" + "Item [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], Aug6: [{}])\n", + GetName(), + account_name, + augment_slot, + item->ID, + aug1, + aug2, + aug3, + aug4, + aug5, + aug6 + ); return false; } } - if(enforceusable) { + if(enforce_usable) { // check for class usability if(item->Classes && !(classes &= augtest->Classes)) { - Message(Chat::Red, "Augment %u (Aug%i) will result in an item not usable by any class.", augments[iter], (iter + 1)); - LogInventory("Player [{}] on account [{}] attempted to create an item unusable by any class.\n(Item: [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], Aug6: [{}])\n", - GetName(), account_name, item->ID, aug1, aug2, aug3, aug4, aug5, aug6); + Message( + Chat::Red, + fmt::format( + "{} ({}) in Augment Slot {} will result in an item unusable by any class.", + database.CreateItemLink(augments[iter]), + augments[iter], + augment_slot + ).c_str() + ); + LogInventory( + "Player [{}] on account [{}] attempted to create an item unusable by any class.\n" + "Item [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], Aug6: [{}])\n", + GetName(), + account_name, + item->ID, + aug1, + aug2, + aug3, + aug4, + aug5, + aug6 + ); return false; } // check for race usability if(item->Races && !(races &= augtest->Races)) { - Message(Chat::Red, "Augment %u (Aug%i) will result in an item not usable by any race.", augments[iter], (iter + 1)); - LogInventory("Player [{}] on account [{}] attempted to create an item unusable by any race.\n(Item: [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], Aug6: [{}])\n", - GetName(), account_name, item->ID, aug1, aug2, aug3, aug4, aug5, aug6); + Message( + Chat::Red, + fmt::format( + "{} ({}) in Augment Slot {} will result in an item unusable by any race.", + database.CreateItemLink(augments[iter]), + augments[iter], + augment_slot + ).c_str() + ); + LogInventory( + "Player [{}] on account [{}] attempted to create an item unusable by any race.\n" + "Item [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], Aug6: [{}])\n", + GetName(), + account_name, + item->ID, + aug1, + aug2, + aug3, + aug4, + aug5, + aug6 + ); return false; } // check for slot usability if(item->Slots && !(slots &= augtest->Slots)) { - Message(Chat::Red, "Augment %u (Aug%i) will result in an item not usable in any slot.", augments[iter], (iter + 1)); - LogInventory("Player [{}] on account [{}] attempted to create an item unusable in any slot.\n(Item: [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], Aug6: [{}])\n", - GetName(), account_name, item->ID, aug1, aug2, aug3, aug4, aug5, aug6); + Message( + Chat::Red, + fmt::format( + "{} ({}) in Augment Slot {} will result in an item unusable in any slot.", + database.CreateItemLink(augments[iter]), + augments[iter], + augment_slot + ).c_str() + ); + LogInventory( + "Player [{}] on account [{}] attempted to create an item unusable in any slot.\n" + "Item [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], Aug6: [{}])\n", + GetName(), + account_name, + item->ID, + aug1, + aug2, + aug3, + aug4, + aug5, + aug6 + ); return false; } @@ -506,12 +701,11 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, // if the item is stackable and the charge amount is -1 or 0 then set to 1 charge. // removed && item->MaxCharges == 0 if -1 or 0 was passed max charges is irrelevant - if(charges <= 0 && item->Stackable) + if(charges <= 0 && item->Stackable) { charges = 1; - - // if the charges is -1, then no charge value was passed in set to max charges - else if(charges == -1) + } else if(charges == -1) { // if the charges is -1, then no charge value was passed in set to max charges charges = item->MaxCharges; + } // in any other situation just use charges as passed @@ -520,35 +714,67 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, if(inst == nullptr) { Message(Chat::Red, "An unknown server error has occurred and your item was not created."); // this goes to logfile since this is a major error - LogError("Player [{}] on account [{}] encountered an unknown item creation error.\n(Item: [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], Aug6: [{}])\n", - GetName(), account_name, item->ID, aug1, aug2, aug3, aug4, aug5, aug6); + LogError( + "Player [{}] on account [{}] encountered an unknown item creation error.\n" + "Item [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], Aug6: [{}])\n", + GetName(), + account_name, + item->ID, + aug1, + aug2, + aug3, + aug4, + aug5, + aug6 + ); return false; } // add any validated augments for (int iter = EQ::invaug::SOCKET_BEGIN; iter <= EQ::invaug::SOCKET_END; ++iter) { - if(augments[iter]) + if(augments[iter]) { inst->PutAugment(&database, iter, augments[iter]); + } } // attune item - if(attuned && inst->GetItem()->Attuneable) + if(attuned && inst->GetItem()->Attuneable) { inst->SetAttuned(true); + } inst->SetOrnamentIcon(ornament_icon); inst->SetOrnamentationIDFile(ornament_idfile); inst->SetOrnamentHeroModel(ornament_hero_model); // check to see if item is usable in requested slot - if (enforceusable && (to_slot >= EQ::invslot::EQUIPMENT_BEGIN && to_slot <= EQ::invslot::EQUIPMENT_END)) { + if (enforce_usable && (to_slot >= EQ::invslot::EQUIPMENT_BEGIN && to_slot <= EQ::invslot::EQUIPMENT_END)) { uint32 slottest = to_slot; - if(!(slots & ((uint32)1 << slottest))) { - Message(0, "This item is not equipable at slot %u - moving to cursor.", to_slot); - LogInventory("Player [{}] on account [{}] attempted to equip an item unusable in slot [{}] - moved to cursor.\n(Item: [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], Aug6: [{}])\n", - GetName(), account_name, to_slot, item->ID, aug1, aug2, aug3, aug4, aug5, aug6); - + Message( + Chat::White, + fmt::format( + "{} ({}) cannot be equipped in {} ({}), moving to cursor.", + database.CreateItemLink(item->ID), + item->ID, + EQ::invslot::GetInvPossessionsSlotName(to_slot), + to_slot + ).c_str() + ); + LogInventory( + "Player [{}] on account [{}] attempted to equip an item unusable in slot [{}] - moved to cursor.\n" + "Item [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], Aug6: [{}])\n", + GetName(), + account_name, + to_slot, + item->ID, + aug1, + aug2, + aug3, + aug4, + aug5, + aug6 + ); to_slot = EQ::invslot::slotCursor; } } @@ -557,8 +783,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, if (to_slot == EQ::invslot::slotCursor) { PushItemOnCursor(*inst); SendItemPacket(EQ::invslot::slotCursor, inst, ItemPacketLimbo); - } - else { + } else { PutItemInInventory(to_slot, *inst, true); } @@ -566,8 +791,9 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, // discover item and any augments if((RuleB(Character, EnableDiscoveredItems)) && !GetGM()) { - if(!IsDiscovered(item_id)) + if(!IsDiscovered(item_id)) { DiscoverItem(item_id); + } /* // Augments should have been discovered prior to being placed on an item. for (int iter = AUG_BEGIN; iter < EQ::constants::ITEM_COMMON_SIZE; ++iter) { @@ -2522,7 +2748,7 @@ void Client::DisenchantSummonedBags(bool client_update) { for (auto slot_id = EQ::invslot::GENERAL_BEGIN; slot_id <= EQ::invslot::GENERAL_END; ++slot_id) { if (((uint64)1 << slot_id) & GetInv().GetLookup()->PossessionsBitmask == 0) - continue; // not useable this session - will be disenchanted once player logs in on client that doesn't exclude affected slots + continue; // not usable this session - will be disenchanted once player logs in on client that doesn't exclude affected slots auto inst = m_inv[slot_id]; if (!inst) { continue; } diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index eb9bef15d..441b490a1 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -2141,12 +2141,12 @@ void Lua_Client::SetEXPModifier(uint32 zone_id, double exp_modifier) { void Lua_Client::AddLDoNLoss(uint32 theme_id) { Lua_Safe_Call_Void(); - self->AddLDoNLoss(theme_id); + self->UpdateLDoNWinLoss(theme_id); } void Lua_Client::AddLDoNWin(uint32 theme_id) { Lua_Safe_Call_Void(); - self->AddLDoNWin(theme_id); + self->UpdateLDoNWinLoss(theme_id, true); } void Lua_Client::SetHideMe(bool hide_me_state) { @@ -2281,6 +2281,16 @@ void Lua_Client::SummonBaggedItems(uint32 bag_item_id, luabind::adl::object bag_ self->SummonBaggedItems(bag_item_id, bagged_items); } +void Lua_Client::RemoveLDoNLoss(uint32 theme_id) { + Lua_Safe_Call_Void(); + self->UpdateLDoNWinLoss(theme_id, false, true); +} + +void Lua_Client::RemoveLDoNWin(uint32 theme_id) { + Lua_Safe_Call_Void(); + self->UpdateLDoNWinLoss(theme_id, true, true); +} + luabind::scope lua_register_client() { return luabind::class_("Client") .def(luabind::constructor<>()) @@ -2661,7 +2671,9 @@ luabind::scope lua_register_client() { .def("SetGMStatus", (void(Lua_Client::*)(int32))&Lua_Client::SetGMStatus) .def("UntrainDiscBySpellID", (void(Lua_Client::*)(uint16))&Lua_Client::UntrainDiscBySpellID) .def("UntrainDiscBySpellID", (void(Lua_Client::*)(uint16,bool))&Lua_Client::UntrainDiscBySpellID) - .def("SummonBaggedItems", (void(Lua_Client::*)(uint32,luabind::adl::object))&Lua_Client::SummonBaggedItems); + .def("SummonBaggedItems", (void(Lua_Client::*)(uint32,luabind::adl::object))&Lua_Client::SummonBaggedItems) + .def("RemoveLDoNLoss", (void(Lua_Client::*)(uint32))&Lua_Client::RemoveLDoNLoss) + .def("RemoveLDoNWin", (void(Lua_Client::*)(uint32))&Lua_Client::RemoveLDoNWin); } luabind::scope lua_register_inventory_where() { diff --git a/zone/lua_client.h b/zone/lua_client.h index add5089b7..a5fbd0834 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -81,6 +81,8 @@ public: uint32 GetTotalSecondsPlayed(); void AddLDoNLoss(uint32 theme_id); void AddLDoNWin(uint32 theme_id); + void RemoveLDoNLoss(uint32 theme_id); + void RemoveLDoNWin(uint32 theme_id); void UpdateLDoNPoints(uint32 theme_id, int points); void SetDeity(int v); void AddEXP(uint32 add_exp); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index b6652302b..283ed5db8 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -1889,6 +1889,14 @@ void lua_add_ldon_win(uint32 theme_id) { quest_manager.addldonwin(theme_id); } +void lua_remove_ldon_loss(uint32 theme_id) { + quest_manager.removeldonloss(theme_id); +} + +void lua_remove_ldon_win(uint32 theme_id) { + quest_manager.addldonwin(theme_id); +} + std::string lua_get_clean_npc_name_by_id(uint32 npc_id) { return quest_manager.getcleannpcnamebyid(npc_id); } @@ -1927,37 +1935,37 @@ int lua_get_spell_stat(uint32 spell_id, std::string stat_identifier, uint8 slot) void lua_cross_zone_add_ldon_loss_by_char_id(int character_id, uint32 theme_id) { uint8 update_type = CZUpdateType_Character; - uint8 update_subtype = CZLDoNUpdateSubtype_Loss; + uint8 update_subtype = CZLDoNUpdateSubtype_AddLoss; quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, character_id, theme_id); } void lua_cross_zone_add_ldon_loss_by_group_id(int group_id, uint32 theme_id) { uint8 update_type = CZUpdateType_Group; - uint8 update_subtype = CZLDoNUpdateSubtype_Loss; + uint8 update_subtype = CZLDoNUpdateSubtype_AddLoss; quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, group_id, theme_id); } void lua_cross_zone_add_ldon_loss_by_raid_id(int raid_id, uint32 theme_id) { uint8 update_type = CZUpdateType_Raid; - uint8 update_subtype = CZLDoNUpdateSubtype_Loss; + uint8 update_subtype = CZLDoNUpdateSubtype_AddLoss; quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, raid_id, theme_id); } void lua_cross_zone_add_ldon_loss_by_guild_id(int guild_id, uint32 theme_id) { uint8 update_type = CZUpdateType_Guild; - uint8 update_subtype = CZLDoNUpdateSubtype_Loss; + uint8 update_subtype = CZLDoNUpdateSubtype_AddLoss; quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, guild_id, theme_id); } void lua_cross_zone_add_ldon_loss_by_expedition_id(uint32 expedition_id, uint32 theme_id) { uint8 update_type = CZUpdateType_Expedition; - uint8 update_subtype = CZLDoNUpdateSubtype_Loss; + uint8 update_subtype = CZLDoNUpdateSubtype_AddLoss; quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, expedition_id, theme_id); } void lua_cross_zone_add_ldon_loss_by_client_name(const char* client_name, uint32 theme_id) { uint8 update_type = CZUpdateType_ClientName; - uint8 update_subtype = CZLDoNUpdateSubtype_Loss; + uint8 update_subtype = CZLDoNUpdateSubtype_AddLoss; int update_identifier = 0; int points = 1; quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, update_identifier, theme_id, points, client_name); @@ -1965,74 +1973,74 @@ void lua_cross_zone_add_ldon_loss_by_client_name(const char* client_name, uint32 void lua_cross_zone_add_ldon_points_by_char_id(int character_id, uint32 theme_id, int points) { uint8 update_type = CZUpdateType_Character; - uint8 update_subtype = CZLDoNUpdateSubtype_Points; + uint8 update_subtype = CZLDoNUpdateSubtype_AddPoints; quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, character_id, theme_id, points); } void lua_cross_zone_add_ldon_points_by_group_id(int group_id, uint32 theme_id, int points) { uint8 update_type = CZUpdateType_Group; - uint8 update_subtype = CZLDoNUpdateSubtype_Points; + uint8 update_subtype = CZLDoNUpdateSubtype_AddPoints; quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, group_id, theme_id, points); } void lua_cross_zone_add_ldon_points_by_raid_id(int raid_id, uint32 theme_id, int points) { uint8 update_type = CZUpdateType_Raid; - uint8 update_subtype = CZLDoNUpdateSubtype_Points; + uint8 update_subtype = CZLDoNUpdateSubtype_AddPoints; quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, raid_id, theme_id, points); } void lua_cross_zone_add_ldon_points_by_guild_id(int guild_id, uint32 theme_id, int points) { uint8 update_type = CZUpdateType_Guild; - uint8 update_subtype = CZLDoNUpdateSubtype_Points; + uint8 update_subtype = CZLDoNUpdateSubtype_AddPoints; quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, guild_id, theme_id, points); } void lua_cross_zone_add_ldon_points_by_expedition_id(uint32 expedition_id, uint32 theme_id, int points) { uint8 update_type = CZUpdateType_Expedition; - uint8 update_subtype = CZLDoNUpdateSubtype_Points; + uint8 update_subtype = CZLDoNUpdateSubtype_AddPoints; quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, expedition_id, theme_id, points); } void lua_cross_zone_add_ldon_points_by_client_name(const char* client_name, uint32 theme_id, int points) { uint8 update_type = CZUpdateType_ClientName; - uint8 update_subtype = CZLDoNUpdateSubtype_Points; + uint8 update_subtype = CZLDoNUpdateSubtype_AddPoints; int update_identifier = 0; quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, update_identifier, theme_id, points, client_name); } void lua_cross_zone_add_ldon_win_by_char_id(int character_id, uint32 theme_id) { uint8 update_type = CZUpdateType_Character; - uint8 update_subtype = CZLDoNUpdateSubtype_Win; + uint8 update_subtype = CZLDoNUpdateSubtype_AddWin; quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, character_id, theme_id); } void lua_cross_zone_add_ldon_win_by_group_id(int group_id, uint32 theme_id) { uint8 update_type = CZUpdateType_Group; - uint8 update_subtype = CZLDoNUpdateSubtype_Win; + uint8 update_subtype = CZLDoNUpdateSubtype_AddWin; quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, group_id, theme_id); } void lua_cross_zone_add_ldon_win_by_raid_id(int raid_id, uint32 theme_id) { uint8 update_type = CZUpdateType_Raid; - uint8 update_subtype = CZLDoNUpdateSubtype_Win; + uint8 update_subtype = CZLDoNUpdateSubtype_AddWin; quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, raid_id, theme_id); } void lua_cross_zone_add_ldon_win_by_guild_id(int guild_id, uint32 theme_id) { uint8 update_type = CZUpdateType_Guild; - uint8 update_subtype = CZLDoNUpdateSubtype_Win; + uint8 update_subtype = CZLDoNUpdateSubtype_AddWin; quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, guild_id, theme_id); } void lua_cross_zone_add_ldon_win_by_expedition_id(uint32 expedition_id, uint32 theme_id) { uint8 update_type = CZUpdateType_Expedition; - uint8 update_subtype = CZLDoNUpdateSubtype_Win; + uint8 update_subtype = CZLDoNUpdateSubtype_AddWin; quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, expedition_id, theme_id); } void lua_cross_zone_add_ldon_win_by_client_name(const char* client_name, uint32 theme_id) { uint8 update_type = CZUpdateType_ClientName; - uint8 update_subtype = CZLDoNUpdateSubtype_Win; + uint8 update_subtype = CZLDoNUpdateSubtype_AddWin; int update_identifier = 0; int points = 1; quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, update_identifier, theme_id, points, client_name); @@ -2523,6 +2531,82 @@ void lua_cross_zone_move_instance_by_client_name(const char* client_name, uint16 quest_manager.CrossZoneMove(update_type, update_subtype, update_identifier, zone_short_name, instance_id, client_name); } +void lua_cross_zone_remove_ldon_loss_by_char_id(int character_id, uint32 theme_id) { + uint8 update_type = CZUpdateType_Character; + uint8 update_subtype = CZLDoNUpdateSubtype_RemoveLoss; + quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, character_id, theme_id); +} + +void lua_cross_zone_remove_ldon_loss_by_group_id(int group_id, uint32 theme_id) { + uint8 update_type = CZUpdateType_Group; + uint8 update_subtype = CZLDoNUpdateSubtype_RemoveLoss; + quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, group_id, theme_id); +} + +void lua_cross_zone_remove_ldon_loss_by_raid_id(int raid_id, uint32 theme_id) { + uint8 update_type = CZUpdateType_Raid; + uint8 update_subtype = CZLDoNUpdateSubtype_RemoveLoss; + quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, raid_id, theme_id); +} + +void lua_cross_zone_remove_ldon_loss_by_guild_id(int guild_id, uint32 theme_id) { + uint8 update_type = CZUpdateType_Guild; + uint8 update_subtype = CZLDoNUpdateSubtype_RemoveLoss; + quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, guild_id, theme_id); +} + +void lua_cross_zone_remove_ldon_loss_by_expedition_id(uint32 expedition_id, uint32 theme_id) { + uint8 update_type = CZUpdateType_Expedition; + uint8 update_subtype = CZLDoNUpdateSubtype_RemoveLoss; + quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, expedition_id, theme_id); +} + +void lua_cross_zone_remove_ldon_loss_by_client_name(const char* client_name, uint32 theme_id) { + uint8 update_type = CZUpdateType_ClientName; + uint8 update_subtype = CZLDoNUpdateSubtype_RemoveLoss; + int update_identifier = 0; + int points = 1; + quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, update_identifier, theme_id, points, client_name); +} + +void lua_cross_zone_remove_ldon_win_by_char_id(int character_id, uint32 theme_id) { + uint8 update_type = CZUpdateType_Character; + uint8 update_subtype = CZLDoNUpdateSubtype_RemoveWin; + quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, character_id, theme_id); +} + +void lua_cross_zone_remove_ldon_win_by_group_id(int group_id, uint32 theme_id) { + uint8 update_type = CZUpdateType_Group; + uint8 update_subtype = CZLDoNUpdateSubtype_RemoveWin; + quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, group_id, theme_id); +} + +void lua_cross_zone_remove_ldon_win_by_raid_id(int raid_id, uint32 theme_id) { + uint8 update_type = CZUpdateType_Raid; + uint8 update_subtype = CZLDoNUpdateSubtype_RemoveWin; + quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, raid_id, theme_id); +} + +void lua_cross_zone_remove_ldon_win_by_guild_id(int guild_id, uint32 theme_id) { + uint8 update_type = CZUpdateType_Guild; + uint8 update_subtype = CZLDoNUpdateSubtype_RemoveWin; + quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, guild_id, theme_id); +} + +void lua_cross_zone_remove_ldon_win_by_expedition_id(uint32 expedition_id, uint32 theme_id) { + uint8 update_type = CZUpdateType_Expedition; + uint8 update_subtype = CZLDoNUpdateSubtype_RemoveWin; + quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, expedition_id, theme_id); +} + +void lua_cross_zone_remove_ldon_win_by_client_name(const char* client_name, uint32 theme_id) { + uint8 update_type = CZUpdateType_ClientName; + uint8 update_subtype = CZLDoNUpdateSubtype_RemoveWin; + int update_identifier = 0; + int points = 1; + quest_manager.CrossZoneLDoNUpdate(update_type, update_subtype, update_identifier, theme_id, points, client_name); +} + void lua_cross_zone_remove_spell_by_char_id(int character_id, uint32 spell_id) { uint8 update_type = CZUpdateType_Character; uint8 update_subtype = CZSpellUpdateSubtype_Remove; @@ -2824,50 +2908,50 @@ void lua_cross_zone_update_activity_by_client_name(const char* client_name, uint } void lua_world_wide_add_ldon_loss(uint32 theme_id) { - uint8 update_type = WWLDoNUpdateType_Loss; + uint8 update_type = WWLDoNUpdateType_AddLoss; quest_manager.WorldWideLDoNUpdate(update_type, theme_id); } void lua_world_wide_add_ldon_loss(uint32 theme_id, uint8 min_status) { - uint8 update_type = WWLDoNUpdateType_Loss; + uint8 update_type = WWLDoNUpdateType_AddLoss; int points = 1; quest_manager.WorldWideLDoNUpdate(update_type, theme_id, points, min_status); } void lua_world_wide_add_ldon_loss(uint32 theme_id, uint8 min_status, uint8 max_status) { - uint8 update_type = WWLDoNUpdateType_Loss; + uint8 update_type = WWLDoNUpdateType_AddLoss; int points = 1; quest_manager.WorldWideLDoNUpdate(update_type, theme_id, points, min_status, max_status); } void lua_world_wide_add_ldon_points(uint32 theme_id, int points) { - uint8 update_type = WWLDoNUpdateType_Points; + uint8 update_type = WWLDoNUpdateType_AddPoints; quest_manager.WorldWideLDoNUpdate(update_type, theme_id, points); } void lua_world_wide_add_ldon_points(uint32 theme_id, int points, uint8 min_status) { - uint8 update_type = WWLDoNUpdateType_Points; + uint8 update_type = WWLDoNUpdateType_AddPoints; quest_manager.WorldWideLDoNUpdate(update_type, theme_id, points, min_status); } void lua_world_wide_add_ldon_points(uint32 theme_id, int points, uint8 min_status, uint8 max_status) { - uint8 update_type = WWLDoNUpdateType_Points; + uint8 update_type = WWLDoNUpdateType_AddPoints; quest_manager.WorldWideLDoNUpdate(update_type, theme_id, points, min_status, max_status); } void lua_world_wide_add_ldon_win(uint32 theme_id) { - uint8 update_type = WWLDoNUpdateType_Win; + uint8 update_type = WWLDoNUpdateType_AddWin; quest_manager.WorldWideLDoNUpdate(update_type, theme_id); } void lua_world_wide_add_ldon_win(uint32 theme_id, uint8 min_status) { - uint8 update_type = WWLDoNUpdateType_Win; + uint8 update_type = WWLDoNUpdateType_AddWin; int points = 1; quest_manager.WorldWideLDoNUpdate(update_type, theme_id, points, min_status); } void lua_world_wide_add_ldon_win(uint32 theme_id, uint8 min_status, uint8 max_status) { - uint8 update_type = WWLDoNUpdateType_Win; + uint8 update_type = WWLDoNUpdateType_AddWin; int points = 1; quest_manager.WorldWideLDoNUpdate(update_type, theme_id, points, min_status, max_status); } @@ -3047,6 +3131,40 @@ void lua_world_wide_move_instance(uint16 instance_id, uint8 min_status, uint8 ma quest_manager.WorldWideMove(update_type, zone_short_name, instance_id, min_status, max_status); } +void lua_world_wide_remove_ldon_loss(uint32 theme_id) { + uint8 update_type = WWLDoNUpdateType_RemoveLoss; + quest_manager.WorldWideLDoNUpdate(update_type, theme_id); +} + +void lua_world_wide_remove_ldon_loss(uint32 theme_id, uint8 min_status) { + uint8 update_type = WWLDoNUpdateType_RemoveLoss; + int points = 1; + quest_manager.WorldWideLDoNUpdate(update_type, theme_id, points, min_status); +} + +void lua_world_wide_remove_ldon_loss(uint32 theme_id, uint8 min_status, uint8 max_status) { + uint8 update_type = WWLDoNUpdateType_RemoveLoss; + int points = 1; + quest_manager.WorldWideLDoNUpdate(update_type, theme_id, points, min_status, max_status); +} + +void lua_world_wide_remove_ldon_win(uint32 theme_id) { + uint8 update_type = WWLDoNUpdateType_RemoveWin; + quest_manager.WorldWideLDoNUpdate(update_type, theme_id); +} + +void lua_world_wide_remove_ldon_win(uint32 theme_id, uint8 min_status) { + uint8 update_type = WWLDoNUpdateType_RemoveWin; + int points = 1; + quest_manager.WorldWideLDoNUpdate(update_type, theme_id, points, min_status); +} + +void lua_world_wide_remove_ldon_win(uint32 theme_id, uint8 min_status, uint8 max_status) { + uint8 update_type = WWLDoNUpdateType_RemoveWin; + int points = 1; + quest_manager.WorldWideLDoNUpdate(update_type, theme_id, points, min_status, max_status); +} + void lua_world_wide_remove_spell(uint32 spell_id) { uint8 update_type = WWSpellUpdateType_Remove; quest_manager.WorldWideSpell(update_type, spell_id); @@ -3753,6 +3871,18 @@ luabind::scope lua_register_general() { luabind::def("cross_zone_move_instance_by_guild_id", &lua_cross_zone_move_instance_by_guild_id), luabind::def("cross_zone_move_instance_by_expedition_id", &lua_cross_zone_move_instance_by_expedition_id), luabind::def("cross_zone_move_instance_by_client_name", &lua_cross_zone_move_instance_by_client_name), + luabind::def("cross_zone_remove_ldon_loss_by_char_id", &lua_cross_zone_remove_ldon_loss_by_char_id), + luabind::def("cross_zone_remove_ldon_loss_by_group_id", &lua_cross_zone_remove_ldon_loss_by_group_id), + luabind::def("cross_zone_remove_ldon_loss_by_raid_id", &lua_cross_zone_remove_ldon_loss_by_raid_id), + luabind::def("cross_zone_remove_ldon_loss_by_guild_id", &lua_cross_zone_remove_ldon_loss_by_guild_id), + luabind::def("cross_zone_remove_ldon_loss_by_expedition_id", &lua_cross_zone_remove_ldon_loss_by_expedition_id), + luabind::def("cross_zone_remove_ldon_loss_by_client_name", &lua_cross_zone_remove_ldon_loss_by_client_name), + luabind::def("cross_zone_remove_ldon_win_by_char_id", &lua_cross_zone_remove_ldon_win_by_char_id), + luabind::def("cross_zone_remove_ldon_win_by_group_id", &lua_cross_zone_remove_ldon_win_by_group_id), + luabind::def("cross_zone_remove_ldon_win_by_raid_id", &lua_cross_zone_remove_ldon_win_by_raid_id), + luabind::def("cross_zone_remove_ldon_win_by_guild_id", &lua_cross_zone_remove_ldon_win_by_guild_id), + luabind::def("cross_zone_remove_ldon_win_by_expedition_id", &lua_cross_zone_remove_ldon_win_by_expedition_id), + luabind::def("cross_zone_remove_ldon_win_by_client_name", &lua_cross_zone_remove_ldon_win_by_client_name), luabind::def("cross_zone_remove_spell_by_char_id", &lua_cross_zone_remove_spell_by_char_id), luabind::def("cross_zone_remove_spell_by_group_id", &lua_cross_zone_remove_spell_by_group_id), luabind::def("cross_zone_remove_spell_by_raid_id", &lua_cross_zone_remove_spell_by_raid_id), diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index de16ec1dd..264b3b09b 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -5555,7 +5555,7 @@ XS(XS_Client_AddLDoNLoss) { Client* THIS; uint32 theme_id = (uint32) SvUV(ST(1)); VALIDATE_THIS_IS_CLIENT; - THIS->AddLDoNLoss(theme_id); + THIS->UpdateLDoNWinLoss(theme_id); } XSRETURN_EMPTY; } @@ -5569,7 +5569,7 @@ XS(XS_Client_AddLDoNWin) { Client* THIS; uint32 theme_id = (uint32) SvUV(ST(1)); VALIDATE_THIS_IS_CLIENT; - THIS->AddLDoNWin(theme_id); + THIS->UpdateLDoNWinLoss(theme_id, true); } XSRETURN_EMPTY; } @@ -5837,6 +5837,34 @@ XS(XS_Client_SummonBaggedItems) { XSRETURN_EMPTY; } +XS(XS_Client_RemoveLDoNLoss); +XS(XS_Client_RemoveLDoNLoss) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: Client::RemoveLDoNLoss(THIS, uint32 theme_id)"); + { + Client* THIS; + uint32 theme_id = (uint32) SvUV(ST(1)); + VALIDATE_THIS_IS_CLIENT; + THIS->UpdateLDoNWinLoss(theme_id, false, true); + } + XSRETURN_EMPTY; +} + +XS(XS_Client_RemoveLDoNWin); +XS(XS_Client_RemoveLDoNWin) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: Client::RemoveLDoNWin(THIS, uint32 theme_id)"); + { + Client* THIS; + uint32 theme_id = (uint32) SvUV(ST(1)); + VALIDATE_THIS_IS_CLIENT; + THIS->UpdateLDoNWinLoss(theme_id, true, true); + } + XSRETURN_EMPTY; +} + #ifdef __cplusplus extern "C" #endif @@ -6062,6 +6090,8 @@ XS(boot_Client) { newXSproto(strcpy(buf, "RemoveAllExpeditionLockouts"), XS_Client_RemoveAllExpeditionLockouts, file, "$;$"); newXSproto(strcpy(buf, "RemoveExpeditionLockout"), XS_Client_RemoveExpeditionLockout, file, "$$$"); newXSproto(strcpy(buf, "RemoveItem"), XS_Client_RemoveItem, file, "$$;$"); + newXSproto(strcpy(buf, "RemoveLDoNLoss"), XS_Client_RemoveLDoNLoss, file, "$$"); + newXSproto(strcpy(buf, "RemoveLDoNWin"), XS_Client_RemoveLDoNWin, file, "$$"); newXSproto(strcpy(buf, "RemoveNoRent"), XS_Client_RemoveNoRent, file, "$"); newXSproto(strcpy(buf, "ResetAA"), XS_Client_ResetAA, file, "$"); newXSproto(strcpy(buf, "ResetAllDisciplineTimers"), XS_Client_ResetAllDisciplineTimers, file, "$"); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index e2fa0617b..89b47aea8 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -1761,14 +1761,30 @@ void QuestManager::addldonpoints(uint32 theme_id, int points) { void QuestManager::addldonloss(uint32 theme_id) { QuestManagerCurrentQuestVars(); - if(initiator) - initiator->AddLDoNLoss(theme_id); + if(initiator) { + initiator->UpdateLDoNWinLoss(theme_id); + } } void QuestManager::addldonwin(uint32 theme_id) { QuestManagerCurrentQuestVars(); - if(initiator) - initiator->AddLDoNWin(theme_id); + if(initiator) { + initiator->UpdateLDoNWinLoss(theme_id, true); + } +} + +void QuestManager::removeldonloss(uint32 theme_id) { + QuestManagerCurrentQuestVars(); + if(initiator) { + initiator->UpdateLDoNWinLoss(theme_id, false, true); + } +} + +void QuestManager::removeldonwin(uint32 theme_id) { + QuestManagerCurrentQuestVars(); + if(initiator) { + initiator->UpdateLDoNWinLoss(theme_id, true, true); + } } void QuestManager::setnexthpevent(int at) { diff --git a/zone/questmgr.h b/zone/questmgr.h index 00221c965..4098fd75a 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -162,6 +162,8 @@ public: void addldonpoints(uint32 theme_id, int points); void addldonloss(uint32 theme_id); void addldonwin(uint32 theme_id); + void removeldonloss(uint32 theme_id); + void removeldonwin(uint32 theme_id); void setnexthpevent(int at); void setnextinchpevent(int at); void respawn(int npc_type, int grid); diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 36d1b7c22..a77eb4a17 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -1953,14 +1953,20 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) auto client = entity_list.GetClientByCharID(update_identifier); if (client) { switch (update_subtype) { - case CZLDoNUpdateSubtype_Loss: - client->AddLDoNLoss(theme_id); + case CZLDoNUpdateSubtype_AddLoss: + client->UpdateLDoNWinLoss(theme_id, false); break; - case CZLDoNUpdateSubtype_Points: + case CZLDoNUpdateSubtype_AddPoints: client->UpdateLDoNPoints(theme_id, points); break; - case CZLDoNUpdateSubtype_Win: - client->AddLDoNWin(theme_id); + case CZLDoNUpdateSubtype_AddWin: + client->UpdateLDoNWinLoss(theme_id, true); + break; + case CZLDoNUpdateSubtype_RemoveLoss: + client->UpdateLDoNWinLoss(theme_id, false, true); + break; + case CZLDoNUpdateSubtype_RemoveWin: + client->UpdateLDoNWinLoss(theme_id, true, true); break; default: break; @@ -1974,14 +1980,20 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) if (client_group->members[member_index] && client_group->members[member_index]->IsClient()) { auto client_group_member = client_group->members[member_index]->CastToClient(); switch (update_subtype) { - case CZLDoNUpdateSubtype_Loss: - client_group_member->AddLDoNLoss(theme_id); + case CZLDoNUpdateSubtype_AddLoss: + client_group_member->UpdateLDoNWinLoss(theme_id, false); break; - case CZLDoNUpdateSubtype_Points: + case CZLDoNUpdateSubtype_AddPoints: client_group_member->UpdateLDoNPoints(theme_id, points); break; - case CZLDoNUpdateSubtype_Win: - client_group_member->AddLDoNWin(theme_id); + case CZLDoNUpdateSubtype_AddWin: + client_group_member->UpdateLDoNWinLoss(theme_id, true); + break; + case CZLDoNUpdateSubtype_RemoveLoss: + client_group_member->UpdateLDoNWinLoss(theme_id, false, true); + break; + case CZLDoNUpdateSubtype_RemoveWin: + client_group_member->UpdateLDoNWinLoss(theme_id, true, true); break; default: break; @@ -1996,14 +2008,20 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) auto client_raid_member = client_raid->members[member_index].member; if (client_raid_member && client_raid_member->IsClient()) { switch (update_subtype) { - case CZLDoNUpdateSubtype_Loss: - client_raid_member->AddLDoNLoss(theme_id); + case CZLDoNUpdateSubtype_AddLoss: + client_raid_member->UpdateLDoNWinLoss(theme_id, false); break; - case CZLDoNUpdateSubtype_Points: + case CZLDoNUpdateSubtype_AddPoints: client_raid_member->UpdateLDoNPoints(theme_id, points); break; - case CZLDoNUpdateSubtype_Win: - client_raid_member->AddLDoNWin(theme_id); + case CZLDoNUpdateSubtype_AddWin: + client_raid_member->UpdateLDoNWinLoss(theme_id, true); + break; + case CZLDoNUpdateSubtype_RemoveLoss: + client_raid_member->UpdateLDoNWinLoss(theme_id, false, true); + break; + case CZLDoNUpdateSubtype_RemoveWin: + client_raid_member->UpdateLDoNWinLoss(theme_id, true, true); break; default: break; @@ -2015,14 +2033,20 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) for (auto &client : entity_list.GetClientList()) { if (client.second->GuildID() > 0 && client.second->GuildID() == update_identifier) { switch (update_subtype) { - case CZLDoNUpdateSubtype_Loss: - client.second->AddLDoNLoss(theme_id); + case CZLDoNUpdateSubtype_AddLoss: + client.second->UpdateLDoNWinLoss(theme_id, false); break; - case CZLDoNUpdateSubtype_Points: + case CZLDoNUpdateSubtype_AddPoints: client.second->UpdateLDoNPoints(theme_id, points); break; - case CZLDoNUpdateSubtype_Win: - client.second->AddLDoNWin(theme_id); + case CZLDoNUpdateSubtype_AddWin: + client.second->UpdateLDoNWinLoss(theme_id, true); + break; + case CZLDoNUpdateSubtype_RemoveLoss: + client.second->UpdateLDoNWinLoss(theme_id, false, true); + break; + case CZLDoNUpdateSubtype_RemoveWin: + client.second->UpdateLDoNWinLoss(theme_id, true, true); break; default: break; @@ -2033,14 +2057,20 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) for (auto &client : entity_list.GetClientList()) { if (client.second->GetExpedition() && client.second->GetExpedition()->GetID() == update_identifier) { switch (update_subtype) { - case CZLDoNUpdateSubtype_Loss: - client.second->AddLDoNLoss(theme_id); + case CZLDoNUpdateSubtype_AddLoss: + client.second->UpdateLDoNWinLoss(theme_id, false); break; - case CZLDoNUpdateSubtype_Points: + case CZLDoNUpdateSubtype_AddPoints: client.second->UpdateLDoNPoints(theme_id, points); break; - case CZLDoNUpdateSubtype_Win: - client.second->AddLDoNWin(theme_id); + case CZLDoNUpdateSubtype_AddWin: + client.second->UpdateLDoNWinLoss(theme_id, true); + break; + case CZLDoNUpdateSubtype_RemoveLoss: + client.second->UpdateLDoNWinLoss(theme_id, false, true); + break; + case CZLDoNUpdateSubtype_RemoveWin: + client.second->UpdateLDoNWinLoss(theme_id, true, true); break; default: break; @@ -2051,14 +2081,20 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) auto client = entity_list.GetClientByName(client_name); if (client) { switch (update_subtype) { - case CZLDoNUpdateSubtype_Loss: - client->AddLDoNLoss(theme_id); + case CZLDoNUpdateSubtype_AddLoss: + client->UpdateLDoNWinLoss(theme_id, false); break; - case CZLDoNUpdateSubtype_Points: + case CZLDoNUpdateSubtype_AddPoints: client->UpdateLDoNPoints(theme_id, points); break; - case CZLDoNUpdateSubtype_Win: - client->AddLDoNWin(theme_id); + case CZLDoNUpdateSubtype_AddWin: + client->UpdateLDoNWinLoss(theme_id, true); + break; + case CZLDoNUpdateSubtype_RemoveLoss: + client->UpdateLDoNWinLoss(theme_id, false, true); + break; + case CZLDoNUpdateSubtype_RemoveWin: + client->UpdateLDoNWinLoss(theme_id, true, true); break; default: break; @@ -2696,19 +2732,29 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) uint8 max_status = WWLU->max_status; for (auto &client : entity_list.GetClientList()) { switch (update_type) { - case WWLDoNUpdateType_Loss: + case WWLDoNUpdateType_AddLoss: if (client.second->Admin() >= min_status && (client.second->Admin() <= max_status || max_status == 0)) { - client.second->AddLDoNLoss(theme_id); + client.second->UpdateLDoNWinLoss(theme_id, false); } break; - case WWLDoNUpdateType_Points: + case WWLDoNUpdateType_AddPoints: if (client.second->Admin() >= min_status && (client.second->Admin() <= max_status || max_status == 0)) { client.second->UpdateLDoNPoints(theme_id, points); } break; - case WWLDoNUpdateType_Win: + case WWLDoNUpdateType_AddWin: if (client.second->Admin() >= min_status && (client.second->Admin() <= max_status || max_status == 0)) { - client.second->AddLDoNWin(theme_id); + client.second->UpdateLDoNWinLoss(theme_id, true); + } + break; + case WWLDoNUpdateType_RemoveLoss: + if (client.second->Admin() >= min_status && (client.second->Admin() <= max_status || max_status == 0)) { + client.second->UpdateLDoNWinLoss(theme_id, false, true); + } + break; + case WWLDoNUpdateType_RemoveWin: + if (client.second->Admin() >= min_status && (client.second->Admin() <= max_status || max_status == 0)) { + client.second->UpdateLDoNWinLoss(theme_id, true, true); } break; }