Compare commits

..

6 Commits

Author SHA1 Message Date
Kinglykrab df746dd07d Add slot ID conversions 2024-11-21 23:29:10 -05:00
Kinglykrab cd158aabca Cleanup 2024-11-21 23:29:10 -05:00
Kinglykrab 95687b57e9 Cleanup 2024-11-21 23:29:10 -05:00
Kinglykrab 77de74a089 Update shareddb.cpp 2024-11-21 23:29:10 -05:00
Kinglykrab 1da7901029 Update worlddb.cpp 2024-11-21 23:29:10 -05:00
Kinglykrab 738a31df51 [Feature] Implement "Big Bags" 2024-11-21 23:29:02 -05:00
112 changed files with 3341 additions and 3059 deletions
-99
View File
@@ -1,102 +1,3 @@
## [22.61.0] 1/6/2025
### Bots
* Fix AA ranks to account for level ([#4567](https://github.com/EQEmu/Server/pull/4567)) @nytmyr 2024-12-07
### Code
* Convert Event Parses to Single Line ([#4569](https://github.com/EQEmu/Server/pull/4569)) @Kinglykrab 2024-12-12
* Fix GM Flag Spell Restriction Bypasses ([#4571](https://github.com/EQEmu/Server/pull/4571)) @Kinglykrab 2025-01-06
* Remove Unused Group Methods ([#4559](https://github.com/EQEmu/Server/pull/4559)) @Kinglykrab 2024-12-12
### Commands
* Add #find bot Subcommand ([#4563](https://github.com/EQEmu/Server/pull/4563)) @Kinglykrab 2024-12-12
* Add #find ldon_theme Subcommand ([#4564](https://github.com/EQEmu/Server/pull/4564)) @Kinglykrab 2024-12-12
* Fix #copycharacter ([#4582](https://github.com/EQEmu/Server/pull/4582)) @Akkadius 2025-01-06
### Databuckets
* Improved Reliability and Performance of Databuckets ([#4562](https://github.com/EQEmu/Server/pull/4562)) @Akkadius 2024-12-12
### Feature
* Enable bazaar window 'Find Trader' functionality ([#4560](https://github.com/EQEmu/Server/pull/4560)) @neckkola 2024-12-12
### Filesystem
* Path Manager Improvements ([#4557](https://github.com/EQEmu/Server/pull/4557)) @Akkadius 2025-01-06
### Fixes
* Allow Items in ROF2 to Stack to 32,767 ([#4556](https://github.com/EQEmu/Server/pull/4556)) @Kinglykrab 2024-12-12
* Fix EVENT_COMBAT on NPC Death ([#4558](https://github.com/EQEmu/Server/pull/4558)) @Kinglykrab 2024-11-28
* Guild Membership Update Fix ([#4581](https://github.com/EQEmu/Server/pull/4581)) @neckkola 2025-01-06
* Guild creation to propagate across zones ([#4575](https://github.com/EQEmu/Server/pull/4575)) @neckkola 2025-01-06
* Repair a EQEMUConfig Memory Leak ([#4584](https://github.com/EQEmu/Server/pull/4584)) @neckkola 2025-01-06
* Repair a LoadNPCEmote MemoryLeak ([#4586](https://github.com/EQEmu/Server/pull/4586)) @neckkola 2025-01-06
* Repair a memory leak in GuildsList ([#4585](https://github.com/EQEmu/Server/pull/4585)) @neckkola 2025-01-06
* Resolve a client crash when logging in or zoning ([#4572](https://github.com/EQEmu/Server/pull/4572)) @neckkola 2024-12-14
### Groups
* Fix AmIMainAssist incorrectly checking for MainTankName ([#4565](https://github.com/EQEmu/Server/pull/4565)) @nytmyr 2024-12-04
### Inventory
* Add GetInventorySlots() Method ([#4566](https://github.com/EQEmu/Server/pull/4566)) @Kinglykrab 2025-01-06
### Logs
* Improve Crash log defaults ([#4579](https://github.com/EQEmu/Server/pull/4579)) @Akkadius 2025-01-06
### Maps
* Fix broken Map MMFS implementation ([#4576](https://github.com/EQEmu/Server/pull/4576)) @Akkadius 2025-01-06
### Network
* Prune / disconnect TCP connections gracefully ([#4574](https://github.com/EQEmu/Server/pull/4574)) @Akkadius 2025-01-06
### Rules
* Add rules for requiring custom files from client ([#4561](https://github.com/EQEmu/Server/pull/4561)) @knervous 2024-12-12
## [22.60.0] 11/25/2024
### Bazaar
* Further refinements for instanced bazaar ([#4544](https://github.com/EQEmu/Server/pull/4544)) @neckkola 2024-11-16
### Code
* Fix build with older C++ libraries ([#4549](https://github.com/EQEmu/Server/pull/4549)) @hgtw 2024-11-24
### Config
* Fix World TCP Address Configuration Default ([#4551](https://github.com/EQEmu/Server/pull/4551)) @Akkadius 2024-11-24
### Fixes
* Fix Issue with Perl EVENT_PAYLOAD ([#4545](https://github.com/EQEmu/Server/pull/4545)) @Kinglykrab 2024-11-24
* Fix Possible Item Loss in Trades ([#4554](https://github.com/EQEmu/Server/pull/4554)) @Kinglykrab 2024-11-24
* Fix Strings::Commify bug with #mystats ([#4547](https://github.com/EQEmu/Server/pull/4547)) @carolus21rex 2024-11-22
* Fix an edge case with augmented items inside parceled containers ([#4546](https://github.com/EQEmu/Server/pull/4546)) @neckkola 2024-11-21
* Fix for bazaar search of containers. ([#4540](https://github.com/EQEmu/Server/pull/4540)) @neckkola 2024-11-15
* Fix for mult-instanced bazaar zones ([#4541](https://github.com/EQEmu/Server/pull/4541)) @neckkola 2024-11-15
* Fix for sending money via Parcel, then changing your mind ([#4552](https://github.com/EQEmu/Server/pull/4552)) @neckkola 2024-11-24
* Fix issue where NPC's are being hidden as traders ([#4539](https://github.com/EQEmu/Server/pull/4539)) @Akkadius 2024-11-15
* Players could become flagged as a Trader when they were not trading ([#4553](https://github.com/EQEmu/Server/pull/4553)) @neckkola 2024-11-24
### Rules
* Add Rule to Disable NPCs Facing Target ([#4543](https://github.com/EQEmu/Server/pull/4543)) @Kinglykrab 2024-11-24
### Tasks
* Update tasks in all zones if invalid zone set ([#4550](https://github.com/EQEmu/Server/pull/4550)) @hgtw 2024-11-25
## [22.59.1] 11/13/2024
### Hotfix
-3
View File
@@ -37,9 +37,6 @@ IF(EQEMU_ADD_PROFILER)
SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--no-as-needed,-lprofiler,--as-needed")
ENDIF(EQEMU_ADD_PROFILER)
IF(USE_MAP_MMFS)
ADD_DEFINITIONS(-DUSE_MAP_MMFS)
ENDIF (USE_MAP_MMFS)
IF(MSVC)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)
+20 -28
View File
@@ -8,14 +8,13 @@ std::vector<BazaarSearchResultsFromDB_Struct>
Bazaar::GetSearchResults(
SharedDatabase &db,
BazaarSearchCriteria_Struct search,
uint32 char_zone_id,
int32 char_zone_instance_id
uint32 char_zone_id
)
{
LogTrading(
"Searching for items with search criteria - item_name [{}] min_cost [{}] max_cost [{}] min_level [{}] "
"max_level [{}] max_results [{}] prestige [{}] augment [{}] trader_entity_id [{}] trader_id [{}] "
"search_scope [{}] char_zone_id [{}], char_zone_instance_id [{}]",
"search_scope [{}] char_zone_id [{}]",
search.item_name,
search.min_cost,
search.max_cost,
@@ -27,8 +26,7 @@ Bazaar::GetSearchResults(
search.trader_entity_id,
search.trader_id,
search.search_scope,
char_zone_id,
char_zone_instance_id
char_zone_id
);
std::string search_criteria_trader("TRUE ");
@@ -36,19 +34,14 @@ Bazaar::GetSearchResults(
if (search.search_scope == NonRoFBazaarSearchScope) {
search_criteria_trader.append(
fmt::format(
" AND trader.char_entity_id = {} AND trader.char_zone_id = {} AND trader.char_zone_instance_id = {}",
" AND trader.char_entity_id = {} AND trader.char_zone_id = {}",
search.trader_entity_id,
Zones::BAZAAR,
char_zone_instance_id
Zones::BAZAAR
)
);
}
else if (search.search_scope == Local_Scope) {
search_criteria_trader.append(fmt::format(
" AND trader.char_zone_id = {} AND trader.char_zone_instance_id = {}",
char_zone_id,
char_zone_instance_id)
);
search_criteria_trader.append(fmt::format(" AND trader.char_zone_id = {}", char_zone_id));
}
else if (search.trader_id > 0) {
search_criteria_trader.append(fmt::format(" AND trader.char_id = {}", search.trader_id));
@@ -69,7 +62,7 @@ Bazaar::GetSearchResults(
std::string query = fmt::format(
"SELECT COUNT(item_id), trader.char_id, trader.item_id, trader.item_sn, trader.item_charges, trader.item_cost, "
"trader.slot_id, SUM(trader.item_charges), trader.char_zone_id, trader.char_entity_id, character_data.name, "
"aug_slot_1, aug_slot_2, aug_slot_3, aug_slot_4, aug_slot_5, aug_slot_6, trader.char_zone_instance_id "
"aug_slot_1, aug_slot_2, aug_slot_3, aug_slot_4, aug_slot_5, aug_slot_6 "
"FROM trader, character_data "
"WHERE {} AND trader.char_id = character_data.id "
"GROUP BY trader.item_sn, trader.item_charges, trader.char_id",
@@ -129,20 +122,19 @@ Bazaar::GetSearchResults(
continue;
}
r.count = Strings::ToInt(row[0]);
r.trader_id = Strings::ToInt(row[1]);
r.serial_number = Strings::ToInt(row[3]);
r.cost = Strings::ToInt(row[5]);
r.slot_id = Strings::ToInt(row[6]);
r.sum_charges = Strings::ToInt(row[7]);
r.stackable = item->Stackable;
r.icon_id = item->Icon;
r.trader_zone_id = Strings::ToInt(row[8]);
r.trader_zone_instance_id = Strings::ToInt(row[17]);
r.trader_entity_id = Strings::ToInt(row[9]);
r.serial_number_RoF = fmt::format("{:016}\0", Strings::ToInt(row[3]));
r.item_name = fmt::format("{:.63}\0", item->Name);
r.trader_name = fmt::format("{:.63}\0", std::string(row[10]).c_str());
r.count = Strings::ToInt(row[0]);
r.trader_id = Strings::ToInt(row[1]);
r.serial_number = Strings::ToInt(row[3]);
r.cost = Strings::ToInt(row[5]);
r.slot_id = Strings::ToInt(row[6]);
r.sum_charges = Strings::ToInt(row[7]);
r.stackable = item->Stackable;
r.icon_id = item->Icon;
r.trader_zone_id = Strings::ToInt(row[8]);
r.trader_entity_id = Strings::ToInt(row[9]);
r.serial_number_RoF = fmt::format("{:016}\0", Strings::ToInt(row[3]));
r.item_name = fmt::format("{:.63}\0", item->Name);
r.trader_name = fmt::format("{:.63}\0", std::string(row[10]).c_str());
LogTradingDetail(
"Searching against item [{}] ({}) for trader [{}]",
+1 -1
View File
@@ -7,7 +7,7 @@
class Bazaar {
public:
static std::vector<BazaarSearchResultsFromDB_Struct>
GetSearchResults(SharedDatabase &db, BazaarSearchCriteria_Struct search, unsigned int char_zone_id, int char_zone_instance_id);
GetSearchResults(SharedDatabase &db, BazaarSearchCriteria_Struct search, unsigned int char_zone_id);
};
-2
View File
@@ -294,8 +294,6 @@ void print_trace()
SendCrashReport(crash_report);
}
LogSys.CloseFileLogs();
exit(1);
}
+1 -49
View File
@@ -1860,35 +1860,7 @@ bool Database::CopyCharacter(
const int64 new_character_id = (CharacterDataRepository::GetMaxId(*this) + 1);
// validate destination name doesn't exist already
const auto& destination_characters = CharacterDataRepository::GetWhere(
*this,
fmt::format(
"`name` = '{}' AND `deleted_at` IS NULL LIMIT 1",
Strings::Escape(destination_character_name)
)
);
if (!destination_characters.empty()) {
LogError("Character [{}] already exists", destination_character_name);
return false;
}
std::vector<std::string> tables_to_zero_id = {
"keyring",
"data_buckets",
"character_instance_safereturns",
"character_expedition_lockouts",
"character_instance_lockouts",
"character_parcels",
"character_tribute",
"player_titlesets",
};
std::vector<std::string> ignore_tables = {
"guilds",
};
size_t total_rows_copied = 0;
std::vector<std::string> tables_to_zero_id = { "keyring", "data_buckets", "character_instance_safereturns" };
TransactionBegin();
@@ -1896,10 +1868,6 @@ bool Database::CopyCharacter(
const std::string& table_name = t.first;
const std::string& character_id_column_name = t.second;
if (Strings::Contains(ignore_tables, table_name)) {
continue;
}
auto results = QueryDatabase(
fmt::format(
"SHOW COLUMNS FROM {}",
@@ -1950,10 +1918,6 @@ bool Database::CopyCharacter(
value = std::to_string(destination_account_id);
}
if (!Strings::IsNumber(value)) {
value = Strings::Escape(value);
}
new_values.emplace_back(value);
}
@@ -1986,11 +1950,6 @@ bool Database::CopyCharacter(
)
);
size_t rows_copied = insert_rows.size(); // Rows copied for this table
total_rows_copied += rows_copied; // Increment grand total
LogInfo("Copying table [{}] rows [{}]", table_name, Strings::Commify(rows_copied));
if (!insert.ErrorMessage().empty()) {
TransactionRollback();
return false;
@@ -2000,13 +1959,6 @@ bool Database::CopyCharacter(
TransactionCommit();
LogInfo(
"Character [{}] copied to [{}] total rows [{}]",
source_character_name,
destination_character_name,
Strings::Commify(total_rows_copied)
);
return true;
}
+70 -7
View File
@@ -5774,13 +5774,76 @@ CREATE INDEX idx_bot_expires ON data_buckets (bot_id, expires);
},
ManifestEntry{
.version = 9286,
.description = "2024_11_26_bazaar_find_trader.sql",
.check = "SHOW COLUMNS FROM `trader` LIKE 'char_zone_instance_id'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `trader`
ADD COLUMN `char_zone_instance_id` INT NULL DEFAULT '0' AFTER `char_zone_id`;
.description = "2024_10_24_sharedbank_guid_primary_key.sql",
.check = "SHOW COLUMN FROM `sharedbank` LIKE 'guid'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `sharedbank`
CHANGE COLUMN `acctid` `account_id` int(11) UNSIGNED NOT NULL DEFAULT 0 FIRST,
CHANGE COLUMN `slotid` `slot_id` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `account_id`,
CHANGE COLUMN `itemid` `item_id` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `slot_id`,
CHANGE COLUMN `augslot1` `augment_one` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `charges`,
CHANGE COLUMN `augslot2` `augment_two` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_one`,
CHANGE COLUMN `augslot3` `augment_three` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_two`,
CHANGE COLUMN `augslot4` `augment_four` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_three`,
CHANGE COLUMN `augslot5` `augment_five` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_four`,
CHANGE COLUMN `augslot6` `augment_six` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_five`,
MODIFY COLUMN `charges` smallint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `item_id`,
ADD COLUMN `color` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `charges`,
ADD COLUMN `ornament_icon` int(11) UNSIGNED NOT NULL AFTER `custom_data`,
ADD COLUMN `ornament_idfile` int(11) UNSIGNED NOT NULL AFTER `ornament_icon`,
ADD COLUMN `ornament_hero_model` int(11) NOT NULL AFTER `ornament_idfile`,
ADD COLUMN `guid` bigint(20) UNSIGNED NOT NULL DEFAULT 0 AFTER `ornament_hero_model`,
ADD PRIMARY KEY (`account_id`, `slot_id`);
)"
},
ManifestEntry{
.version = 9287,
.description = "2024_10_24_inventory_changes.sql",
.check = "SHOW COLUMN FROM `inventory` LIKE 'charid'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `inventory`
CHANGE COLUMN `charid` `character_id` int(11) UNSIGNED NOT NULL DEFAULT 0 FIRST,
CHANGE COLUMN `slotid` `slot_id` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `character_id`,
CHANGE COLUMN `itemid` `item_id` int(11) UNSIGNED NULL DEFAULT 0 AFTER `slot_id`,
CHANGE COLUMN `augslot1` `augment_one` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `color`,
CHANGE COLUMN `augslot2` `augment_two` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_one`,
CHANGE COLUMN `augslot3` `augment_three` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_two`,
CHANGE COLUMN `augslot4` `augment_four` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_three`,
CHANGE COLUMN `augslot5` `augment_five` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_four`,
CHANGE COLUMN `augslot6` `augment_six` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_five`,
CHANGE COLUMN `ornamenticon` `ornament_icon` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `custom_data`,
CHANGE COLUMN `ornamentidfile` `ornament_idfile` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `ornament_icon`,
DROP PRIMARY KEY,
ADD PRIMARY KEY (`character_id`, `slot_id`) USING BTREE;
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 251) + 4010) WHERE `slot_id` BETWEEN 251 AND 260; -- Bag 1
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 261) + 4210) WHERE `slot_id` BETWEEN 261 AND 270; -- Bag 2
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 271) + 4410) WHERE `slot_id` BETWEEN 271 AND 280; -- Bag 3
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 281) + 4610) WHERE `slot_id` BETWEEN 281 AND 290; -- Bag 4
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 291) + 4810) WHERE `slot_id` BETWEEN 291 AND 300; -- Bag 5
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 301) + 5010) WHERE `slot_id` BETWEEN 301 AND 310; -- Bag 6
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 311) + 5210) WHERE `slot_id` BETWEEN 311 AND 320; -- Bag 7
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 321) + 5410) WHERE `slot_id` BETWEEN 321 AND 330; -- Bag 8
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 331) + 5610) WHERE `slot_id` BETWEEN 331 AND 340; -- Bag 9
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 341) + 5810) WHERE `slot_id` BETWEEN 341 AND 350; -- Bag 10
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 351) + 6010) WHERE `slot_id` BETWEEN 351 AND 360; -- Cursor Bag
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2031) + 6210) WHERE `slot_id` BETWEEN 2031 AND 2270; -- Bank Bags
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2531) + 11010) WHERE `slot_id` BETWEEN 2531 AND 2550; -- Shared Bank Bags
)"
},
ManifestEntry{
.version = 9288,
.description = "2024_10_24_merchantlist_temp_uncap.sql",
.check = "SHOW CREATE TABLE `merchantlist_temp`",
.condition = "contains",
.match = "`slot` tinyint(3)",
.sql = R"(
ALTER TABLE `merchantlist_temp`
MODIFY COLUMN `slot` int UNSIGNED NOT NULL DEFAULT 0 AFTER `npcid`;
)"
}
// -- template; copy/paste this when you need to create a new entry
+23 -15
View File
@@ -140,6 +140,29 @@ std::string EQ::constants::GetLanguageName(uint8 language_id)
return EQ::constants::GetLanguageMap().find(language_id)->second;
}
const std::map<uint32, std::string>& EQ::constants::GetLDoNThemeMap()
{
static const std::map<uint32, std::string> ldon_theme_map = {
{ LDoNThemes::Unused, "Unused" },
{ LDoNThemes::GUK, "Deepest Guk" },
{ LDoNThemes::MIR, "Miragul's Menagerie" },
{ LDoNThemes::MMC, "Mistmoore Catacombs" },
{ LDoNThemes::RUJ, "Rujarkian Hills" },
{ LDoNThemes::TAK, "Takish-Hiz" },
};
return ldon_theme_map;
}
std::string EQ::constants::GetLDoNThemeName(uint32 theme_id)
{
if (!EQ::ValueWithin(theme_id, LDoNThemes::Unused, LDoNThemes::TAK)) {
return std::string();
}
return EQ::constants::GetLDoNThemeMap().find(theme_id)->second;
}
const std::map<int8, std::string>& EQ::constants::GetFlyModeMap()
{
static const std::map<int8, std::string> flymode_map = {
@@ -436,18 +459,3 @@ bool ComparisonType::IsValid(uint8 type)
{
return comparison_types.find(type) != comparison_types.end();
}
uint32 LDoNTheme::GetBitmask(uint32 theme_id)
{
return IsValid(theme_id) ? ldon_theme_names[theme_id].second : LDoNTheme::UnusedBit;
}
std::string LDoNTheme::GetName(uint32 theme_id)
{
return IsValid(theme_id) ? ldon_theme_names[theme_id].first : "UNKNOWN LDON THEME";
}
bool LDoNTheme::IsValid(uint32 theme_id)
{
return ldon_theme_names.find(theme_id) != ldon_theme_names.end();
}
+38 -62
View File
@@ -132,7 +132,7 @@ namespace EQ
using RoF2::invtype::KRONO_SIZE;
using RoF2::invtype::OTHER_SIZE;
using Titanium::invtype::TRADE_NPC_SIZE;
using RoF2::invtype::TRADE_NPC_SIZE;
using RoF2::invtype::TYPE_INVALID;
using RoF2::invtype::TYPE_BEGIN;
@@ -159,7 +159,7 @@ namespace EQ
using RoF2::invslot::SLOT_INVALID;
using RoF2::invslot::SLOT_BEGIN;
using Titanium::invslot::SLOT_TRADESKILL_EXPERIMENT_COMBINE;
using RoF2::invslot::SLOT_TRADESKILL_EXPERIMENT_COMBINE;
const int16 SLOT_AUGMENT_GENERIC_RETURN = 1001; // clients don't appear to use this method... (internal inventory return value)
@@ -179,28 +179,28 @@ namespace EQ
using RoF2::invslot::BONUS_STAT_END;
using RoF2::invslot::BONUS_SKILL_END;
using Titanium::invslot::BANK_BEGIN;
using SoF::invslot::BANK_END;
using RoF2::invslot::BANK_BEGIN;
using RoF2::invslot::BANK_END;
using Titanium::invslot::SHARED_BANK_BEGIN;
using Titanium::invslot::SHARED_BANK_END;
using RoF2::invslot::SHARED_BANK_BEGIN;
using RoF2::invslot::SHARED_BANK_END;
using Titanium::invslot::TRADE_BEGIN;
using Titanium::invslot::TRADE_END;
using RoF2::invslot::TRADE_BEGIN;
using RoF2::invslot::TRADE_END;
using Titanium::invslot::TRADE_NPC_END;
using RoF2::invslot::TRADE_NPC_END;
using Titanium::invslot::WORLD_BEGIN;
using Titanium::invslot::WORLD_END;
using RoF2::invslot::WORLD_BEGIN;
using RoF2::invslot::WORLD_END;
using Titanium::invslot::TRIBUTE_BEGIN;
using Titanium::invslot::TRIBUTE_END;
using RoF2::invslot::TRIBUTE_BEGIN;
using RoF2::invslot::TRIBUTE_END;
using Titanium::invslot::GUILD_TRIBUTE_BEGIN;
using Titanium::invslot::GUILD_TRIBUTE_END;
using RoF2::invslot::GUILD_TRIBUTE_BEGIN;
using RoF2::invslot::GUILD_TRIBUTE_END;
const int16 CORPSE_BEGIN = invslot::slotGeneral1;
const int16 CORPSE_END = CORPSE_BEGIN + invslot::slotCursor;
const int16 CORPSE_END = CORPSE_BEGIN + invslot::slotCursor;
using RoF2::invslot::EQUIPMENT_BITMASK;
using RoF2::invslot::GENERAL_BITMASK;
@@ -214,38 +214,40 @@ namespace EQ
} // namespace invslot
namespace invbag {
using Titanium::invbag::SLOT_INVALID;
using Titanium::invbag::SLOT_BEGIN;
using Titanium::invbag::SLOT_END;
using Titanium::invbag::SLOT_COUNT;
using RoF2::invbag::SLOT_INVALID;
using RoF2::invbag::SLOT_BEGIN;
using RoF2::invbag::SLOT_END;
using RoF2::invbag::SLOT_COUNT;
using Titanium::invbag::GENERAL_BAGS_BEGIN;
using RoF2::invslot::WORLD_END;
const int16 GENERAL_BAGS_BEGIN = WORLD_END + 1;
const int16 GENERAL_BAGS_COUNT = invslot::GENERAL_COUNT * SLOT_COUNT;
const int16 GENERAL_BAGS_END = (GENERAL_BAGS_BEGIN + GENERAL_BAGS_COUNT) - 1;
const int16 GENERAL_BAGS_END = (GENERAL_BAGS_BEGIN + GENERAL_BAGS_COUNT) - 1;
const int16 GENERAL_BAGS_8_COUNT = 8 * SLOT_COUNT;
const int16 GENERAL_BAGS_8_END = (GENERAL_BAGS_BEGIN + GENERAL_BAGS_8_COUNT) - 1;
const int16 GENERAL_BAGS_8_END = (GENERAL_BAGS_BEGIN + GENERAL_BAGS_8_COUNT) - 1;
const int16 CURSOR_BAG_BEGIN = 351;
const int16 CURSOR_BAG_BEGIN = GENERAL_BAGS_END + 1;
const int16 CURSOR_BAG_COUNT = SLOT_COUNT;
const int16 CURSOR_BAG_END = (CURSOR_BAG_BEGIN + CURSOR_BAG_COUNT) - 1;
const int16 CURSOR_BAG_END = (CURSOR_BAG_BEGIN + CURSOR_BAG_COUNT) - 1;
using Titanium::invbag::BANK_BAGS_BEGIN;
const int16 BANK_BAGS_BEGIN = CURSOR_BAG_END + 1;
const int16 BANK_BAGS_COUNT = (invtype::BANK_SIZE * SLOT_COUNT);
const int16 BANK_BAGS_END = (BANK_BAGS_BEGIN + BANK_BAGS_COUNT) - 1;
const int16 BANK_BAGS_END = (BANK_BAGS_BEGIN + BANK_BAGS_COUNT) - 1;
const int16 BANK_BAGS_16_COUNT = 16 * SLOT_COUNT;
const int16 BANK_BAGS_16_END = (BANK_BAGS_BEGIN + BANK_BAGS_16_COUNT) - 1;
const int16 BANK_BAGS_16_END = (BANK_BAGS_BEGIN + BANK_BAGS_16_COUNT) - 1;
using Titanium::invbag::SHARED_BANK_BAGS_BEGIN;
const int16 SHARED_BANK_BAGS_BEGIN = BANK_BAGS_END + 1;
const int16 SHARED_BANK_BAGS_COUNT = invtype::SHARED_BANK_SIZE * SLOT_COUNT;
const int16 SHARED_BANK_BAGS_END = (SHARED_BANK_BAGS_BEGIN + SHARED_BANK_BAGS_COUNT) - 1;
const int16 SHARED_BANK_BAGS_END = (SHARED_BANK_BAGS_BEGIN + SHARED_BANK_BAGS_COUNT) - 1;
using Titanium::invbag::TRADE_BAGS_BEGIN;
const int16 TRADE_BAGS_BEGIN = SHARED_BANK_BAGS_END + 1;
const int16 TRADE_BAGS_COUNT = invtype::TRADE_SIZE * SLOT_COUNT;
const int16 TRADE_BAGS_END = (TRADE_BAGS_BEGIN + TRADE_BAGS_COUNT) - 1;
const int16 TRADE_BAGS_END = (TRADE_BAGS_BEGIN + TRADE_BAGS_COUNT) - 1;
using Titanium::invbag::GetInvBagIndexName;
using RoF2::invbag::GetInvBagIndexName;
} // namespace invbag
@@ -352,6 +354,9 @@ namespace EQ
extern const std::map<uint8, std::string>& GetLanguageMap();
std::string GetLanguageName(uint8 language_id);
extern const std::map<uint32, std::string>& GetLDoNThemeMap();
std::string GetLDoNThemeName(uint32 theme_id);
extern const std::map<int8, std::string>& GetFlyModeMap();
std::string GetFlyModeName(int8 flymode_id);
@@ -748,35 +753,6 @@ static std::map<uint32, std::string> stance_names = {
{ Stance::AEBurn, "AE Burn" }
};
namespace LDoNTheme {
constexpr uint32 Unused = 0;
constexpr uint32 GUK = 1;
constexpr uint32 MIR = 2;
constexpr uint32 MMC = 3;
constexpr uint32 RUJ = 4;
constexpr uint32 TAK = 5;
constexpr uint32 UnusedBit = 0;
constexpr uint32 GUKBit = 1;
constexpr uint32 MIRBit = 2;
constexpr uint32 MMCBit = 4;
constexpr uint32 RUJBit = 8;
constexpr uint32 TAKBit = 16;
uint32 GetBitmask(uint32 theme_id);
std::string GetName(uint32 theme_id);
bool IsValid(uint32 theme_id);
}
static std::map<uint32, std::pair<std::string, uint32>> ldon_theme_names = {
{ LDoNTheme::Unused, { "Unused", LDoNTheme::UnusedBit }, },
{ LDoNTheme::GUK, { "Deepest Guk", LDoNTheme::GUKBit }, },
{ LDoNTheme::MIR, { "Miragul's Menagerie", LDoNTheme::MIRBit }, },
{ LDoNTheme::MMC, { "Mistmoore Catacombs", LDoNTheme::MMCBit }, },
{ LDoNTheme::RUJ, { "Rujarkian Hills", LDoNTheme::RUJBit }, },
{ LDoNTheme::TAK, { "Takish-Hiz", LDoNTheme::TAKBit }, },
};
namespace PCNPCOnlyFlagType {
constexpr int PC = 1;
constexpr int NPC = 2;
+18
View File
@@ -993,6 +993,24 @@ 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
};
enum StartZoneIndex {
Odus = 0,
Qeynos,
+1 -5
View File
@@ -3742,8 +3742,7 @@ struct GetItems_Struct{
struct BecomeTrader_Struct {
uint32 action;
uint16 zone_id;
uint16 zone_instance_id;
uint32 zone_id;
uint32 trader_id;
uint32 entity_id;
char trader_name[64];
@@ -6348,7 +6347,6 @@ enum BazaarTraderBarterActions {
TraderAck2 = 22,
AddTraderToBazaarWindow = 24,
RemoveTraderFromBazaarWindow = 25,
FirstOpenSearch = 26,
ClickTrader = 28,
DeliveryCostUpdate = 29
};
@@ -6388,7 +6386,6 @@ struct BazaarSearchResultsFromDB_Struct {
uint32 icon_id;
uint32 sum_charges;
uint32 trader_zone_id;
int32 trader_zone_instance_id;
uint32 trader_entity_id;
uint32 item_stat;
bool stackable;
@@ -6410,7 +6407,6 @@ struct BazaarSearchResultsFromDB_Struct {
CEREAL_NVP(icon_id),
CEREAL_NVP(sum_charges),
CEREAL_NVP(trader_zone_id),
CEREAL_NVP(trader_zone_instance_id),
CEREAL_NVP(trader_entity_id),
CEREAL_NVP(item_stat),
CEREAL_NVP(stackable),
+1 -1
View File
@@ -94,7 +94,7 @@ void EQEmuConfig::parse_config()
auto_database_updates = true;
}
WorldIP = _root["server"]["world"]["tcp"].get("ip", "127.0.0.1").asString();
WorldIP = _root["server"]["world"]["tcp"].get("host", "127.0.0.1").asString();
WorldTCPPort = Strings::ToUnsignedInt(_root["server"]["world"]["tcp"].get("port", "9000").asString());
TelnetIP = _root["server"]["world"]["telnet"].get("ip", "127.0.0.1").asString();
+1 -1
View File
@@ -137,9 +137,9 @@ class EQEmuConfig
{
}
virtual ~EQEmuConfig() {}
public:
virtual ~EQEmuConfig() {}
// Produce a const singleton
static const EQEmuConfig *get()
-8
View File
@@ -25,8 +25,6 @@
#include "repositories/discord_webhooks_repository.h"
#include "repositories/logsys_categories_repository.h"
#include "termcolor/rang.hpp"
#include "path_manager.h"
#include "file.h"
#include <iostream>
#include <string>
@@ -87,7 +85,6 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
* Set Defaults
*/
log_settings[Logs::Crash].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Crash].log_to_file = static_cast<uint8>(Logs::General);
log_settings[Logs::MySQLError].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::NPCScaling].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::HotReload].log_to_gmsay = static_cast<uint8>(Logs::General);
@@ -535,11 +532,6 @@ void EQEmuLogSys::StartFileLogs(const std::string &log_name)
{
EQEmuLogSys::CloseFileLogs();
if (!File::Exists(path.GetLogPath())) {
LogInfo("Logs directory not found, creating [{}]", path.GetLogPath());
File::Makedir(path.GetLogPath());
}
/**
* When loading settings, we must have been given a reason in category based logging to output to a file in order to even create or open one...
*/
File diff suppressed because it is too large Load Diff
+2 -11
View File
@@ -147,13 +147,13 @@ namespace EQ
bool HasItemEquippedByID(uint32 item_id);
// Check how many of a specific item the player has equipped by Item ID
uint32 CountItemEquippedByID(uint32 item_id);
int CountItemEquippedByID(uint32 item_id);
// Check if player has a specific augment equipped by Item ID
bool HasAugmentEquippedByID(uint32 item_id);
// Check how many of a specific augment the player has equipped by Item ID
uint32 CountAugmentEquippedByID(uint32 item_id);
int CountAugmentEquippedByID(uint32 item_id);
// Get a list of augments from a specific slot ID
std::vector<uint32> GetAugmentIDsBySlotID(int16 slot_id);
@@ -176,7 +176,6 @@ namespace EQ
// Locate an available inventory slot
int16 FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size = 0, bool is_arrow = false);
int16 FindFreeSlotForTradeItem(const ItemInstance* inst, int16 general_start = invslot::GENERAL_BEGIN, uint8 bag_start = invbag::SLOT_BEGIN);
std::vector<int16> FindAllFreeSlotsThatFitItem(const EQ::ItemData *inst);
int16 FindFirstFreeSlotThatFitsItem(const EQ::ItemData *inst);
// Calculate slot_id for an item within a bag
@@ -199,12 +198,6 @@ namespace EQ
uint8 FindBrightestLightType();
void dumpEntireInventory();
void dumpWornItems();
void dumpInventory();
void dumpBankItems();
void dumpSharedBankItems();
void SetCustomItemData(uint32 character_id, int16 slot_id, const std::string &identifier, const std::string& value);
void SetCustomItemData(uint32 character_id, int16 slot_id, const std::string &identifier, int value);
void SetCustomItemData(uint32 character_id, int16 slot_id, const std::string &identifier, float value);
@@ -217,8 +210,6 @@ namespace EQ
///////////////////////////////
int GetSlotByItemInstCollection(const std::map<int16, ItemInstance*> &collection, ItemInstance *inst);
void dumpItemCollection(const std::map<int16, ItemInstance*> &collection);
void dumpBagContents(ItemInstance *inst, std::map<int16, ItemInstance*>::const_iterator *it);
// Retrieves item within an inventory bucket
ItemInstance* _GetItem(const std::map<int16, ItemInstance*>& bucket, int16 slot_id) const;
-14
View File
@@ -414,12 +414,6 @@ static uint64_t MakeBits(std::span<const uint8_t> data)
return bits;
}
template <typename T>
concept has_from_chars = requires (const char* first, const char* last, T value)
{
std::from_chars(first, last, value);
};
template <typename T>
static T FromString(std::string_view sv)
{
@@ -428,14 +422,6 @@ static T FromString(std::string_view sv)
// return false for empty (zero-length) strings
return !sv.empty();
}
else if constexpr (std::is_same_v<T, float> && !has_from_chars<T>)
{
return std::strtof(std::string(sv).c_str(), nullptr);
}
else if constexpr (std::is_same_v<T, double> && !has_from_chars<T>)
{
return std::strtod(std::string(sv).c_str(), nullptr);
}
else
{
// non numbers return a zero initialized T (could return nullopt instead)
-2
View File
@@ -80,8 +80,6 @@ void EQ::Net::TCPConnection::Start() {
}
}
else if (nread == UV_EOF) {
connection->Disconnect();
if (buf->base) {
delete[] buf->base;
}
+14 -30
View File
@@ -583,21 +583,19 @@ namespace RoF2
auto outapp = new EQApplicationPacket(OP_TraderShop, sizeof(BecomeTrader_Struct));
auto eq = (BecomeTrader_Struct *) outapp->pBuffer;
eq->action = emu->action;
eq->entity_id = emu->entity_id;
eq->trader_id = emu->trader_id;
eq->zone_id = emu->zone_id;
eq->zone_instance_id = emu->zone_instance_id;
eq->action = emu->action;
eq->entity_id = emu->entity_id;
eq->trader_id = emu->trader_id;
eq->zone_id = emu->zone_id;
strn0cpy(eq->trader_name, emu->trader_name, sizeof(eq->trader_name));
LogTrading(
"(RoF2) AddTraderToBazaarWindow action <green>[{}] trader_id <green>[{}] entity_id <green>[{}] "
"zone_id <green>[{}] zone_instance_id <green>[{}]",
"(RoF2) AddTraderToBazaarWindow action <green>[{}] trader_id <green>[{}] entity_id <green>[{}] zone_id <green>[{}]",
eq->action,
eq->trader_id,
eq->entity_id,
eq->zone_id,
eq->zone_instance_id);
eq->zone_id
);
dest->FastQueuePacket(&outapp);
break;
}
@@ -1845,11 +1843,11 @@ namespace RoF2
}
}
safe_delete_array(in->pBuffer);
auto outapp = new EQApplicationPacket(OP_GuildsList);
outapp->size = packet_size;
outapp->pBuffer = buffer;
in->pBuffer = buffer;
in->size = packet_size;
dest->FastQueuePacket(&in);
dest->FastQueuePacket(&outapp);
}
ENCODE(OP_GuildTributeDonateItem)
@@ -6220,11 +6218,6 @@ namespace RoF2
FINISH_DIRECT_DECODE();
break;
}
case structs::RoF2BazaarTraderBuyerActions::FirstOpenSearch: {
__packet->SetOpcode(OP_BazaarSearch);
LogTrading("(RoF2) First time opening Bazaar Search since zoning. Action <green>[{}]", action);
break;
}
case structs::RoF2BazaarTraderBuyerActions::WelcomeMessage: {
__packet->SetOpcode(OP_BazaarSearch);
LogTrading("(RoF2) WelcomeMessage action <green>[{}]", action);
@@ -6365,18 +6358,9 @@ namespace RoF2
//sprintf(hdr.unknown000, "06e0002Y1W00");
strn0cpy(hdr.unknown000, fmt::format("{:016}\0", inst->GetSerialNumber()).c_str(),sizeof(hdr.unknown000));
hdr.stacksize = 1;
if (item->ID == PARCEL_MONEY_ITEM_ID) {
hdr.stacksize = inst->GetPrice();
} else if (inst->IsStackable()) {
if (inst->GetCharges() > std::numeric_limits<int16>::max()) {
hdr.stacksize = std::numeric_limits<uint32>::max();
} else {
hdr.stacksize = inst->GetCharges();
}
}
hdr.stacksize =
item->ID == PARCEL_MONEY_ITEM_ID ? inst->GetPrice() : (inst->IsStackable() ? ((inst->GetCharges() > 1000)
? 0xFFFFFFFF : inst->GetCharges()) : 1);
hdr.unknown004 = 0;
structs::InventorySlot_Struct slot_id{};
+81 -49
View File
@@ -1,5 +1,5 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
@@ -37,7 +37,7 @@ namespace RoF2
const bool AllowOverLevelEquipment = true;
const bool AllowEmptyBagInBag = true;
const bool AllowEmptyBagInBag = true;
const bool AllowClickCastFromBag = true;
} /*inventory*/
@@ -77,38 +77,38 @@ namespace RoF2
} // namespace enum_
using namespace enum_;
const int16 POSSESSIONS_SIZE = 34;
const int16 BANK_SIZE = 24;
const int16 SHARED_BANK_SIZE = 2;
const int16 TRADE_SIZE = 8;
const int16 WORLD_SIZE = 10;
const int16 LIMBO_SIZE = 36;
const int16 TRIBUTE_SIZE = 5;
const int16 TROPHY_TRIBUTE_SIZE = 0;//unknown
const int16 GUILD_TRIBUTE_SIZE = 2;//unverified
const int16 MERCHANT_SIZE = 200;
const int16 DELETED_SIZE = 0;//unknown - "Recovery Tab"
const int16 CORPSE_SIZE = POSSESSIONS_SIZE;
const int16 BAZAAR_SIZE = 200;
const int16 INSPECT_SIZE = 23;
const int16 REAL_ESTATE_SIZE = 0;//unknown
const int16 VIEW_MOD_PC_SIZE = POSSESSIONS_SIZE;
const int16 VIEW_MOD_BANK_SIZE = BANK_SIZE;
const int16 POSSESSIONS_SIZE = 34;
const int16 BANK_SIZE = 24;
const int16 SHARED_BANK_SIZE = 2;
const int16 TRADE_SIZE = 8;
const int16 WORLD_SIZE = 10;
const int16 LIMBO_SIZE = 36;
const int16 TRIBUTE_SIZE = 5;
const int16 TROPHY_TRIBUTE_SIZE = 0;//unknown
const int16 GUILD_TRIBUTE_SIZE = 2;//unverified
const int16 MERCHANT_SIZE = 500;
const int16 DELETED_SIZE = 0;//unknown - "Recovery Tab"
const int16 CORPSE_SIZE = POSSESSIONS_SIZE;
const int16 BAZAAR_SIZE = 200;
const int16 INSPECT_SIZE = 23;
const int16 REAL_ESTATE_SIZE = 0;//unknown
const int16 VIEW_MOD_PC_SIZE = POSSESSIONS_SIZE;
const int16 VIEW_MOD_BANK_SIZE = BANK_SIZE;
const int16 VIEW_MOD_SHARED_BANK_SIZE = SHARED_BANK_SIZE;
const int16 VIEW_MOD_LIMBO_SIZE = LIMBO_SIZE;
const int16 ALT_STORAGE_SIZE = 0;//unknown - "Shroud Bank"
const int16 ARCHIVED_SIZE = 0;//unknown
const int16 MAIL_SIZE = 0;//unknown
const int16 VIEW_MOD_LIMBO_SIZE = LIMBO_SIZE;
const int16 ALT_STORAGE_SIZE = 0;//unknown - "Shroud Bank"
const int16 ARCHIVED_SIZE = 0;//unknown
const int16 MAIL_SIZE = 0;//unknown
const int16 GUILD_TROPHY_TRIBUTE_SIZE = 0;//unknown
const int16 KRONO_SIZE = 0;//unknown
const int16 OTHER_SIZE = 0;//unknown
const int16 KRONO_SIZE = 0;//unknown
const int16 OTHER_SIZE = 0;//unknown
const int16 TRADE_NPC_SIZE = 4; // defined by implication
const int16 TYPE_INVALID = IINVALID;
const int16 TYPE_BEGIN = typePossessions;
const int16 TYPE_END = typeOther;
const int16 TYPE_COUNT = (TYPE_END - TYPE_BEGIN) + 1;
const int16 TYPE_BEGIN = typePossessions;
const int16 TYPE_END = typeOther;
const int16 TYPE_COUNT = (TYPE_END - TYPE_BEGIN) + 1;
int16 GetInvTypeSize(int16 inv_type);
const char* GetInvTypeName(int16 inv_type);
@@ -162,33 +162,54 @@ namespace RoF2
} // namespace enum_
using namespace enum_;
const int16 SLOT_INVALID = IINVALID;
const int16 SLOT_BEGIN = INULL;
const int16 SLOT_TRADESKILL_EXPERIMENT_COMBINE = 1000;
const int16 SLOT_INVALID = IINVALID;
const int16 SLOT_BEGIN = INULL;
const int16 BANK_BEGIN = 2000;
const int16 BANK_END = (BANK_BEGIN + invtype::BANK_SIZE) - 1;
const int16 SHARED_BANK_BEGIN = 2500;
const int16 SHARED_BANK_END = (SHARED_BANK_BEGIN + invtype::SHARED_BANK_SIZE) - 1;
const int16 TRADE_BEGIN = 3000;
const int16 TRADE_END = (TRADE_BEGIN + invtype::TRADE_SIZE) - 1;
const int16 TRADE_NPC_END = (TRADE_BEGIN + invtype::TRADE_NPC_SIZE) - 1; // defined by implication
const int16 WORLD_BEGIN = 4000;
const int16 WORLD_END = (WORLD_BEGIN + invtype::WORLD_SIZE) - 1;
const int16 TRIBUTE_BEGIN = 400;
const int16 TRIBUTE_END = (TRIBUTE_BEGIN + invtype::TRIBUTE_SIZE) - 1;
const int16 GUILD_TRIBUTE_BEGIN = 450;
const int16 GUILD_TRIBUTE_END = (GUILD_TRIBUTE_BEGIN + invtype::GUILD_TRIBUTE_SIZE) - 1;
const int16 POSSESSIONS_BEGIN = slotCharm;
const int16 POSSESSIONS_END = slotCursor;
const int16 POSSESSIONS_END = slotCursor;
const int16 POSSESSIONS_COUNT = (POSSESSIONS_END - POSSESSIONS_BEGIN) + 1;
const int16 EQUIPMENT_BEGIN = slotCharm;
const int16 EQUIPMENT_END = slotAmmo;
const int16 EQUIPMENT_END = slotAmmo;
const int16 EQUIPMENT_COUNT = (EQUIPMENT_END - EQUIPMENT_BEGIN) + 1;
const int16 GENERAL_BEGIN = slotGeneral1;
const int16 GENERAL_END = slotGeneral10;
const int16 GENERAL_END = slotGeneral10;
const int16 GENERAL_COUNT = (GENERAL_END - GENERAL_BEGIN) + 1;
const int16 BONUS_BEGIN = invslot::slotCharm;
const int16 BONUS_STAT_END = invslot::slotPowerSource;
const int16 BONUS_BEGIN = invslot::slotCharm;
const int16 BONUS_STAT_END = invslot::slotPowerSource;
const int16 BONUS_SKILL_END = invslot::slotAmmo;
const int16 CORPSE_BEGIN = invslot::slotGeneral1;
const int16 CORPSE_END = invslot::slotGeneral1 + invslot::slotCursor;
const int16 CORPSE_END = invslot::slotGeneral1 + invslot::slotCursor;
const uint64 EQUIPMENT_BITMASK = 0x00000000007FFFFF;
const uint64 GENERAL_BITMASK = 0x00000001FF800000;
const uint64 CURSOR_BITMASK = 0x0000000200000000;
const uint64 EQUIPMENT_BITMASK = 0x00000000007FFFFF;
const uint64 GENERAL_BITMASK = 0x00000001FF800000;
const uint64 CURSOR_BITMASK = 0x0000000200000000;
const uint64 POSSESSIONS_BITMASK = (EQUIPMENT_BITMASK | GENERAL_BITMASK | CURSOR_BITMASK); // based on 34-slot count (RoF+)
const uint64 CORPSE_BITMASK = (GENERAL_BITMASK | CURSOR_BITMASK | (EQUIPMENT_BITMASK << 34)); // based on 34-slot count (RoF+)
const uint64 CORPSE_BITMASK = (GENERAL_BITMASK | CURSOR_BITMASK | (EQUIPMENT_BITMASK << 34)); // based on 34-slot count (RoF+)
const char* GetInvPossessionsSlotName(int16 inv_slot);
@@ -199,10 +220,21 @@ namespace RoF2
namespace invbag {
inline EQ::versions::ClientVersion GetInvBagRef() { return EQ::versions::ClientVersion::RoF2; }
const int16 SLOT_INVALID = IINVALID;
const int16 SLOT_BEGIN = INULL;
const int16 SLOT_END = 9; //254;
const int16 SLOT_COUNT = 10; //255; // server Size will be 255..unsure what actual client is (test)
const int16 SLOT_TRADESKILL_EXPERIMENT_COMBINE = 1000;
const int16 SLOT_INVALID = IINVALID;
const int16 SLOT_BEGIN = INULL;
const int16 SLOT_COUNT = 200;
const int16 SLOT_END = SLOT_COUNT - 1;
const int16 GENERAL_BAGS_BEGIN = 251;
const int16 CURSOR_BAG_BEGIN = 351;
const int16 BANK_BAGS_BEGIN = 2031;
const int16 SHARED_BANK_BAGS_BEGIN = 2531;
const int16 TRADE_BAGS_BEGIN = 3031;
const char* GetInvBagIndexName(int16 bag_index);
@@ -212,9 +244,9 @@ namespace RoF2
inline EQ::versions::ClientVersion GetInvAugRef() { return EQ::versions::ClientVersion::RoF2; }
const int16 SOCKET_INVALID = IINVALID;
const int16 SOCKET_BEGIN = INULL;
const int16 SOCKET_END = 5;
const int16 SOCKET_COUNT = 6;
const int16 SOCKET_BEGIN = INULL;
const int16 SOCKET_END = 5;
const int16 SOCKET_COUNT = 6;
const char* GetInvAugIndexName(int16 aug_index);
@@ -291,7 +323,7 @@ namespace RoF2
namespace spells {
inline EQ::versions::ClientVersion GetSkillsRef() { return EQ::versions::ClientVersion::RoF2; }
enum class CastingSlot : uint32 {
Gem1 = 0,
Gem2 = 1,
@@ -314,7 +346,7 @@ namespace RoF2
const int SPELL_ID_MAX = 45000;
const int SPELLBOOK_SIZE = 720;
const int SPELL_GEM_COUNT = static_cast<uint32>(CastingSlot::MaxGems);
const int LONG_BUFFS = 42;
const int SHORT_BUFFS = 20;
const int DISC_BUFFS = 1;
+1 -2
View File
@@ -3119,8 +3119,7 @@ enum RoF2BazaarTraderBuyerActions {
BazaarInspect = 18,
ClickTrader = 28,
ItemMove = 19,
ReconcileItems = 20,
FirstOpenSearch = 26
ReconcileItems = 20
};
enum RoF2BuyerActions {
+6 -6
View File
@@ -2463,25 +2463,25 @@ struct WhoAllReturnStruct {
struct BeginTrader_Struct {
uint32 action;
uint32 unknown04;
uint64 serial_number[80];
uint32 cost[80];
uint64 serial_number[EQ::invtype::BAZAAR_SIZE];
uint32 cost[EQ::invtype::BAZAAR_SIZE];
};
struct Trader_Struct {
uint32 action;
uint32 unknown004;
uint64 item_id[80];
uint32 item_cost[80];
uint64 item_id[EQ::invtype::BAZAAR_SIZE];
uint32 item_cost[EQ::invtype::BAZAAR_SIZE];
};
struct ClickTrader_Struct {
uint32 code;
uint32 unknown[161];//damn soe this is totally pointless :/ but at least your finally using memset! Good job :) -LE
uint32 itemcost[80];
uint32 itemcost[EQ::invtype::BAZAAR_SIZE];
};
struct GetItems_Struct{
uint32 items[80];
uint32 items[EQ::invtype::BAZAAR_SIZE];
};
struct BecomeTrader_Struct {
+73 -59
View File
@@ -5,19 +5,31 @@
#include "strings.h"
#include <filesystem>
namespace fs = std::filesystem;
inline std::string striptrailingslash(const std::string &file_path)
{
if (file_path.back() == '/' || file_path.back() == '\\') {
return file_path.substr(0, file_path.length() - 1);
}
return file_path;
}
void PathManager::LoadPaths()
{
m_server_path = File::FindEqemuConfigPath();
if (!m_server_path.empty()) {
std::filesystem::current_path(m_server_path);
}
if (m_server_path.empty()) {
LogInfo("Failed to load server path");
return;
}
std::filesystem::current_path(m_server_path);
LogInfo("server [{}]", m_server_path);
if (!EQEmuConfig::LoadConfig()) {
LogError("Failed to load eqemu config");
@@ -26,64 +38,66 @@ void PathManager::LoadPaths()
const auto c = EQEmuConfig::get();
auto resolve_path = [&](const std::string& dir, const std::vector<std::string>& fallback_dirs = {}) -> std::string {
// relative
if (File::Exists((fs::path{m_server_path} / dir).string())) {
return fs::relative(fs::path{m_server_path} / dir).lexically_normal().string();
}
// absolute
if (File::Exists(fs::path{dir}.string())) {
return fs::absolute(fs::path{dir}).string();
}
// fallback search options if specified
for (const auto& fallback : fallback_dirs) {
if (File::Exists((fs::path{m_server_path} / fallback).string())) {
return fs::relative(fs::path{m_server_path} / fallback).lexically_normal().string();
}
}
// if all else fails, just set it to the config value
return dir;
};
m_maps_path = resolve_path(c->MapDir, {"maps", "Maps"});
m_quests_path = resolve_path(c->QuestDir);
m_plugins_path = resolve_path(c->PluginDir);
m_lua_modules_path = resolve_path(c->LuaModuleDir);
m_lua_mods_path = resolve_path("mods");
m_patch_path = resolve_path(c->PatchDir);
m_opcode_path = resolve_path(c->OpcodeDir);
m_shared_memory_path = resolve_path(c->SharedMemDir);
m_log_path = resolve_path(c->LogDir, {"logs"});
// Log all paths in a loop
std::vector<std::pair<std::string, std::string>> paths = {
{"server", m_server_path},
{"logs", m_log_path},
{"lua mods", m_lua_mods_path},
{"lua_modules", m_lua_modules_path},
{"maps", m_maps_path},
{"patches", m_patch_path},
{"opcode", m_opcode_path},
{"plugins", m_plugins_path},
{"quests", m_quests_path},
{"shared_memory", m_shared_memory_path}
};
constexpr int name_width = 15;
constexpr int path_width = 0;
constexpr int break_length = 70;
std::cout << std::endl;
LogInfo("{}", Strings::Repeat("-", break_length));
for (const auto& [name, in_path] : paths) {
if (!in_path.empty()) {
LogInfo("{:>{}} > [{:<{}}]", name, name_width, in_path, path_width);
}
// maps
if (File::Exists(fs::path{m_server_path + "/" + c->MapDir}.string())) {
m_maps_path = fs::relative(fs::path{m_server_path + "/" + c->MapDir}).string();
}
LogInfo("{}", Strings::Repeat("-", break_length));
else if (File::Exists(fs::path{m_server_path + "/maps"}.string())) {
m_maps_path = fs::relative(fs::path{m_server_path + "/maps"}).string();
}
else if (File::Exists(fs::path{m_server_path + "/Maps"}.string())) {
m_maps_path = fs::relative(fs::path{m_server_path + "/Maps"}).string();
}
// quests
if (File::Exists(fs::path{m_server_path + "/" + c->QuestDir}.string())) {
m_quests_path = fs::relative(fs::path{m_server_path + "/" + c->QuestDir}).string();
}
// plugins
if (File::Exists(fs::path{m_server_path + "/" + c->PluginDir}.string())) {
m_plugins_path = fs::relative(fs::path{m_server_path + "/" + c->PluginDir}).string();
}
// lua_modules
if (File::Exists(fs::path{m_server_path + "/" + c->LuaModuleDir}.string())) {
m_lua_modules_path = fs::relative(fs::path{m_server_path + "/" + c->LuaModuleDir}).string();
}
// lua mods
if (File::Exists(fs::path{ m_server_path + "/mods" }.string())) {
m_lua_mods_path = fs::relative(fs::path{ m_server_path + "/mods" }).string();
}
// patches
if (File::Exists(fs::path{m_server_path + "/" + c->PatchDir}.string())) {
m_patch_path = fs::relative(fs::path{m_server_path + "/" + c->PatchDir}).string();
}
// patches
if (File::Exists(fs::path{ m_server_path + "/" + c->OpcodeDir }.string())) {
m_opcode_path = fs::relative(fs::path{ m_server_path + "/" + c->OpcodeDir }).string();
}
// shared_memory_path
if (File::Exists(fs::path{m_server_path + "/" + c->SharedMemDir}.string())) {
m_shared_memory_path = fs::relative(fs::path{ m_server_path + "/" + c->SharedMemDir }).string();
}
// logging path
if (File::Exists(fs::path{m_server_path + "/" + c->LogDir}.string())) {
m_log_path = fs::relative(fs::path{m_server_path + "/" + c->LogDir}).string();
}
LogInfo("logs path [{}]", m_log_path);
LogInfo("lua mods path [{}]", m_lua_mods_path);
LogInfo("lua_modules path [{}]", m_lua_modules_path);
LogInfo("maps path [{}]", m_maps_path);
LogInfo("patches path [{}]", m_patch_path);
LogInfo("opcode path [{}]", m_opcode_path);
LogInfo("plugins path [{}]", m_plugins_path);
LogInfo("quests path [{}]", m_quests_path);
LogInfo("shared_memory path [{}]", m_shared_memory_path);
}
const std::string &PathManager::GetServerPath() const
@@ -49,23 +49,23 @@ public:
std::string field;
switch (theme_id) {
case LDoNTheme::GUK: {
case LDoNThemes::GUK: {
field = "guk_";
break;
}
case LDoNTheme::MIR: {
case LDoNThemes::MIR: {
field = "mir_";
break;
}
case LDoNTheme::MMC: {
case LDoNThemes::MMC: {
field = "mmc_";
break;
}
case LDoNTheme::RUJ: {
case LDoNThemes::RUJ: {
field = "ruj_";
break;
}
case LDoNTheme::TAK: {
case LDoNThemes::TAK: {
field = "tak_";
break;
}
@@ -19,48 +19,48 @@
class BaseInventoryRepository {
public:
struct Inventory {
uint32_t charid;
uint32_t slotid;
uint32_t itemid;
uint32_t character_id;
uint32_t slot_id;
uint32_t item_id;
uint16_t charges;
uint32_t color;
uint32_t augslot1;
uint32_t augslot2;
uint32_t augslot3;
uint32_t augslot4;
uint32_t augslot5;
int32_t augslot6;
uint32_t augment_one;
uint32_t augment_two;
uint32_t augment_three;
uint32_t augment_four;
uint32_t augment_five;
uint32_t augment_six;
uint8_t instnodrop;
std::string custom_data;
uint32_t ornamenticon;
uint32_t ornamentidfile;
uint32_t ornament_icon;
uint32_t ornament_idfile;
int32_t ornament_hero_model;
uint64_t guid;
};
static std::string PrimaryKey()
{
return std::string("charid");
return std::string("character_id");
}
static std::vector<std::string> Columns()
{
return {
"charid",
"slotid",
"itemid",
"character_id",
"slot_id",
"item_id",
"charges",
"color",
"augslot1",
"augslot2",
"augslot3",
"augslot4",
"augslot5",
"augslot6",
"augment_one",
"augment_two",
"augment_three",
"augment_four",
"augment_five",
"augment_six",
"instnodrop",
"custom_data",
"ornamenticon",
"ornamentidfile",
"ornament_icon",
"ornament_idfile",
"ornament_hero_model",
"guid",
};
@@ -69,21 +69,21 @@ public:
static std::vector<std::string> SelectColumns()
{
return {
"charid",
"slotid",
"itemid",
"character_id",
"slot_id",
"item_id",
"charges",
"color",
"augslot1",
"augslot2",
"augslot3",
"augslot4",
"augslot5",
"augslot6",
"augment_one",
"augment_two",
"augment_three",
"augment_four",
"augment_five",
"augment_six",
"instnodrop",
"custom_data",
"ornamenticon",
"ornamentidfile",
"ornament_icon",
"ornament_idfile",
"ornament_hero_model",
"guid",
};
@@ -126,21 +126,21 @@ public:
{
Inventory e{};
e.charid = 0;
e.slotid = 0;
e.itemid = 0;
e.character_id = 0;
e.slot_id = 0;
e.item_id = 0;
e.charges = 0;
e.color = 0;
e.augslot1 = 0;
e.augslot2 = 0;
e.augslot3 = 0;
e.augslot4 = 0;
e.augslot5 = 0;
e.augslot6 = 0;
e.augment_one = 0;
e.augment_two = 0;
e.augment_three = 0;
e.augment_four = 0;
e.augment_five = 0;
e.augment_six = 0;
e.instnodrop = 0;
e.custom_data = "";
e.ornamenticon = 0;
e.ornamentidfile = 0;
e.ornament_icon = 0;
e.ornament_idfile = 0;
e.ornament_hero_model = 0;
e.guid = 0;
@@ -153,7 +153,7 @@ public:
)
{
for (auto &inventory : inventorys) {
if (inventory.charid == inventory_id) {
if (inventory.character_id == inventory_id) {
return inventory;
}
}
@@ -179,21 +179,21 @@ public:
if (results.RowCount() == 1) {
Inventory e{};
e.charid = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.slotid = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.itemid = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.character_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.slot_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.charges = row[3] ? static_cast<uint16_t>(strtoul(row[3], nullptr, 10)) : 0;
e.color = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.augslot1 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.augslot2 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.augslot3 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.augslot4 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.augslot5 = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.augslot6 = row[10] ? static_cast<int32_t>(atoi(row[10])) : 0;
e.augment_one = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.augment_two = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.augment_three = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.augment_four = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.augment_five = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.augment_six = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.instnodrop = row[11] ? static_cast<uint8_t>(strtoul(row[11], nullptr, 10)) : 0;
e.custom_data = row[12] ? row[12] : "";
e.ornamenticon = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.ornamentidfile = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.ornament_icon = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.ornament_idfile = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.ornament_hero_model = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0;
e.guid = row[16] ? strtoull(row[16], nullptr, 10) : 0;
@@ -229,21 +229,21 @@ public:
auto columns = Columns();
v.push_back(columns[0] + " = " + std::to_string(e.charid));
v.push_back(columns[1] + " = " + std::to_string(e.slotid));
v.push_back(columns[2] + " = " + std::to_string(e.itemid));
v.push_back(columns[0] + " = " + std::to_string(e.character_id));
v.push_back(columns[1] + " = " + std::to_string(e.slot_id));
v.push_back(columns[2] + " = " + std::to_string(e.item_id));
v.push_back(columns[3] + " = " + std::to_string(e.charges));
v.push_back(columns[4] + " = " + std::to_string(e.color));
v.push_back(columns[5] + " = " + std::to_string(e.augslot1));
v.push_back(columns[6] + " = " + std::to_string(e.augslot2));
v.push_back(columns[7] + " = " + std::to_string(e.augslot3));
v.push_back(columns[8] + " = " + std::to_string(e.augslot4));
v.push_back(columns[9] + " = " + std::to_string(e.augslot5));
v.push_back(columns[10] + " = " + std::to_string(e.augslot6));
v.push_back(columns[5] + " = " + std::to_string(e.augment_one));
v.push_back(columns[6] + " = " + std::to_string(e.augment_two));
v.push_back(columns[7] + " = " + std::to_string(e.augment_three));
v.push_back(columns[8] + " = " + std::to_string(e.augment_four));
v.push_back(columns[9] + " = " + std::to_string(e.augment_five));
v.push_back(columns[10] + " = " + std::to_string(e.augment_six));
v.push_back(columns[11] + " = " + std::to_string(e.instnodrop));
v.push_back(columns[12] + " = '" + Strings::Escape(e.custom_data) + "'");
v.push_back(columns[13] + " = " + std::to_string(e.ornamenticon));
v.push_back(columns[14] + " = " + std::to_string(e.ornamentidfile));
v.push_back(columns[13] + " = " + std::to_string(e.ornament_icon));
v.push_back(columns[14] + " = " + std::to_string(e.ornament_idfile));
v.push_back(columns[15] + " = " + std::to_string(e.ornament_hero_model));
v.push_back(columns[16] + " = " + std::to_string(e.guid));
@@ -253,7 +253,7 @@ public:
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.charid
e.character_id
)
);
@@ -267,21 +267,21 @@ public:
{
std::vector<std::string> v;
v.push_back(std::to_string(e.charid));
v.push_back(std::to_string(e.slotid));
v.push_back(std::to_string(e.itemid));
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.charges));
v.push_back(std::to_string(e.color));
v.push_back(std::to_string(e.augslot1));
v.push_back(std::to_string(e.augslot2));
v.push_back(std::to_string(e.augslot3));
v.push_back(std::to_string(e.augslot4));
v.push_back(std::to_string(e.augslot5));
v.push_back(std::to_string(e.augslot6));
v.push_back(std::to_string(e.augment_one));
v.push_back(std::to_string(e.augment_two));
v.push_back(std::to_string(e.augment_three));
v.push_back(std::to_string(e.augment_four));
v.push_back(std::to_string(e.augment_five));
v.push_back(std::to_string(e.augment_six));
v.push_back(std::to_string(e.instnodrop));
v.push_back("'" + Strings::Escape(e.custom_data) + "'");
v.push_back(std::to_string(e.ornamenticon));
v.push_back(std::to_string(e.ornamentidfile));
v.push_back(std::to_string(e.ornament_icon));
v.push_back(std::to_string(e.ornament_idfile));
v.push_back(std::to_string(e.ornament_hero_model));
v.push_back(std::to_string(e.guid));
@@ -294,7 +294,7 @@ public:
);
if (results.Success()) {
e.charid = results.LastInsertedID();
e.character_id = results.LastInsertedID();
return e;
}
@@ -313,21 +313,21 @@ public:
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.charid));
v.push_back(std::to_string(e.slotid));
v.push_back(std::to_string(e.itemid));
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.charges));
v.push_back(std::to_string(e.color));
v.push_back(std::to_string(e.augslot1));
v.push_back(std::to_string(e.augslot2));
v.push_back(std::to_string(e.augslot3));
v.push_back(std::to_string(e.augslot4));
v.push_back(std::to_string(e.augslot5));
v.push_back(std::to_string(e.augslot6));
v.push_back(std::to_string(e.augment_one));
v.push_back(std::to_string(e.augment_two));
v.push_back(std::to_string(e.augment_three));
v.push_back(std::to_string(e.augment_four));
v.push_back(std::to_string(e.augment_five));
v.push_back(std::to_string(e.augment_six));
v.push_back(std::to_string(e.instnodrop));
v.push_back("'" + Strings::Escape(e.custom_data) + "'");
v.push_back(std::to_string(e.ornamenticon));
v.push_back(std::to_string(e.ornamentidfile));
v.push_back(std::to_string(e.ornament_icon));
v.push_back(std::to_string(e.ornament_idfile));
v.push_back(std::to_string(e.ornament_hero_model));
v.push_back(std::to_string(e.guid));
@@ -363,21 +363,21 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
Inventory e{};
e.charid = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.slotid = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.itemid = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.character_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.slot_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.charges = row[3] ? static_cast<uint16_t>(strtoul(row[3], nullptr, 10)) : 0;
e.color = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.augslot1 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.augslot2 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.augslot3 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.augslot4 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.augslot5 = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.augslot6 = row[10] ? static_cast<int32_t>(atoi(row[10])) : 0;
e.augment_one = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.augment_two = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.augment_three = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.augment_four = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.augment_five = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.augment_six = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.instnodrop = row[11] ? static_cast<uint8_t>(strtoul(row[11], nullptr, 10)) : 0;
e.custom_data = row[12] ? row[12] : "";
e.ornamenticon = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.ornamentidfile = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.ornament_icon = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.ornament_idfile = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.ornament_hero_model = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0;
e.guid = row[16] ? strtoull(row[16], nullptr, 10) : 0;
@@ -404,21 +404,21 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
Inventory e{};
e.charid = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.slotid = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.itemid = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.character_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.slot_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.charges = row[3] ? static_cast<uint16_t>(strtoul(row[3], nullptr, 10)) : 0;
e.color = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.augslot1 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.augslot2 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.augslot3 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.augslot4 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.augslot5 = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.augslot6 = row[10] ? static_cast<int32_t>(atoi(row[10])) : 0;
e.augment_one = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.augment_two = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.augment_three = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.augment_four = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.augment_five = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.augment_six = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.instnodrop = row[11] ? static_cast<uint8_t>(strtoul(row[11], nullptr, 10)) : 0;
e.custom_data = row[12] ? row[12] : "";
e.ornamenticon = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.ornamentidfile = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.ornament_icon = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.ornament_idfile = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.ornament_hero_model = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0;
e.guid = row[16] ? strtoull(row[16], nullptr, 10) : 0;
@@ -495,21 +495,21 @@ public:
{
std::vector<std::string> v;
v.push_back(std::to_string(e.charid));
v.push_back(std::to_string(e.slotid));
v.push_back(std::to_string(e.itemid));
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.charges));
v.push_back(std::to_string(e.color));
v.push_back(std::to_string(e.augslot1));
v.push_back(std::to_string(e.augslot2));
v.push_back(std::to_string(e.augslot3));
v.push_back(std::to_string(e.augslot4));
v.push_back(std::to_string(e.augslot5));
v.push_back(std::to_string(e.augslot6));
v.push_back(std::to_string(e.augment_one));
v.push_back(std::to_string(e.augment_two));
v.push_back(std::to_string(e.augment_three));
v.push_back(std::to_string(e.augment_four));
v.push_back(std::to_string(e.augment_five));
v.push_back(std::to_string(e.augment_six));
v.push_back(std::to_string(e.instnodrop));
v.push_back("'" + Strings::Escape(e.custom_data) + "'");
v.push_back(std::to_string(e.ornamenticon));
v.push_back(std::to_string(e.ornamentidfile));
v.push_back(std::to_string(e.ornament_icon));
v.push_back(std::to_string(e.ornament_idfile));
v.push_back(std::to_string(e.ornament_hero_model));
v.push_back(std::to_string(e.guid));
@@ -534,21 +534,21 @@ public:
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.charid));
v.push_back(std::to_string(e.slotid));
v.push_back(std::to_string(e.itemid));
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.charges));
v.push_back(std::to_string(e.color));
v.push_back(std::to_string(e.augslot1));
v.push_back(std::to_string(e.augslot2));
v.push_back(std::to_string(e.augslot3));
v.push_back(std::to_string(e.augslot4));
v.push_back(std::to_string(e.augslot5));
v.push_back(std::to_string(e.augslot6));
v.push_back(std::to_string(e.augment_one));
v.push_back(std::to_string(e.augment_two));
v.push_back(std::to_string(e.augment_three));
v.push_back(std::to_string(e.augment_four));
v.push_back(std::to_string(e.augment_five));
v.push_back(std::to_string(e.augment_six));
v.push_back(std::to_string(e.instnodrop));
v.push_back("'" + Strings::Escape(e.custom_data) + "'");
v.push_back(std::to_string(e.ornamenticon));
v.push_back(std::to_string(e.ornamentidfile));
v.push_back(std::to_string(e.ornament_icon));
v.push_back(std::to_string(e.ornament_idfile));
v.push_back(std::to_string(e.ornament_hero_model));
v.push_back(std::to_string(e.guid));
@@ -0,0 +1,560 @@
/**
* DO NOT MODIFY THIS FILE
*
* This repository was automatically generated and is NOT to be modified directly.
* Any repository modifications are meant to be made to the repository extending the base.
* Any modifications to base repositories are to be made by the generator only
*
* @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://docs.eqemu.io/developer/repositories
*/
#ifndef EQEMU_BASE_SHAREDBANK_REPOSITORY_H
#define EQEMU_BASE_SHAREDBANK_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseSharedbankRepository {
public:
struct Sharedbank {
uint32_t account_id;
uint32_t slot_id;
uint32_t item_id;
uint16_t charges;
uint32_t color;
uint32_t augment_one;
uint32_t augment_two;
uint32_t augment_three;
uint32_t augment_four;
uint32_t augment_five;
uint32_t augment_six;
std::string custom_data;
uint32_t ornament_icon;
uint32_t ornament_idfile;
int32_t ornament_hero_model;
uint64_t guid;
};
static std::string PrimaryKey()
{
return std::string("account_id");
}
static std::vector<std::string> Columns()
{
return {
"account_id",
"slot_id",
"item_id",
"charges",
"color",
"augment_one",
"augment_two",
"augment_three",
"augment_four",
"augment_five",
"augment_six",
"custom_data",
"ornament_icon",
"ornament_idfile",
"ornament_hero_model",
"guid",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"account_id",
"slot_id",
"item_id",
"charges",
"color",
"augment_one",
"augment_two",
"augment_three",
"augment_four",
"augment_five",
"augment_six",
"custom_data",
"ornament_icon",
"ornament_idfile",
"ornament_hero_model",
"guid",
};
}
static std::string ColumnsRaw()
{
return std::string(Strings::Implode(", ", Columns()));
}
static std::string SelectColumnsRaw()
{
return std::string(Strings::Implode(", ", SelectColumns()));
}
static std::string TableName()
{
return std::string("sharedbank");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static Sharedbank NewEntity()
{
Sharedbank e{};
e.account_id = 0;
e.slot_id = 0;
e.item_id = 0;
e.charges = 0;
e.color = 0;
e.augment_one = 0;
e.augment_two = 0;
e.augment_three = 0;
e.augment_four = 0;
e.augment_five = 0;
e.augment_six = 0;
e.custom_data = "";
e.ornament_icon = 0;
e.ornament_idfile = 0;
e.ornament_hero_model = 0;
e.guid = 0;
return e;
}
static Sharedbank GetSharedbank(
const std::vector<Sharedbank> &sharedbanks,
int sharedbank_id
)
{
for (auto &sharedbank : sharedbanks) {
if (sharedbank.account_id == sharedbank_id) {
return sharedbank;
}
}
return NewEntity();
}
static Sharedbank FindOne(
Database& db,
int sharedbank_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
sharedbank_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
Sharedbank e{};
e.account_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.slot_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.charges = row[3] ? static_cast<uint16_t>(strtoul(row[3], nullptr, 10)) : 0;
e.color = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.augment_one = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.augment_two = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.augment_three = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.augment_four = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.augment_five = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.augment_six = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.custom_data = row[11] ? row[11] : "";
e.ornament_icon = row[12] ? static_cast<uint32_t>(strtoul(row[12], nullptr, 10)) : 0;
e.ornament_idfile = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.ornament_hero_model = row[14] ? static_cast<int32_t>(atoi(row[14])) : 0;
e.guid = row[15] ? strtoull(row[15], nullptr, 10) : 0;
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int sharedbank_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
sharedbank_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const Sharedbank &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[0] + " = " + std::to_string(e.account_id));
v.push_back(columns[1] + " = " + std::to_string(e.slot_id));
v.push_back(columns[2] + " = " + std::to_string(e.item_id));
v.push_back(columns[3] + " = " + std::to_string(e.charges));
v.push_back(columns[4] + " = " + std::to_string(e.color));
v.push_back(columns[5] + " = " + std::to_string(e.augment_one));
v.push_back(columns[6] + " = " + std::to_string(e.augment_two));
v.push_back(columns[7] + " = " + std::to_string(e.augment_three));
v.push_back(columns[8] + " = " + std::to_string(e.augment_four));
v.push_back(columns[9] + " = " + std::to_string(e.augment_five));
v.push_back(columns[10] + " = " + std::to_string(e.augment_six));
v.push_back(columns[11] + " = '" + Strings::Escape(e.custom_data) + "'");
v.push_back(columns[12] + " = " + std::to_string(e.ornament_icon));
v.push_back(columns[13] + " = " + std::to_string(e.ornament_idfile));
v.push_back(columns[14] + " = " + std::to_string(e.ornament_hero_model));
v.push_back(columns[15] + " = " + std::to_string(e.guid));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.account_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static Sharedbank InsertOne(
Database& db,
Sharedbank e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.account_id));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.charges));
v.push_back(std::to_string(e.color));
v.push_back(std::to_string(e.augment_one));
v.push_back(std::to_string(e.augment_two));
v.push_back(std::to_string(e.augment_three));
v.push_back(std::to_string(e.augment_four));
v.push_back(std::to_string(e.augment_five));
v.push_back(std::to_string(e.augment_six));
v.push_back("'" + Strings::Escape(e.custom_data) + "'");
v.push_back(std::to_string(e.ornament_icon));
v.push_back(std::to_string(e.ornament_idfile));
v.push_back(std::to_string(e.ornament_hero_model));
v.push_back(std::to_string(e.guid));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.account_id = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<Sharedbank> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.account_id));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.charges));
v.push_back(std::to_string(e.color));
v.push_back(std::to_string(e.augment_one));
v.push_back(std::to_string(e.augment_two));
v.push_back(std::to_string(e.augment_three));
v.push_back(std::to_string(e.augment_four));
v.push_back(std::to_string(e.augment_five));
v.push_back(std::to_string(e.augment_six));
v.push_back("'" + Strings::Escape(e.custom_data) + "'");
v.push_back(std::to_string(e.ornament_icon));
v.push_back(std::to_string(e.ornament_idfile));
v.push_back(std::to_string(e.ornament_hero_model));
v.push_back(std::to_string(e.guid));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseInsert(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static std::vector<Sharedbank> All(Database& db)
{
std::vector<Sharedbank> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
Sharedbank e{};
e.account_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.slot_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.charges = row[3] ? static_cast<uint16_t>(strtoul(row[3], nullptr, 10)) : 0;
e.color = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.augment_one = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.augment_two = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.augment_three = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.augment_four = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.augment_five = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.augment_six = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.custom_data = row[11] ? row[11] : "";
e.ornament_icon = row[12] ? static_cast<uint32_t>(strtoul(row[12], nullptr, 10)) : 0;
e.ornament_idfile = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.ornament_hero_model = row[14] ? static_cast<int32_t>(atoi(row[14])) : 0;
e.guid = row[15] ? strtoull(row[15], nullptr, 10) : 0;
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<Sharedbank> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<Sharedbank> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {}",
BaseSelect(),
where_filter
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
Sharedbank e{};
e.account_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.slot_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.charges = row[3] ? static_cast<uint16_t>(strtoul(row[3], nullptr, 10)) : 0;
e.color = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.augment_one = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.augment_two = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.augment_three = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.augment_four = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.augment_five = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.augment_six = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.custom_data = row[11] ? row[11] : "";
e.ornament_icon = row[12] ? static_cast<uint32_t>(strtoul(row[12], nullptr, 10)) : 0;
e.ornament_idfile = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.ornament_hero_model = row[14] ? static_cast<int32_t>(atoi(row[14])) : 0;
e.guid = row[15] ? strtoull(row[15], nullptr, 10) : 0;
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static std::string BaseReplace()
{
return fmt::format(
"REPLACE INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static int ReplaceOne(
Database& db,
const Sharedbank &e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.account_id));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.charges));
v.push_back(std::to_string(e.color));
v.push_back(std::to_string(e.augment_one));
v.push_back(std::to_string(e.augment_two));
v.push_back(std::to_string(e.augment_three));
v.push_back(std::to_string(e.augment_four));
v.push_back(std::to_string(e.augment_five));
v.push_back(std::to_string(e.augment_six));
v.push_back("'" + Strings::Escape(e.custom_data) + "'");
v.push_back(std::to_string(e.ornament_icon));
v.push_back(std::to_string(e.ornament_idfile));
v.push_back(std::to_string(e.ornament_hero_model));
v.push_back(std::to_string(e.guid));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseReplace(),
Strings::Implode(",", v)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int ReplaceMany(
Database& db,
const std::vector<Sharedbank> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.account_id));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.charges));
v.push_back(std::to_string(e.color));
v.push_back(std::to_string(e.augment_one));
v.push_back(std::to_string(e.augment_two));
v.push_back(std::to_string(e.augment_three));
v.push_back(std::to_string(e.augment_four));
v.push_back(std::to_string(e.augment_five));
v.push_back(std::to_string(e.augment_six));
v.push_back("'" + Strings::Escape(e.custom_data) + "'");
v.push_back(std::to_string(e.ornament_icon));
v.push_back(std::to_string(e.ornament_idfile));
v.push_back(std::to_string(e.ornament_hero_model));
v.push_back(std::to_string(e.guid));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseReplace(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
};
#endif //EQEMU_BASE_SHAREDBANK_REPOSITORY_H
@@ -28,14 +28,13 @@ public:
uint32_t aug_slot_4;
uint32_t aug_slot_5;
uint32_t aug_slot_6;
uint32_t item_sn;
int32_t item_sn;
int32_t item_charges;
uint32_t item_cost;
uint64_t item_cost;
uint8_t slot_id;
uint32_t char_entity_id;
uint32_t char_zone_id;
int32_t char_zone_instance_id;
uint8_t active_transaction;
int8_t active_transaction;
};
static std::string PrimaryKey()
@@ -61,7 +60,6 @@ public:
"slot_id",
"char_entity_id",
"char_zone_id",
"char_zone_instance_id",
"active_transaction",
};
}
@@ -84,7 +82,6 @@ public:
"slot_id",
"char_entity_id",
"char_zone_id",
"char_zone_instance_id",
"active_transaction",
};
}
@@ -126,23 +123,22 @@ public:
{
Trader e{};
e.id = 0;
e.char_id = 0;
e.item_id = 0;
e.aug_slot_1 = 0;
e.aug_slot_2 = 0;
e.aug_slot_3 = 0;
e.aug_slot_4 = 0;
e.aug_slot_5 = 0;
e.aug_slot_6 = 0;
e.item_sn = 0;
e.item_charges = 0;
e.item_cost = 0;
e.slot_id = 0;
e.char_entity_id = 0;
e.char_zone_id = 0;
e.char_zone_instance_id = 0;
e.active_transaction = 0;
e.id = 0;
e.char_id = 0;
e.item_id = 0;
e.aug_slot_1 = 0;
e.aug_slot_2 = 0;
e.aug_slot_3 = 0;
e.aug_slot_4 = 0;
e.aug_slot_5 = 0;
e.aug_slot_6 = 0;
e.item_sn = 0;
e.item_charges = 0;
e.item_cost = 0;
e.slot_id = 0;
e.char_entity_id = 0;
e.char_zone_id = 0;
e.active_transaction = 0;
return e;
}
@@ -179,23 +175,22 @@ public:
if (results.RowCount() == 1) {
Trader e{};
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.item_sn = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.item_charges = row[10] ? static_cast<int32_t>(atoi(row[10])) : 0;
e.item_cost = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
e.slot_id = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0;
e.char_entity_id = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.char_zone_id = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.char_zone_instance_id = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0;
e.active_transaction = row[16] ? static_cast<uint8_t>(strtoul(row[16], nullptr, 10)) : 0;
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.item_sn = row[9] ? static_cast<int32_t>(atoi(row[9])) : 0;
e.item_charges = row[10] ? static_cast<int32_t>(atoi(row[10])) : 0;
e.item_cost = row[11] ? strtoull(row[11], nullptr, 10) : 0;
e.slot_id = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0;
e.char_entity_id = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.char_zone_id = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.active_transaction = row[15] ? static_cast<int8_t>(atoi(row[15])) : 0;
return e;
}
@@ -243,8 +238,7 @@ public:
v.push_back(columns[12] + " = " + std::to_string(e.slot_id));
v.push_back(columns[13] + " = " + std::to_string(e.char_entity_id));
v.push_back(columns[14] + " = " + std::to_string(e.char_zone_id));
v.push_back(columns[15] + " = " + std::to_string(e.char_zone_instance_id));
v.push_back(columns[16] + " = " + std::to_string(e.active_transaction));
v.push_back(columns[15] + " = " + std::to_string(e.active_transaction));
auto results = db.QueryDatabase(
fmt::format(
@@ -281,7 +275,6 @@ public:
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.char_entity_id));
v.push_back(std::to_string(e.char_zone_id));
v.push_back(std::to_string(e.char_zone_instance_id));
v.push_back(std::to_string(e.active_transaction));
auto results = db.QueryDatabase(
@@ -327,7 +320,6 @@ public:
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.char_entity_id));
v.push_back(std::to_string(e.char_zone_id));
v.push_back(std::to_string(e.char_zone_instance_id));
v.push_back(std::to_string(e.active_transaction));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
@@ -362,23 +354,22 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
Trader e{};
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.item_sn = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.item_charges = row[10] ? static_cast<int32_t>(atoi(row[10])) : 0;
e.item_cost = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
e.slot_id = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0;
e.char_entity_id = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.char_zone_id = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.char_zone_instance_id = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0;
e.active_transaction = row[16] ? static_cast<uint8_t>(strtoul(row[16], nullptr, 10)) : 0;
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.item_sn = row[9] ? static_cast<int32_t>(atoi(row[9])) : 0;
e.item_charges = row[10] ? static_cast<int32_t>(atoi(row[10])) : 0;
e.item_cost = row[11] ? strtoull(row[11], nullptr, 10) : 0;
e.slot_id = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0;
e.char_entity_id = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.char_zone_id = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.active_transaction = row[15] ? static_cast<int8_t>(atoi(row[15])) : 0;
all_entries.push_back(e);
}
@@ -403,23 +394,22 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
Trader e{};
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.item_sn = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.item_charges = row[10] ? static_cast<int32_t>(atoi(row[10])) : 0;
e.item_cost = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
e.slot_id = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0;
e.char_entity_id = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.char_zone_id = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.char_zone_instance_id = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0;
e.active_transaction = row[16] ? static_cast<uint8_t>(strtoul(row[16], nullptr, 10)) : 0;
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.item_sn = row[9] ? static_cast<int32_t>(atoi(row[9])) : 0;
e.item_charges = row[10] ? static_cast<int32_t>(atoi(row[10])) : 0;
e.item_cost = row[11] ? strtoull(row[11], nullptr, 10) : 0;
e.slot_id = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0;
e.char_entity_id = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.char_zone_id = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.active_transaction = row[15] ? static_cast<int8_t>(atoi(row[15])) : 0;
all_entries.push_back(e);
}
@@ -509,7 +499,6 @@ public:
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.char_entity_id));
v.push_back(std::to_string(e.char_zone_id));
v.push_back(std::to_string(e.char_zone_instance_id));
v.push_back(std::to_string(e.active_transaction));
auto results = db.QueryDatabase(
@@ -548,7 +537,6 @@ public:
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.char_entity_id));
v.push_back(std::to_string(e.char_zone_id));
v.push_back(std::to_string(e.char_zone_instance_id));
v.push_back(std::to_string(e.active_transaction));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
+37 -300
View File
@@ -3,310 +3,47 @@
#include "../database.h"
#include "../strings.h"
#include "base/base_sharedbank_repository.h"
class SharedbankRepository {
class SharedbankRepository: public BaseSharedbankRepository {
public:
struct Sharedbank {
int acctid;
int slotid;
int itemid;
int16 charges;
int augslot1;
int augslot2;
int augslot3;
int augslot4;
int augslot5;
int augslot6;
std::string custom_data;
};
static std::string PrimaryKey()
{
return std::string("");
}
/**
* This file was auto generated and can be modified and extended upon
*
* Base repository methods are automatically
* generated in the "base" version of this repository. The base repository
* is immutable and to be left untouched, while methods in this class
* are used as extension methods for more specific persistence-layer
* accessors or mutators.
*
* Base Methods (Subject to be expanded upon in time)
*
* Note: Not all tables are designed appropriately to fit functionality with all base methods
*
* InsertOne
* UpdateOne
* DeleteOne
* FindOne
* GetWhere(std::string where_filter)
* DeleteWhere(std::string where_filter)
* InsertMany
* All
*
* Example custom methods in a repository
*
* SharedbankRepository::GetByZoneAndVersion(int zone_id, int zone_version)
* SharedbankRepository::GetWhereNeverExpires()
* SharedbankRepository::GetWhereXAndY()
* SharedbankRepository::DeleteWhereXAndY()
*
* Most of the above could be covered by base methods, but if you as a developer
* find yourself re-using logic for other parts of the code, its best to just make a
* method that can be re-used easily elsewhere especially if it can use a base repository
* method and encapsulate filters there
*/
static std::vector<std::string> Columns()
{
return {
"acctid",
"slotid",
"itemid",
"charges",
"augslot1",
"augslot2",
"augslot3",
"augslot4",
"augslot5",
"augslot6",
"custom_data",
};
}
static std::string ColumnsRaw()
{
return std::string(Strings::Implode(", ", Columns()));
}
static std::string InsertColumnsRaw()
{
std::vector<std::string> insert_columns;
for (auto &column : Columns()) {
if (column == PrimaryKey()) {
continue;
}
insert_columns.push_back(column);
}
return std::string(Strings::Implode(", ", insert_columns));
}
static std::string TableName()
{
return std::string("sharedbank");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
ColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
InsertColumnsRaw()
);
}
static Sharedbank NewEntity()
{
Sharedbank entry{};
entry.acctid = 0;
entry.slotid = 0;
entry.itemid = 0;
entry.charges = 0;
entry.augslot1 = 0;
entry.augslot2 = 0;
entry.augslot3 = 0;
entry.augslot4 = 0;
entry.augslot5 = 0;
entry.augslot6 = 0;
entry.custom_data = 0;
return entry;
}
static Sharedbank GetSharedbankEntry(
const std::vector<Sharedbank> &sharedbanks,
int sharedbank_id
)
{
for (auto &sharedbank : sharedbanks) {
if (sharedbank. == sharedbank_id) {
return sharedbank;
}
}
return NewEntity();
}
static Sharedbank FindOne(
int sharedbank_id
)
{
auto results = database.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
BaseSelect(),
sharedbank_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
Sharedbank entry{};
entry.acctid = atoi(row[0]);
entry.slotid = atoi(row[1]);
entry.itemid = atoi(row[2]);
entry.charges = atoi(row[3]);
entry.augslot1 = atoi(row[4]);
entry.augslot2 = atoi(row[5]);
entry.augslot3 = atoi(row[6]);
entry.augslot4 = atoi(row[7]);
entry.augslot5 = atoi(row[8]);
entry.augslot6 = atoi(row[9]);
entry.custom_data = row[10];
return entry;
}
return NewEntity();
}
static int DeleteOne(
int sharedbank_id
)
{
auto results = database.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
sharedbank_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Sharedbank sharedbank_entry
)
{
std::vector<std::string> update_values;
auto columns = Columns();
update_values.push_back(columns[0] + " = " + std::to_string(sharedbank_entry.acctid));
update_values.push_back(columns[1] + " = " + std::to_string(sharedbank_entry.slotid));
update_values.push_back(columns[2] + " = " + std::to_string(sharedbank_entry.itemid));
update_values.push_back(columns[3] + " = " + std::to_string(sharedbank_entry.charges));
update_values.push_back(columns[4] + " = " + std::to_string(sharedbank_entry.augslot1));
update_values.push_back(columns[5] + " = " + std::to_string(sharedbank_entry.augslot2));
update_values.push_back(columns[6] + " = " + std::to_string(sharedbank_entry.augslot3));
update_values.push_back(columns[7] + " = " + std::to_string(sharedbank_entry.augslot4));
update_values.push_back(columns[8] + " = " + std::to_string(sharedbank_entry.augslot5));
update_values.push_back(columns[9] + " = " + std::to_string(sharedbank_entry.augslot6));
update_values.push_back(columns[10] + " = '" + Strings::Escape(sharedbank_entry.custom_data) + "'");
auto results = database.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", update_values),
PrimaryKey(),
sharedbank_entry.
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static Sharedbank InsertOne(
Sharedbank sharedbank_entry
)
{
std::vector<std::string> insert_values;
insert_values.push_back(std::to_string(sharedbank_entry.acctid));
insert_values.push_back(std::to_string(sharedbank_entry.slotid));
insert_values.push_back(std::to_string(sharedbank_entry.itemid));
insert_values.push_back(std::to_string(sharedbank_entry.charges));
insert_values.push_back(std::to_string(sharedbank_entry.augslot1));
insert_values.push_back(std::to_string(sharedbank_entry.augslot2));
insert_values.push_back(std::to_string(sharedbank_entry.augslot3));
insert_values.push_back(std::to_string(sharedbank_entry.augslot4));
insert_values.push_back(std::to_string(sharedbank_entry.augslot5));
insert_values.push_back(std::to_string(sharedbank_entry.augslot6));
insert_values.push_back("'" + Strings::Escape(sharedbank_entry.custom_data) + "'");
auto results = database.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", insert_values)
)
);
if (results.Success()) {
sharedbank_entry.id = results.LastInsertedID();
return sharedbank_entry;
}
sharedbank_entry = InstanceListRepository::NewEntity();
return sharedbank_entry;
}
static int InsertMany(
std::vector<Sharedbank> sharedbank_entries
)
{
std::vector<std::string> insert_chunks;
for (auto &sharedbank_entry: sharedbank_entries) {
std::vector<std::string> insert_values;
insert_values.push_back(std::to_string(sharedbank_entry.acctid));
insert_values.push_back(std::to_string(sharedbank_entry.slotid));
insert_values.push_back(std::to_string(sharedbank_entry.itemid));
insert_values.push_back(std::to_string(sharedbank_entry.charges));
insert_values.push_back(std::to_string(sharedbank_entry.augslot1));
insert_values.push_back(std::to_string(sharedbank_entry.augslot2));
insert_values.push_back(std::to_string(sharedbank_entry.augslot3));
insert_values.push_back(std::to_string(sharedbank_entry.augslot4));
insert_values.push_back(std::to_string(sharedbank_entry.augslot5));
insert_values.push_back(std::to_string(sharedbank_entry.augslot6));
insert_values.push_back("'" + Strings::Escape(sharedbank_entry.custom_data) + "'");
insert_chunks.push_back("(" + Strings::Implode(",", insert_values) + ")");
}
std::vector<std::string> insert_values;
auto results = database.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseInsert(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static std::vector<Sharedbank> All()
{
std::vector<Sharedbank> all_entries;
auto results = database.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
Sharedbank entry{};
entry.acctid = atoi(row[0]);
entry.slotid = atoi(row[1]);
entry.itemid = atoi(row[2]);
entry.charges = atoi(row[3]);
entry.augslot1 = atoi(row[4]);
entry.augslot2 = atoi(row[5]);
entry.augslot3 = atoi(row[6]);
entry.augslot4 = atoi(row[7]);
entry.augslot5 = atoi(row[8]);
entry.augslot6 = atoi(row[9]);
entry.custom_data = row[10];
all_entries.push_back(entry);
}
return all_entries;
}
// Custom extended repository methods here
};
+6 -9
View File
@@ -16,7 +16,6 @@ public:
struct DistinctTraders_Struct {
uint32 trader_id;
uint32 zone_id;
uint32 zone_instance_id;
uint32 entity_id;
std::string trader_name;
};
@@ -36,8 +35,7 @@ public:
GetBazaarSearchResults(
SharedDatabase &db,
BazaarSearchCriteria_Struct search,
uint32 char_zone_id,
int32 char_zone_instance_id
uint32 char_zone_id
);
static BulkTraders_Struct GetDistinctTraders(Database &db)
@@ -46,7 +44,7 @@ public:
std::vector<DistinctTraders_Struct> distinct_traders;
auto results = db.QueryDatabase(
"SELECT DISTINCT(t.char_id), t.char_zone_id, t.char_zone_instance_id, t.char_entity_id, c.name "
"SELECT DISTINCT(t.char_id), t.char_zone_id, t.char_entity_id, c.name "
"FROM trader AS t "
"JOIN character_data AS c ON t.char_id = c.id;"
);
@@ -56,11 +54,10 @@ public:
for (auto row: results) {
DistinctTraders_Struct e{};
e.trader_id = Strings::ToInt(row[0]);
e.zone_id = Strings::ToInt(row[1]);
e.zone_instance_id = Strings::ToInt(row[2]);
e.entity_id = Strings::ToInt(row[3]);
e.trader_name = row[4] ? row[4] : "";
e.trader_id = Strings::ToInt(row[0]);
e.zone_id = Strings::ToInt(row[1]);
e.entity_id = Strings::ToInt(row[2]);
e.trader_name = row[3] ? row[3] : "";
all_entries.name_length += e.trader_name.length() + 1;
all_entries.traders.push_back(e);
+1 -5
View File
@@ -339,10 +339,7 @@ RULE_STRING(World, MOTD, "", "Server MOTD sent on login, change from empty to ha
RULE_STRING(World, Rules, "", "Server Rules, change from empty to have this be used instead of variables table 'rules' value, lines are pipe (|) separated, example: A|B|C")
RULE_BOOL(World, EnableAutoLogin, false, "Enables or disables auto login of characters, allowing people to log characters in directly from loginserver to ingame")
RULE_BOOL(World, EnablePVPRegions, true, "Enables or disables PVP Regions automatically setting your PVP flag")
RULE_STRING(World, SupportedClients, "", "Comma-delimited list of clients to restrict to. Supported values are Titanium | SoF | SoD | UF | RoF | RoF2. Example: Titanium,RoF2")
RULE_STRING(World, CustomFilesKey, "", "Enable if the server requires custom files and sends a key to validate. Empty string to disable. Example: eqcustom_v1")
RULE_STRING(World, CustomFilesUrl, "github.com/knervous/eqnexus/releases", "URL to display at character select if client is missing custom files")
RULE_INT(World, CustomFilesAdminLevel, 20, "Admin level at which custom file key is not required when CustomFilesKey is specified")
RULE_STRING(World, SupportedClients, "RoF2", "Comma-delimited list of clients to restrict to. Supported values are Titanium | SoF | SoD | UF | RoF | RoF2. Example: Titanium,RoF2")
RULE_CATEGORY_END()
RULE_CATEGORY(Zone)
@@ -684,7 +681,6 @@ RULE_BOOL(NPC, DisableLastNames, false, "Enable to disable NPC Last Names")
RULE_BOOL(NPC, NPCIgnoreLevelBasedHasteCaps, false, "Ignores hard coded level based haste caps.")
RULE_INT(NPC, NPCHasteCap, 150, "Haste cap for non-v3(over haste) haste")
RULE_INT(NPC, NPCHastev3Cap, 25, "Haste cap for v3(over haste) haste")
RULE_STRING(NPC, ExcludedFaceTargetRaces, "52,72,73,141,233,328,329,372,376,377,378,379,380,381,382,383,404,422,423,424,425,426,428,429,445,449,460,462,463,500,501,502,503,504,505,506,507,508,509,510,511,513,514,515,516,533,534,535,536,537,538,539,540,541,542,543,544,545,546,550,551,552,553,554,555,556,557,567,573,577,586,589,590,591,592,593,595,596,599,601,616,619,621,628,629,630,633,634,635,636,665,683,684,685,691,692,693,694,702,703,705,706,707,710,711,714,720,2250,2254", "Race IDs excluded from facing target when hailed")
RULE_CATEGORY_END()
RULE_CATEGORY(Aggro)
+2 -1
View File
@@ -319,6 +319,8 @@
// player events
#define ServerOP_PlayerEvent 0x5100
#define ServerOP_DataBucketCacheUpdate 0x5200
enum {
CZUpdateType_Character,
CZUpdateType_Group,
@@ -1943,7 +1945,6 @@ struct ServerOP_GuildMessage_Struct {
struct TraderMessaging_Struct {
uint32 action;
uint32 zone_id;
uint32 instance_id;
uint32 trader_id;
uint32 entity_id;
char trader_name[64];
+298 -379
View File
@@ -48,6 +48,7 @@
#include "repositories/skill_caps_repository.h"
#include "repositories/inventory_repository.h"
#include "repositories/books_repository.h"
#include "repositories/sharedbank_repository.h"
namespace ItemField
{
@@ -190,242 +191,268 @@ SharedDatabase::MailKeys SharedDatabase::GetMailKey(int character_id)
return MailKeys{};
}
bool SharedDatabase::SaveCursor(uint32 char_id, std::list<EQ::ItemInstance*>::const_iterator &start, std::list<EQ::ItemInstance*>::const_iterator &end)
bool SharedDatabase::SaveCursor(
uint32 char_id,
std::list<EQ::ItemInstance*>::const_iterator& start,
std::list<EQ::ItemInstance*>::const_iterator& end
)
{
// Delete cursor items
const std::string query = StringFormat("DELETE FROM inventory WHERE charid = %i "
"AND ((slotid >= 8000 AND slotid <= 8999) "
"OR slotid = %i OR (slotid >= %i AND slotid <= %i) )",
char_id, EQ::invslot::slotCursor,
EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END);
const auto results = QueryDatabase(query);
if (!results.Success()) {
std::cout << "Clearing cursor failed: " << results.ErrorMessage() << std::endl;
return false;
}
const int deleted = InventoryRepository::DeleteWhere(
*this,
fmt::format(
"`character_id` = {} AND (`slot_id` = {} OR `slot_id` BETWEEN {} AND {})",
char_id,
EQ::invslot::slotCursor,
EQ::invbag::CURSOR_BAG_BEGIN,
EQ::invbag::CURSOR_BAG_END
)
);
int i = 8000;
for(auto& it = start; it != end; ++it, i++) {
if (i > 8999) { break; } // shouldn't be anything in the queue that indexes this high
const EQ::ItemInstance *inst = *it;
const int16 use_slot = (i == 8000) ? EQ::invslot::slotCursor : i;
int16 i = EQ::invslot::slotCursor;
for (auto& it = start; it != end; ++it, i++) {
// shouldn't be anything in the queue that indexes this high
if (i > EQ::invbag::CURSOR_BAG_END) {
break;
}
const EQ::ItemInstance* inst = *it;
const int16 use_slot = i == EQ::invslot::slotCursor ? EQ::invslot::slotCursor : i;
if (!SaveInventory(char_id, inst, use_slot)) {
return false;
}
}
}
return true;
}
bool SharedDatabase::VerifyInventory(uint32 account_id, int16 slot_id, const EQ::ItemInstance* inst)
{
// Delete cursor items
const std::string query = StringFormat("SELECT itemid, charges FROM sharedbank "
"WHERE acctid = %d AND slotid = %d",
account_id, slot_id);
auto results = QueryDatabase(query);
if (!results.Success()) {
//returning true is less harmful in the face of a query error
return true;
if (!inst || !inst->GetItem()) {
return false;
}
if (results.RowCount() == 0)
return false;
const auto& l = SharedbankRepository::GetWhere(
*this,
fmt::format(
"`account_id` = {} AND `slot_id` = {} LIMIT 1",
account_id,
slot_id
)
);
auto& row = results.begin();
if (l.empty()) {
return false;
}
const uint32 id = Strings::ToUnsignedInt(row[0]);
const uint16 charges = Strings::ToUnsignedInt(row[1]);
const auto& e = l.front();
uint16 expect_charges;
uint16 expect_charges = inst->GetCharges() >= 0 ? inst->GetCharges() : std::numeric_limits<int16>::max();
if(inst->GetCharges() >= 0)
expect_charges = inst->GetCharges();
else
expect_charges = 0x7FFF;
if(id != inst->GetItem()->ID || charges != expect_charges)
return false;
return true;
return e.item_id == inst->GetID() && e.charges == expect_charges;
}
bool SharedDatabase::SaveInventory(uint32 char_id, const EQ::ItemInstance* inst, int16 slot_id) {
//never save tribute slots:
if (slot_id >= EQ::invslot::TRIBUTE_BEGIN && slot_id <= EQ::invslot::TRIBUTE_END)
return true;
if (slot_id >= EQ::invslot::GUILD_TRIBUTE_BEGIN && slot_id <= EQ::invslot::GUILD_TRIBUTE_END)
bool SharedDatabase::SaveInventory(uint32 char_id, const EQ::ItemInstance* inst, int16 slot_id)
{
// Don't save any Tribute slots
if (
EQ::ValueWithin(slot_id, EQ::invslot::GUILD_TRIBUTE_BEGIN, EQ::invslot::GUILD_TRIBUTE_END) ||
EQ::ValueWithin(slot_id, EQ::invslot::TRIBUTE_BEGIN, EQ::invslot::TRIBUTE_END)
) {
return true;
}
if (slot_id >= EQ::invslot::SHARED_BANK_BEGIN && slot_id <= EQ::invbag::SHARED_BANK_BAGS_END) {
// Shared bank inventory
if (
EQ::ValueWithin(slot_id, EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END) ||
EQ::ValueWithin(slot_id, EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END)
) {
if (!inst) {
return DeleteSharedBankSlot(char_id, slot_id);
}
else {
} else {
// Needed to clear out bag slots that 'REPLACE' in UpdateSharedBankSlot does not overwrite..otherwise, duplication occurs
// (This requires that parent then child items be sent..which should be how they are currently passed)
if (EQ::InventoryProfile::SupportsContainers(slot_id))
if (EQ::InventoryProfile::SupportsContainers(slot_id)) {
DeleteSharedBankSlot(char_id, slot_id);
}
return UpdateSharedBankSlot(char_id, inst, slot_id);
}
}
else if (!inst) { // All other inventory
} else if (!inst) { // All other inventory
return DeleteInventorySlot(char_id, slot_id);
}
// Needed to clear out bag slots that 'REPLACE' in UpdateInventorySlot does not overwrite..otherwise, duplication occurs
// (This requires that parent then child items be sent..which should be how they are currently passed)
if (EQ::InventoryProfile::SupportsContainers(slot_id))
if (EQ::InventoryProfile::SupportsContainers(slot_id)) {
DeleteInventorySlot(char_id, slot_id);
return UpdateInventorySlot(char_id, inst, slot_id);
}
bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const EQ::ItemInstance* inst, int16 slot_id) {
// need to check 'inst' argument for valid pointer
uint32 augslot[EQ::invaug::SOCKET_COUNT] = { 0, 0, 0, 0, 0, 0 };
if (inst->IsClassCommon()) {
for (int i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) {
const EQ::ItemInstance *auginst = inst->GetItem(i);
augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : 0;
}
}
uint16 charges;
if(inst->GetCharges() >= 0)
charges = inst->GetCharges();
else
charges = 0x7FFF;
// Update/Insert item
const std::string query = StringFormat("REPLACE INTO inventory "
"(charid, slotid, itemid, charges, instnodrop, custom_data, color, "
"augslot1, augslot2, augslot3, augslot4, augslot5, augslot6, ornamenticon, ornamentidfile, ornament_hero_model, guid) "
"VALUES( %lu, %lu, %lu, %lu, %lu, '%s', %lu, "
"%lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu)",
static_cast<unsigned long>(char_id), static_cast<unsigned long>(slot_id), static_cast<unsigned long>(inst->GetItem()->ID),
static_cast<unsigned long>(charges), static_cast<unsigned long>(inst->IsAttuned() ? 1 : 0),
inst->GetCustomDataString().c_str(), static_cast<unsigned long>(inst->GetColor()),
static_cast<unsigned long>(augslot[0]), static_cast<unsigned long>(augslot[1]), static_cast<unsigned long>(augslot[2]),
static_cast<unsigned long>(augslot[3]), static_cast<unsigned long>(augslot[4]), static_cast<unsigned long>(augslot[5]), static_cast<unsigned long>(inst->GetOrnamentationIcon()),
static_cast<unsigned long>(inst->GetOrnamentationIDFile()), static_cast<unsigned long>(inst->GetOrnamentHeroModel()), inst->GetSerialNumber());
const auto results = QueryDatabase(query);
// Save bag contents, if slot supports bag contents
if (inst->IsClassBag() && EQ::InventoryProfile::SupportsContainers(slot_id))
// Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID'
// messages through attrition (and the modded code in SaveInventory)
for (uint8 idx = EQ::invbag::SLOT_BEGIN; idx < inst->GetItem()->BagSlots && idx <= EQ::invbag::SLOT_END; idx++) {
const EQ::ItemInstance* baginst = inst->GetItem(idx);
SaveInventory(char_id, baginst, EQ::InventoryProfile::CalcSlotId(slot_id, idx));
}
if (!results.Success()) {
return false;
}
return true;
return UpdateInventorySlot(char_id, inst, slot_id);
}
bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const EQ::ItemInstance* inst, int16 slot_id) {
// need to check 'inst' argument for valid pointer
uint32 augslot[EQ::invaug::SOCKET_COUNT] = { 0, 0, 0, 0, 0, 0 };
if (inst->IsClassCommon()) {
for (int i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) {
const EQ::ItemInstance *auginst = inst->GetItem(i);
augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : 0;
}
bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const EQ::ItemInstance* inst, int16 slot_id)
{
if (!inst || !inst->GetItem()) {
return false;
}
// Update/Insert item
const uint32 account_id = GetAccountIDByChar(char_id);
uint16 charges;
if(inst->GetCharges() >= 0)
charges = inst->GetCharges();
else
charges = 0x7FFF;
std::vector<uint32> augment_ids = inst->GetAugmentIDs();
const std::string query = StringFormat("REPLACE INTO sharedbank "
"(acctid, slotid, itemid, charges, custom_data, "
"augslot1, augslot2, augslot3, augslot4, augslot5, augslot6) "
"VALUES( %lu, %lu, %lu, %lu, '%s', "
"%lu, %lu, %lu, %lu, %lu, %lu)",
static_cast<unsigned long>(account_id), static_cast<unsigned long>(slot_id), static_cast<unsigned long>(inst->GetItem()->ID),
static_cast<unsigned long>(charges), inst->GetCustomDataString().c_str(), static_cast<unsigned long>(augslot[0]),
static_cast<unsigned long>(augslot[1]), static_cast<unsigned long>(augslot[2]), static_cast<unsigned long>(augslot[3]), static_cast<unsigned long>(augslot[4]),
static_cast<unsigned long>(augslot[5]));
const auto results = QueryDatabase(query);
uint16 charges = inst->GetCharges() >= 0 ? inst->GetCharges() : std::numeric_limits<int16>::max();
// Save bag contents, if slot supports bag contents
auto e = InventoryRepository::NewEntity();
e.character_id = char_id;
e.slot_id = slot_id;
e.item_id = inst->GetID();
e.charges = charges;
e.color = inst->GetColor();
e.augment_one = augment_ids[0];
e.augment_two = augment_ids[1];
e.augment_three = augment_ids[2];
e.augment_four = augment_ids[3];
e.augment_five = augment_ids[4];
e.augment_six = augment_ids[5];
e.instnodrop = inst->IsAttuned() ? 1 : 0;
e.custom_data = inst->GetCustomDataString();
e.ornament_icon = inst->GetOrnamentationIcon();
e.ornament_idfile = inst->GetOrnamentationIDFile();
e.ornament_hero_model = inst->GetOrnamentHeroModel();
e.guid = inst->GetSerialNumber();
const int replaced = InventoryRepository::ReplaceOne(*this, e);
// Save bag contents, if slot supports bag contents
if (inst->IsClassBag() && EQ::InventoryProfile::SupportsContainers(slot_id)) {
// Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID'
// messages through attrition (and the modded code in SaveInventory)
for (uint8 idx = EQ::invbag::SLOT_BEGIN; idx < inst->GetItem()->BagSlots && idx <= EQ::invbag::SLOT_END; idx++) {
const EQ::ItemInstance* baginst = inst->GetItem(idx);
SaveInventory(char_id, baginst, EQ::InventoryProfile::CalcSlotId(slot_id, idx));
for (
uint8 i = EQ::invbag::SLOT_BEGIN;
i < inst->GetItem()->BagSlots && i <= EQ::invbag::SLOT_END;
i++
) {
const EQ::ItemInstance* bag_inst = inst->GetItem(i);
SaveInventory(char_id, bag_inst, EQ::InventoryProfile::CalcSlotId(slot_id, i));
}
}
if (!results.Success()) {
return false;
}
return true;
return replaced;
}
bool SharedDatabase::DeleteInventorySlot(uint32 char_id, int16 slot_id) {
bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const EQ::ItemInstance* inst, int16 slot_id)
{
if (!inst || !inst->GetItem()) {
return false;
}
// Delete item
std::string query = StringFormat("DELETE FROM inventory WHERE charid = %i AND slotid = %i", char_id, slot_id);
auto results = QueryDatabase(query);
if (!results.Success()) {
return false;
}
std::vector<uint32> augment_ids = inst->GetAugmentIDs();
// Delete bag slots, if need be
if (!EQ::InventoryProfile::SupportsContainers(slot_id))
return true;
uint16 charges = inst->GetCharges() >= 0 ? inst->GetCharges() : std::numeric_limits<int16>::max();
const int16 base_slot_id = EQ::InventoryProfile::CalcSlotId(slot_id, EQ::invbag::SLOT_BEGIN);
query = StringFormat("DELETE FROM inventory WHERE charid = %i AND slotid >= %i AND slotid < %i",
char_id, base_slot_id, (base_slot_id+10));
results = QueryDatabase(query);
if (!results.Success()) {
return false;
}
const uint32 account_id = GetAccountIDByChar(char_id);
// @merth: need to delete augments here
return true;
auto e = SharedbankRepository::NewEntity();
e.account_id = account_id;
e.slot_id = slot_id;
e.item_id = inst->GetID();
e.charges = charges;
e.color = inst->GetColor();
e.augment_one = augment_ids[0];
e.augment_two = augment_ids[1];
e.augment_three = augment_ids[2];
e.augment_four = augment_ids[3];
e.augment_five = augment_ids[4];
e.augment_six = augment_ids[5];
e.custom_data = inst->GetCustomDataString();
e.ornament_icon = inst->GetOrnamentationIcon();
e.ornament_idfile = inst->GetOrnamentationIDFile();
e.ornament_hero_model = inst->GetOrnamentHeroModel();
e.guid = inst->GetSerialNumber();
const int replaced = SharedbankRepository::ReplaceOne(*this, e);
// Save bag contents, if slot supports bag contents
if (inst->IsClassBag() && EQ::InventoryProfile::SupportsContainers(slot_id)) {
// Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID'
// messages through attrition (and the modded code in SaveInventory)
for (
uint8 i = EQ::invbag::SLOT_BEGIN;
i < inst->GetItem()->BagSlots && i <= EQ::invbag::SLOT_END;
i++
) {
const EQ::ItemInstance* bag_inst = inst->GetItem(i);
SaveInventory(char_id, bag_inst, EQ::InventoryProfile::CalcSlotId(slot_id, i));
}
}
return replaced;
}
bool SharedDatabase::DeleteSharedBankSlot(uint32 char_id, int16 slot_id) {
bool SharedDatabase::DeleteInventorySlot(uint32 char_id, int16 slot_id)
{
const int deleted = InventoryRepository::DeleteWhere(
*this,
fmt::format(
"`character_id` = {} AND `slot_id` = {}",
char_id,
slot_id
)
);
// Delete item
const uint32 account_id = GetAccountIDByChar(char_id);
std::string query = StringFormat("DELETE FROM sharedbank WHERE acctid=%i AND slotid=%i", account_id, slot_id);
auto results = QueryDatabase(query);
if (!results.Success()) {
return false;
}
if (!deleted) {
return false;
}
// Delete bag slots, if need be
if (!EQ::InventoryProfile::SupportsContainers(slot_id))
return true;
if (!EQ::InventoryProfile::SupportsContainers(slot_id)) {
return true;
}
const int16 base_slot_id = EQ::InventoryProfile::CalcSlotId(slot_id, EQ::invbag::SLOT_BEGIN);
query = StringFormat("DELETE FROM sharedbank WHERE acctid = %i "
"AND slotid >= %i AND slotid < %i",
account_id, base_slot_id, (base_slot_id+10));
results = QueryDatabase(query);
if (!results.Success()) {
return false;
}
const int16 base_slot_id = EQ::InventoryProfile::CalcSlotId(slot_id, EQ::invbag::SLOT_BEGIN);
// @merth: need to delete augments here
return true;
return InventoryRepository::DeleteWhere(
*this,
fmt::format(
"`character_id` = {} AND `slot_id` BETWEEN {} AND {}",
char_id,
base_slot_id,
base_slot_id + (EQ::invbag::SLOT_COUNT - 1)
)
);
}
bool SharedDatabase::DeleteSharedBankSlot(uint32 char_id, int16 slot_id)
{
const uint32 account_id = GetAccountIDByChar(char_id);
const int deleted = SharedbankRepository::DeleteWhere(
*this,
fmt::format(
"`account_id` = {} AND `slot_id` = {}",
account_id,
slot_id
)
);
if (!deleted) {
return false;
}
if (!EQ::InventoryProfile::SupportsContainers(slot_id)) {
return true;
}
const int16 base_slot_id = EQ::InventoryProfile::CalcSlotId(slot_id, EQ::invbag::SLOT_BEGIN);
return SharedbankRepository::DeleteWhere(
*this,
fmt::format(
"`account_id` = {} AND `slotid` BETWEEN {} AND {}",
account_id,
base_slot_id,
base_slot_id + (EQ::invbag::SLOT_COUNT - 1)
)
);
}
@@ -550,96 +577,81 @@ bool SharedDatabase::SetStartingItems(
// Retrieve shared bank inventory based on either account or character
bool SharedDatabase::GetSharedBank(uint32 id, EQ::InventoryProfile *inv, bool is_charid)
{
std::string query;
const uint32 account_id = is_charid ? GetAccountIDByChar(id) : id;
if (is_charid) {
query = fmt::format(
"SELECT sb.slotid, sb.itemid, sb.charges, "
"sb.augslot1, sb.augslot2, sb.augslot3, "
"sb.augslot4, sb.augslot5, sb.augslot6, sb.custom_data "
"FROM sharedbank sb INNER JOIN character_data ch "
"ON ch.account_id = sb.acctid WHERE ch.id = {} ORDER BY sb.slotid",
id
);
} else {
query = fmt::format(
"SELECT slotid, itemid, charges, "
"augslot1, augslot2, augslot3, "
"augslot4, augslot5, augslot6, custom_data "
"FROM sharedbank WHERE acctid = {} ORDER BY slotid",
id
);
}
auto results = QueryDatabase(query);
// If we have no results we still need to return true
if (!results.Success()) {
if (!account_id) {
return false;
}
for (auto row : results) {
int16 slot_id = static_cast<int16>(Strings::ToInt(row[0]));
uint32 item_id = Strings::ToUnsignedInt(row[1]);
const int16 charges = static_cast<int16>(Strings::ToInt(row[2]));
const auto& l = SharedbankRepository::GetWhere(
*this,
fmt::format(
"`account_id` = {}",
account_id
)
);
uint32 aug[EQ::invaug::SOCKET_COUNT];
aug[0] = Strings::ToUnsignedInt(row[3]);
aug[1] = Strings::ToUnsignedInt(row[4]);
aug[2] = Strings::ToUnsignedInt(row[5]);
aug[3] = Strings::ToUnsignedInt(row[6]);
aug[4] = Strings::ToUnsignedInt(row[7]);
aug[5] = Strings::ToUnsignedInt(row[8]);
if (l.empty()) {
return true;
}
const EQ::ItemData *item = GetItem(item_id);
for (const auto& e : l) {
uint32 augment_ids[EQ::invaug::SOCKET_COUNT] = {
e.augment_one,
e.augment_two,
e.augment_three,
e.augment_four,
e.augment_five,
e.augment_six
};
const EQ::ItemData* item = GetItem(e.item_id);
if (!item) {
LogError(
"Warning: [{}] [{}] has an invalid item_id [{}] in inventory slot [{}]",
is_charid ? "charid" : "acctid",
"Warning: {} [{}] has an invalid item_id [{}] in slot_id [{}]",
is_charid ? "character_id" : "account_id",
id,
item_id,
slot_id
e.item_id,
e.slot_id
);
continue;
}
auto inst = CreateBaseItem(item, charges);
EQ::ItemInstance* inst = CreateBaseItem(item, e.charges);
if (!inst) {
continue;
}
if (inst && item->IsClassCommon()) {
if (item->IsClassCommon()) {
for (int i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) {
if (aug[i]) {
inst->PutAugment(this, i, aug[i]);
if (augment_ids[i]) {
inst->PutAugment(this, i, augment_ids[i]);
}
}
}
if (inst && row[9]) {
std::string data_str(row[9]);
inst->SetCustomDataString(data_str);
if (!e.custom_data.empty()) {
inst->SetCustomDataString(e.custom_data);
}
// theoretically inst can be nullptr ... this would be very bad ...
const int16 put_slot_id = inv->PutItem(slot_id, *inst);
const int16 put_slot_id = inv->PutItem(e.slot_id, *inst);
safe_delete(inst);
// Save ptr to item in inventory
if (put_slot_id != INVALID_INDEX) {
continue;
}
LogError(
"Warning: Invalid slot_id for item in shared bank inventory: [{}]=[{}], item_id=[{}], slot_id=[{}]",
is_charid ? "charid" : "acctid",
"Warning: Invalid slot_id for item in shared bank inventory for {} [{}] item_id [{}] slot_id [{}]",
is_charid ? "character_id" : "account_id",
id,
item_id,
slot_id
e.item_id,
e.slot_id
);
if (is_charid) {
SaveInventory(id, nullptr, slot_id);
SaveInventory(id, nullptr, e.slot_id);
}
}
@@ -647,72 +659,77 @@ bool SharedDatabase::GetSharedBank(uint32 id, EQ::InventoryProfile *inv, bool is
}
// Overloaded: Retrieve character inventory based on character id (zone entry)
bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv)
bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile* inv)
{
if (!char_id || !inv)
if (!char_id || !inv) {
return false;
}
// Retrieve character inventory
auto results = InventoryRepository::GetWhere(*this, fmt::format("`charid` = '{}' ORDER BY `slotid`;", char_id));
auto results = InventoryRepository::GetWhere(
*this,
fmt::format(
"`character_id` = '{}' ORDER BY `slot_id`",
char_id
)
);
if (results.empty()) {
LogError("Error loading inventory for char_id {} from the database.", char_id);
return false;
}
for (auto const &row: results) {
for (auto const& row: results) {
if (row.guid != 0) {
EQ::ItemInstance::AddGUIDToMap(row.guid);
}
}
const auto timestamps = GetItemRecastTimestamps(char_id);
auto cv_conflict = false;
const auto pmask = inv->GetLookup()->PossessionsBitmask;
const auto bank_size = inv->GetLookup()->InventoryTypeSize.Bank;
const auto timestamps = GetItemRecastTimestamps(char_id);
auto cv_conflict = false;
const auto pmask = inv->GetLookup()->PossessionsBitmask;
const auto bank_size = inv->GetLookup()->InventoryTypeSize.Bank;
std::vector<InventoryRepository::Inventory> queue{};
for (auto &row: results) {
const int16 slot_id = row.slotid;
const uint32 item_id = row.itemid;
std::vector<InventoryRepository::Inventory> queue{ };
for (auto& row: results) {
const int16 slot_id = row.slot_id;
const uint32 item_id = row.item_id;
const uint16 charges = row.charges;
const uint32 color = row.color;
const bool instnodrop = row.instnodrop;
const uint32 ornament_icon = row.ornamenticon;
const uint32 ornament_idfile = row.ornamentidfile;
const bool instnodrop = row.instnodrop;
const uint32 ornament_icon = row.ornament_icon;
const uint32 ornament_idfile = row.ornament_idfile;
const uint32 ornament_hero_model = row.ornament_hero_model;
uint32 aug[EQ::invaug::SOCKET_COUNT];
aug[0] = row.augslot1;
aug[1] = row.augslot2;
aug[2] = row.augslot3;
aug[3] = row.augslot4;
aug[4] = row.augslot5;
aug[5] = row.augslot6;
uint32 augment_ids[EQ::invaug::SOCKET_COUNT] = {
row.augment_one,
row.augment_two,
row.augment_three,
row.augment_four,
row.augment_five,
row.augment_six
};
if (slot_id <= EQ::invslot::POSSESSIONS_END && slot_id >= EQ::invslot::POSSESSIONS_BEGIN) {
if (EQ::ValueWithin(slot_id, EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END)) {
// Titanium thru UF check
if (((static_cast<uint64>(1) << slot_id) & pmask) == 0) {
cv_conflict = true;
continue;
}
}
else if (slot_id <= EQ::invbag::GENERAL_BAGS_END && slot_id >= EQ::invbag::GENERAL_BAGS_BEGIN) {
} else if (EQ::ValueWithin(slot_id, EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END)) {
// Titanium thru UF check
const auto parent_slot = EQ::invslot::GENERAL_BEGIN + (
(slot_id - EQ::invbag::GENERAL_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT);
const auto parent_slot = EQ::invslot::GENERAL_BEGIN + ((slot_id - EQ::invbag::GENERAL_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT);
if (((static_cast<uint64>(1) << parent_slot) & pmask) == 0) {
cv_conflict = true;
continue;
}
}
else if (slot_id <= EQ::invslot::BANK_END && slot_id >= EQ::invslot::BANK_BEGIN) {
} else if (EQ::ValueWithin(slot_id, EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END)) {
// Titanium check
if ((slot_id - EQ::invslot::BANK_BEGIN) >= bank_size) {
cv_conflict = true;
continue;
}
}
else if (slot_id <= EQ::invbag::BANK_BAGS_END && slot_id >= EQ::invbag::BANK_BAGS_BEGIN) {
} else if (EQ::ValueWithin(slot_id, EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END)) {
// Titanium check
const auto parent_index = ((slot_id - EQ::invbag::BANK_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT);
if (parent_index >= bank_size) {
@@ -721,7 +738,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv)
}
}
auto *item = GetItem(item_id);
auto* item = GetItem(item_id);
if (!item) {
LogError(
"Warning: charid [{}] has an invalid item_id [{}] in inventory slot [{}]",
@@ -732,7 +749,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv)
continue;
}
auto *inst = CreateBaseItem(item, charges);
auto* inst = CreateBaseItem(item, charges);
if (!inst) {
continue;
}
@@ -745,8 +762,13 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv)
inst->SetOrnamentationIDFile(ornament_idfile);
inst->SetOrnamentHeroModel(item->HerosForgeModel);
if (instnodrop || (inst->GetItem()->Attuneable && slot_id >= EQ::invslot::EQUIPMENT_BEGIN && slot_id <=
EQ::invslot::EQUIPMENT_END)) {
if (
instnodrop ||
(
inst->GetItem()->Attuneable &&
EQ::ValueWithin(slot_id, EQ::invslot::EQUIPMENT_BEGIN, EQ::invslot::EQUIPMENT_END)
)
) {
inst->SetAttuned(true);
}
@@ -754,52 +776,37 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv)
inst->SetColor(color);
}
if (charges == 0x7FFF) {
if (charges == std::numeric_limits<int16>::max()) {
inst->SetCharges(-1);
}
else if (charges == 0 && inst->IsStackable()) {
} else if (charges == 0 && inst->IsStackable()) {
// Stackable items need a minimum charge of 1 remain moveable.
inst->SetCharges(1);
}
else {
} else {
inst->SetCharges(charges);
}
if (item->RecastDelay) {
if (item->RecastType != RECAST_TYPE_UNLINKED_ITEM && timestamps.count(item->RecastType)) {
inst->SetRecastTimestamp(timestamps.at(item->RecastType));
}
else if (item->RecastType == RECAST_TYPE_UNLINKED_ITEM && timestamps.count(item->ID)) {
} else if (item->RecastType == RECAST_TYPE_UNLINKED_ITEM && timestamps.count(item->ID)) {
inst->SetRecastTimestamp(timestamps.at(item->ID));
}
else {
} else {
inst->SetRecastTimestamp(0);
}
}
if (item->IsClassCommon()) {
for (int i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) {
if (aug[i]) {
inst->PutAugment(this, i, aug[i]);
if (augment_ids[i]) {
inst->PutAugment(this, i, augment_ids[i]);
}
}
}
int16 put_slot_id;
if (slot_id >= 8000 && slot_id <= 8999) {
if (EQ::ValueWithin(slot_id, EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END)) {
put_slot_id = inv->PushCursor(*inst);
}
else if (slot_id >= 3111 && slot_id <= 3179) {
// Admins: please report any occurrences of this error
LogError(
"Warning: Defunct location for item in inventory: charid={}, item_id={}, slot_id={} .. pushing to cursor...",
char_id,
item_id,
slot_id
);
put_slot_id = inv->PushCursor(*inst);
}
else {
} else {
put_slot_id = inv->PutItem(slot_id, *inst);
}
@@ -811,7 +818,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv)
// Save ptr to item in inventory
if (put_slot_id == INVALID_INDEX) {
LogError(
"Warning: Invalid slot_id for item in inventory: charid=[{}], item_id=[{}], slot_id=[{}]",
"Warning: Invalid slot_id for item in inventory for character_id [{}] item_id [{}] slot_id [{}]",
char_id,
item_id,
slot_id
@@ -820,7 +827,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv)
}
if (cv_conflict) {
const std::string &char_name = GetCharName(char_id);
const std::string& char_name = GetCharName(char_id);
LogError(
"ClientVersion/Expansion conflict during inventory load at zone entry for [{}] (charid: [{}], inver: [{}], gmi: [{}])",
char_name,
@@ -840,94 +847,6 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv)
return GetSharedBank(char_id, inv, true);
}
// Overloaded: Retrieve character inventory based on account_id and character name (char select)
bool SharedDatabase::GetInventory(uint32 account_id, char *name, EQ::InventoryProfile *inv) // deprecated
{
// Retrieve character inventory
const std::string query =
StringFormat("SELECT slotid, itemid, charges, color, augslot1, "
"augslot2, augslot3, augslot4, augslot5, augslot6, instnodrop, custom_data, ornamenticon, "
"ornamentidfile, ornament_hero_model "
"FROM inventory INNER JOIN character_data ch "
"ON ch.id = charid WHERE ch.name = '%s' AND ch.account_id = %i ORDER BY slotid",
name, account_id);
auto results = QueryDatabase(query);
if (!results.Success()) {
LogError("If you got an error related to the 'instnodrop' field, run the "
"following SQL Queries:\nalter table inventory add instnodrop "
"tinyint(1) unsigned default 0 not null;\n");
return false;
}
for (auto& row = results.begin(); row != results.end(); ++row) {
int16 slot_id = Strings::ToInt(row[0]);
uint32 item_id = Strings::ToUnsignedInt(row[1]);
const int8 charges = Strings::ToInt(row[2]);
const uint32 color = Strings::ToUnsignedInt(row[3]);
uint32 aug[EQ::invaug::SOCKET_COUNT];
aug[0] = Strings::ToUnsignedInt(row[4]);
aug[1] = Strings::ToUnsignedInt(row[5]);
aug[2] = Strings::ToUnsignedInt(row[6]);
aug[3] = Strings::ToUnsignedInt(row[7]);
aug[4] = Strings::ToUnsignedInt(row[8]);
aug[5] = Strings::ToUnsignedInt(row[9]);
const bool instnodrop = (row[10] && static_cast<uint16>(Strings::ToUnsignedInt(row[10])));
const uint32 ornament_icon = Strings::ToUnsignedInt(row[12]);
const uint32 ornament_idfile = Strings::ToUnsignedInt(row[13]);
uint32 ornament_hero_model = Strings::ToUnsignedInt(row[14]);
const EQ::ItemData *item = GetItem(item_id);
if (!item)
continue;
EQ::ItemInstance *inst = CreateBaseItem(item, charges);
if (inst == nullptr)
continue;
inst->SetAttuned(instnodrop);
if (row[11]) {
std::string data_str(row[11]);
inst->SetCustomDataString(data_str);
}
inst->SetOrnamentIcon(ornament_icon);
inst->SetOrnamentationIDFile(ornament_idfile);
inst->SetOrnamentHeroModel(item->HerosForgeModel);
if (color > 0)
inst->SetColor(color);
inst->SetCharges(charges);
if (item->IsClassCommon()) {
for (int i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) {
if (aug[i])
inst->PutAugment(this, i, aug[i]);
}
}
int16 put_slot_id;
if (slot_id >= 8000 && slot_id <= 8999)
put_slot_id = inv->PushCursor(*inst);
else
put_slot_id = inv->PutItem(slot_id, *inst);
safe_delete(inst);
// Save ptr to item in inventory
if (put_slot_id == INVALID_INDEX)
LogError("Warning: Invalid slot_id for item in inventory: name={}, acctid={}, item_id={}, slot_id={}",
name, account_id, item_id, slot_id);
}
// Retrieve shared inventory
return GetSharedBank(account_id, inv, false);
}
std::map<uint32, uint32> SharedDatabase::GetItemRecastTimestamps(uint32 char_id)
{
std::map<uint32, uint32> timers;
@@ -1279,7 +1198,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_
// Bag
item.BagSize = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::bagsize]));
item.BagSlots = static_cast<uint8>(EQ::Clamp(Strings::ToInt(row[ItemField::bagslots]), 0, 10)); // Will need to be changed from std::min to just use database value when bag slots are increased
item.BagSlots = static_cast<uint8>(EQ::Clamp(Strings::ToInt(row[ItemField::bagslots]), 0, static_cast<int>(EQ::invbag::SLOT_COUNT)));
item.BagType = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::bagtype]));
item.BagWR = static_cast<uint8>(EQ::Clamp(Strings::ToInt(row[ItemField::bagwr]), 0, 100));
-1
View File
@@ -104,7 +104,6 @@ public:
int32 GetSharedPlatinum(uint32 account_id);
bool SetSharedPlatinum(uint32 account_id, int32 amount_to_add);
bool GetInventory(uint32 char_id, EQ::InventoryProfile *inv);
bool GetInventory(uint32 account_id, char *name, EQ::InventoryProfile *inv); // deprecated
std::map<uint32, uint32> GetItemRecastTimestamps(uint32 char_id);
uint32 GetItemRecastTimestamp(uint32 char_id, uint32 recast_type);
void ClearOldRecastTimestamps(uint32 char_id);
+3 -4
View File
@@ -83,8 +83,7 @@ struct ActivityInformation {
if (zone_ids.empty()) {
return true;
}
bool found_zone = std::any_of(zone_ids.begin(), zone_ids.end(),
[zone_id](int id) { return id <= 0 || id == zone_id; });
bool found_zone = std::find(zone_ids.begin(), zone_ids.end(), zone_id) != zone_ids.end();
return found_zone && (zone_version == version || zone_version == -1);
}
@@ -101,7 +100,7 @@ struct ActivityInformation {
out.WriteInt32(activity_type == TaskActivityType::GiveCash ? 1 : goal_count);
out.WriteLengthString(skill_list); // used in SkillOn objective type string, "-1" for none
out.WriteLengthString(spell_list); // used in CastOn objective type string, "0" for none
out.WriteString(zones); // used in ui zone columns and task select "begins in" (may have multiple, invalid id for "Unknown Zone", empty for "ALL")
out.WriteString(zones); // used in objective zone column and task select "begins in" (may have multiple, "0" for "unknown zone", empty for "ALL")
}
else
{
@@ -115,7 +114,7 @@ struct ActivityInformation {
out.WriteString(description_override);
if (client_version >= EQ::versions::ClientVersion::RoF) {
out.WriteString(zones); // target zone version internal id (unused client side)
out.WriteString(zones); // serialized again after description (seems unused)
}
}
+2 -2
View File
@@ -25,7 +25,7 @@
// Build variables
// these get injected during the build pipeline
#define CURRENT_VERSION "22.61.0-dev" // always append -dev to the current version for custom-builds
#define CURRENT_VERSION "22.59.1-dev" // always append -dev to the current version for custom-builds
#define LOGIN_VERSION "0.8.0"
#define COMPILE_DATE __DATE__
#define COMPILE_TIME __TIME__
@@ -42,7 +42,7 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9286
#define CURRENT_BINARY_DATABASE_VERSION 9288
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9045
#endif
+12
View File
@@ -51,6 +51,12 @@ WorldServer::WorldServer(std::shared_ptr<EQ::Net::ServertalkServerConnection> wo
ServerOP_LSAccountUpdate,
std::bind(&WorldServer::ProcessLSAccountUpdate, this, std::placeholders::_1, std::placeholders::_2)
);
m_keepalive = std::make_unique<EQ::Timer>(
1000,
true,
std::bind(&WorldServer::OnKeepAlive, this, std::placeholders::_1)
);
}
WorldServer::~WorldServer() = default;
@@ -1301,6 +1307,12 @@ const std::string &WorldServer::GetVersion() const
return m_version;
}
void WorldServer::OnKeepAlive(EQ::Timer *t)
{
ServerPacket pack(ServerOP_KeepAlive, 0);
m_connection->SendPacket(&pack);
}
void WorldServer::FormatWorldServerName(char *name, int8 server_list_type)
{
std::string server_long_name = name;
+7
View File
@@ -187,6 +187,13 @@ private:
bool m_is_server_logged_in;
bool m_is_server_trusted;
/**
* Keepalive
* @param t
*/
void OnKeepAlive(EQ::Timer *t);
std::unique_ptr<EQ::Timer> m_keepalive;
static void FormatWorldServerName(char *name, int8 server_list_type);
};
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "eqemu-server",
"version": "22.61.0",
"version": "22.59.1",
"repository": {
"type": "git",
"url": "https://github.com/EQEmu/Server.git"
+1 -1
View File
@@ -10,7 +10,7 @@ require (
require (
github.com/golang/protobuf v1.3.2 // indirect
github.com/google/go-querystring v1.1.0 // indirect
golang.org/x/crypto v0.31.0 // indirect
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/net v0.23.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
)
+2 -2
View File
@@ -10,8 +10,8 @@ github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
@@ -142,7 +142,6 @@ foreach my $table_to_generate (@tables) {
"guild_bank",
"inventory_versions",
"raid_leaders",
"sharedbank",
"trader_audit",
"eqtime",
"db_version",
+2 -2
View File
@@ -12,12 +12,12 @@ void WorldserverCLI::CopyCharacter(int argc, char **argv, argh::parser &cmd, std
};
std::vector<std::string> options = {};
EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv);
if (cmd[{"-h", "--help"}]) {
return;
}
EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv);
std::string source_character_name = cmd(2).str();
std::string destination_character_name = cmd(3).str();
std::string destination_account_name = cmd(4).str();
+16 -22
View File
@@ -541,17 +541,6 @@ bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app)
skip_char_info = true;
}
}
const auto& custom_files_key = RuleS(World, CustomFilesKey);
if (!skip_char_info && !custom_files_key.empty() && cle->Admin() < RuleI(World, CustomFilesAdminLevel)) {
// Modified clients can utilize this unused block in login_info to send custom payloads on login
// which indicates they are using custom client files with the correct version, based on key payload.
const auto client_key = std::string(reinterpret_cast<char*>(login_info->unknown064));
if (custom_files_key != client_key) {
std::string message = fmt::format("Missing Files [{}]", RuleS(World, CustomFilesUrl) );
SendUnsupportedClientPacket(message);
skip_char_info = true;
}
}
if (!skip_char_info) {
SendExpansionInfo();
@@ -2380,21 +2369,26 @@ bool Client::StoreCharacter(
auto e = InventoryRepository::NewEntity();
e.charid = character_id;
e.character_id = character_id;
for (int16 slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invbag::BANK_BAGS_END;) {
const auto inst = p_inventory_profile->GetItem(slot_id);
if (inst) {
e.slotid = slot_id;
e.itemid = inst->GetItem()->ID;
e.charges = inst->GetCharges();
e.color = inst->GetColor();
e.augslot1 = inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN);
e.augslot2 = inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 1);
e.augslot3 = inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 2);
e.augslot4 = inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 3);
e.augslot5 = inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 4);
e.augslot6 = inst->GetAugmentItemID(EQ::invaug::SOCKET_END);
e.slot_id = slot_id;
e.item_id = inst->GetItem()->ID;
e.charges = inst->GetCharges();
e.color = inst->GetColor();
e.augment_one = inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN);
e.augment_two = inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 1);
e.augment_three = inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 2);
e.augment_four = inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 3);
e.augment_five = inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 4);
e.augment_six = inst->GetAugmentItemID(EQ::invaug::SOCKET_END);
e.instnodrop = inst->IsAttuned() ? 1 : 0;
e.ornament_icon = inst->GetOrnamentationIcon();
e.ornament_idfile = inst->GetOrnamentationIDFile();
e.ornament_hero_model = inst->GetOrnamentHeroModel();
e.guid = inst->GetSerialNumber();
v.emplace_back(e);
}
+10
View File
@@ -595,6 +595,11 @@ bool LoginServer::Connect()
);
}
m_keepalive = std::make_unique<EQ::Timer>(
1000,
true,
std::bind(&LoginServer::OnKeepAlive, this, std::placeholders::_1));
return true;
}
@@ -711,3 +716,8 @@ void LoginServer::SendAccountUpdate(ServerPacket *pack)
}
}
void LoginServer::OnKeepAlive(EQ::Timer *t)
{
ServerPacket pack(ServerOP_KeepAlive, 0);
SendPacket(&pack);
}
+1
View File
@@ -50,6 +50,7 @@ private:
void ProcessLSRemoteAddr(uint16_t opcode, EQ::Net::Packet &p);
void ProcessLSAccountUpdate(uint16_t opcode, EQ::Net::Packet &p);
void OnKeepAlive(EQ::Timer *t);
std::unique_ptr<EQ::Timer> m_keepalive;
std::unique_ptr<EQ::Net::ServertalkClient> m_client;
+6
View File
@@ -22,6 +22,7 @@ void QueryServConnection::AddConnection(std::shared_ptr<EQ::Net::ServertalkServe
connection->OnMessage(ServerOP_QueryServGeneric, std::bind(&QueryServConnection::HandleGenericMessage, this, std::placeholders::_1, std::placeholders::_2));
connection->OnMessage(ServerOP_LFGuildUpdate, std::bind(&QueryServConnection::HandleLFGuildUpdateMessage, this, std::placeholders::_1, std::placeholders::_2));
m_streams.emplace(std::make_pair(connection->GetUUID(), connection));
m_keepalive = std::make_unique<EQ::Timer>(1000, true, std::bind(&QueryServConnection::OnKeepAlive, this, std::placeholders::_1));
}
void QueryServConnection::RemoveConnection(std::shared_ptr<EQ::Net::ServertalkServerConnection> connection)
@@ -53,3 +54,8 @@ bool QueryServConnection::SendPacket(ServerPacket* pack)
return true;
}
void QueryServConnection::OnKeepAlive(EQ::Timer *t)
{
ServerPacket pack(ServerOP_KeepAlive, 0);
SendPacket(&pack);
}
+1
View File
@@ -15,6 +15,7 @@ public:
void HandleGenericMessage(uint16_t opcode, EQ::Net::Packet &p);
void HandleLFGuildUpdateMessage(uint16_t opcode, EQ::Net::Packet &p);
bool SendPacket(ServerPacket* pack);
void OnKeepAlive(EQ::Timer *t);
private:
std::map<std::string, std::shared_ptr<EQ::Net::ServertalkServerConnection>> m_streams;
std::unique_ptr<EQ::Timer> m_keepalive;
+12
View File
@@ -31,6 +31,8 @@ void UCSConnection::SetConnection(std::shared_ptr<EQ::Net::ServertalkServerConne
)
);
}
m_keepalive = std::make_unique<EQ::Timer>(1000, true, std::bind(&UCSConnection::OnKeepAlive, this, std::placeholders::_1));
}
const std::shared_ptr<EQ::Net::ServertalkServerConnection> &UCSConnection::GetConnection() const
@@ -90,3 +92,13 @@ void UCSConnection::SendMessage(const char *From, const char *Message)
SendPacket(pack);
safe_delete(pack);
}
void UCSConnection::OnKeepAlive(EQ::Timer *t)
{
if (!connection) {
return;
}
ServerPacket pack(ServerOP_KeepAlive, 0);
connection->SendPacket(&pack);
}
+5
View File
@@ -23,6 +23,11 @@ private:
inline std::string GetIP() const { return (connection && connection->Handle()) ? connection->Handle()->RemoteIP() : 0; }
std::shared_ptr<EQ::Net::ServertalkServerConnection> connection;
/**
* Keepalive
*/
std::unique_ptr<EQ::Timer> m_keepalive;
void OnKeepAlive(EQ::Timer *t);
};
#endif /*UCS_H_*/
+65 -89
View File
@@ -26,6 +26,7 @@
#include <vector>
#include "sof_char_create_data.h"
#include "../common/repositories/character_instance_safereturns_repository.h"
#include "../common/repositories/inventory_repository.h"
#include "../common/repositories/criteria/content_filter_criteria.h"
#include "../common/zone_store.h"
@@ -857,115 +858,90 @@ bool WorldDatabase::LoadCharacterCreateCombos()
// this is a slightly modified version of SharedDatabase::GetInventory(...) for character select use-only
bool WorldDatabase::GetCharSelInventory(uint32 account_id, char *name, EQ::InventoryProfile *inv)
{
if (!account_id || !name || !inv)
if (!account_id || !name || !inv) {
return false;
}
std::string query = StringFormat(
"SELECT"
" slotid,"
" itemid,"
" charges,"
" color,"
" augslot1,"
" augslot2,"
" augslot3,"
" augslot4,"
" augslot5,"
" augslot6,"
" instnodrop,"
" custom_data,"
" ornamenticon,"
" ornamentidfile,"
" ornament_hero_model "
"FROM"
" inventory "
"INNER JOIN"
" character_data ch "
"ON"
" ch.id = charid "
"WHERE"
" ch.name = '%s' "
"AND"
" ch.account_id = %i "
"AND"
" slotid >= %i "
"AND"
" slotid <= %i",
name,
account_id,
EQ::invslot::slotHead,
EQ::invslot::slotFeet
const uint32 character_id = GetCharacterID(name);
if (!character_id) {
return false;
}
const auto& l = InventoryRepository::GetWhere(
*this,
fmt::format(
"`character_id` = {} AND `slot_id` BETWEEN {} AND {}",
character_id,
EQ::invslot::slotHead,
EQ::invslot::slotFeet
)
);
auto results = QueryDatabase(query);
if (!results.Success())
return false;
for (auto row = results.begin(); row != results.end(); ++row) {
int16 slot_id = Strings::ToInt(row[0]);
if (l.empty()) {
return true;
}
switch (slot_id) {
case EQ::invslot::slotFace:
case EQ::invslot::slotEar2:
case EQ::invslot::slotNeck:
case EQ::invslot::slotShoulders:
case EQ::invslot::slotBack:
case EQ::invslot::slotFinger1:
case EQ::invslot::slotFinger2:
continue;
default:
break;
for (const auto& e : l) {
switch (e.slot_id) {
case EQ::invslot::slotFace:
case EQ::invslot::slotEar2:
case EQ::invslot::slotNeck:
case EQ::invslot::slotShoulders:
case EQ::invslot::slotBack:
case EQ::invslot::slotFinger1:
case EQ::invslot::slotFinger2:
continue;
default:
break;
}
uint32 item_id = Strings::ToInt(row[1]);
int8 charges = Strings::ToInt(row[2]);
uint32 color = Strings::ToUnsignedInt(row[3]);
uint32 aug[EQ::invaug::SOCKET_COUNT];
aug[0] = (uint32)Strings::ToInt(row[4]);
aug[1] = (uint32)Strings::ToInt(row[5]);
aug[2] = (uint32)Strings::ToInt(row[6]);
aug[3] = (uint32)Strings::ToInt(row[7]);
aug[4] = (uint32)Strings::ToInt(row[8]);
aug[5] = (uint32)Strings::ToInt(row[9]);
uint32 augment_ids[EQ::invaug::SOCKET_COUNT] = {
e.augment_one,
e.augment_two,
e.augment_three,
e.augment_four,
e.augment_five,
e.augment_six
};
bool instnodrop = ((row[10] && (uint16)Strings::ToInt(row[10])) ? true : false);
uint32 ornament_icon = (uint32)Strings::ToUnsignedInt(row[12]);
uint32 ornament_idfile = (uint32)Strings::ToUnsignedInt(row[13]);
uint32 ornament_hero_model = (uint32)Strings::ToUnsignedInt(row[14]);
const EQ::ItemData *item = content_db.GetItem(item_id);
if (!item)
const EQ::ItemData* item = content_db.GetItem(e.item_id);
if (!item) {
continue;
EQ::ItemInstance *inst = content_db.CreateBaseItem(item, charges);
if (inst == nullptr)
continue;
inst->SetAttuned(instnodrop);
if (row[11]) {
std::string data_str(row[11]);
inst->SetCustomDataString(data_str);
}
inst->SetOrnamentIcon(ornament_icon);
inst->SetOrnamentationIDFile(ornament_idfile);
inst->SetOrnamentHeroModel(item->HerosForgeModel);
EQ::ItemInstance *inst = content_db.CreateBaseItem(item, e.charges);
if (color > 0)
inst->SetColor(color);
if (!inst) {
continue;
}
inst->SetCharges(charges);
inst->SetCharges(e.charges);
if (e.color > 0) {
inst->SetColor(e.color);
}
if (item->IsClassCommon()) {
for (int i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) {
if (aug[i])
inst->PutAugment(this, i, aug[i]);
if (augment_ids[i]) {
inst->PutAugment(this, i, augment_ids[i]);
}
}
}
inv->PutItem(slot_id, *inst);
inst->SetAttuned(e.instnodrop);
if (!e.custom_data.empty()) {
inst->SetCustomDataString(e.custom_data);
}
inst->SetOrnamentIcon(e.ornament_icon);
inst->SetOrnamentationIDFile(e.ornament_idfile);
inst->SetOrnamentHeroModel(e.ornament_hero_model);
inv->PutItem(e.slot_id, *inst);
safe_delete(inst);
}
+8
View File
@@ -42,6 +42,7 @@ ZSList::ZSList()
memset(pLockedZones, 0, sizeof(pLockedZones));
m_tick = std::make_unique<EQ::Timer>(5000, true, std::bind(&ZSList::OnTick, this, std::placeholders::_1));
m_keepalive = std::make_unique<EQ::Timer>(1000, true, std::bind(&ZSList::OnKeepAlive, this, std::placeholders::_1));
}
ZSList::~ZSList() {
@@ -845,6 +846,13 @@ void ZSList::OnTick(EQ::Timer *t)
web_interface.SendEvent(out);
}
void ZSList::OnKeepAlive(EQ::Timer *t)
{
for (auto &zone : zone_server_list) {
zone->SendKeepAlive();
}
}
const std::list<std::unique_ptr<ZoneServer>> &ZSList::getZoneServerList() const
{
return zone_server_list;
+1
View File
@@ -72,6 +72,7 @@ public:
private:
void OnTick(EQ::Timer *t);
void OnKeepAlive(EQ::Timer *t);
uint32 NextID;
uint16 pLockedZones[MaxLockedZones];
uint32 CurGroupID;
+5
View File
@@ -1564,6 +1564,11 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
DynamicZone::HandleZoneMessage(pack);
break;
}
case ServerOP_DataBucketCacheUpdate: {
zoneserver_list.SendPacket(pack);
break;
}
case ServerOP_GuildTributeUpdate: {
auto data = (GuildTributeUpdate *)pack->pBuffer;
auto guild = guild_mgr.GetGuildByGuildID(data->guild_id);
+22 -7
View File
@@ -1550,7 +1550,10 @@ void Mob::DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts, boo
hit.damage_done = 0;
}
parse->EventBotMerc(EVENT_USE_SKILL, this, nullptr,
parse->EventBotMerc(
EVENT_USE_SKILL,
this,
nullptr,
[&]() {
return fmt::format(
"{} {}",
@@ -3075,7 +3078,10 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
std::vector<std::any> args = { corpse };
parse->EventMercNPC(EVENT_DEATH_COMPLETE, this, owner_or_self,
parse->EventMercNPC(
EVENT_DEATH_COMPLETE,
this,
owner_or_self,
[&]() {
return fmt::format(
"{} {} {} {} {} {} {} {} {}",
@@ -3090,7 +3096,8 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
m_combat_record.GetHealingReceived()
);
},
0, &args
0,
&args
);
// Zone controller process EVENT_DEATH_ZONE (Death events)
@@ -4259,7 +4266,10 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
if (attacker) {
args = { this };
parse->EventMob(EVENT_DAMAGE_GIVEN, attacker, this,
parse->EventMob(
EVENT_DAMAGE_GIVEN,
attacker,
this,
[&]() {
return fmt::format(
"{} {} {} {} {} {} {} {} {}",
@@ -4274,13 +4284,17 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
static_cast<int>(special)
);
},
0, &args
0,
&args
);
}
args = { attacker };
damage_override = parse->EventMob(EVENT_DAMAGE_TAKEN, this, attacker,
damage_override = parse->EventMob(
EVENT_DAMAGE_TAKEN,
this,
attacker,
[&]() {
return fmt::format(
"{} {} {} {} {} {} {} {} {}",
@@ -4295,7 +4309,8 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
static_cast<int>(special)
);
},
0, &args
0,
&args
);
if (damage_override > 0) {
+17 -4
View File
@@ -1265,7 +1265,7 @@ void Bot::LoadAAs() {
}
while(current) {
if (current->level_req > GetLevel() || !CanUseAlternateAdvancementRank(current)) {
if (!CanUseAlternateAdvancementRank(current)) {
current = nullptr;
} else {
current = current->next;
@@ -3089,7 +3089,6 @@ bool Bot::Spawn(Client* botCharacterOwner) {
m_targetable = true;
entity_list.AddBot(this, true, true);
ClearDataBucketCache();
DataBucket::GetDataBuckets(this);
LoadBotSpellSettings();
if (!AI_AddBotSpells(GetBotSpellID())) {
@@ -4193,7 +4192,14 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client*
std::vector<std::any> args = { return_iterator.return_item_instance };
parse->EventBot(EVENT_UNEQUIP_ITEM_BOT, this, nullptr, export_string, return_iterator.return_item_instance->GetID(), &args);
parse->EventBot(
EVENT_UNEQUIP_ITEM_BOT,
this,
nullptr,
export_string,
return_iterator.return_item_instance->GetID(),
&args
);
}
if (return_instance) {
@@ -4258,7 +4264,14 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client*
std::vector<std::any> args = { trade_iterator.trade_item_instance };
parse->EventBot(EVENT_EQUIP_ITEM_BOT, this, nullptr, export_string, trade_iterator.trade_item_instance->GetID(), &args);
parse->EventBot(
EVENT_EQUIP_ITEM_BOT,
this,
nullptr,
export_string,
trade_iterator.trade_item_instance->GetID(),
&args
);
}
trade_iterator.trade_item_instance = nullptr; // actual deletion occurs in client delete below
+157 -140
View File
@@ -329,7 +329,7 @@ Client::Client(EQStreamInterface *ieqs) : Mob(
adventure_stats_timer = nullptr;
adventure_leaderboard_timer = nullptr;
adv_data = nullptr;
adv_requested_theme = LDoNTheme::Unused;
adv_requested_theme = LDoNThemes::Unused;
adv_requested_id = 0;
adv_requested_member_count = 0;
@@ -1469,7 +1469,7 @@ bool Client::UpdateLDoNPoints(uint32 theme_id, int points)
bool is_loss = false;
switch (theme_id) {
case LDoNTheme::Unused: { // No theme, so distribute evenly across all
case LDoNThemes::Unused: { // No theme, so distribute evenly across all
int split_points = (points / 5);
int guk_points = (split_points + (points % 5));
@@ -1522,12 +1522,12 @@ bool Client::UpdateLDoNPoints(uint32 theme_id, int points)
points -= split_points;
if (split_points != 0) { // if anything left, recursively loop thru again
UpdateLDoNPoints(LDoNTheme::Unused, split_points);
UpdateLDoNPoints(LDoNThemes::Unused, split_points);
}
break;
}
case LDoNTheme::GUK: {
case LDoNThemes::GUK: {
if (points < 0) {
if (m_pp.ldon_points_guk < (0 - points)) {
return false;
@@ -1539,7 +1539,7 @@ bool Client::UpdateLDoNPoints(uint32 theme_id, int points)
m_pp.ldon_points_guk += points;
break;
}
case LDoNTheme::MIR: {
case LDoNThemes::MIR: {
if (points < 0) {
if (m_pp.ldon_points_mir < (0 - points)) {
return false;
@@ -1551,7 +1551,7 @@ bool Client::UpdateLDoNPoints(uint32 theme_id, int points)
m_pp.ldon_points_mir += points;
break;
}
case LDoNTheme::MMC: {
case LDoNThemes::MMC: {
if (points < 0) {
if (m_pp.ldon_points_mmc < (0 - points)) {
return false;
@@ -1563,7 +1563,7 @@ bool Client::UpdateLDoNPoints(uint32 theme_id, int points)
m_pp.ldon_points_mmc += points;
break;
}
case LDoNTheme::RUJ: {
case LDoNThemes::RUJ: {
if (points < 0) {
if (m_pp.ldon_points_ruj < (0 - points)) {
return false;
@@ -1575,7 +1575,7 @@ bool Client::UpdateLDoNPoints(uint32 theme_id, int points)
m_pp.ldon_points_ruj += points;
break;
}
case LDoNTheme::TAK: {
case LDoNThemes::TAK: {
if (points < 0) {
if (m_pp.ldon_points_tak < (0 - points)) {
return false;
@@ -1623,23 +1623,23 @@ bool Client::UpdateLDoNPoints(uint32 theme_id, int points)
void Client::SetLDoNPoints(uint32 theme_id, uint32 points)
{
switch (theme_id) {
case LDoNTheme::GUK: {
case LDoNThemes::GUK: {
m_pp.ldon_points_guk = points;
break;
}
case LDoNTheme::MIR: {
case LDoNThemes::MIR: {
m_pp.ldon_points_mir = points;
break;
}
case LDoNTheme::MMC: {
case LDoNThemes::MMC: {
m_pp.ldon_points_mmc = points;
break;
}
case LDoNTheme::RUJ: {
case LDoNThemes::RUJ: {
m_pp.ldon_points_ruj = points;
break;
}
case LDoNTheme::TAK: {
case LDoNThemes::TAK: {
m_pp.ldon_points_tak = points;
break;
}
@@ -5676,15 +5676,15 @@ uint32 Client::GetLDoNPointsTheme(uint32 t)
{
switch(t)
{
case LDoNTheme::GUK:
case LDoNThemes::GUK:
return m_pp.ldon_points_guk;
case LDoNTheme::MIR:
case LDoNThemes::MIR:
return m_pp.ldon_points_mir;
case LDoNTheme::MMC:
case LDoNThemes::MMC:
return m_pp.ldon_points_mmc;
case LDoNTheme::RUJ:
case LDoNThemes::RUJ:
return m_pp.ldon_points_ruj;
case LDoNTheme::TAK:
case LDoNThemes::TAK:
return m_pp.ldon_points_tak;
default:
return 0;
@@ -5695,15 +5695,15 @@ uint32 Client::GetLDoNWinsTheme(uint32 t)
{
switch(t)
{
case LDoNTheme::GUK:
case LDoNThemes::GUK:
return m_pp.ldon_wins_guk;
case LDoNTheme::MIR:
case LDoNThemes::MIR:
return m_pp.ldon_wins_mir;
case LDoNTheme::MMC:
case LDoNThemes::MMC:
return m_pp.ldon_wins_mmc;
case LDoNTheme::RUJ:
case LDoNThemes::RUJ:
return m_pp.ldon_wins_ruj;
case LDoNTheme::TAK:
case LDoNThemes::TAK:
return m_pp.ldon_wins_tak;
default:
return 0;
@@ -5714,15 +5714,15 @@ uint32 Client::GetLDoNLossesTheme(uint32 t)
{
switch(t)
{
case LDoNTheme::GUK:
case LDoNThemes::GUK:
return m_pp.ldon_losses_guk;
case LDoNTheme::MIR:
case LDoNThemes::MIR:
return m_pp.ldon_losses_mir;
case LDoNTheme::MMC:
case LDoNThemes::MMC:
return m_pp.ldon_losses_mmc;
case LDoNTheme::RUJ:
case LDoNThemes::RUJ:
return m_pp.ldon_losses_ruj;
case LDoNTheme::TAK:
case LDoNThemes::TAK:
return m_pp.ldon_losses_tak;
default:
return 0;
@@ -5731,35 +5731,35 @@ uint32 Client::GetLDoNLossesTheme(uint32 t)
void Client::UpdateLDoNWinLoss(uint32 theme_id, bool win, bool remove) {
switch (theme_id) {
case LDoNTheme::GUK:
case LDoNThemes::GUK:
if (win) {
m_pp.ldon_wins_guk += (remove ? -1 : 1);
} else {
m_pp.ldon_losses_guk += (remove ? -1 : 1);
}
break;
case LDoNTheme::MIR:
case LDoNThemes::MIR:
if (win) {
m_pp.ldon_wins_mir += (remove ? -1 : 1);
} else {
m_pp.ldon_losses_mir += (remove ? -1 : 1);
}
break;
case LDoNTheme::MMC:
case LDoNThemes::MMC:
if (win) {
m_pp.ldon_wins_mmc += (remove ? -1 : 1);
} else {
m_pp.ldon_losses_mmc += (remove ? -1 : 1);
}
break;
case LDoNTheme::RUJ:
case LDoNThemes::RUJ:
if (win) {
m_pp.ldon_wins_ruj += (remove ? -1 : 1);
} else {
m_pp.ldon_losses_ruj += (remove ? -1 : 1);
}
break;
case LDoNTheme::TAK:
case LDoNThemes::TAK:
if (win) {
m_pp.ldon_wins_tak += (remove ? -1 : 1);
} else {
@@ -6227,7 +6227,7 @@ void Client::NewAdventure(int id, int theme, const char *text, int member_count,
void Client::ClearPendingAdventureData()
{
adv_requested_id = 0;
adv_requested_theme = LDoNTheme::Unused;
adv_requested_theme = LDoNThemes::Unused;
safe_delete_array(adv_requested_data);
adv_requested_member_count = 0;
}
@@ -9124,7 +9124,7 @@ void Client::SetPrimaryWeaponOrnamentation(uint32 model_id)
auto l = InventoryRepository::GetWhere(
database,
fmt::format(
"`charid` = {} AND `slotid` = {}",
"`character_id` = {} AND `slot_id` = {}",
character_id,
EQ::invslot::slotPrimary
)
@@ -9136,7 +9136,7 @@ void Client::SetPrimaryWeaponOrnamentation(uint32 model_id)
auto e = l.front();
e.ornamentidfile = model_id;
e.ornament_idfile = model_id;
const int updated = InventoryRepository::UpdateOne(database, e);
@@ -9157,7 +9157,7 @@ void Client::SetSecondaryWeaponOrnamentation(uint32 model_id)
auto l = InventoryRepository::GetWhere(
database,
fmt::format(
"`charid` = {} AND `slotid` = {}",
"`character_id` = {} AND `slot_id` = {}",
character_id,
EQ::invslot::slotSecondary
)
@@ -9169,7 +9169,7 @@ void Client::SetSecondaryWeaponOrnamentation(uint32 model_id)
auto e = l.front();
e.ornamentidfile = model_id;
e.ornament_idfile = model_id;
const int updated = InventoryRepository::UpdateOne(database, e);
@@ -10461,15 +10461,27 @@ void Client::SendToInstance(std::string instance_type, std::string zone_short_na
MovePC(zone_id, instance_id, x, y, z, heading);
}
uint32 Client::CountItem(uint32 item_id)
int Client::CountItem(uint32 item_id)
{
uint32 quantity = 0;
int quantity = 0;
EQ::ItemInstance *item = nullptr;
for (const int16& slot_id : GetInventorySlots()) {
item = GetInv().GetItem(slot_id);
if (item && item->GetID() == item_id) {
quantity += (item->IsStackable() ? item->GetCharges() : 1);
static const int16 slots[][2] = {
{ EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END },
{ EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END },
{ EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END},
{ EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END },
{ EQ::invslot::GUILD_TRIBUTE_BEGIN, EQ::invslot::GUILD_TRIBUTE_END },
{ EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END },
{ EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END },
{ EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END },
};
const size_t slot_index_count = sizeof(slots) / sizeof(slots[0]);
for (int slot_index = 0; slot_index < slot_index_count; ++slot_index) {
for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) {
item = GetInv().GetItem(slot_id);
if (item && item->GetID() == item_id) {
quantity += (item->IsStackable() ? item->GetCharges() : 1);
}
}
}
@@ -10486,26 +10498,30 @@ void Client::ResetItemCooldown(uint32 item_id)
int recast_type = item_d->RecastType;
bool found_item = false;
for (const int16& slot_id : GetInventorySlots()) {
item = GetInv().GetItem(slot_id);
if (item) {
item_d = item->GetItem();
if (
item_d &&
item->GetID() == item_id ||
(
item_d->RecastType != RECAST_TYPE_UNLINKED_ITEM &&
item_d->RecastType == recast_type
)
) {
item->SetRecastTimestamp(0);
DeleteItemRecastTimer(item_d->ID);
SendItemPacket(slot_id, item, ItemPacketCharmUpdate);
found_item = true;
static const int16 slots[][2] = {
{ EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END },
{ EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END },
{ EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END},
{ EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END },
{ EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END },
{ EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END },
{ EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END },
};
const size_t slot_index_count = sizeof(slots) / sizeof(slots[0]);
for (int slot_index = 0; slot_index < slot_index_count; ++slot_index) {
for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) {
item = GetInv().GetItem(slot_id);
if (item) {
item_d = item->GetItem();
if (item_d && item->GetID() == item_id || (item_d->RecastType != RECAST_TYPE_UNLINKED_ITEM && item_d->RecastType == recast_type)) {
item->SetRecastTimestamp(0);
DeleteItemRecastTimer(item_d->ID);
SendItemPacket(slot_id, item, ItemPacketCharmUpdate);
found_item = true;
}
}
}
}
if (!found_item) {
DeleteItemRecastTimer(item_id); //We didn't find the item but we still want to remove the timer
}
@@ -10540,20 +10556,25 @@ void Client::SetItemCooldown(uint32 item_id, bool use_saved_timer, uint32 in_sec
final_time = total_time - current_time;
}
for (const int16& slot_id : GetInventorySlots()) {
item = GetInv().GetItem(slot_id);
if (item) {
item_d = item->GetItem();
if (
item_d &&
item->GetID() == item_id ||
(
item_d->RecastType != RECAST_TYPE_UNLINKED_ITEM &&
item_d->RecastType == recast_type
)
) {
item->SetRecastTimestamp(total_time);
SendItemPacket(slot_id, item, ItemPacketCharmUpdate);
static const int16 slots[][2] = {
{ EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END },
{ EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END },
{ EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END},
{ EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END },
{ EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END },
{ EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END },
{ EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END },
};
const size_t slot_index_count = sizeof(slots) / sizeof(slots[0]);
for (int slot_index = 0; slot_index < slot_index_count; ++slot_index) {
for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) {
item = GetInv().GetItem(slot_id);
if (item) {
item_d = item->GetItem();
if (item_d && item->GetID() == item_id || (item_d->RecastType != RECAST_TYPE_UNLINKED_ITEM && item_d->RecastType == recast_type)) {
item->SetRecastTimestamp(total_time);
SendItemPacket(slot_id, item, ItemPacketCharmUpdate);
}
}
}
}
@@ -10596,26 +10617,38 @@ uint32 Client::GetItemCooldown(uint32 item_id)
void Client::RemoveItem(uint32 item_id, uint32 quantity)
{
uint32 removed_count = 0;
EQ::ItemInstance *item = nullptr;
static const int16 slots[][2] = {
{ EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END },
{ EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END },
{ EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END},
{ EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END },
{ EQ::invslot::GUILD_TRIBUTE_BEGIN, EQ::invslot::GUILD_TRIBUTE_END },
{ EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END },
{ EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END },
{ EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END },
};
int16 removed_count = 0;
const size_t slot_index_count = sizeof(slots) / sizeof(slots[0]);
for (int slot_index = 0; slot_index < slot_index_count; ++slot_index) {
for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) {
if (removed_count == quantity) {
break;
}
for (const int16& slot_id : GetInventorySlots()) {
if (removed_count == quantity) {
break;
}
item = GetInv().GetItem(slot_id);
if (item && item->GetID() == item_id) {
uint32 charges = item->IsStackable() ? item->GetCharges() : 0;
uint32 stack_size = std::max(charges, static_cast<uint32>(1));
if ((removed_count + stack_size) <= quantity) {
removed_count += stack_size;
DeleteItemInInventory(slot_id, charges, true);
} else {
uint32 amount_left = (quantity - removed_count);
if (amount_left > 0 && stack_size >= amount_left) {
removed_count += amount_left;
DeleteItemInInventory(slot_id, amount_left, true);
item = GetInv().GetItem(slot_id);
if (item && item->GetID() == item_id) {
int16 charges = item->IsStackable() ? item->GetCharges() : 0;
int16 stack_size = std::max(charges, static_cast<int16>(1));
if ((removed_count + stack_size) <= quantity) {
removed_count += stack_size;
DeleteItemInInventory(slot_id, charges, true);
} else {
int16 amount_left = (quantity - removed_count);
if (amount_left > 0 && stack_size >= amount_left) {
removed_count += amount_left;
DeleteItemInInventory(slot_id, amount_left, true);
}
}
}
}
@@ -12787,28 +12820,37 @@ uint16 Client::GetSkill(EQ::skills::SkillType skill_id) const
void Client::RemoveItemBySerialNumber(uint32 serial_number, uint32 quantity)
{
EQ::ItemInstance *item = nullptr;
static const int16 slots[][2] = {
{ EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END },
{ EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END },
{ EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END},
{ EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END },
{ EQ::invslot::GUILD_TRIBUTE_BEGIN, EQ::invslot::GUILD_TRIBUTE_END },
{ EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END },
{ EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END },
{ EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END },
};
int16 removed_count = 0;
const size_t slot_index_count = sizeof(slots) / sizeof(slots[0]);
for (int slot_index = 0; slot_index < slot_index_count; ++slot_index) {
for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) {
if (removed_count == quantity) {
break;
}
uint32 removed_count = 0;
const auto& slot_ids = GetInventorySlots();
for (const int16& slot_id : slot_ids) {
if (removed_count == quantity) {
break;
}
item = GetInv().GetItem(slot_id);
if (item && item->GetSerialNumber() == serial_number) {
uint32 charges = item->IsStackable() ? item->GetCharges() : 0;
uint32 stack_size = std::max(charges, static_cast<uint32>(1));
if ((removed_count + stack_size) <= quantity) {
removed_count += stack_size;
DeleteItemInInventory(slot_id, charges, true);
} else {
uint32 amount_left = (quantity - removed_count);
if (amount_left > 0 && stack_size >= amount_left) {
removed_count += amount_left;
DeleteItemInInventory(slot_id, amount_left, true);
item = GetInv().GetItem(slot_id);
if (item && item->GetSerialNumber() == serial_number) {
int16 charges = item->IsStackable() ? item->GetCharges() : 0;
int16 stack_size = std::max(charges, static_cast<int16>(1));
if ((removed_count + stack_size) <= quantity) {
removed_count += stack_size;
DeleteItemInInventory(slot_id, charges, true);
} else {
int16 amount_left = (quantity - removed_count);
if (amount_left > 0 && stack_size >= amount_left) {
removed_count += amount_left;
DeleteItemInInventory(slot_id, amount_left, true);
}
}
}
}
@@ -13033,28 +13075,3 @@ void Client::ClientToNpcAggroProcess()
LogAggro("Checking Reverse Aggro (client->npc) scanned_npcs ([{}])", npc_scan_count);
}
}
const std::vector<int16>& Client::GetInventorySlots()
{
static const std::vector<std::pair<int16, int16>> slots = {
{ EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END },
{ EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END },
{ EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END },
{ EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END },
{ EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END },
{ EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END },
{ EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END },
};
static std::vector<int16> slot_ids;
if (slot_ids.empty()) {
for (const auto& [begin, end] : slots) {
for (int16 slot_id = begin; slot_id <= end; ++slot_id) {
slot_ids.emplace_back(slot_id);
}
}
}
return slot_ids;
}
+1 -2
View File
@@ -467,7 +467,6 @@ public:
inline ExtendedProfile_Struct& GetEPP() { return m_epp; }
inline EQ::InventoryProfile& GetInv() { return m_inv; }
inline const EQ::InventoryProfile& GetInv() const { return m_inv; }
const std::vector<int16>& GetInventorySlots();
inline PetInfo* GetPetInfo(int pet_info_type) { return pet_info_type == PetInfoType::Suspended ? &m_suspendedminion : &m_petinfo; }
inline InspectMessage_Struct& GetInspectMessage() { return m_inspect_message; }
inline const InspectMessage_Struct& GetInspectMessage() const { return m_inspect_message; }
@@ -1094,7 +1093,7 @@ public:
bool PushItemOnCursor(const EQ::ItemInstance& inst, bool client_update = false);
void SendCursorBuffer();
void DeleteItemInInventory(int16 slot_id, int16 quantity = 0, bool client_update = false, bool update_db = true);
uint32 CountItem(uint32 item_id);
int CountItem(uint32 item_id);
void ResetItemCooldown(uint32 item_id);
void SetItemCooldown(uint32 item_id, bool use_saved_timer = false, uint32 in_seconds = 1);
uint32 GetItemCooldown(uint32 item_id);
+149 -89
View File
@@ -524,6 +524,7 @@ int Client::HandlePacket(const EQApplicationPacket *app)
// Finish client connecting state
void Client::CompleteConnect()
{
UpdateWho();
client_state = CLIENT_CONNECTED;
SendAllPackets();
@@ -860,7 +861,7 @@ void Client::CompleteConnect()
if (IsInAGuild()) {
if (firstlogon == 1) {
guild_mgr.UpdateDbMemberOnline(CharacterID(), true);
SendGuildMembersList();
guild_mgr.SendToWorldSendGuildMembersList(GuildID());
}
guild_mgr.SendGuildMemberUpdateToWorld(GetName(), GuildID(), zone->GetZoneID(), time(nullptr));
@@ -912,6 +913,10 @@ void Client::CompleteConnect()
CastToClient()->FastQueuePacket(&outapp);
}
if (ClientVersion() >= EQ::versions::ClientVersion::RoF) {
SendBulkBazaarTraders();
}
// TODO: load these states
// We at least will set them to the correct state for now
if (m_ClientVersionBit & EQ::versions::maskUFAndLater && GetPet()) {
@@ -1408,7 +1413,6 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
drakkin_details = m_pp.drakkin_details;
// Load Data Buckets
ClearDataBucketCache();
DataBucket::GetDataBuckets(this);
// Max Level for Character:PerCharacterQglobalMaxLevel and Character:PerCharacterBucketMaxLevel
@@ -1635,11 +1639,6 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
m_pp.abilitySlotRefresh = 0;
}
#ifdef _EQDEBUG
printf("Dumping inventory on load:\n");
m_inv.dumpEntireInventory();
#endif
/* Reset to max so they dont drown on zone in if its underwater */
m_pp.air_remaining = 60;
/* Check for PVP Zone status*/
@@ -2019,38 +2018,38 @@ void Client::Handle_OP_AdventureMerchantPurchase(const EQApplicationPacket *app)
return;
}
if (item->LDoNTheme <= LDoNTheme::TAKBit) {
if (item->LDoNTheme <= LDoNThemeBits::TAKBit) {
uint32 ldon_theme;
if (item->LDoNTheme & LDoNTheme::TAKBit) {
if (item->LDoNTheme & LDoNThemeBits::TAKBit) {
if (m_pp.ldon_points_tak < item_cost) {
cannot_afford = true;
ldon_theme = LDoNTheme::TAK;
ldon_theme = LDoNThemes::TAK;
}
} else if (item->LDoNTheme & LDoNTheme::RUJBit) {
} else if (item->LDoNTheme & LDoNThemeBits::RUJBit) {
if (m_pp.ldon_points_ruj < item_cost) {
cannot_afford = true;
ldon_theme = LDoNTheme::RUJ;
ldon_theme = LDoNThemes::RUJ;
}
} else if (item->LDoNTheme & LDoNTheme::MMCBit) {
} else if (item->LDoNTheme & LDoNThemeBits::MMCBit) {
if (m_pp.ldon_points_mmc < item_cost) {
cannot_afford = true;
ldon_theme = LDoNTheme::MMC;
ldon_theme = LDoNThemes::MMC;
}
} else if (item->LDoNTheme & LDoNTheme::MIRBit) {
} else if (item->LDoNTheme & LDoNThemeBits::MIRBit) {
if (m_pp.ldon_points_mir < item_cost) {
cannot_afford = true;
ldon_theme = LDoNTheme::MIR;
ldon_theme = LDoNThemes::MIR;
}
} else if (item->LDoNTheme & LDoNTheme::GUKBit) {
} else if (item->LDoNTheme & LDoNThemeBits::GUKBit) {
if (m_pp.ldon_points_guk < item_cost) {
cannot_afford = true;
ldon_theme = LDoNTheme::GUK;
ldon_theme = LDoNThemes::GUK;
}
}
merchant_type = fmt::format(
"{} Point{}",
LDoNTheme::GetName(ldon_theme),
EQ::constants::GetLDoNThemeName(ldon_theme),
item_cost != 1 ? "s" : ""
);
}
@@ -2194,19 +2193,19 @@ void Client::Handle_OP_AdventureMerchantRequest(const EQApplicationPacket *app)
item = database.GetItem(ml.item);
if (item) {
uint32 theme = LDoNTheme::Unused;
if (item->LDoNTheme > LDoNTheme::TAKBit) {
theme = LDoNTheme::Unused;
} else if (item->LDoNTheme & LDoNTheme::TAKBit) {
theme = LDoNTheme::TAK;
} else if (item->LDoNTheme & LDoNTheme::RUJBit) {
theme = LDoNTheme::RUJ;
} else if (item->LDoNTheme & LDoNTheme::MMCBit) {
theme = LDoNTheme::MMC;
} else if (item->LDoNTheme & LDoNTheme::MIRBit) {
theme = LDoNTheme::MIR;
} else if (item->LDoNTheme & LDoNTheme::GUKBit) {
theme = LDoNTheme::GUK;
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::MIRBit) {
theme = LDoNThemes::MIR;
} else if (item->LDoNTheme & LDoNThemeBits::GUKBit) {
theme = LDoNThemes::GUK;
}
ss << "^" << item->Name << "|";
ss << item->ID << "|";
@@ -3247,14 +3246,30 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app)
args.push_back(old_aug);
if (parse->ItemHasQuestSub(tobe_auged, EVENT_UNAUGMENT_ITEM)) {
parse->EventItem(EVENT_UNAUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args);
parse->EventItem(
EVENT_UNAUGMENT_ITEM,
this,
tobe_auged,
nullptr,
"",
in_augment->augment_index,
&args
);
}
args.assign(1, tobe_auged);
args.push_back(false);
if (parse->ItemHasQuestSub(old_aug, EVENT_AUGMENT_REMOVE)) {
parse->EventItem(EVENT_AUGMENT_REMOVE, this, old_aug, nullptr, "", in_augment->augment_index, &args);
parse->EventItem(
EVENT_AUGMENT_REMOVE,
this,
old_aug,
nullptr,
"",
in_augment->augment_index,
&args
);
}
if (parse->PlayerHasQuestSub(EVENT_AUGMENT_REMOVE_CLIENT)) {
@@ -3286,13 +3301,29 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app)
args.push_back(aug);
if (parse->ItemHasQuestSub(tobe_auged, EVENT_AUGMENT_ITEM)) {
parse->EventItem(EVENT_AUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args);
parse->EventItem(
EVENT_AUGMENT_ITEM,
this,
tobe_auged,
nullptr,
"",
in_augment->augment_index,
&args
);
}
args.assign(1, tobe_auged);
if (parse->ItemHasQuestSub(aug, EVENT_AUGMENT_INSERT)) {
parse->EventItem(EVENT_AUGMENT_INSERT, this, aug, nullptr, "", in_augment->augment_index, &args);
parse->EventItem(
EVENT_AUGMENT_INSERT,
this,
aug,
nullptr,
"",
in_augment->augment_index,
&args
);
}
args.push_back(aug);
@@ -3362,14 +3393,30 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app)
args.push_back(aug);
if (parse->ItemHasQuestSub(tobe_auged, EVENT_UNAUGMENT_ITEM)) {
parse->EventItem(EVENT_UNAUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args);
parse->EventItem(
EVENT_UNAUGMENT_ITEM,
this,
tobe_auged,
nullptr,
"",
in_augment->augment_index,
&args
);
}
args.assign(1, tobe_auged);
args.push_back(false);
if (parse->ItemHasQuestSub(aug, EVENT_AUGMENT_REMOVE)) {
parse->EventItem(EVENT_AUGMENT_REMOVE, this, aug, nullptr, "", in_augment->augment_index, &args);
parse->EventItem(
EVENT_AUGMENT_REMOVE,
this,
aug,
nullptr,
"",
in_augment->augment_index,
&args
);
}
args.push_back(aug);
@@ -3434,14 +3481,30 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app)
args.push_back(aug);
if (parse->ItemHasQuestSub(tobe_auged, EVENT_UNAUGMENT_ITEM)) {
parse->EventItem(EVENT_UNAUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args);
parse->EventItem(
EVENT_UNAUGMENT_ITEM,
this,
tobe_auged,
nullptr,
"",
in_augment->augment_index,
&args
);
}
args.assign(1, tobe_auged);
args.push_back(true);
if (parse->ItemHasQuestSub(aug, EVENT_AUGMENT_REMOVE)) {
parse->EventItem(EVENT_AUGMENT_REMOVE, this, aug, nullptr, "", in_augment->augment_index, &args);
parse->EventItem(
EVENT_AUGMENT_REMOVE,
this,
aug,
nullptr,
"",
in_augment->augment_index,
&args
);
}
args.push_back(aug);
@@ -3917,10 +3980,6 @@ void Client::Handle_OP_BazaarSearch(const EQApplicationPacket *app)
SendBazaarWelcome();
break;
}
case FirstOpenSearch: {
SendBulkBazaarTraders();
break;
}
default: {
LogError("Malformed BazaarSearch_Struct packet received, ignoring\n");
}
@@ -4415,7 +4474,14 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app)
int i = 0;
if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) {
i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, p_inst, nullptr, "", castspell->inventoryslot);
i = parse->EventItem(
EVENT_ITEM_CLICK_CAST,
this,
p_inst,
nullptr,
"",
castspell->inventoryslot
);
}
if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) {
@@ -4447,7 +4513,14 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app)
int i = 0;
if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) {
i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, p_inst, nullptr, "", castspell->inventoryslot);
i = parse->EventItem(
EVENT_ITEM_CLICK_CAST,
this,
p_inst,
nullptr,
"",
castspell->inventoryslot
);
}
if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) {
@@ -7937,7 +8010,6 @@ void Client::Handle_OP_GuildCreate(const EQApplicationPacket *app)
SetGuildID(new_guild_id);
SendGuildList();
guild_mgr.MemberAdd(new_guild_id, CharacterID(), GetLevel(), GetClass(), GUILD_LEADER, GetZoneID(), GetName());
guild_mgr.SendGuildRefresh(new_guild_id, true, true, true, true);
guild_mgr.SendToWorldSendGuildList();
SendGuildSpawnAppearance();
@@ -9514,7 +9586,14 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
int i = 0;
if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) {
i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, p_inst, nullptr, "", slot_id);
i = parse->EventItem(
EVENT_ITEM_CLICK_CAST,
this,
p_inst,
nullptr,
"",
slot_id
);
}
if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) {
@@ -9578,7 +9657,14 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
int i = 0;
if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) {
i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, clickaug, nullptr, "", slot_id);
i = parse->EventItem(
EVENT_ITEM_CLICK_CAST,
this,
clickaug,
nullptr,
"",
slot_id
);
}
if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) {
@@ -10678,8 +10764,7 @@ void Client::Handle_OP_MoveCoin(const EQApplicationPacket *app)
void Client::Handle_OP_MoveItem(const EQApplicationPacket *app)
{
if (!CharacterID())
{
if (!CharacterID()) {
return;
}
@@ -10688,60 +10773,35 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app)
return;
}
MoveItem_Struct* mi = (MoveItem_Struct*)app->pBuffer;
if (spellend_timer.Enabled() && casting_spell_id && !IsBardSong(casting_spell_id))
{
if (mi->from_slot != mi->to_slot && (mi->from_slot <= EQ::invslot::GENERAL_END || mi->from_slot > 39) && IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot))
{
const EQ::ItemInstance *itm_from = GetInv().GetItem(mi->from_slot);
const EQ::ItemInstance *itm_to = GetInv().GetItem(mi->to_slot);
auto message = fmt::format("Player issued a move item from {}(item id {}) to {}(item id {}) while casting {}.",
MoveItem_Struct* mi = (MoveItem_Struct*) app->pBuffer;
if (spellend_timer.Enabled() && casting_spell_id && !IsBardSong(casting_spell_id)) {
if (mi->from_slot != mi->to_slot && (mi->from_slot <= EQ::invslot::GENERAL_END || mi->from_slot > 39) &&
IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot)) {
const EQ::ItemInstance* itm_from = GetInv().GetItem(mi->from_slot);
const EQ::ItemInstance* itm_to = GetInv().GetItem(mi->to_slot);
auto message = fmt::format(
"Player issued a move item from {}(item id {}) to {}(item id {}) while casting {}.",
mi->from_slot,
itm_from ? itm_from->GetID() : 0,
mi->to_slot,
itm_to ? itm_to->GetID() : 0,
casting_spell_id);
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message});
casting_spell_id
);
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{ .message = message });
Kick("Inventory desync"); // Kick client to prevent client and server from getting out-of-sync inventory slots
return;
}
}
// Illegal bagslot usage checks. Currently, user only receives a message if this check is triggered.
bool mi_hack = false;
if (mi->from_slot >= EQ::invbag::GENERAL_BAGS_BEGIN && mi->from_slot <= EQ::invbag::CURSOR_BAG_END) {
if (mi->from_slot >= EQ::invbag::CURSOR_BAG_BEGIN) { mi_hack = true; }
else {
int16 from_parent = m_inv.CalcSlotId(mi->from_slot);
if (!m_inv[from_parent]) { mi_hack = true; }
else if (!m_inv[from_parent]->IsClassBag()) { mi_hack = true; }
else if (m_inv.CalcBagIdx(mi->from_slot) >= m_inv[from_parent]->GetItem()->BagSlots) { mi_hack = true; }
}
}
if (mi->to_slot >= EQ::invbag::GENERAL_BAGS_BEGIN && mi->to_slot <= EQ::invbag::CURSOR_BAG_END) {
if (mi->to_slot >= EQ::invbag::CURSOR_BAG_BEGIN) { mi_hack = true; }
else {
int16 to_parent = m_inv.CalcSlotId(mi->to_slot);
if (!m_inv[to_parent]) { mi_hack = true; }
else if (!m_inv[to_parent]->IsClassBag()) { mi_hack = true; }
else if (m_inv.CalcBagIdx(mi->to_slot) >= m_inv[to_parent]->GetItem()->BagSlots) { mi_hack = true; }
}
}
if (mi_hack) { Message(Chat::Yellow, "Caution: Illegal use of inaccessible bag slots!"); }
if (!SwapItem(mi) && IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot)) {
SwapItemResync(mi);
bool error = false;
InterrogateInventory(this, false, true, false, error, false);
if (error)
if (error) {
InterrogateInventory(this, true, false, true, error);
}
}
return;
}
void Client::Handle_OP_MoveMultipleItems(const EQApplicationPacket *app)
+60 -40
View File
@@ -179,7 +179,7 @@ bool Client::Process() {
}
if (IsInAGuild()) {
guild_mgr.UpdateDbMemberOnline(CharacterID(), false);
guild_mgr.SendGuildMemberUpdateToWorld(GetName(), GuildID(), 0, time(nullptr));
guild_mgr.SendToWorldSendGuildMembersList(GuildID());
}
SetDynamicZoneMemberStatus(DynamicZoneMemberStatus::Offline);
@@ -202,7 +202,7 @@ bool Client::Process() {
Save();
if (IsInAGuild()) {
guild_mgr.UpdateDbMemberOnline(CharacterID(), false);
guild_mgr.SendGuildMemberUpdateToWorld(GetName(), GuildID(), 0, time(nullptr));
guild_mgr.SendToWorldSendGuildMembersList(GuildID());
}
if (GetMerc())
@@ -578,7 +578,7 @@ bool Client::Process() {
}
if (IsInAGuild()) {
guild_mgr.UpdateDbMemberOnline(CharacterID(), false);
guild_mgr.SendGuildMemberUpdateToWorld(GetName(), GuildID(), 0, time(nullptr));
guild_mgr.SendToWorldSendGuildMembersList(GuildID());
}
return false;
@@ -770,65 +770,83 @@ void Client::BulkSendInventoryItems()
EQ::OutBuffer ob;
EQ::OutBuffer::pos_type last_pos = ob.tellp();
// Possessions items
for (int16 slot_id = EQ::invslot::POSSESSIONS_BEGIN; slot_id <= EQ::invslot::POSSESSIONS_END; slot_id++) {
// Equipment items
for (int16 slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; slot_id++) {
const EQ::ItemInstance* inst = m_inv[slot_id];
if (!inst)
if (!inst) {
continue;
}
inst->Serialize(ob, slot_id);
if (ob.tellp() == last_pos)
if (ob.tellp() == last_pos) {
LogInventory("Serialization failed on item slot [{}] during BulkSendInventoryItems. Item skipped", slot_id);
}
last_pos = ob.tellp();
}
if (!RuleB(Inventory, LazyLoadBank)) {
// Bank items
for (int16 slot_id = EQ::invslot::BANK_BEGIN; slot_id <= EQ::invslot::BANK_END; slot_id++) {
const EQ::ItemInstance* inst = m_inv[slot_id];
if (!inst)
continue;
// General items
for (int16 slot_id = EQ::invslot::GENERAL_BEGIN; slot_id <= EQ::invslot::GENERAL_END; slot_id++) {
const EQ::ItemInstance* inst = m_inv[slot_id];
if (!inst) {
continue;
}
inst->Serialize(ob, slot_id);
inst->Serialize(ob, slot_id);
if (ob.tellp() == last_pos)
LogInventory("Serialization failed on item slot [{}] during BulkSendInventoryItems. Item skipped", slot_id);
if (ob.tellp() == last_pos) {
LogInventory("Serialization failed on item slot [{}] during BulkSendInventoryItems. Item skipped", slot_id);
}
last_pos = ob.tellp();
}
last_pos = ob.tellp();
}
// SharedBank items
for (int16 slot_id = EQ::invslot::SHARED_BANK_BEGIN; slot_id <= EQ::invslot::SHARED_BANK_END; slot_id++) {
const EQ::ItemInstance* inst = m_inv[slot_id];
if (!inst)
continue;
if (!RuleB(Inventory, LazyLoadBank)) {
// Bank items
for (int16 slot_id = EQ::invslot::BANK_BEGIN; slot_id <= EQ::invslot::BANK_END; slot_id++) {
const EQ::ItemInstance* inst = m_inv[slot_id];
if (!inst) {
continue;
}
inst->Serialize(ob, slot_id);
inst->Serialize(ob, slot_id);
if (ob.tellp() == last_pos)
LogInventory("Serialization failed on item slot [{}] during BulkSendInventoryItems. Item skipped", slot_id);
if (ob.tellp() == last_pos) {
LogInventory("Serialization failed on item slot [{}] during BulkSendInventoryItems. Item skipped", slot_id);
}
last_pos = ob.tellp();
}
}
last_pos = ob.tellp();
}
auto outapp = new EQApplicationPacket(OP_CharInventory);
outapp->size = ob.size();
outapp->pBuffer = ob.detach();
QueuePacket(outapp);
safe_delete(outapp);
// SharedBank items
for (int16 slot_id = EQ::invslot::SHARED_BANK_BEGIN; slot_id <= EQ::invslot::SHARED_BANK_END; slot_id++) {
const EQ::ItemInstance* inst = m_inv[slot_id];
if (!inst) {
continue;
}
inst->Serialize(ob, slot_id);
if (ob.tellp() == last_pos) {
LogInventory("Serialization failed on item slot [{}] during BulkSendInventoryItems. Item skipped", slot_id);
}
last_pos = ob.tellp();
}
}
auto outapp = new EQApplicationPacket(OP_CharInventory);
outapp->size = ob.size();
outapp->pBuffer = ob.detach();
QueuePacket(outapp);
safe_delete(outapp);
}
void Client::BulkSendMerchantInventory(int merchant_id, int npcid) {
const EQ::ItemData* handy_item = nullptr;
uint32 merchant_slots = 80; //The max number of items passed in the transaction.
if (m_ClientVersionBit & EQ::versions::maskRoFAndLater) { // RoF+ can send 200 items
merchant_slots = 200;
}
const EQ::ItemData *item = nullptr;
auto merchant_list = zone->merchanttable[merchant_id];
auto npc = entity_list.GetMobByNpcTypeID(npcid);
@@ -840,6 +858,8 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) {
}
}
const int16 merchant_slots = (m_ClientVersionBit & EQ::versions::maskRoFAndLater) ? EQ::invtype::MERCHANT_SIZE : 80;
auto temporary_merchant_list = zone->tmpmerchanttable[npcid];
uint32 slot_id = 1;
uint8 handy_chance = 0;
+4 -6
View File
@@ -845,7 +845,7 @@ LootItem *Corpse::GetItem(uint16 lootslot, LootItem **bag_item_data)
// convert above code to for loop
for (const auto &item: m_item_list) {
if (item->equip_slot >= bagstart && item->equip_slot < bagstart + 10) {
if (item->equip_slot >= bagstart && item->equip_slot < bagstart + EQ::invbag::SLOT_COUNT) {
bag_item_data[item->equip_slot - bagstart] = item;
}
}
@@ -1472,7 +1472,7 @@ void Corpse::LootCorpseItem(Client *c, const EQApplicationPacket *app)
const EQ::ItemData *item = nullptr;
EQ::ItemInstance *inst = nullptr;
LootItem *item_data = nullptr, *bag_item_data[10] = {};
LootItem *item_data = nullptr, *bag_item_data[EQ::invbag::SLOT_COUNT] = {};
memset(bag_item_data, 0, sizeof(bag_item_data));
if (GetPlayerKillItem() > 1) {
@@ -1871,10 +1871,9 @@ bool Corpse::HasItem(uint32 item_id)
return false;
}
uint32 Corpse::CountItem(uint32 item_id)
uint16 Corpse::CountItem(uint32 item_id)
{
uint32 item_count = 0;
uint16 item_count = 0;
if (!database.GetItem(item_id)) {
return item_count;
}
@@ -1894,7 +1893,6 @@ uint32 Corpse::CountItem(uint32 item_id)
item_count += i->charges > 0 ? i->charges : 1;
}
}
return item_count;
}
+1 -1
View File
@@ -196,7 +196,7 @@ public:
/* Corpse: Loot */
void QueryLoot(Client *to);
bool HasItem(uint32 item_id);
uint32 CountItem(uint32 item_id);
uint16 CountItem(uint32 item_id);
uint32 GetItemIDBySlot(uint16 loot_slot);
uint16 GetFirstLootSlotByItemID(uint32 item_id);
std::vector<int> GetLootList();
+275 -153
View File
@@ -8,7 +8,7 @@
extern WorldServer worldserver;
std::vector<DataBucketsRepository::DataBuckets> g_data_bucket_cache = {};
std::vector<DataBucketCacheEntry> g_data_bucket_cache = {};
void DataBucket::SetData(const std::string &bucket_key, const std::string &bucket_value, std::string expires_time)
{
@@ -58,14 +58,14 @@ void DataBucket::SetData(const DataBucketKey &k)
b.value = k.value;
if (bucket_id) {
// update the cache if it exists
if (CanCache(k)) {
for (auto &e: g_data_bucket_cache) {
if (CheckBucketMatch(e, k)) {
e = b;
break;
}
// loop cache and update cache value and timestamp
for (auto &ce: g_data_bucket_cache) {
if (CheckBucketMatch(ce.e, k)) {
ce.e = b;
ce.updated_time = GetCurrentTimeUNIX();
ce.update_action = DataBucketCacheUpdateAction::Upsert;
SendDataBucketCacheUpdate(ce);
break;
}
}
@@ -74,18 +74,28 @@ void DataBucket::SetData(const DataBucketKey &k)
else {
b.key_ = k.key;
b = DataBucketsRepository::InsertOne(database, b);
if (!ExistsInCache(b)) {
// add data bucket and timestamp to cache
auto ce = DataBucketCacheEntry{
.e = b,
.updated_time = DataBucket::GetCurrentTimeUNIX(),
.update_action = DataBucketCacheUpdateAction::Upsert
};
g_data_bucket_cache.emplace_back(ce);
SendDataBucketCacheUpdate(ce);
// add to cache if it doesn't exist
if (CanCache(k) && !ExistsInCache(b)) {
DeleteFromMissesCache(b);
g_data_bucket_cache.emplace_back(b);
}
}
}
std::string DataBucket::GetData(const std::string &bucket_key)
{
return GetData(DataBucketKey{.key = bucket_key}).value;
DataBucketKey k = {};
k.key = bucket_key;
return GetData(k).value;
}
// GetData fetches bucket data from the database or cache if it exists
@@ -102,27 +112,22 @@ DataBucketsRepository::DataBuckets DataBucket::GetData(const DataBucketKey &k, b
k.npc_id
);
bool can_cache = CanCache(k);
// check the cache first if we can cache
if (can_cache) {
for (const auto &e: g_data_bucket_cache) {
if (CheckBucketMatch(e, k)) {
if (e.expires > 0 && e.expires < std::time(nullptr)) {
LogDataBuckets("Attempted to read expired key [{}] removing from cache", e.key_);
DeleteData(k);
return DataBucketsRepository::NewEntity();
}
// this is a bucket miss, return empty entity
// we still cache bucket misses, so we don't have to hit the database
if (e.id == 0) {
return DataBucketsRepository::NewEntity();
}
LogDataBuckets("Returning key [{}] value [{}] from cache", e.key_, e.value);
return e;
for (const auto &ce: g_data_bucket_cache) {
if (CheckBucketMatch(ce.e, k)) {
if (ce.e.expires > 0 && ce.e.expires < std::time(nullptr)) {
LogDataBuckets("Attempted to read expired key [{}] removing from cache", ce.e.key_);
DeleteData(k);
return DataBucketsRepository::NewEntity();
}
// this is a bucket miss, return empty entity
// we still cache bucket misses, so we don't have to hit the database
if (ce.e.id == 0) {
return DataBucketsRepository::NewEntity();
}
LogDataBuckets("Returning key [{}] value [{}] from cache", ce.e.key_, ce.e.value);
return ce.e;
}
}
@@ -139,21 +144,23 @@ DataBucketsRepository::DataBuckets DataBucket::GetData(const DataBucketKey &k, b
// if we're ignoring the misses cache, don't add to the cache
// the only place this is ignored is during the initial read of SetData
bool add_to_misses_cache = !ignore_misses_cache && can_cache;
if (add_to_misses_cache) {
if (!ignore_misses_cache) {
size_t size_before = g_data_bucket_cache.size();
// cache bucket misses, so we don't have to hit the database
// when scripts try to read a bucket that doesn't exist
g_data_bucket_cache.emplace_back(
DataBucketsRepository::DataBuckets{
.id = 0,
.key_ = k.key,
.value = "",
.expires = 0,
.character_id = k.character_id,
.npc_id = k.npc_id,
.bot_id = k.bot_id
DataBucketCacheEntry{
.e = DataBucketsRepository::DataBuckets{
.id = 0,
.key_ = k.key,
.value = "",
.expires = 0,
.character_id = k.character_id,
.npc_id = k.npc_id,
.bot_id = k.bot_id
},
.updated_time = DataBucket::GetCurrentTimeUNIX()
}
);
@@ -171,54 +178,60 @@ DataBucketsRepository::DataBuckets DataBucket::GetData(const DataBucketKey &k, b
return {};
}
auto bucket = r.front();
// if the entry has expired, delete it
if (bucket.expires > 0 && bucket.expires < (long long) std::time(nullptr)) {
if (r[0].expires > 0 && r[0].expires < (long long) std::time(nullptr)) {
DeleteData(k);
return {};
}
// add to cache if it doesn't exist
if (can_cache) {
bool has_cache = false;
for (auto &e: g_data_bucket_cache) {
if (e.id == bucket.id) {
has_cache = true;
break;
}
}
if (!has_cache) {
g_data_bucket_cache.emplace_back(bucket);
bool has_cache = false;
for (auto &ce: g_data_bucket_cache) {
if (ce.e.id == r[0].id) {
has_cache = true;
break;
}
}
return bucket;
if (!has_cache) {
// add data bucket and timestamp to cache
g_data_bucket_cache.emplace_back(
DataBucketCacheEntry{
.e = r[0],
.updated_time = DataBucket::GetCurrentTimeUNIX()
}
);
}
return r[0];
}
std::string DataBucket::GetDataExpires(const std::string &bucket_key)
{
return GetDataExpires(DataBucketKey{.key = bucket_key});
DataBucketKey k = {};
k.key = bucket_key;
return GetDataExpires(k);
}
std::string DataBucket::GetDataRemaining(const std::string &bucket_key)
{
return GetDataRemaining(DataBucketKey{.key = bucket_key});
DataBucketKey k = {};
k.key = bucket_key;
return GetDataRemaining(k);
}
bool DataBucket::DeleteData(const std::string &bucket_key)
{
return DeleteData(DataBucketKey{.key = bucket_key});
DataBucketKey k = {};
k.key = bucket_key;
return DeleteData(k);
}
// GetDataBuckets bulk loads all data buckets for a mob
bool DataBucket::GetDataBuckets(Mob *mob)
{
DataBucketLoadType::Type t{};
const uint32 id = mob->GetMobTypeIdentifier();
DataBucketLoadType::Type t;
const uint32 id = mob->GetMobTypeIdentifier();
if (!id) {
return false;
@@ -230,39 +243,46 @@ bool DataBucket::GetDataBuckets(Mob *mob)
else if (mob->IsClient()) {
t = DataBucketLoadType::Client;
}
else if (mob->IsNPC()) {
t = DataBucketLoadType::NPC;
}
BulkLoadEntitiesToCache(t, {id});
BulkLoadEntities(t, {id});
return true;
}
bool DataBucket::DeleteData(const DataBucketKey &k)
{
if (CanCache(k)) {
size_t size_before = g_data_bucket_cache.size();
size_t size_before = g_data_bucket_cache.size();
// delete from cache where contents match
g_data_bucket_cache.erase(
std::remove_if(
g_data_bucket_cache.begin(),
g_data_bucket_cache.end(),
[&](DataBucketsRepository::DataBuckets &e) {
return CheckBucketMatch(e, k);
// delete from cache where contents match
g_data_bucket_cache.erase(
std::remove_if(
g_data_bucket_cache.begin(),
g_data_bucket_cache.end(),
[&](DataBucketCacheEntry &ce) {
bool match = CheckBucketMatch(ce.e, k);
if (match) {
ce.update_action = DataBucketCacheUpdateAction::Delete;
SendDataBucketCacheUpdate(ce);
}
),
g_data_bucket_cache.end()
);
LogDataBuckets(
"Deleting bucket key [{}] bot_id [{}] character_id [{}] npc_id [{}] cache size before [{}] after [{}]",
k.key,
k.bot_id,
k.character_id,
k.npc_id,
size_before,
g_data_bucket_cache.size()
);
}
return match;
}
),
g_data_bucket_cache.end()
);
LogDataBuckets(
"Deleting bucket key [{}] bot_id [{}] character_id [{}] npc_id [{}] cache size before [{}] after [{}]",
k.key,
k.bot_id,
k.character_id,
k.npc_id,
size_before,
g_data_bucket_cache.size()
);
return DataBucketsRepository::DeleteWhere(
database,
@@ -351,21 +371,23 @@ bool DataBucket::CheckBucketMatch(const DataBucketsRepository::DataBuckets &dbe,
);
}
void DataBucket::BulkLoadEntitiesToCache(DataBucketLoadType::Type t, std::vector<uint32> ids)
void DataBucket::BulkLoadEntities(DataBucketLoadType::Type t, std::vector<uint32> ids)
{
if (ids.empty()) {
return;
}
if (ids.size() == 1) {
bool has_cache = false;
for (const auto &e: g_data_bucket_cache) {
bool has_cache = false;
for (const auto &ce: g_data_bucket_cache) {
if (t == DataBucketLoadType::Bot) {
has_cache = e.bot_id == ids[0];
has_cache = ce.e.bot_id == ids[0];
}
else if (t == DataBucketLoadType::Client) {
has_cache = e.character_id == ids[0];
has_cache = ce.e.character_id == ids[0];
}
else if (t == DataBucketLoadType::NPC) {
has_cache = ce.e.npc_id == ids[0];
}
}
@@ -384,6 +406,9 @@ void DataBucket::BulkLoadEntitiesToCache(DataBucketLoadType::Type t, std::vector
case DataBucketLoadType::Client:
column = "character_id";
break;
case DataBucketLoadType::NPC:
column = "npc_id";
break;
default:
LogError("Incorrect LoadType [{}]", static_cast<int>(t));
break;
@@ -417,7 +442,12 @@ void DataBucket::BulkLoadEntitiesToCache(DataBucketLoadType::Type t, std::vector
if (!ExistsInCache(e)) {
LogDataBucketsDetail("bucket id [{}] bucket key [{}] bucket value [{}]", e.id, e.key_, e.value);
g_data_bucket_cache.emplace_back(e);
g_data_bucket_cache.emplace_back(
DataBucketCacheEntry{
.e = e,
.updated_time = GetCurrentTimeUNIX()
}
);
}
}
@@ -431,7 +461,7 @@ void DataBucket::BulkLoadEntitiesToCache(DataBucketLoadType::Type t, std::vector
);
}
void DataBucket::DeleteCachedBuckets(DataBucketLoadType::Type type, uint32 id)
void DataBucket::DeleteCachedBuckets(DataBucketLoadType::Type t, uint32 id)
{
size_t size_before = g_data_bucket_cache.size();
@@ -439,10 +469,11 @@ void DataBucket::DeleteCachedBuckets(DataBucketLoadType::Type type, uint32 id)
std::remove_if(
g_data_bucket_cache.begin(),
g_data_bucket_cache.end(),
[&](DataBucketsRepository::DataBuckets &e) {
[&](DataBucketCacheEntry &ce) {
return (
(type == DataBucketLoadType::Bot && e.bot_id == id) ||
(type == DataBucketLoadType::Client && e.character_id == id)
(t == DataBucketLoadType::Bot && ce.e.bot_id == id) ||
(t == DataBucketLoadType::Client && ce.e.character_id == id) ||
(t == DataBucketLoadType::NPC && ce.e.npc_id == id)
);
}
),
@@ -451,17 +482,24 @@ void DataBucket::DeleteCachedBuckets(DataBucketLoadType::Type type, uint32 id)
LogDataBuckets(
"LoadType [{}] id [{}] cache size before [{}] after [{}]",
DataBucketLoadType::Name[type],
DataBucketLoadType::Name[t],
id,
size_before,
g_data_bucket_cache.size()
);
}
bool DataBucket::ExistsInCache(const DataBucketsRepository::DataBuckets &entry)
int64_t DataBucket::GetCurrentTimeUNIX()
{
for (const auto &e: g_data_bucket_cache) {
if (e.id == entry.id) {
return std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::system_clock::now().time_since_epoch()
).count();
}
bool DataBucket::ExistsInCache(const DataBucketsRepository::DataBuckets &e)
{
for (const auto &ce: g_data_bucket_cache) {
if (ce.e.id == e.id) {
return true;
}
}
@@ -469,6 +507,134 @@ bool DataBucket::ExistsInCache(const DataBucketsRepository::DataBuckets &entry)
return false;
}
bool DataBucket::SendDataBucketCacheUpdate(const DataBucketCacheEntry &e)
{
if (!e.e.id) {
return false;
}
EQ::Net::DynamicPacket p;
p.PutSerialize(0, e);
auto pack_size = sizeof(ServerDataBucketCacheUpdate_Struct) + p.Length();
auto pack = new ServerPacket(ServerOP_DataBucketCacheUpdate, static_cast<uint32_t>(pack_size));
auto buf = reinterpret_cast<ServerDataBucketCacheUpdate_Struct *>(pack->pBuffer);
buf->cereal_size = static_cast<uint32_t>(p.Length());
memcpy(buf->cereal_data, p.Data(), p.Length());
worldserver.SendPacket(pack);
return true;
}
void DataBucket::HandleWorldMessage(ServerPacket *p)
{
DataBucketCacheEntry n;
auto s = (ServerDataBucketCacheUpdate_Struct *) p->pBuffer;
EQ::Util::MemoryStreamReader ss(s->cereal_data, s->cereal_size);
cereal::BinaryInputArchive archive(ss);
archive(n);
LogDataBucketsDetail(
"Received cache packet for id [{}] key [{}] value [{}] action [{}]",
n.e.id,
n.e.key_,
n.e.value,
static_cast<int>(n.update_action)
);
// delete
if (n.update_action == DataBucketCacheUpdateAction::Delete) {
DeleteFromMissesCache(n.e);
g_data_bucket_cache.erase(
std::remove_if(
g_data_bucket_cache.begin(),
g_data_bucket_cache.end(),
[&](DataBucketCacheEntry &ce) {
bool match = n.e.id > 0 && ce.e.id == n.e.id;
if (match) {
LogDataBuckets(
"[delete] cache key [{}] id [{}] cache_size before [{}] after [{}]",
ce.e.key_,
ce.e.id,
g_data_bucket_cache.size(),
g_data_bucket_cache.size() - 1
);
}
return match;
}
),
g_data_bucket_cache.end()
);
return;
}
// update
bool has_key = false;
for (auto &ce: g_data_bucket_cache) {
// update cache
if (ce.e.id == n.e.id) {
// reject old updates
int64 time_delta = ce.updated_time - n.updated_time;
if (ce.updated_time >= n.updated_time) {
LogDataBuckets(
"Attempted to update older cache key [{}] rejecting old time [{}] new time [{}] delta [{}] cache_size [{}]",
ce.e.key_,
ce.updated_time,
n.updated_time,
time_delta,
g_data_bucket_cache.size()
);
return;
}
DeleteFromMissesCache(n.e);
LogDataBuckets(
"[update] cache id [{}] key [{}] value [{}] old time [{}] new time [{}] delta [{}] cache_size [{}]",
ce.e.id,
ce.e.key_,
n.e.value,
ce.updated_time,
n.updated_time,
time_delta,
g_data_bucket_cache.size()
);
ce.e = n.e;
ce.updated_time = n.updated_time;
has_key = true;
break;
}
}
// create
if (!has_key) {
DeleteFromMissesCache(n.e);
size_t size_before = g_data_bucket_cache.size();
g_data_bucket_cache.emplace_back(
DataBucketCacheEntry{
.e = n.e,
.updated_time = GetCurrentTimeUNIX()
}
);
LogDataBuckets(
"[create] Adding new cache id [{}] key [{}] value [{}] cache size before [{}] after [{}]",
n.e.id,
n.e.key_,
n.e.value,
size_before,
g_data_bucket_cache.size()
);
}
}
void DataBucket::DeleteFromMissesCache(DataBucketsRepository::DataBuckets e)
{
// delete from cache where there might have been a written bucket miss to the cache
@@ -479,11 +645,11 @@ void DataBucket::DeleteFromMissesCache(DataBucketsRepository::DataBuckets e)
std::remove_if(
g_data_bucket_cache.begin(),
g_data_bucket_cache.end(),
[&](DataBucketsRepository::DataBuckets &ce) {
return ce.id == 0 && ce.key_ == e.key_ &&
ce.character_id == e.character_id &&
ce.npc_id == e.npc_id &&
ce.bot_id == e.bot_id;
[&](DataBucketCacheEntry &ce) {
return ce.e.id == 0 && ce.e.key_ == e.key_ &&
ce.e.character_id == e.character_id &&
ce.e.npc_id == e.npc_id &&
ce.e.bot_id == e.bot_id;
}
),
g_data_bucket_cache.end()
@@ -501,47 +667,3 @@ void DataBucket::ClearCache()
g_data_bucket_cache.clear();
LogInfo("Cleared data buckets cache");
}
void DataBucket::DeleteFromCache(uint64 id, DataBucketLoadType::Type type)
{
size_t size_before = g_data_bucket_cache.size();
g_data_bucket_cache.erase(
std::remove_if(
g_data_bucket_cache.begin(),
g_data_bucket_cache.end(),
[&](DataBucketsRepository::DataBuckets &e) {
switch (type) {
case DataBucketLoadType::Bot:
return e.bot_id == id;
case DataBucketLoadType::Client:
return e.character_id == id;
default:
return false;
}
}
),
g_data_bucket_cache.end()
);
LogDataBuckets(
"Deleted [{}] id [{}] from cache size before [{}] after [{}]",
DataBucketLoadType::Name[type],
id,
size_before,
g_data_bucket_cache.size()
);
}
// CanCache returns whether a bucket can be cached or not
// characters are only in one zone at a time so we can cache locally to the zone
// bots (not implemented) are only in one zone at a time so we can cache locally to the zone
// npcs (ids) can be in multiple zones so we can't cache locally to the zone
bool DataBucket::CanCache(const DataBucketKey &key)
{
if (key.character_id > 0 || key.bot_id > 0) {
return true;
}
return false;
}
+34 -5
View File
@@ -1,3 +1,7 @@
//
// Created by Akkadius on 7/7/18.
//
#ifndef EQEMU_DATABUCKET_H
#define EQEMU_DATABUCKET_H
@@ -8,6 +12,27 @@
#include "../common/json/json_archive_single_line.h"
#include "../common/servertalk.h"
enum DataBucketCacheUpdateAction : uint8 {
Upsert,
Delete
};
struct DataBucketCacheEntry {
DataBucketsRepository::DataBuckets e;
int64_t updated_time{};
DataBucketCacheUpdateAction update_action{};
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(e),
CEREAL_NVP(updated_time),
CEREAL_NVP(update_action)
);
}
};
struct DataBucketKey {
std::string key;
std::string value;
@@ -21,12 +46,14 @@ namespace DataBucketLoadType {
enum Type : uint8 {
Bot,
Client,
NPC,
MaxType
};
static const std::string Name[Type::MaxType] = {
"Bot",
"Client",
"NPC",
};
}
@@ -41,6 +68,8 @@ public:
static bool GetDataBuckets(Mob *mob);
static int64_t GetCurrentTimeUNIX();
// scoped bucket methods
static void SetData(const DataBucketKey &k);
static bool DeleteData(const DataBucketKey &k);
@@ -51,15 +80,15 @@ public:
// bucket repository versus key matching
static bool CheckBucketMatch(const DataBucketsRepository::DataBuckets &dbe, const DataBucketKey &k);
static bool ExistsInCache(const DataBucketsRepository::DataBuckets &entry);
static bool ExistsInCache(const DataBucketsRepository::DataBuckets &e);
static void BulkLoadEntitiesToCache(DataBucketLoadType::Type t, std::vector<uint32> ids);
static void DeleteCachedBuckets(DataBucketLoadType::Type type, uint32 id);
static void BulkLoadEntities(DataBucketLoadType::Type t, std::vector<uint32> ids);
static void DeleteCachedBuckets(DataBucketLoadType::Type t, uint32 id);
static bool SendDataBucketCacheUpdate(const DataBucketCacheEntry &e);
static void HandleWorldMessage(ServerPacket *p);
static void DeleteFromMissesCache(DataBucketsRepository::DataBuckets e);
static void ClearCache();
static void DeleteFromCache(uint64 id, DataBucketLoadType::Type type);
static bool CanCache(const DataBucketKey &key);
};
#endif //EQEMU_DATABUCKET_H
+1 -1
View File
@@ -1736,7 +1736,7 @@ void PerlembParser::ExportEventVariables(
case EVENT_PAYLOAD: {
Seperator sep(data);
ExportVar(package_name.c_str(), "payload_id", sep.arg[0]);
ExportVar(package_name.c_str(), "payload_value", sep.argplus[1]);
ExportVar(package_name.c_str(), "payload_value", sep.arg[1]);
break;
}
+20 -20
View File
@@ -278,25 +278,25 @@ int Perl__getinventoryslotid(std::string identifier)
else if (identifier == "generalbags.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN;
else if (identifier == "generalbags.end") result = EQ::invbag::GENERAL_BAGS_END;
else if (identifier == "general1bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN;
else if (identifier == "general1bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 9;
else if (identifier == "general2bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + 10;
else if (identifier == "general2bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 19;
else if (identifier == "general3bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + 20;
else if (identifier == "general3bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 29;
else if (identifier == "general4bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + 30;
else if (identifier == "general4bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 39;
else if (identifier == "general5bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + 40;
else if (identifier == "general5bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 49;
else if (identifier == "general6bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + 50;
else if (identifier == "general6bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 59;
else if (identifier == "general7bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + 60;
else if (identifier == "general7bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 69;
else if (identifier == "general8bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + 70;
else if (identifier == "general8bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 79;
else if (identifier == "general9bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + 80;
else if (identifier == "general9bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 89;
else if (identifier == "general10bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + 90;
else if (identifier == "general10bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 99;
else if (identifier == "general1bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + (EQ::invbag::SLOT_COUNT - 1);
else if (identifier == "general2bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + EQ::invbag::SLOT_COUNT;
else if (identifier == "general2bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + ((EQ::invbag::SLOT_COUNT * 2) - 1);
else if (identifier == "general3bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + (EQ::invbag::SLOT_COUNT * 2);
else if (identifier == "general3bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + ((EQ::invbag::SLOT_COUNT * 3) - 1);
else if (identifier == "general4bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + (EQ::invbag::SLOT_COUNT * 3);
else if (identifier == "general4bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + ((EQ::invbag::SLOT_COUNT * 4) - 1);
else if (identifier == "general5bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + (EQ::invbag::SLOT_COUNT * 4);
else if (identifier == "general5bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + ((EQ::invbag::SLOT_COUNT * 5) - 1);
else if (identifier == "general6bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + (EQ::invbag::SLOT_COUNT * 5);
else if (identifier == "general6bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + ((EQ::invbag::SLOT_COUNT * 6) - 1);
else if (identifier == "general7bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + (EQ::invbag::SLOT_COUNT * 6);
else if (identifier == "general7bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + ((EQ::invbag::SLOT_COUNT * 7) - 1);
else if (identifier == "general8bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + (EQ::invbag::SLOT_COUNT * 7);
else if (identifier == "general8bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + ((EQ::invbag::SLOT_COUNT * 8) - 1);
else if (identifier == "general9bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + (EQ::invbag::SLOT_COUNT * 8);
else if (identifier == "general9bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + ((EQ::invbag::SLOT_COUNT * 9) - 1);
else if (identifier == "general10bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + (EQ::invbag::SLOT_COUNT * 9);
else if (identifier == "general10bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + ((EQ::invbag::SLOT_COUNT * 10) - 1);
else if (identifier == "cursorbag.begin") result = EQ::invbag::CURSOR_BAG_BEGIN;
else if (identifier == "cursorbag.end") result = EQ::invbag::CURSOR_BAG_END;
else if (identifier == "bank.begin") result = EQ::invslot::BANK_BEGIN;
@@ -1446,7 +1446,7 @@ int Perl__collectitems(uint32_t item_id, bool remove_item)
return quest_manager.collectitems(item_id, remove_item);
}
uint32 Perl__countitem(uint32_t item_id)
int Perl__countitem(uint32_t item_id)
{
return quest_manager.countitem(item_id);
}
+14 -2
View File
@@ -1817,13 +1817,25 @@ void EntityList::DuelMessage(Mob *winner, Mob *loser, bool flee)
if (parse->PlayerHasQuestSub(EVENT_DUEL_WIN)) {
std::vector<std::any> args = { winner, loser };
parse->EventPlayer(EVENT_DUEL_WIN, winner->CastToClient(), loser->GetName(), loser->CastToClient()->CharacterID(), &args);
parse->EventPlayer(
EVENT_DUEL_WIN,
winner->CastToClient(),
loser->GetName(),
loser->CastToClient()->CharacterID(),
&args
);
}
if (parse->PlayerHasQuestSub(EVENT_DUEL_LOSE)) {
std::vector<std::any> args = { winner, loser };
parse->EventPlayer(EVENT_DUEL_LOSE, loser->CastToClient(), winner->GetName(), winner->CastToClient()->CharacterID(), &args);
parse->EventPlayer(
EVENT_DUEL_LOSE,
loser->CastToClient(),
winner->GetName(),
winner->CastToClient()->CharacterID(),
&args
);
}
}
+25 -15
View File
@@ -2,21 +2,31 @@
void command_emptyinventory(Client *c, const Seperator *sep)
{
Client* t = c;
auto target = c;
if (c->GetGM() && c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
target = c->GetTarget()->CastToClient();
}
EQ::ItemInstance *item = nullptr;
uint32 removed_count = 0;
for (const int16& slot_id : t->GetInventorySlots()) {
item = t->GetInv().GetItem(slot_id);
if (item) {
uint32 stack_size = std::max(static_cast<uint32>(item->GetCharges()), static_cast<uint32>(1));
removed_count += stack_size;
t->DeleteItemInInventory(slot_id, 0, true);
static const int16 slots[][2] = {
{ EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END },
{ EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END },
{ EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END},
{ EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END },
{ EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END },
{ EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END },
{ EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END },
};
int removed_count = 0;
const size_t size = sizeof(slots) / sizeof(slots[0]);
for (int slot_index = 0; slot_index < size; ++slot_index) {
for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) {
item = target->GetInv().GetItem(slot_id);
if (item) {
int stack_size = std::max(static_cast<int>(item->GetCharges()), 1);
removed_count += stack_size;
target->DeleteItemInInventory(slot_id, 0, true);
}
}
}
@@ -25,8 +35,8 @@ void command_emptyinventory(Client *c, const Seperator *sep)
Chat::White,
fmt::format(
"{} {} no items to delete.",
c->GetTargetDescription(t, TargetDescriptionType::UCYou),
c == t ? "have" : "has"
c->GetTargetDescription(target, TargetDescriptionType::UCYou),
c == target ? "have" : "has"
).c_str()
);
return;
@@ -36,9 +46,9 @@ void command_emptyinventory(Client *c, const Seperator *sep)
Chat::White,
fmt::format(
"Inventory cleared for {}, {} item{} deleted.",
c->GetTargetDescription(t),
c->GetTargetDescription(target),
removed_count,
removed_count != 1 ? "s" : ""
).c_str()
);
}
}
-13
View File
@@ -1,7 +1,6 @@
#include "../client.h"
#include "find/aa.cpp"
#include "find/body_type.cpp"
#include "find/bot.cpp"
#include "find/bug_category.cpp"
#include "find/character.cpp"
#include "find/class.cpp"
@@ -12,7 +11,6 @@
#include "find/faction.cpp"
#include "find/item.cpp"
#include "find/language.cpp"
#include "find/ldon_theme.cpp"
#include "find/npctype.cpp"
#include "find/object_type.cpp"
#include "find/race.cpp"
@@ -49,7 +47,6 @@ void command_find(Client *c, const Seperator *sep)
Cmd{.cmd = "faction", .u = "faction [Search Criteria]", .fn = FindFaction, .a = {"#findfaction"}},
Cmd{.cmd = "item", .u = "item [Search Criteria]", .fn = FindItem, .a = {"#fi", "#finditem"}},
Cmd{.cmd = "language", .u = "language [Search Criteria]", .fn = FindLanguage, .a = {"#findlanguage"}},
Cmd{.cmd = "ldon_theme", .u = "ldon_theme [Search Criteria]", .fn = FindLDoNTheme, .a = {"#findldontheme"}},
Cmd{
.cmd = "npctype", .u = "npctype [Search Criteria]", .fn = FindNPCType, .a = {
"#fn",
@@ -68,16 +65,6 @@ void command_find(Client *c, const Seperator *sep)
Cmd{.cmd = "zone", .u = "zone [Search Criteria]", .fn = FindZone, .a = {"#fz", "#findzone"}},
};
if (RuleB(Bots, Enabled)) {
commands.emplace_back(
Cmd{.cmd = "bot", .u = "bot [Search Criteria]", .fn = FindBot, .a = {"#findbot"}}
);
std::sort(commands.begin(), commands.end(), [](const Cmd& a, const Cmd& b) {
return a.cmd < b.cmd;
});
}
// Check for arguments
const auto arguments = sep->argnum;
if (!arguments) {
-95
View File
@@ -1,95 +0,0 @@
#include "../../client.h"
#include "../../common/repositories/bot_data_repository.h"
void FindBot(Client *c, const Seperator *sep)
{
if (sep->IsNumber(2)) {
const auto bot_id = Strings::ToUnsignedInt(sep->arg[2]);
const auto& e = BotDataRepository::FindOne(content_db, bot_id);
if (!e.bot_id) {
c->Message(
Chat::White,
fmt::format(
"Bot ID {} does not exist or is invalid.",
bot_id
).c_str()
);
return;
}
c->Message(
Chat::White,
fmt::format(
"Bot ID {} | {}",
bot_id,
e.name
).c_str()
);
return;
}
const auto search_criteria = Strings::ToLower(sep->argplus[2]);
const auto& l = BotDataRepository::GetWhere(
content_db,
fmt::format(
"LOWER(`name`) LIKE '%%{}%%' AND `name` NOT LIKE '%-deleted-%' ORDER BY `bot_id` ASC LIMIT 50",
search_criteria
)
);
if (l.empty()) {
c->Message(
Chat::White,
fmt::format(
"No bots found matching '{}'.",
sep->argplus[2]
).c_str()
);
}
auto found_count = 0;
for (const auto& e : l) {
c->Message(
Chat::White,
fmt::format(
"Bot ID {} | {}",
Strings::Commify(e.bot_id),
e.name
).c_str()
);
found_count++;
if (found_count == 50) {
break;
}
}
if (found_count == 50) {
c->Message(
Chat::White,
fmt::format(
"50 Bots found matching '{}', max reached.",
sep->argplus[2]
).c_str()
);
return;
}
c->Message(
Chat::White,
fmt::format(
"{} Bot{} found matching '{}'.",
found_count,
found_count != 1 ? "s" : "",
sep->argplus[2]
).c_str()
);
}
+1 -1
View File
@@ -36,7 +36,7 @@ void FindCharacter(Client *c, const Seperator *sep)
const auto& l = CharacterDataRepository::GetWhere(
content_db,
fmt::format(
"LOWER(`name`) LIKE '%%{}%%' AND `name` NOT LIKE '%-deleted-%' ORDER BY `id` ASC LIMIT 50",
"LOWER(`name`) LIKE '%%{}%%' ORDER BY `id` ASC LIMIT 50",
search_criteria
)
);
+1 -1
View File
@@ -57,7 +57,7 @@ void FindClass(Client *c, const Seperator *sep)
(
IsPlayerClass(class_id) ?
fmt::format(
" ({})",
" | ({})",
Strings::Commify(GetPlayerClassBit(class_id))
) :
""
-65
View File
@@ -1,65 +0,0 @@
#include "../../client.h"
void FindLDoNTheme(Client *c, const Seperator *sep)
{
if (sep->IsNumber(2)) {
const uint32 theme_id = Strings::ToUnsignedInt(sep->arg[2]);
if (LDoNTheme::IsValid(theme_id)) {
c->Message(
Chat::White,
fmt::format(
"Theme {} | {} ({})",
theme_id,
LDoNTheme::GetName(theme_id),
LDoNTheme::GetBitmask(theme_id)
).c_str()
);
return;
}
c->Message(
Chat::White,
fmt::format(
"Theme ID {} was not found.",
theme_id
).c_str()
);
return;
}
const std::string& search_criteria = Strings::ToLower(sep->argplus[2]);
uint32 found_count = 0;
for (const auto& l : ldon_theme_names) {
const std::string& ldon_theme_name_lower = Strings::ToLower(l.second.first);
if (!Strings::Contains(ldon_theme_name_lower, search_criteria)) {
continue;
}
c->Message(
Chat::White,
fmt::format(
"Theme {} | {} ({})",
l.first,
l.second.first,
l.second.second
).c_str()
);
found_count++;
}
c->Message(
Chat::White,
fmt::format(
"{} Theme{} found matching '{}'.",
found_count,
found_count != 1 ? "s" : "",
sep->argplus[2]
).c_str()
);
}
+13 -15
View File
@@ -3,21 +3,20 @@
void SetAdventurePoints(Client *c, const Seperator *sep)
{
const uint16 arguments = sep->argnum;
const auto arguments = sep->argnum;
if (arguments < 3 || !sep->IsNumber(2) || !sep->IsNumber(3)) {
c->Message(Chat::White, "Usage: #set adventure_points [Theme] [Points]");
c->Message(Chat::White, "Valid themes are as follows:");
for (const auto& e : ldon_theme_names) {
if (e.first != LDoNTheme::Unused) {
for (const auto& e : EQ::constants::GetLDoNThemeMap()) {
if (e.first != LDoNThemes::Unused) {
c->Message(
Chat::White,
fmt::format(
"Theme {} | {} ({})",
"Theme {} | {}",
e.first,
e.second.first,
e.second.second
e.second
).c_str()
);
}
@@ -26,26 +25,25 @@ void SetAdventurePoints(Client *c, const Seperator *sep)
return;
}
Client* t = c;
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
const uint32 theme_id = Strings::ToUnsignedInt(sep->arg[2]);
const uint32 points = Strings::ToUnsignedInt(sep->arg[3]);
const uint32 points = Strings::ToUnsignedInt(sep->arg[3]);
if (!LDoNTheme::IsValid(theme_id)) {
if (!EQ::ValueWithin(theme_id, LDoNThemes::GUK, LDoNThemes::TAK)) {
c->Message(Chat::White, "Valid themes are as follows:");
for (const auto& e : ldon_theme_names) {
if (e.first != LDoNTheme::Unused) {
for (const auto& e : EQ::constants::GetLDoNThemeMap()) {
if (e.first != LDoNThemes::Unused) {
c->Message(
Chat::White,
fmt::format(
"Theme {} | {} ({})",
"Theme {} | {}",
e.first,
e.second.first,
e.second.second
e.second
).c_str()
);
}
@@ -58,7 +56,7 @@ void SetAdventurePoints(Client *c, const Seperator *sep)
Chat::White,
fmt::format(
"Set {} Points to {} for {}.",
LDoNTheme::GetName(theme_id),
EQ::constants::GetLDoNThemeName(theme_id),
Strings::Commify(points),
c->GetTargetDescription(t)
).c_str()
+2 -2
View File
@@ -89,11 +89,11 @@ void ShowCurrencies(Client *c, const Seperator *sep)
}
}
for (const auto& l : ldon_theme_names) {
for (const auto& l : EQ::constants::GetLDoNThemeMap()) {
const uint32 ldon_currency_value = t->GetLDoNPointsTheme(l.first);
if (ldon_currency_value) {
currency_table += DialogueWindow::TableRow(
DialogueWindow::TableCell(l.second.first) +
DialogueWindow::TableCell(l.second) +
DialogueWindow::TableCell(Strings::Commify(ldon_currency_value))
);
+4 -4
View File
@@ -310,7 +310,7 @@ void ShowInventory(Client *c, const Seperator *sep)
Chat::White,
fmt::format(
"Slot {} | {} ({}){}",
(8000 + limboIndex),
(14000 + limboIndex),
item_data->ID,
linker.GenerateLink(),
(
@@ -339,7 +339,7 @@ void ShowInventory(Client *c, const Seperator *sep)
Chat::White,
fmt::format(
"Slot {} (Augment Slot {}) | {} ({}){}",
(8000 + limboIndex),
(14000 + limboIndex),
augment_index,
linker.GenerateLink(),
item_data->ID,
@@ -375,7 +375,7 @@ void ShowInventory(Client *c, const Seperator *sep)
Chat::White,
fmt::format(
"Slot {} Bag Slot {} | {} ({}){}",
(8000 + limboIndex),
(14000 + limboIndex),
sub_index,
linker.GenerateLink(),
item_data->ID,
@@ -407,7 +407,7 @@ void ShowInventory(Client *c, const Seperator *sep)
Chat::White,
fmt::format(
"Slot {} Bag Slot {} (Augment Slot {}) | {} ({}){}",
(8000 + limboIndex),
(14000 + limboIndex),
sub_index,
augment_index,
linker.GenerateLink(),
+1 -1
View File
@@ -2419,7 +2419,7 @@ bool Group::AmIMainAssist(const char *mob_name)
if (!mob_name)
return false;
return !((bool)MainAssistName.compare(mob_name));
return !((bool)MainTankName.compare(mob_name));
}
bool Group::AmIPuller(const char *mob_name)
+2
View File
@@ -63,6 +63,7 @@ public:
void AddMember(const std::string& new_member_name);
void SendUpdate(uint32 type,Mob* member);
void SendLeadershipAAUpdate();
void SendWorldGroup(uint32 zone_id,Mob* zoningmember);
bool DelMemberOOZ(const char *Name);
bool DelMember(Mob* oldmember,bool ignoresender = false);
void DisbandGroup(bool joinraid = false);
@@ -72,6 +73,7 @@ public:
bool IsGroupMember(Mob* c);
bool IsGroupMember(const char* name);
bool Process();
bool IsGroup() { return true; }
void SendGroupJoinOOZ(Mob* NewMember);
void CastGroupSpell(Mob* caster,uint16 spellid);
void SplitExp(ExpSource exp_source, const uint64 exp, Mob* other);
+1 -1
View File
@@ -83,9 +83,9 @@ public:
void SendRankName(uint32 guild_id, uint32 rank, std::string rank_name);
void SendAllRankNames(uint32 guild_id, uint32 char_id);
BaseGuildManager::GuildInfo* GetGuildByGuildID(uint32 guild_id);
virtual void SendGuildRefresh(uint32 guild_id, bool name, bool motd, bool rank, bool relation);
protected:
virtual void SendGuildRefresh(uint32 guild_id, bool name, bool motd, bool rank, bool relation);
virtual void SendCharRefresh(uint32 old_guild_id, uint32 guild_id, uint32 charid);
virtual void SendRankUpdate(uint32 CharID);
virtual void SendGuildDelete(uint32 guild_id);
+40 -14
View File
@@ -1909,13 +1909,20 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
return false;
}
//verify shared bank transactions in the database
if (src_inst && src_slot_id >= EQ::invslot::SHARED_BANK_BEGIN && src_slot_id <= EQ::invbag::SHARED_BANK_BAGS_END) {
if (
src_inst &&
(
EQ::ValueWithin(src_slot_id, EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END) ||
EQ::ValueWithin(src_slot_id, EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END)
)
) {
if(!database.VerifyInventory(account_id, src_slot_id, src_inst)) {
LogError("Player [{}] on account [{}] was found exploiting the shared bank.\n", GetName(), account_name);
DeleteItemInInventory(dst_slot_id,0,true);
return(false);
}
if (src_slot_id >= EQ::invslot::SHARED_BANK_BEGIN && src_slot_id <= EQ::invslot::SHARED_BANK_END && src_inst->IsClassBag()){
if (EQ::ValueWithin(src_slot_id, EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END) && src_inst->IsClassBag()){
for (uint8 idx = EQ::invbag::SLOT_BEGIN; idx <= EQ::invbag::SLOT_END; idx++) {
const EQ::ItemInstance* baginst = src_inst->GetItem(idx);
if (baginst && !database.VerifyInventory(account_id, EQ::InventoryProfile::CalcSlotId(src_slot_id, idx), baginst)){
@@ -1924,13 +1931,21 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
}
}
}
if (dst_inst && dst_slot_id >= EQ::invslot::SHARED_BANK_BEGIN && dst_slot_id <= EQ::invbag::SHARED_BANK_BAGS_END) {
if (
dst_inst &&
(
EQ::ValueWithin(dst_slot_id, EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END) ||
EQ::ValueWithin(dst_slot_id, EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END)
)
) {
if(!database.VerifyInventory(account_id, dst_slot_id, dst_inst)) {
LogError("Player [{}] on account [{}] was found exploting the shared bank.\n", GetName(), account_name);
DeleteItemInInventory(src_slot_id,0,true);
return(false);
}
if (dst_slot_id >= EQ::invslot::SHARED_BANK_BEGIN && dst_slot_id <= EQ::invslot::SHARED_BANK_END && dst_inst->IsClassBag()){
if (EQ::ValueWithin(dst_slot_id, EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END) && dst_inst->IsClassBag()){
for (uint8 idx = EQ::invbag::SLOT_BEGIN; idx <= EQ::invbag::SLOT_END; idx++) {
const EQ::ItemInstance* baginst = dst_inst->GetItem(idx);
if (baginst && !database.VerifyInventory(account_id, EQ::InventoryProfile::CalcSlotId(dst_slot_id, idx), baginst)){
@@ -1943,10 +1958,20 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
// Check for No Drop Hacks
Mob* with = trade->With();
if (((with && with->IsClient() && !with->CastToClient()->IsBecomeNPC() && dst_slot_id >= EQ::invslot::TRADE_BEGIN && dst_slot_id <= EQ::invslot::TRADE_END) ||
(dst_slot_id >= EQ::invslot::SHARED_BANK_BEGIN && dst_slot_id <= EQ::invbag::SHARED_BANK_BAGS_END))
&& GetInv().CheckNoDrop(src_slot_id)
&& !CanTradeFVNoDropItem()) {
if (
(
(
with &&
with->IsClient() &&
!with->CastToClient()->IsBecomeNPC() &&
EQ::ValueWithin(dst_slot_id, EQ::invslot::TRADE_BEGIN, EQ::invslot::TRADE_END)
) ||
EQ::ValueWithin(dst_slot_id, EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END) ||
EQ::ValueWithin(dst_slot_id, EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END)
) &&
GetInv().CheckNoDrop(src_slot_id) &&
!CanTradeFVNoDropItem()
) {
auto ndh_inst = m_inv[src_slot_id];
std::string ndh_item_data;
if (ndh_inst == nullptr) {
@@ -3641,7 +3666,7 @@ bool Client::InterrogateInventory(Client* requester, bool log, bool silent, bool
if (cursor_itr == m_inv.cursor_cbegin())
continue;
instmap[8000 + limbo] = *cursor_itr;
instmap[EQ::invbag::CURSOR_BAG_BEGIN + limbo] = *cursor_itr;
}
// call InterrogateInventory_ for error check
@@ -3744,11 +3769,12 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const EQ::ItemI
// very basic error checking - can be elaborated upon if more in-depth testing is needed...
if (
(head >= EQ::invslot::EQUIPMENT_BEGIN && head <= EQ::invslot::EQUIPMENT_END) ||
(head >= EQ::invslot::TRIBUTE_BEGIN && head <= EQ::invslot::TRIBUTE_END) ||
(head >= EQ::invslot::GUILD_TRIBUTE_BEGIN && head <= EQ::invslot::GUILD_TRIBUTE_END) ||
(head >= EQ::invslot::WORLD_BEGIN && head <= EQ::invslot::WORLD_END) ||
(head >= 8000 && head <= 8101)) {
EQ::ValueWithin(head, EQ::invslot::EQUIPMENT_BEGIN, EQ::invslot::EQUIPMENT_END) ||
EQ::ValueWithin(head, EQ::invslot::TRIBUTE_BEGIN, EQ::invslot::TRIBUTE_END) ||
EQ::ValueWithin(head, EQ::invslot::GUILD_TRIBUTE_BEGIN, EQ::invslot::GUILD_TRIBUTE_END) ||
EQ::ValueWithin(head, EQ::invslot::WORLD_BEGIN, EQ::invslot::WORLD_END) ||
EQ::ValueWithin(head, EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END)
) {
switch (depth)
{
case 0: // requirement: inst is extant
+2 -2
View File
@@ -859,9 +859,9 @@ bool NPC::HasItem(uint32 item_id)
return false;
}
uint32 NPC::CountItem(uint32 item_id)
uint16 NPC::CountItem(uint32 item_id)
{
uint32 item_count = 0;
uint16 item_count = 0;
if (!database.GetItem(item_id)) {
return item_count;
}
+3 -4
View File
@@ -274,7 +274,7 @@ void Lua_Bot::SetSpellDurationRaid(int spell_id, int duration, int level, bool a
self->SetSpellDuration(spell_id, duration, level, ApplySpellType::Raid, allow_pets, is_raid_group_only);
}
uint32 Lua_Bot::CountAugmentEquippedByID(uint32 item_id) {
int Lua_Bot::CountAugmentEquippedByID(uint32 item_id) {
Lua_Safe_Call_Int();
return self->GetInv().CountAugmentEquippedByID(item_id);
}
@@ -284,7 +284,7 @@ bool Lua_Bot::HasAugmentEquippedByID(uint32 item_id) {
return self->GetInv().HasAugmentEquippedByID(item_id);
}
uint32 Lua_Bot::CountItemEquippedByID(uint32 item_id) {
int Lua_Bot::CountItemEquippedByID(uint32 item_id) {
Lua_Safe_Call_Int();
return self->GetInv().CountItemEquippedByID(item_id);
}
@@ -701,9 +701,8 @@ luabind::scope lua_register_bot() {
.def("ClearItemReuseTimer", (void(Lua_Bot::*)(uint32))&Lua_Bot::ClearItemReuseTimer)
.def("ClearSpellRecastTimer", (void(Lua_Bot::*)())&Lua_Bot::ClearSpellRecastTimer)
.def("ClearSpellRecastTimer", (void(Lua_Bot::*)(uint16))&Lua_Bot::ClearSpellRecastTimer)
.def("CountAugmentEquippedByID", (uint32(Lua_Bot::*)(uint32))&Lua_Bot::CountAugmentEquippedByID)
.def("CountBotItem", (uint32(Lua_Bot::*)(uint32))&Lua_Bot::CountBotItem)
.def("CountItemEquippedByID", (uint32(Lua_Bot::*)(uint32))&Lua_Bot::CountItemEquippedByID)
.def("CountItemEquippedByID", (int(Lua_Bot::*)(uint32))&Lua_Bot::CountItemEquippedByID)
.def("DeleteBot", (void(Lua_Bot::*)(void))&Lua_Bot::DeleteBot)
.def("DeleteBucket", (void(Lua_Bot::*)(std::string))&Lua_Bot::DeleteBucket)
.def("Escape", (void(Lua_Bot::*)(void))&Lua_Bot::Escape)
+2 -2
View File
@@ -127,8 +127,8 @@ public:
void SetSpellRecastTimer(uint16 spell_id);
void SetSpellRecastTimer(uint16 spell_id, uint32 reuse_timer);
uint32 CountAugmentEquippedByID(uint32 item_id);
uint32 CountItemEquippedByID(uint32 item_id);
int CountAugmentEquippedByID(uint32 item_id);
int CountItemEquippedByID(uint32 item_id);
bool HasAugmentEquippedByID(uint32 item_id);
bool HasItemEquippedByID(uint32 item_id);
int GetHealAmount();
+6 -22
View File
@@ -2287,7 +2287,7 @@ void Lua_Client::SendToInstance(std::string instance_type, std::string zone_shor
self->SendToInstance(instance_type, zone_short_name, instance_version, x, y, z, heading, instance_identifier, duration);
}
uint32 Lua_Client::CountItem(uint32 item_id) {
int Lua_Client::CountItem(uint32 item_id) {
Lua_Safe_Call_Int();
return self->CountItem(item_id);
}
@@ -2480,7 +2480,7 @@ void Lua_Client::AddItem(luabind::object item_table) {
);
}
uint32 Lua_Client::CountAugmentEquippedByID(uint32 item_id) {
int Lua_Client::CountAugmentEquippedByID(uint32 item_id) {
Lua_Safe_Call_Int();
return self->GetInv().CountAugmentEquippedByID(item_id);
}
@@ -2490,7 +2490,7 @@ bool Lua_Client::HasAugmentEquippedByID(uint32 item_id) {
return self->GetInv().HasAugmentEquippedByID(item_id);
}
uint32 Lua_Client::CountItemEquippedByID(uint32 item_id) {
int Lua_Client::CountItemEquippedByID(uint32 item_id) {
Lua_Safe_Call_Int();
return self->GetInv().CountItemEquippedByID(item_id);
}
@@ -3436,21 +3436,6 @@ void Lua_Client::AreaTaunt(float range, int bonus_hate)
entity_list.AETaunt(self, range, bonus_hate);
}
luabind::object Lua_Client::GetInventorySlots(lua_State* L) {
auto lua_table = luabind::newtable(L);
if (d_) {
auto self = reinterpret_cast<NativeType*>(d_);
int index = 1;
for (const int16& slot_id : self->GetInventorySlots()) {
lua_table[index] = slot_id;
index++;
}
}
return lua_table;
}
luabind::scope lua_register_client() {
return luabind::class_<Lua_Client, Lua_Mob>("Client")
.def(luabind::constructor<>())
@@ -3529,9 +3514,9 @@ luabind::scope lua_register_client() {
.def("ClearXTargets", (void(Lua_Client::*)(void))&Lua_Client::ClearXTargets)
.def("ClearZoneFlag", (void(Lua_Client::*)(uint32))&Lua_Client::ClearZoneFlag)
.def("Connected", (bool(Lua_Client::*)(void))&Lua_Client::Connected)
.def("CountAugmentEquippedByID", (uint32(Lua_Client::*)(uint32))&Lua_Client::CountAugmentEquippedByID)
.def("CountItem", (uint32(Lua_Client::*)(uint32))&Lua_Client::CountItem)
.def("CountItemEquippedByID", (uint32(Lua_Client::*)(uint32))&Lua_Client::CountItemEquippedByID)
.def("CountAugmentEquippedByID", (int(Lua_Client::*)(uint32))&Lua_Client::CountAugmentEquippedByID)
.def("CountItem", (int(Lua_Client::*)(uint32))&Lua_Client::CountItem)
.def("CountItemEquippedByID", (int(Lua_Client::*)(uint32))&Lua_Client::CountItemEquippedByID)
.def("CreateExpedition", (Lua_Expedition(Lua_Client::*)(luabind::object))&Lua_Client::CreateExpedition)
.def("CreateExpedition", (Lua_Expedition(Lua_Client::*)(std::string, uint32, uint32, std::string, uint32, uint32))&Lua_Client::CreateExpedition)
.def("CreateExpedition", (Lua_Expedition(Lua_Client::*)(std::string, uint32, uint32, std::string, uint32, uint32, bool))&Lua_Client::CreateExpedition)
@@ -3665,7 +3650,6 @@ luabind::scope lua_register_client() {
.def("GetInstrumentMod", (int(Lua_Client::*)(int))&Lua_Client::GetInstrumentMod)
.def("GetIntoxication", (int(Lua_Client::*)(void))&Lua_Client::GetIntoxication)
.def("GetInventory", (Lua_Inventory(Lua_Client::*)(void))&Lua_Client::GetInventory)
.def("GetInventorySlots", (luabind::object(Lua_Client::*)(lua_State* L))&Lua_Client::GetInventorySlots)
.def("GetInvulnerableEnvironmentDamage", (bool(Lua_Client::*)(void))&Lua_Client::GetInvulnerableEnvironmentDamage)
.def("GetItemIDAt", (int(Lua_Client::*)(int))&Lua_Client::GetItemIDAt)
.def("GetItemCooldown", (uint32(Lua_Client::*)(uint32))&Lua_Client::GetItemCooldown)
+3 -4
View File
@@ -441,14 +441,14 @@ public:
void Popup(const char* title, const char* text, uint32 popup_id, uint32 negative_id, uint32 button_type, uint32 duration);
void Popup(const char* title, const char* text, uint32 popup_id, uint32 negative_id, uint32 button_type, uint32 duration, const char* button_name_one, const char* button_name_two);
void Popup(const char* title, const char* text, uint32 popup_id, uint32 negative_id, uint32 button_type, uint32 duration, const char* button_name_one, const char* button_name_two, uint32 sound_controls);
uint32 CountItem(uint32 item_id);
int CountItem(uint32 item_id);
void RemoveItem(uint32 item_id);
void RemoveItem(uint32 item_id, uint32 quantity);
void SetGMStatus(int new_status);
int16 GetGMStatus();
void AddItem(luabind::object item_table);
uint32 CountAugmentEquippedByID(uint32 item_id);
uint32 CountItemEquippedByID(uint32 item_id);
int CountAugmentEquippedByID(uint32 item_id);
int CountItemEquippedByID(uint32 item_id);
bool HasAugmentEquippedByID(uint32 item_id);
bool HasItemEquippedByID(uint32 item_id);
int GetHealAmount();
@@ -509,7 +509,6 @@ public:
void AreaTaunt();
void AreaTaunt(float range);
void AreaTaunt(float range, int bonus_hate);
luabind::object GetInventorySlots(lua_State* L);
void ApplySpell(int spell_id);
void ApplySpell(int spell_id, int duration);
+2 -2
View File
@@ -177,7 +177,7 @@ bool Lua_Corpse::HasItem(uint32 item_id) {
return self->HasItem(item_id);
}
uint32 Lua_Corpse::CountItem(uint32 item_id) {
uint16 Lua_Corpse::CountItem(uint32 item_id) {
Lua_Safe_Call_Int();
return self->CountItem(item_id);
}
@@ -226,7 +226,7 @@ luabind::scope lua_register_corpse() {
.def("AllowMobLoot", (void(Lua_Corpse::*)(Lua_Mob, uint8))&Lua_Corpse::AllowMobLoot)
.def("Bury", (void(Lua_Corpse::*)(void))&Lua_Corpse::Bury)
.def("CanMobLoot", (bool(Lua_Corpse::*)(int))&Lua_Corpse::CanMobLoot)
.def("CountItem", (uint32(Lua_Corpse::*)(uint32))&Lua_Corpse::CountItem)
.def("CountItem", (uint16(Lua_Corpse::*)(uint32))&Lua_Corpse::CountItem)
.def("CountItems", (uint32(Lua_Corpse::*)(void))&Lua_Corpse::CountItems)
.def("Delete", (void(Lua_Corpse::*)(void))&Lua_Corpse::Delete)
.def("Depop", (void(Lua_Corpse::*)(void))&Lua_Corpse::Depop)
+1 -1
View File
@@ -62,7 +62,7 @@ public:
uint32 GetPlatinum();
void AddLooter(Lua_Mob who);
bool HasItem(uint32 item_id);
uint32 CountItem(uint32 item_id);
uint16 CountItem(uint32 item_id);
uint32 GetItemIDBySlot(uint16 loot_slot);
uint16 GetFirstLootSlotByItemID(uint32 item_id);
Lua_Corpse_Loot_List GetLootList(lua_State* L);
+4 -4
View File
@@ -164,7 +164,7 @@ int Lua_Inventory::GetSlotByItemInst(Lua_ItemInst inst) {
return self->GetSlotByItemInst(inst);
}
uint32 Lua_Inventory::CountAugmentEquippedByID(uint32 item_id) {
int Lua_Inventory::CountAugmentEquippedByID(uint32 item_id) {
Lua_Safe_Call_Int();
return self->CountAugmentEquippedByID(item_id);
}
@@ -174,7 +174,7 @@ bool Lua_Inventory::HasAugmentEquippedByID(uint32 item_id) {
return self->HasAugmentEquippedByID(item_id);
}
uint32 Lua_Inventory::CountItemEquippedByID(uint32 item_id) {
int Lua_Inventory::CountItemEquippedByID(uint32 item_id) {
Lua_Safe_Call_Int();
return self->CountItemEquippedByID(item_id);
}
@@ -208,8 +208,8 @@ luabind::scope lua_register_inventory() {
.def("CalcSlotId", (int(Lua_Inventory::*)(int,int))&Lua_Inventory::CalcSlotId)
.def("CanItemFitInContainer", (bool(Lua_Inventory::*)(Lua_Item,Lua_Item))&Lua_Inventory::CanItemFitInContainer)
.def("CheckNoDrop", (bool(Lua_Inventory::*)(int))&Lua_Inventory::CheckNoDrop)
.def("CountAugmentEquippedByID", (uint32(Lua_Inventory::*)(uint32))&Lua_Inventory::CountAugmentEquippedByID)
.def("CountItemEquippedByID", (uint32(Lua_Inventory::*)(uint32))&Lua_Inventory::CountItemEquippedByID)
.def("CountAugmentEquippedByID", (int(Lua_Inventory::*)(uint32))&Lua_Inventory::CountAugmentEquippedByID)
.def("CountItemEquippedByID", (int(Lua_Inventory::*)(uint32))&Lua_Inventory::CountItemEquippedByID)
.def("DeleteItem", (bool(Lua_Inventory::*)(int))&Lua_Inventory::DeleteItem)
.def("DeleteItem", (bool(Lua_Inventory::*)(int,int))&Lua_Inventory::DeleteItem)
.def("FindFreeSlot", (int(Lua_Inventory::*)(bool,bool))&Lua_Inventory::FindFreeSlot)
+2 -2
View File
@@ -43,8 +43,8 @@ public:
bool DeleteItem(int slot_id);
bool DeleteItem(int slot_id, int quantity);
bool CheckNoDrop(int slot_id);
uint32 CountAugmentEquippedByID(uint32 item_id);
uint32 CountItemEquippedByID(uint32 item_id);
int CountAugmentEquippedByID(uint32 item_id);
int CountItemEquippedByID(uint32 item_id);
Lua_ItemInst PopItem(int slot_id);
bool HasAugmentEquippedByID(uint32 item_id);
bool HasItemEquippedByID(uint32 item_id);
+2 -2
View File
@@ -597,7 +597,7 @@ bool Lua_NPC::HasItem(uint32 item_id)
return self->HasItem(item_id);
}
uint32 Lua_NPC::CountItem(uint32 item_id)
uint16 Lua_NPC::CountItem(uint32 item_id)
{
Lua_Safe_Call_Int();
return self->CountItem(item_id);
@@ -862,7 +862,7 @@ luabind::scope lua_register_npc() {
.def("CheckNPCFactionAlly", (int(Lua_NPC::*)(int))&Lua_NPC::CheckNPCFactionAlly)
.def("ClearItemList", (void(Lua_NPC::*)(void))&Lua_NPC::ClearLootItems)
.def("ClearLastName", (void(Lua_NPC::*)(void))&Lua_NPC::ClearLastName)
.def("CountItem", (uint32(Lua_NPC::*)(uint32))&Lua_NPC::CountItem)
.def("CountItem", (uint16(Lua_NPC::*)(uint32))&Lua_NPC::CountItem)
.def("CountLoot", (int(Lua_NPC::*)(void))&Lua_NPC::CountLoot)
.def("DeleteBucket", (void(Lua_NPC::*)(std::string))&Lua_NPC::DeleteBucket)
.def("DescribeSpecialAbilities", (void(Lua_NPC::*)(Lua_Client))&Lua_NPC::DescribeSpecialAbilities)
+1 -1
View File
@@ -146,7 +146,7 @@ public:
void ChangeLastName(std::string last_name);
void ClearLastName();
bool HasItem(uint32 item_id);
uint32 CountItem(uint32 item_id);
uint16 CountItem(uint32 item_id);
uint32 GetLootItemIDBySlot(uint16 loot_slot);
uint16 GetFirstLootSlotByItemID(uint32 item_id);
float GetHealScale();
+5 -5
View File
@@ -320,7 +320,7 @@ bool Map::Load(const std::string &filename)
}
#ifdef USE_MAP_MMFS
if (loaded_map_file)
if (v)
return SaveMMF(filename, force_mmf_overwrite);
#endif /*USE_MAP_MMFS*/
@@ -338,7 +338,7 @@ bool Map::Load(const std::string &filename)
}
#ifdef USE_MAP_MMFS
if (loaded_map_file)
if (v)
return SaveMMF(filename, force_mmf_overwrite);
#endif /*USE_MAP_MMFS*/
@@ -1064,7 +1064,7 @@ bool Map::LoadMMF(const std::string& map_file_name, bool force_mmf_overwrite)
fclose(f);
std::vector<char> rm_buffer(rm_buffer_size);
uint32 v = EQ::InflateData(mmf_buffer.data(), mmf_buffer_size, rm_buffer.data(), rm_buffer_size);
uint32 v = InflateData(mmf_buffer.data(), mmf_buffer_size, rm_buffer.data(), rm_buffer_size);
if (imp) {
imp->rm->release();
@@ -1120,11 +1120,11 @@ bool Map::SaveMMF(const std::string& map_file_name, bool force_mmf_overwrite)
}
uint32 rm_buffer_size = rm_buffer.size();
uint32 mmf_buffer_size = EQ::EstimateDeflateBuffer(rm_buffer.size());
uint32 mmf_buffer_size = EstimateDeflateBuffer(rm_buffer.size());
std::vector<char> mmf_buffer(mmf_buffer_size);
mmf_buffer_size = EQ::DeflateData(rm_buffer.data(), rm_buffer.size(), mmf_buffer.data(), mmf_buffer.size());
mmf_buffer_size = DeflateData(rm_buffer.data(), rm_buffer.size(), mmf_buffer.data(), mmf_buffer.size());
if (!mmf_buffer_size) {
LogInfo("Failed to save Map MMF file: [{}] - null MMF buffer size", mmf_file_name.c_str());
return false;
+32 -45
View File
@@ -572,8 +572,6 @@ Mob::~Mob()
m_close_mobs.clear();
ClearDataBucketCache();
LeaveHealRotationTargetPool();
}
@@ -2050,19 +2048,19 @@ void Mob::SendStatsWindow(Client* c, bool use_window)
case 0: {
mod2a_name = "Avoidance";
mod2b_name = "Combat Effects";
mod2a_cap = RuleI(Character, ItemAvoidanceCap);
mod2b_cap = RuleI(Character, ItemCombatEffectsCap);
mod2a_cap = Strings::Commify(RuleI(Character, ItemAvoidanceCap));
mod2b_cap = Strings::Commify(RuleI(Character, ItemCombatEffectsCap));
if (IsBot()) {
mod2a = CastToBot()->GetAvoidance();
mod2a = Strings::Commify(CastToBot()->GetAvoidance());
} else if (IsClient()) {
mod2a = CastToClient()->GetAvoidance();
mod2a = Strings::Commify(CastToClient()->GetAvoidance());
}
if (IsBot()) {
mod2b = CastToBot()->GetCombatEffects();
mod2b = Strings::Commify(CastToBot()->GetCombatEffects());
} else if (IsClient()) {
mod2b = CastToClient()->GetCombatEffects();
mod2b = Strings::Commify(CastToClient()->GetCombatEffects());
}
break;
@@ -2070,19 +2068,19 @@ void Mob::SendStatsWindow(Client* c, bool use_window)
case 1: {
mod2a_name = "Accuracy";
mod2b_name = "Strikethrough";
mod2a_cap = RuleI(Character, ItemAccuracyCap);
mod2b_cap = RuleI(Character, ItemStrikethroughCap);
mod2a_cap = Strings::Commify(RuleI(Character, ItemAccuracyCap));
mod2b_cap = Strings::Commify(RuleI(Character, ItemStrikethroughCap));
if (IsBot()) {
mod2a = CastToBot()->GetAccuracy();
mod2a = Strings::Commify(CastToBot()->GetAccuracy());
} else if (IsClient()) {
mod2a = CastToClient()->GetAccuracy();
mod2a = Strings::Commify(CastToClient()->GetAccuracy());
}
if (IsBot()) {
mod2b = CastToBot()->GetStrikeThrough();
mod2b = Strings::Commify(CastToBot()->GetStrikeThrough());
} else if (IsClient()) {
mod2b = CastToClient()->GetStrikeThrough();
mod2b = Strings::Commify(CastToClient()->GetStrikeThrough());
}
break;
@@ -2090,20 +2088,20 @@ void Mob::SendStatsWindow(Client* c, bool use_window)
case 2: {
mod2a_name = "Shielding";
mod2b_name = "Spell Shielding";
mod2a_cap = RuleI(Character, ItemShieldingCap);
mod2b_cap = RuleI(Character, ItemSpellShieldingCap);
mod2a_cap = Strings::Commify(RuleI(Character, ItemShieldingCap));
mod2b_cap = Strings::Commify(RuleI(Character, ItemSpellShieldingCap));
if (IsBot()) {
mod2a = CastToBot()->GetShielding();
mod2a = Strings::Commify(CastToBot()->GetShielding());
} else if (IsClient()) {
mod2a = CastToClient()->GetShielding();
mod2a = Strings::Commify(CastToClient()->GetShielding());
}
if (IsBot()) {
mod2b = CastToBot()->GetSpellShield();
mod2b = Strings::Commify(CastToBot()->GetSpellShield());
} else if (IsClient()) {
mod2b = CastToClient()->GetSpellShield();
mod2b = Strings::Commify(CastToClient()->GetSpellShield());
}
break;
@@ -2111,19 +2109,19 @@ void Mob::SendStatsWindow(Client* c, bool use_window)
case 3: {
mod2a_name = "Stun Resist";
mod2b_name = "DOT Shielding";
mod2a_cap = RuleI(Character, ItemStunResistCap);
mod2b_cap = RuleI(Character, ItemDoTShieldingCap);
mod2a_cap = Strings::Commify(RuleI(Character, ItemStunResistCap));
mod2b_cap = Strings::Commify(RuleI(Character, ItemDoTShieldingCap));
if (IsBot()) {
mod2a = CastToBot()->GetStunResist();
mod2a = Strings::Commify(CastToBot()->GetStunResist());
} else if (IsClient()) {
mod2a = CastToClient()->GetStunResist();
mod2a = Strings::Commify(CastToClient()->GetStunResist());
}
if (IsBot()) {
mod2b = CastToBot()->GetDoTShield();
mod2b = Strings::Commify(CastToBot()->GetDoTShield());
} else if (IsClient()) {
mod2b = CastToClient()->GetDoTShield();
mod2b = Strings::Commify(CastToClient()->GetDoTShield());
}
break;
@@ -5327,7 +5325,14 @@ void Mob::ExecWeaponProc(const EQ::ItemInstance* inst, uint16 spell_id, Mob* on,
//It should be safe as we don't have any truly const EQ::ItemInstance floating around anywhere.
//So we'll live with it for now
if (parse->ItemHasQuestSub(const_cast<EQ::ItemInstance*>(inst), EVENT_WEAPON_PROC)) {
int i = parse->EventItem(EVENT_WEAPON_PROC, CastToClient(), const_cast<EQ::ItemInstance*>(inst), on, "", spell_id);
int i = parse->EventItem(
EVENT_WEAPON_PROC,
CastToClient(),
const_cast<EQ::ItemInstance*>(inst),
on,
"",
spell_id
);
if (i != 0) {
return;
@@ -8608,21 +8613,3 @@ std::unordered_map<uint16, Mob *> &Mob::GetCloseMobList(float distance)
{
return entity_list.GetCloseMobList(this, distance);
}
void Mob::ClearDataBucketCache()
{
if (IsOfClientBot()) {
uint64 id = 0;
DataBucketLoadType::Type t{};
if (IsBot()) {
id = CastToBot()->GetBotID();
t = DataBucketLoadType::Bot;
}
else if (IsClient()) {
id = CastToClient()->CharacterID();
t = DataBucketLoadType::Client;
}
DataBucket::DeleteFromCache(id, t);
}
}
-2
View File
@@ -1491,8 +1491,6 @@ public:
std::unordered_map<uint16, Mob *> &GetCloseMobList(float distance = 0.0f);
void CheckScanCloseMobsMovingTimer();
void ClearDataBucketCache();
protected:
void CommonDamage(Mob* other, int64 &damage, const uint16 spell_id, const EQ::skills::SkillType attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic, eSpecialAttacks specal = eSpecialAttacks::None);
static uint16 GetProcID(uint16 spell_id, uint8 effect_index);
+3 -11
View File
@@ -1815,18 +1815,12 @@ void Mob::AI_Event_NoLongerEngaged() {
StopNavigation();
ClearRampage();
parse->EventBotMercNPC(EVENT_COMBAT, this, nullptr, [&]() { return "0"; });
if (IsNPC()) {
SetPrimaryAggro(false);
SetAssistAggro(false);
if (
CastToNPC()->GetCombatEvent() &&
GetHP() > 0 &&
entity_list.GetNPCByID(GetID())
) {
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_COMBAT)) {
parse->EventNPC(EVENT_COMBAT, CastToNPC(), nullptr, "0", 0);
}
if (CastToNPC()->GetCombatEvent() && GetHP() > 0) {
const uint32 emote_id = CastToNPC()->GetEmoteID();
if (emote_id) {
CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::LeaveCombat, emote_id);
@@ -1835,8 +1829,6 @@ void Mob::AI_Event_NoLongerEngaged() {
m_combat_record.Stop();
CastToNPC()->SetCombatEvent(false);
}
} else {
parse->EventBotMerc(EVENT_COMBAT, this, nullptr, [&]() { return "0"; });
}
}
+8 -34
View File
@@ -3297,28 +3297,16 @@ uint32 NPC::GetSpawnKillCount()
return(0);
}
void NPC::DoQuestPause(Mob* m)
{
if (!m) {
return;
}
if (IsMoving() && !IsOnHatelist(m)) {
void NPC::DoQuestPause(Mob *other) {
if(IsMoving() && !IsOnHatelist(other)) {
PauseWandering(RuleI(NPC, SayPauseTimeInSec));
if (FacesTarget() && !m->sneaking) {
FaceTarget(m);
}
} else if (!IsMoving()) {
if (
FacesTarget() &&
!m->sneaking &&
GetAppearance() != eaSitting &&
GetAppearance() != eaDead
) {
FaceTarget(m);
}
if (other && !other->sneaking)
FaceTarget(other);
} else if(!IsMoving()) {
if (other && !other->sneaking && GetAppearance() != eaSitting && GetAppearance() != eaDead)
FaceTarget(other);
}
}
void NPC::ChangeLastName(std::string last_name)
@@ -4250,17 +4238,3 @@ void NPC::DoNpcToNpcAggroScan()
false
);
}
bool NPC::FacesTarget()
{
const std::string& excluded_races_rule = RuleS(NPC, ExcludedFaceTargetRaces);
if (excluded_races_rule.empty()) {
return true;
}
const auto& v = Strings::Split(excluded_races_rule, ",");
return std::find(v.begin(), v.end(), std::to_string(GetBaseRace())) == v.end();
}
+2 -3
View File
@@ -222,7 +222,7 @@ public:
void RemoveLootCash();
void QueryLoot(Client *to, bool is_pet_query = false);
bool HasItem(uint32 item_id);
uint32 CountItem(uint32 item_id);
uint16 CountItem(uint32 item_id);
uint32 GetLootItemIDBySlot(uint16 loot_slot);
uint16 GetFirstLootSlotByItemID(uint32 item_id);
std::vector<int> GetLootList();
@@ -482,8 +482,7 @@ public:
NPC_Emote_Struct* GetNPCEmote(uint32 emote_id, uint8 event_);
void DoNPCEmote(uint8 event_, uint32 emote_id, Mob* t = nullptr);
bool CanTalk();
void DoQuestPause(Mob* m);
bool FacesTarget();
void DoQuestPause(Mob *other);
inline void SetSpellScale(float amt) { spellscale = amt; }
inline float GetSpellScale() { return spellscale; }
-13
View File
@@ -278,19 +278,6 @@ void Client::DoParcelSend(const Parcel_Struct *parcel_in)
return;
}
if (parcel_in->money_flag && parcel_in->item_slot != INVALID_INDEX) {
Message(
Chat::Yellow,
fmt::format(
"{} tells you, 'I am confused! Do you want to send money or an item?'",
merchant->GetCleanName()
).c_str()
);
DoParcelCancel();
SendParcelAck();
return;
}
auto num_of_parcels = GetParcelCount();
if (num_of_parcels >= RuleI(Parcel, ParcelMaxItems)) {
SendParcelIconStatus();
+3 -3
View File
@@ -145,7 +145,7 @@ EQ::ItemInstance* Perl_Bot_GetAugmentAt(Bot* self, int16 slot_id, uint8 augment_
return nullptr;
}
uint32 Perl_Bot_CountAugmentEquippedByID(Bot* self, uint32 item_id)
int Perl_Bot_CountAugmentEquippedByID(Bot* self, uint32 item_id)
{
return self->GetInv().CountAugmentEquippedByID(item_id);
}
@@ -155,7 +155,7 @@ bool Perl_Bot_HasAugmentEquippedByID(Bot* self, uint32 item_id)
return self->GetInv().HasAugmentEquippedByID(item_id);
}
uint32 Perl_Bot_CountItemEquippedByID(Bot* self, uint32 item_id)
int Perl_Bot_CountItemEquippedByID(Bot* self, uint32 item_id)
{
return self->GetInv().CountItemEquippedByID(item_id);
}
@@ -650,7 +650,7 @@ void perl_register_bot()
package.add("ApplySpellRaid", (void(*)(Bot*, int, int, int, bool))&Perl_Bot_ApplySpellRaid);
package.add("ApplySpellRaid", (void(*)(Bot*, int, int, int, bool, bool))&Perl_Bot_ApplySpellRaid);
package.add("Camp", (void(*)(Bot*))&Perl_Bot_Camp);
package.add("Camp", (void(*)(Bot*, bool))&Perl_Bot_Camp);
package.add("Camp", (void(*)(Bot*, bool))&Perl_Bot_Camp);
package.add("ClearDisciplineReuseTimer", (void(*)(Bot*))&Perl_Bot_ClearDisciplineReuseTimer);
package.add("ClearDisciplineReuseTimer", (void(*)(Bot*, uint16))&Perl_Bot_ClearDisciplineReuseTimer);
package.add("ClearItemReuseTimer", (void(*)(Bot*))&Perl_Bot_ClearItemReuseTimer);
+3 -16
View File
@@ -2209,7 +2209,7 @@ void Perl_Client_SendToInstance(Client* self, std::string instance_type, std::st
self->SendToInstance(instance_type, zone_short_name, instance_version, x, y, z, heading, instance_identifier, duration);
}
uint32 Perl_Client_CountItem(Client* self, uint32 item_id)
int Perl_Client_CountItem(Client* self, uint32 item_id)
{
return self->CountItem(item_id);
}
@@ -2388,7 +2388,7 @@ void Perl_Client_AddItem(Client* self, perl::reference table_ref)
augment_four, augment_five, augment_six, attuned, slot_id);
}
uint32 Perl_Client_CountAugmentEquippedByID(Client* self, uint32 item_id)
int Perl_Client_CountAugmentEquippedByID(Client* self, uint32 item_id)
{
return self->GetInv().CountAugmentEquippedByID(item_id);
}
@@ -2398,7 +2398,7 @@ bool Perl_Client_HasAugmentEquippedByID(Client* self, uint32 item_id)
return self->GetInv().HasAugmentEquippedByID(item_id);
}
uint32 Perl_Client_CountItemEquippedByID(Client* self, uint32 item_id)
int Perl_Client_CountItemEquippedByID(Client* self, uint32 item_id)
{
return self->GetInv().CountItemEquippedByID(item_id);
}
@@ -3212,18 +3212,6 @@ Merc* Perl_Client_GetMerc(Client* self)
return self->GetMerc();
}
perl::array Perl_Client_GetInventorySlots(Client* self)
{
perl::array result;
const auto& v = self->GetInventorySlots();
for (int i = 0; i < v.size(); ++i) {
result.push_back(v[i]);
}
return result;
}
void perl_register_client()
{
perl::interpreter perl(PERL_GET_THX);
@@ -3438,7 +3426,6 @@ void perl_register_client()
package.add("GetInstanceID", &Perl_Client_GetInstanceID);
package.add("GetInstrumentMod", &Perl_Client_GetInstrumentMod);
package.add("GetInventory", &Perl_Client_GetInventory);
package.add("GetInventorySlots", &Perl_Client_GetInventorySlots);
package.add("GetInvulnerableEnvironmentDamage", &Perl_Client_GetInvulnerableEnvironmentDamage);
package.add("GetItemAt", &Perl_Client_GetItemAt);
package.add("GetItemCooldown", &Perl_Client_GetItemCooldown);
+2 -2
View File
@@ -150,7 +150,7 @@ bool Perl_Inventory_HasAugmentEquippedByID(EQ::InventoryProfile* self, uint32_t
return self->HasAugmentEquippedByID(item_id);
}
uint32 Perl_Inventory_CountAugmentEquippedByID(EQ::InventoryProfile* self, uint32_t item_id)
int Perl_Inventory_CountAugmentEquippedByID(EQ::InventoryProfile* self, uint32_t item_id)
{
return self->CountAugmentEquippedByID(item_id);
}
@@ -160,7 +160,7 @@ bool Perl_Inventory_HasItemEquippedByID(EQ::InventoryProfile* self, uint32_t ite
return self->HasItemEquippedByID(item_id);
}
uint32 Perl_Inventory_CountItemEquippedByID(EQ::InventoryProfile* self, uint32_t item_id)
int Perl_Inventory_CountItemEquippedByID(EQ::InventoryProfile* self, uint32_t item_id)
{
return self->CountItemEquippedByID(item_id);
}

Some files were not shown because too many files have changed in this diff Show More