Compare commits

..

25 Commits

Author SHA1 Message Date
Akkadius 6b65dd3a00 Update console_server_connection.cpp 2024-12-14 21:50:53 -06:00
Akkadius aa8b0570d6 [Telnet] Automatically prune connections 2024-12-14 21:16:14 -06:00
Mitch Freeman 4493ebebab [Bug Fix] Resolve a client crash when logging in or zoning (#4572) 2024-12-14 14:27:43 -05:00
Alex King 77793f364e [Commands] Add #find bot Subcommand (#4563)
* [Commands] Add #find bot Subcommand

* Update find.cpp

* Update find.cpp
2024-12-12 16:55:33 -06:00
Alex King e258aaa068 [Bug Fix] Allow Items in ROF2 to Stack to 32,767 (#4556)
* [Bug Fix] Allow Items in ROF2 to Stack to 32,767

* Update rof2.cpp
2024-12-12 16:39:38 -06:00
Paul Johnson 3b779ef301 [Rules] Add rules for requiring custom files from client (#4561)
* rules for enabling requiring custom files

* shorten default

* variable name

* check account status for enforcing client key

* rule for custom files admin level

---------

Co-authored-by: Paul Johnson <Paul@pjohnsomac-6366.digi.box>
2024-12-12 01:47:50 -06:00
Alex King 3f3c0f2fda [Commands] Add #find ldon_theme Subcommand (#4564) 2024-12-12 01:27:25 -06:00
Alex King 0f164c456e [Cleanup] Remove Unused Group Methods (#4559) 2024-12-12 01:25:36 -06:00
Mitch Freeman 6172c49b08 [Feature] Enable bazaar window 'Find Trader' functionality (#4560)
* First pass to enable trader 'Find Trader' functionality

* Move SendBulkTraders out of zoning routines and send as part of the opening of the bazaar search window.
Add zone instance to SendBulkTraders to support multi-instanced bazaars.
2024-12-12 01:25:12 -06:00
Chris Miles 66a7dd0143 [Databuckets] Improved Reliability and Performance of Databuckets (#4562)
* [Databuckets] Don't broadcast client-scoped updates

* Remove temp feature flag

* Remove distributed caching, only cache for character scoped data, simplify

* Update bot.cpp

* Cleanup

* Update data_bucket.cpp

* Cleanup

* Cleanup

* Remove BulkLoadEntities from LoadNPCTypes

* Update data_bucket.cpp

* Cleanup

* More cleanup

* More cleanup

* BulkLoadEntities to BulkLoadEntitiesToCache

* Add CanCache in DeleteData to gate an unnecessary call
2024-12-12 01:17:08 -06:00
Alex King 5c6e7a8b09 [Cleanup] Convert Event Parses to Single Line (#4569)
* [Cleanup] Convert Event Parses to Single Line

* Push

* Update spells.cpp

* Update spells.cpp

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2024-12-12 00:43:22 -06:00
dependabot[bot] bd85fc96a0 Bump golang.org/x/crypto in /utils/scripts/build/should-release (#4570)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.21.0 to 0.31.0.
- [Commits](https://github.com/golang/crypto/compare/v0.21.0...v0.31.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-12 00:17:28 -06:00
nytmyr 8e40e5357c [Bots] Fix AA ranks to account for level (#4567)
Previously level requirement was only being checked on the initial rank of an AA. If passed, bots would gain all ranks for that AA regardless of level, this will now check for the level requirement for each rank before granting the AA
2024-12-06 23:58:11 -05:00
nytmyr 5f0b999ca9 [Groups] Fix AmIMainAssist incorrectly checking for MainTankName (#4565) 2024-12-04 16:04:34 -05:00
Alex King fe9df46a24 [Bug Fix] Fix EVENT_COMBAT on NPC Death (#4558) 2024-11-27 20:30:29 -05:00
Alex King 3d7cf4235c [Release] 22.60.0 (#4555) 2024-11-25 17:17:03 -06:00
hg 187ee10218 [Tasks] Update tasks in all zones if invalid zone set (#4550)
This allows task elements to update in any zone when it has an invalid
zone id <= 0. This has the same effect as leaving the zones field empty
except "Unknown Zone" instead of "ALL" will be shown in task windows.

Note that Titanium shows "ALL" for a zone id of 0 despite it being an
invalid zone id. This could be manipulated server side to match newer
clients but there isn't much benefit since any other invalid zone id
below 0 can be used to do the same.
2024-11-25 18:02:14 -05:00
Alex King 6bd758b3dd [Rules] Add Rule to Disable NPCs Facing Target (#4543) 2024-11-24 17:30:44 -06:00
Alex King 9938755517 [Bug Fix] Fix Possible Item Loss in Trades (#4554) 2024-11-24 17:29:27 -06:00
Chris Miles 630da0eee6 [Config] Fix World TCP Address Configuration Default (#4551) 2024-11-24 17:27:31 -06:00
Alex King 3158386aa3 [Bug Fix] Fix Issue with Perl EVENT_PAYLOAD (#4545) 2024-11-24 17:19:40 -06:00
hg 12ada57ee8 [Code] Fix build with older C++ libraries (#4549)
This adds a compile time concept to determine if from_chars has
floating-point support and uses fallbacks if not.

This is a C++17 feature but support for floats was only added to
libstdc++ with GCC 11.1 and LLVM libc++ in 20.0 (unreleased).
2024-11-24 17:18:36 -06:00
Mitch Freeman 7a841c11c5 [Bug Fix] Players could become flagged as a Trader when they were not trading (#4553) 2024-11-24 17:17:01 -06:00
Mitch Freeman a49d1446b7 [Bug Fix] Fix for sending money via Parcel, then changing your mind (#4552) 2024-11-24 17:15:18 -06:00
carolus21rex b2d0fa6a2f [Bug Fix] Fix Strings::Commify bug with #mystats (#4547)
* Fix a formatting bug with #mystats

When using values larger than 1,000, we were calling commify on a string that already had commas. This resulted in the value 1005 looking like 1,,005.

* Update mob.cpp

---------

Co-authored-by: Alex King <89047260+Kinglykrab@users.noreply.github.com>
2024-11-22 16:23:48 -05:00
71 changed files with 2561 additions and 2900 deletions
+34
View File
@@ -1,3 +1,37 @@
## [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
+28 -20
View File
@@ -8,13 +8,14 @@ std::vector<BazaarSearchResultsFromDB_Struct>
Bazaar::GetSearchResults(
SharedDatabase &db,
BazaarSearchCriteria_Struct search,
uint32 char_zone_id
uint32 char_zone_id,
int32 char_zone_instance_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 [{}]",
"search_scope [{}] char_zone_id [{}], char_zone_instance_id [{}]",
search.item_name,
search.min_cost,
search.max_cost,
@@ -26,7 +27,8 @@ Bazaar::GetSearchResults(
search.trader_entity_id,
search.trader_id,
search.search_scope,
char_zone_id
char_zone_id,
char_zone_instance_id
);
std::string search_criteria_trader("TRUE ");
@@ -34,14 +36,19 @@ 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_entity_id = {} AND trader.char_zone_id = {} AND trader.char_zone_instance_id = {}",
search.trader_entity_id,
Zones::BAZAAR
Zones::BAZAAR,
char_zone_instance_id
)
);
}
else if (search.search_scope == Local_Scope) {
search_criteria_trader.append(fmt::format(" AND trader.char_zone_id = {}", char_zone_id));
search_criteria_trader.append(fmt::format(
" AND trader.char_zone_id = {} AND trader.char_zone_instance_id = {}",
char_zone_id,
char_zone_instance_id)
);
}
else if (search.trader_id > 0) {
search_criteria_trader.append(fmt::format(" AND trader.char_id = {}", search.trader_id));
@@ -62,7 +69,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 "
"aug_slot_1, aug_slot_2, aug_slot_3, aug_slot_4, aug_slot_5, aug_slot_6, trader.char_zone_instance_id "
"FROM trader, character_data "
"WHERE {} AND trader.char_id = character_data.id "
"GROUP BY trader.item_sn, trader.item_charges, trader.char_id",
@@ -122,19 +129,20 @@ 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_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_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());
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);
GetSearchResults(SharedDatabase &db, BazaarSearchCriteria_Struct search, unsigned int char_zone_id, int char_zone_instance_id);
};
+7 -94
View File
@@ -5774,100 +5774,13 @@ CREATE INDEX idx_bot_expires ON data_buckets (bot_id, expires);
},
ManifestEntry{
.version = 9286,
.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 2040; -- Bank Bag 1
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2041) + 6410) WHERE `slot_id` BETWEEN 2041 AND 2050; -- Bank Bag 2
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2051) + 6610) WHERE `slot_id` BETWEEN 2051 AND 2060; -- Bank Bag 3
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2061) + 6810) WHERE `slot_id` BETWEEN 2061 AND 2070; -- Bank Bag 4
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2071) + 7010) WHERE `slot_id` BETWEEN 2071 AND 2080; -- Bank Bag 5
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2081) + 7210) WHERE `slot_id` BETWEEN 2081 AND 2090; -- Bank Bag 6
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2091) + 7410) WHERE `slot_id` BETWEEN 2091 AND 2100; -- Bank Bag 7
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2101) + 7610) WHERE `slot_id` BETWEEN 2101 AND 2110; -- Bank Bag 8
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2111) + 7810) WHERE `slot_id` BETWEEN 2111 AND 2120; -- Bank Bag 9
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2121) + 8010) WHERE `slot_id` BETWEEN 2121 AND 2130; -- Bank Bag 10
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2131) + 8210) WHERE `slot_id` BETWEEN 2131 AND 2140; -- Bank Bag 11
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2141) + 8410) WHERE `slot_id` BETWEEN 2141 AND 2150; -- Bank Bag 12
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2151) + 8610) WHERE `slot_id` BETWEEN 2151 AND 2160; -- Bank Bag 13
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2161) + 8810) WHERE `slot_id` BETWEEN 2161 AND 2170; -- Bank Bag 14
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2171) + 9010) WHERE `slot_id` BETWEEN 2171 AND 2180; -- Bank Bag 15
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2181) + 9210) WHERE `slot_id` BETWEEN 2181 AND 2190; -- Bank Bag 16
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2191) + 9410) WHERE `slot_id` BETWEEN 2191 AND 2200; -- Bank Bag 17
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2201) + 9610) WHERE `slot_id` BETWEEN 2201 AND 2210; -- Bank Bag 18
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2211) + 9810) WHERE `slot_id` BETWEEN 2211 AND 2220; -- Bank Bag 19
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2221) + 10010) WHERE `slot_id` BETWEEN 2221 AND 2230; -- Bank Bag 20
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2231) + 10210) WHERE `slot_id` BETWEEN 2231 AND 2240; -- Bank Bag 21
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2241) + 10410) WHERE `slot_id` BETWEEN 2241 AND 2250; -- Bank Bag 22
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2251) + 10610) WHERE `slot_id` BETWEEN 2251 AND 2260; -- Bank Bag 23
UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2261) + 10810) WHERE `slot_id` BETWEEN 2261 AND 2270; -- Bank Bag 24
UPDATE `sharedbank` SET `slot_id` = ((`slot_id` - 2531) + 11010) WHERE `slot_id` BETWEEN 2531 AND 2540; -- Shared Bank Bag 1
UPDATE `sharedbank` SET `slot_id` = ((`slot_id` - 2541) + 11210) WHERE `slot_id` BETWEEN 2541 AND 2550; -- Shared Bank Bag 2
)"
},
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`;
.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`;
)"
}
// -- template; copy/paste this when you need to create a new entry
+15 -23
View File
@@ -140,29 +140,6 @@ 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 = {
@@ -459,3 +436,18 @@ 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();
}
+62 -38
View File
@@ -132,7 +132,7 @@ namespace EQ
using RoF2::invtype::KRONO_SIZE;
using RoF2::invtype::OTHER_SIZE;
using RoF2::invtype::TRADE_NPC_SIZE;
using Titanium::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 RoF2::invslot::SLOT_TRADESKILL_EXPERIMENT_COMBINE;
using Titanium::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 RoF2::invslot::BANK_BEGIN;
using RoF2::invslot::BANK_END;
using Titanium::invslot::BANK_BEGIN;
using SoF::invslot::BANK_END;
using RoF2::invslot::SHARED_BANK_BEGIN;
using RoF2::invslot::SHARED_BANK_END;
using Titanium::invslot::SHARED_BANK_BEGIN;
using Titanium::invslot::SHARED_BANK_END;
using RoF2::invslot::TRADE_BEGIN;
using RoF2::invslot::TRADE_END;
using Titanium::invslot::TRADE_BEGIN;
using Titanium::invslot::TRADE_END;
using RoF2::invslot::TRADE_NPC_END;
using Titanium::invslot::TRADE_NPC_END;
using RoF2::invslot::WORLD_BEGIN;
using RoF2::invslot::WORLD_END;
using Titanium::invslot::WORLD_BEGIN;
using Titanium::invslot::WORLD_END;
using RoF2::invslot::TRIBUTE_BEGIN;
using RoF2::invslot::TRIBUTE_END;
using Titanium::invslot::TRIBUTE_BEGIN;
using Titanium::invslot::TRIBUTE_END;
using RoF2::invslot::GUILD_TRIBUTE_BEGIN;
using RoF2::invslot::GUILD_TRIBUTE_END;
using Titanium::invslot::GUILD_TRIBUTE_BEGIN;
using Titanium::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,40 +214,38 @@ namespace EQ
} // namespace invslot
namespace invbag {
using RoF2::invbag::SLOT_INVALID;
using RoF2::invbag::SLOT_BEGIN;
using RoF2::invbag::SLOT_END;
using RoF2::invbag::SLOT_COUNT;
using Titanium::invbag::SLOT_INVALID;
using Titanium::invbag::SLOT_BEGIN;
using Titanium::invbag::SLOT_END;
using Titanium::invbag::SLOT_COUNT;
using RoF2::invslot::WORLD_END;
const int16 GENERAL_BAGS_BEGIN = WORLD_END + 1;
using Titanium::invbag::GENERAL_BAGS_BEGIN;
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 = GENERAL_BAGS_END + 1;
const int16 CURSOR_BAG_BEGIN = 351;
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;
const int16 BANK_BAGS_BEGIN = CURSOR_BAG_END + 1;
using Titanium::invbag::BANK_BAGS_BEGIN;
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;
const int16 SHARED_BANK_BAGS_BEGIN = BANK_BAGS_END + 1;
using Titanium::invbag::SHARED_BANK_BAGS_BEGIN;
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;
const int16 TRADE_BAGS_BEGIN = SHARED_BANK_BAGS_END + 1;
using Titanium::invbag::TRADE_BAGS_BEGIN;
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 RoF2::invbag::GetInvBagIndexName;
using Titanium::invbag::GetInvBagIndexName;
} // namespace invbag
@@ -354,9 +352,6 @@ 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);
@@ -753,6 +748,35 @@ 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,24 +993,6 @@ 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,
+5 -1
View File
@@ -3742,7 +3742,8 @@ struct GetItems_Struct{
struct BecomeTrader_Struct {
uint32 action;
uint32 zone_id;
uint16 zone_id;
uint16 zone_instance_id;
uint32 trader_id;
uint32 entity_id;
char trader_name[64];
@@ -6347,6 +6348,7 @@ enum BazaarTraderBarterActions {
TraderAck2 = 22,
AddTraderToBazaarWindow = 24,
RemoveTraderFromBazaarWindow = 25,
FirstOpenSearch = 26,
ClickTrader = 28,
DeliveryCostUpdate = 29
};
@@ -6386,6 +6388,7 @@ 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;
@@ -6407,6 +6410,7 @@ 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("host", "127.0.0.1").asString();
WorldIP = _root["server"]["world"]["tcp"].get("ip", "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();
File diff suppressed because it is too large Load Diff
+9
View File
@@ -176,6 +176,7 @@ 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
@@ -198,6 +199,12 @@ 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);
@@ -210,6 +217,8 @@ 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,6 +414,12 @@ 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)
{
@@ -422,6 +428,14 @@ 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)
+10 -3
View File
@@ -4,6 +4,7 @@
#include "../eqemu_logsys.h"
#include "../servertalk.h"
#include "../rulesys.h"
#include "../event/timer.h"
#include <fmt/format.h>
EQ::Net::ConsoleServerConnection::ConsoleServerConnection(ConsoleServer *parent, std::shared_ptr<TCPConnection> connection)
@@ -21,7 +22,11 @@ EQ::Net::ConsoleServerConnection::ConsoleServerConnection(ConsoleServer *parent,
m_connection->OnDisconnect(std::bind(&ConsoleServerConnection::OnDisconnect, this, std::placeholders::_1));
m_connection->Start();
ClearBuffer();
m_keepalive = std::make_unique<EQ::Timer>(1000, true, [this](EQ::Timer *t) {
m_connection->Write("", 0);
});
auto addr = m_connection->RemoteIP();
SendLine(fmt::format("Establishing connection from: {0}:{1}", addr, m_connection->RemotePort()));
@@ -85,12 +90,12 @@ void EQ::Net::ConsoleServerConnection::QueueMessage(const std::string &msg)
}
else {
std::string cmd(m_line, m_line + m_cursor);
size_t len = m_user.length() + 2 + cmd.length();
for (size_t i = 0; i < len; ++i) {
Send("\x08");
}
if (msg.length() < cmd.length()) {
Send(msg);
size_t blank_spaces = 2 + cmd.length() - msg.length();
@@ -227,6 +232,8 @@ void EQ::Net::ConsoleServerConnection::OnRead(TCPConnection *c, const unsigned c
void EQ::Net::ConsoleServerConnection::OnDisconnect(TCPConnection *c)
{
LogInfo("Console connection disconnected");
m_parent->ConnectionDisconnected(this);
}
+2
View File
@@ -1,6 +1,7 @@
#pragma once
#include "tcp_server.h"
#include "../event/timer.h"
#include <memory>
#include <map>
@@ -58,6 +59,7 @@ namespace EQ
int m_user_id;
int m_admin;
bool m_accept_messages;
std::unique_ptr<EQ::Timer> m_keepalive;
size_t m_cursor;
char m_line[MaxConsoleLineLength];
+26 -10
View File
@@ -583,19 +583,21 @@ 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->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;
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>[{}]",
"(RoF2) AddTraderToBazaarWindow action <green>[{}] trader_id <green>[{}] entity_id <green>[{}] "
"zone_id <green>[{}] zone_instance_id <green>[{}]",
eq->action,
eq->trader_id,
eq->entity_id,
eq->zone_id
);
eq->zone_id,
eq->zone_instance_id);
dest->FastQueuePacket(&outapp);
break;
}
@@ -6218,6 +6220,11 @@ 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);
@@ -6358,9 +6365,18 @@ namespace RoF2
//sprintf(hdr.unknown000, "06e0002Y1W00");
strn0cpy(hdr.unknown000, fmt::format("{:016}\0", inst->GetSerialNumber()).c_str(),sizeof(hdr.unknown000));
hdr.stacksize =
item->ID == PARCEL_MONEY_ITEM_ID ? inst->GetPrice() : (inst->IsStackable() ? ((inst->GetCharges() > 1000)
? 0xFFFFFFFF : inst->GetCharges()) : 1);
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.unknown004 = 0;
structs::InventorySlot_Struct slot_id{};
+49 -81
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 = 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 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 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,54 +162,33 @@ namespace RoF2
} // namespace enum_
using namespace enum_;
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 SLOT_INVALID = IINVALID;
const int16 SLOT_BEGIN = INULL;
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);
@@ -220,21 +199,10 @@ namespace RoF2
namespace invbag {
inline EQ::versions::ClientVersion GetInvBagRef() { return EQ::versions::ClientVersion::RoF2; }
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 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 char* GetInvBagIndexName(int16 bag_index);
@@ -244,9 +212,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);
@@ -323,7 +291,7 @@ namespace RoF2
namespace spells {
inline EQ::versions::ClientVersion GetSkillsRef() { return EQ::versions::ClientVersion::RoF2; }
enum class CastingSlot : uint32 {
Gem1 = 0,
Gem2 = 1,
@@ -346,7 +314,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;
+2 -1
View File
@@ -3119,7 +3119,8 @@ enum RoF2BazaarTraderBuyerActions {
BazaarInspect = 18,
ClickTrader = 28,
ItemMove = 19,
ReconcileItems = 20
ReconcileItems = 20,
FirstOpenSearch = 26
};
enum RoF2BuyerActions {
+6 -6
View File
@@ -2463,25 +2463,25 @@ struct WhoAllReturnStruct {
struct BeginTrader_Struct {
uint32 action;
uint32 unknown04;
uint64 serial_number[EQ::invtype::BAZAAR_SIZE];
uint32 cost[EQ::invtype::BAZAAR_SIZE];
uint64 serial_number[80];
uint32 cost[80];
};
struct Trader_Struct {
uint32 action;
uint32 unknown004;
uint64 item_id[EQ::invtype::BAZAAR_SIZE];
uint32 item_cost[EQ::invtype::BAZAAR_SIZE];
uint64 item_id[80];
uint32 item_cost[80];
};
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[EQ::invtype::BAZAAR_SIZE];
uint32 itemcost[80];
};
struct GetItems_Struct{
uint32 items[EQ::invtype::BAZAAR_SIZE];
uint32 items[80];
};
struct BecomeTrader_Struct {
@@ -49,23 +49,23 @@ public:
std::string field;
switch (theme_id) {
case LDoNThemes::GUK: {
case LDoNTheme::GUK: {
field = "guk_";
break;
}
case LDoNThemes::MIR: {
case LDoNTheme::MIR: {
field = "mir_";
break;
}
case LDoNThemes::MMC: {
case LDoNTheme::MMC: {
field = "mmc_";
break;
}
case LDoNThemes::RUJ: {
case LDoNTheme::RUJ: {
field = "ruj_";
break;
}
case LDoNThemes::TAK: {
case LDoNTheme::TAK: {
field = "tak_";
break;
}
@@ -19,48 +19,48 @@
class BaseInventoryRepository {
public:
struct Inventory {
uint32_t character_id;
uint32_t slot_id;
uint32_t item_id;
uint32_t charid;
uint32_t slotid;
uint32_t itemid;
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;
uint32_t augslot1;
uint32_t augslot2;
uint32_t augslot3;
uint32_t augslot4;
uint32_t augslot5;
int32_t augslot6;
uint8_t instnodrop;
std::string custom_data;
uint32_t ornament_icon;
uint32_t ornament_idfile;
uint32_t ornamenticon;
uint32_t ornamentidfile;
int32_t ornament_hero_model;
uint64_t guid;
};
static std::string PrimaryKey()
{
return std::string("character_id");
return std::string("charid");
}
static std::vector<std::string> Columns()
{
return {
"character_id",
"slot_id",
"item_id",
"charid",
"slotid",
"itemid",
"charges",
"color",
"augment_one",
"augment_two",
"augment_three",
"augment_four",
"augment_five",
"augment_six",
"augslot1",
"augslot2",
"augslot3",
"augslot4",
"augslot5",
"augslot6",
"instnodrop",
"custom_data",
"ornament_icon",
"ornament_idfile",
"ornamenticon",
"ornamentidfile",
"ornament_hero_model",
"guid",
};
@@ -69,21 +69,21 @@ public:
static std::vector<std::string> SelectColumns()
{
return {
"character_id",
"slot_id",
"item_id",
"charid",
"slotid",
"itemid",
"charges",
"color",
"augment_one",
"augment_two",
"augment_three",
"augment_four",
"augment_five",
"augment_six",
"augslot1",
"augslot2",
"augslot3",
"augslot4",
"augslot5",
"augslot6",
"instnodrop",
"custom_data",
"ornament_icon",
"ornament_idfile",
"ornamenticon",
"ornamentidfile",
"ornament_hero_model",
"guid",
};
@@ -126,21 +126,21 @@ public:
{
Inventory e{};
e.character_id = 0;
e.slot_id = 0;
e.item_id = 0;
e.charid = 0;
e.slotid = 0;
e.itemid = 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.augslot1 = 0;
e.augslot2 = 0;
e.augslot3 = 0;
e.augslot4 = 0;
e.augslot5 = 0;
e.augslot6 = 0;
e.instnodrop = 0;
e.custom_data = "";
e.ornament_icon = 0;
e.ornament_idfile = 0;
e.ornamenticon = 0;
e.ornamentidfile = 0;
e.ornament_hero_model = 0;
e.guid = 0;
@@ -153,7 +153,7 @@ public:
)
{
for (auto &inventory : inventorys) {
if (inventory.character_id == inventory_id) {
if (inventory.charid == inventory_id) {
return inventory;
}
}
@@ -179,21 +179,21 @@ public:
if (results.RowCount() == 1) {
Inventory e{};
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.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.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.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.instnodrop = row[11] ? static_cast<uint8_t>(strtoul(row[11], nullptr, 10)) : 0;
e.custom_data = row[12] ? row[12] : "";
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.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_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.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[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[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[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[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.ornament_icon));
v.push_back(columns[14] + " = " + std::to_string(e.ornament_idfile));
v.push_back(columns[13] + " = " + std::to_string(e.ornamenticon));
v.push_back(columns[14] + " = " + std::to_string(e.ornamentidfile));
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.character_id
e.charid
)
);
@@ -267,21 +267,21 @@ public:
{
std::vector<std::string> v;
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.charid));
v.push_back(std::to_string(e.slotid));
v.push_back(std::to_string(e.itemid));
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(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.instnodrop));
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.ornamenticon));
v.push_back(std::to_string(e.ornamentidfile));
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.character_id = results.LastInsertedID();
e.charid = 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.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.charid));
v.push_back(std::to_string(e.slotid));
v.push_back(std::to_string(e.itemid));
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(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.instnodrop));
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.ornamenticon));
v.push_back(std::to_string(e.ornamentidfile));
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.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.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.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.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.instnodrop = row[11] ? static_cast<uint8_t>(strtoul(row[11], nullptr, 10)) : 0;
e.custom_data = row[12] ? row[12] : "";
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.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_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.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.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.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.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.instnodrop = row[11] ? static_cast<uint8_t>(strtoul(row[11], nullptr, 10)) : 0;
e.custom_data = row[12] ? row[12] : "";
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.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_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.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.charid));
v.push_back(std::to_string(e.slotid));
v.push_back(std::to_string(e.itemid));
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(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.instnodrop));
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.ornamenticon));
v.push_back(std::to_string(e.ornamentidfile));
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.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.charid));
v.push_back(std::to_string(e.slotid));
v.push_back(std::to_string(e.itemid));
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(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.instnodrop));
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.ornamenticon));
v.push_back(std::to_string(e.ornamentidfile));
v.push_back(std::to_string(e.ornament_hero_model));
v.push_back(std::to_string(e.guid));
@@ -1,560 +0,0 @@
/**
* 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,13 +28,14 @@ public:
uint32_t aug_slot_4;
uint32_t aug_slot_5;
uint32_t aug_slot_6;
int32_t item_sn;
uint32_t item_sn;
int32_t item_charges;
uint64_t item_cost;
uint32_t item_cost;
uint8_t slot_id;
uint32_t char_entity_id;
uint32_t char_zone_id;
int8_t active_transaction;
int32_t char_zone_instance_id;
uint8_t active_transaction;
};
static std::string PrimaryKey()
@@ -60,6 +61,7 @@ public:
"slot_id",
"char_entity_id",
"char_zone_id",
"char_zone_instance_id",
"active_transaction",
};
}
@@ -82,6 +84,7 @@ public:
"slot_id",
"char_entity_id",
"char_zone_id",
"char_zone_instance_id",
"active_transaction",
};
}
@@ -123,22 +126,23 @@ 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.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.char_zone_instance_id = 0;
e.active_transaction = 0;
return e;
}
@@ -175,22 +179,23 @@ 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<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;
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;
return e;
}
@@ -238,7 +243,8 @@ 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.active_transaction));
v.push_back(columns[15] + " = " + std::to_string(e.char_zone_instance_id));
v.push_back(columns[16] + " = " + std::to_string(e.active_transaction));
auto results = db.QueryDatabase(
fmt::format(
@@ -275,6 +281,7 @@ 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(
@@ -320,6 +327,7 @@ 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) + ")");
@@ -354,22 +362,23 @@ 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<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;
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;
all_entries.push_back(e);
}
@@ -394,22 +403,23 @@ 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<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;
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;
all_entries.push_back(e);
}
@@ -499,6 +509,7 @@ 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(
@@ -537,6 +548,7 @@ 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) + ")");
+300 -37
View File
@@ -3,47 +3,310 @@
#include "../database.h"
#include "../strings.h"
#include "base/base_sharedbank_repository.h"
class SharedbankRepository: public BaseSharedbankRepository {
class SharedbankRepository {
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;
};
/**
* 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::string PrimaryKey()
{
return std::string("");
}
// Custom extended repository methods here
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;
}
};
+9 -6
View File
@@ -16,6 +16,7 @@ public:
struct DistinctTraders_Struct {
uint32 trader_id;
uint32 zone_id;
uint32 zone_instance_id;
uint32 entity_id;
std::string trader_name;
};
@@ -35,7 +36,8 @@ public:
GetBazaarSearchResults(
SharedDatabase &db,
BazaarSearchCriteria_Struct search,
uint32 char_zone_id
uint32 char_zone_id,
int32 char_zone_instance_id
);
static BulkTraders_Struct GetDistinctTraders(Database &db)
@@ -44,7 +46,7 @@ public:
std::vector<DistinctTraders_Struct> distinct_traders;
auto results = db.QueryDatabase(
"SELECT DISTINCT(t.char_id), t.char_zone_id, t.char_entity_id, c.name "
"SELECT DISTINCT(t.char_id), t.char_zone_id, t.char_zone_instance_id, t.char_entity_id, c.name "
"FROM trader AS t "
"JOIN character_data AS c ON t.char_id = c.id;"
);
@@ -54,10 +56,11 @@ public:
for (auto row: results) {
DistinctTraders_Struct e{};
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] : "";
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] : "";
all_entries.name_length += e.trader_name.length() + 1;
all_entries.traders.push_back(e);
+5 -1
View File
@@ -339,7 +339,10 @@ 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, "RoF2", "Comma-delimited list of clients to restrict to. Supported values are Titanium | SoF | SoD | UF | RoF | RoF2. Example: Titanium,RoF2")
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_CATEGORY_END()
RULE_CATEGORY(Zone)
@@ -681,6 +684,7 @@ 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)
+1 -2
View File
@@ -319,8 +319,6 @@
// player events
#define ServerOP_PlayerEvent 0x5100
#define ServerOP_DataBucketCacheUpdate 0x5200
enum {
CZUpdateType_Character,
CZUpdateType_Group,
@@ -1945,6 +1943,7 @@ 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];
+387 -306
View File
@@ -48,7 +48,6 @@
#include "repositories/skill_caps_repository.h"
#include "repositories/inventory_repository.h"
#include "repositories/books_repository.h"
#include "repositories/sharedbank_repository.h"
namespace ItemField
{
@@ -191,268 +190,242 @@ 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)
{
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
)
);
// 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;
}
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;
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;
if (!SaveInventory(char_id, inst, use_slot)) {
return false;
}
}
}
return true;
}
bool SharedDatabase::VerifyInventory(uint32 account_id, int16 slot_id, const EQ::ItemInstance* inst)
{
if (!inst || !inst->GetItem()) {
return false;
}
const auto& l = SharedbankRepository::GetWhere(
*this,
fmt::format(
"`account_id` = {} AND `slot_id` = {} LIMIT 1",
account_id,
slot_id
)
);
if (l.empty()) {
return false;
}
const auto& e = l.front();
uint16 expect_charges = inst->GetCharges() >= 0 ? inst->GetCharges() : std::numeric_limits<int16>::max();
return e.item_id == inst->GetID() && e.charges == expect_charges;
}
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)
) {
// 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 (
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 (results.RowCount() == 0)
return false;
auto& row = results.begin();
const uint32 id = Strings::ToUnsignedInt(row[0]);
const uint16 charges = Strings::ToUnsignedInt(row[1]);
uint16 expect_charges;
if(inst->GetCharges() >= 0)
expect_charges = inst->GetCharges();
else
expect_charges = 0x7FFF;
if(id != inst->GetItem()->ID || charges != expect_charges)
return false;
return true;
}
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)
return true;
if (slot_id >= EQ::invslot::SHARED_BANK_BEGIN && slot_id <= EQ::invbag::SHARED_BANK_BAGS_END) {
// Shared bank inventory
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);
return UpdateInventorySlot(char_id, inst, slot_id);
}
bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const EQ::ItemInstance* inst, int16 slot_id)
{
if (!inst || !inst->GetItem()) {
return false;
}
bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const EQ::ItemInstance* inst, int16 slot_id) {
// need to check 'inst' argument for valid pointer
std::vector<uint32> augment_ids = inst->GetAugmentIDs();
uint16 charges = inst->GetCharges() >= 0 ? inst->GetCharges() : std::numeric_limits<int16>::max();
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 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));
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;
}
}
return replaced;
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;
}
bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const EQ::ItemInstance* inst, int16 slot_id)
{
if (!inst || !inst->GetItem()) {
return false;
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;
}
}
std::vector<uint32> augment_ids = inst->GetAugmentIDs();
uint16 charges = inst->GetCharges() >= 0 ? inst->GetCharges() : std::numeric_limits<int16>::max();
// Update/Insert item
const uint32 account_id = GetAccountIDByChar(char_id);
uint16 charges;
if(inst->GetCharges() >= 0)
charges = inst->GetCharges();
else
charges = 0x7FFF;
auto e = SharedbankRepository::NewEntity();
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);
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
// 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));
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));
}
}
return replaced;
if (!results.Success()) {
return false;
}
return true;
}
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
)
);
bool SharedDatabase::DeleteInventorySlot(uint32 char_id, int16 slot_id) {
if (!deleted) {
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;
}
// Delete bag slots, if need be
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 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;
}
// @merth: need to delete augments here
return true;
}
bool SharedDatabase::DeleteSharedBankSlot(uint32 char_id, int16 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;
}
// 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);
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;
}
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 `slot_id` BETWEEN {} AND {}",
account_id,
base_slot_id,
base_slot_id + (EQ::invbag::SLOT_COUNT - 1)
)
);
// @merth: need to delete augments here
return true;
}
@@ -577,81 +550,96 @@ bool SharedDatabase::SetStartingItems(
// Retrieve shared bank inventory based on either account or character
bool SharedDatabase::GetSharedBank(uint32 id, EQ::InventoryProfile *inv, bool is_charid)
{
const uint32 account_id = is_charid ? GetAccountIDByChar(id) : id;
std::string query;
if (!account_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()) {
return false;
}
const auto& l = SharedbankRepository::GetWhere(
*this,
fmt::format(
"`account_id` = {}",
account_id
)
);
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]));
if (l.empty()) {
return true;
}
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]);
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);
const EQ::ItemData *item = GetItem(item_id);
if (!item) {
LogError(
"Warning: {} [{}] has an invalid item_id [{}] in slot_id [{}]",
is_charid ? "character_id" : "account_id",
"Warning: [{}] [{}] has an invalid item_id [{}] in inventory slot [{}]",
is_charid ? "charid" : "acctid",
id,
e.item_id,
e.slot_id
item_id,
slot_id
);
continue;
}
EQ::ItemInstance* inst = CreateBaseItem(item, e.charges);
auto inst = CreateBaseItem(item, charges);
if (!inst) {
continue;
}
if (item->IsClassCommon()) {
if (inst && item->IsClassCommon()) {
for (int i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) {
if (augment_ids[i]) {
inst->PutAugment(this, i, augment_ids[i]);
if (aug[i]) {
inst->PutAugment(this, i, aug[i]);
}
}
}
if (!e.custom_data.empty()) {
inst->SetCustomDataString(e.custom_data);
if (inst && row[9]) {
std::string data_str(row[9]);
inst->SetCustomDataString(data_str);
}
const int16 put_slot_id = inv->PutItem(e.slot_id, *inst);
// theoretically inst can be nullptr ... this would be very bad ...
const int16 put_slot_id = inv->PutItem(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 for {} [{}] item_id [{}] slot_id [{}]",
is_charid ? "character_id" : "account_id",
"Warning: Invalid slot_id for item in shared bank inventory: [{}]=[{}], item_id=[{}], slot_id=[{}]",
is_charid ? "charid" : "acctid",
id,
e.item_id,
e.slot_id
item_id,
slot_id
);
if (is_charid) {
SaveInventory(id, nullptr, e.slot_id);
SaveInventory(id, nullptr, slot_id);
}
}
@@ -659,77 +647,72 @@ 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(
"`character_id` = '{}' ORDER BY `slot_id`",
char_id
)
);
auto results = InventoryRepository::GetWhere(*this, fmt::format("`charid` = '{}' ORDER BY `slotid`;", 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.slot_id;
const uint32 item_id = row.item_id;
std::vector<InventoryRepository::Inventory> queue{};
for (auto &row: results) {
const int16 slot_id = row.slotid;
const uint32 item_id = row.itemid;
const uint16 charges = row.charges;
const uint32 color = row.color;
const bool instnodrop = row.instnodrop;
const uint32 ornament_icon = row.ornament_icon;
const uint32 ornament_idfile = row.ornament_idfile;
const bool instnodrop = row.instnodrop;
const uint32 ornament_icon = row.ornamenticon;
const uint32 ornament_idfile = row.ornamentidfile;
const uint32 ornament_hero_model = row.ornament_hero_model;
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
};
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;
if (EQ::ValueWithin(slot_id, EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END)) {
if (slot_id <= EQ::invslot::POSSESSIONS_END && slot_id >= EQ::invslot::POSSESSIONS_BEGIN) {
// Titanium thru UF check
if (((static_cast<uint64>(1) << slot_id) & pmask) == 0) {
cv_conflict = true;
continue;
}
} else if (EQ::ValueWithin(slot_id, EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END)) {
}
else if (slot_id <= EQ::invbag::GENERAL_BAGS_END && slot_id >= EQ::invbag::GENERAL_BAGS_BEGIN) {
// 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 (EQ::ValueWithin(slot_id, EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END)) {
}
else if (slot_id <= EQ::invslot::BANK_END && slot_id >= EQ::invslot::BANK_BEGIN) {
// Titanium check
if ((slot_id - EQ::invslot::BANK_BEGIN) >= bank_size) {
cv_conflict = true;
continue;
}
} else if (EQ::ValueWithin(slot_id, EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END)) {
}
else if (slot_id <= EQ::invbag::BANK_BAGS_END && slot_id >= EQ::invbag::BANK_BAGS_BEGIN) {
// Titanium check
const auto parent_index = ((slot_id - EQ::invbag::BANK_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT);
if (parent_index >= bank_size) {
@@ -738,7 +721,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 [{}]",
@@ -749,7 +732,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile* inv)
continue;
}
auto* inst = CreateBaseItem(item, charges);
auto *inst = CreateBaseItem(item, charges);
if (!inst) {
continue;
}
@@ -762,13 +745,8 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile* inv)
inst->SetOrnamentationIDFile(ornament_idfile);
inst->SetOrnamentHeroModel(item->HerosForgeModel);
if (
instnodrop ||
(
inst->GetItem()->Attuneable &&
EQ::ValueWithin(slot_id, EQ::invslot::EQUIPMENT_BEGIN, EQ::invslot::EQUIPMENT_END)
)
) {
if (instnodrop || (inst->GetItem()->Attuneable && slot_id >= EQ::invslot::EQUIPMENT_BEGIN && slot_id <=
EQ::invslot::EQUIPMENT_END)) {
inst->SetAttuned(true);
}
@@ -776,37 +754,52 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile* inv)
inst->SetColor(color);
}
if (charges == std::numeric_limits<int16>::max()) {
if (charges == 0x7FFF) {
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 (augment_ids[i]) {
inst->PutAugment(this, i, augment_ids[i]);
if (aug[i]) {
inst->PutAugment(this, i, aug[i]);
}
}
}
int16 put_slot_id;
if (EQ::ValueWithin(slot_id, EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END)) {
if (slot_id >= 8000 && slot_id <= 8999) {
put_slot_id = inv->PushCursor(*inst);
} else {
}
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 {
put_slot_id = inv->PutItem(slot_id, *inst);
}
@@ -818,7 +811,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 for character_id [{}] item_id [{}] slot_id [{}]",
"Warning: Invalid slot_id for item in inventory: charid=[{}], item_id=[{}], slot_id=[{}]",
char_id,
item_id,
slot_id
@@ -827,7 +820,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,
@@ -847,6 +840,94 @@ 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;
@@ -1198,7 +1279,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, static_cast<int>(EQ::invbag::SLOT_COUNT)));
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.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,6 +104,7 @@ 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);
+4 -3
View File
@@ -83,7 +83,8 @@ struct ActivityInformation {
if (zone_ids.empty()) {
return true;
}
bool found_zone = std::find(zone_ids.begin(), zone_ids.end(), zone_id) != zone_ids.end();
bool found_zone = std::any_of(zone_ids.begin(), zone_ids.end(),
[zone_id](int id) { return id <= 0 || id == zone_id; });
return found_zone && (zone_version == version || zone_version == -1);
}
@@ -100,7 +101,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 objective zone column and task select "begins in" (may have multiple, "0" for "unknown zone", empty for "ALL")
out.WriteString(zones); // used in ui zone columns and task select "begins in" (may have multiple, invalid id for "Unknown Zone", empty for "ALL")
}
else
{
@@ -114,7 +115,7 @@ struct ActivityInformation {
out.WriteString(description_override);
if (client_version >= EQ::versions::ClientVersion::RoF) {
out.WriteString(zones); // serialized again after description (seems unused)
out.WriteString(zones); // target zone version internal id (unused client side)
}
}
+2 -2
View File
@@ -25,7 +25,7 @@
// Build variables
// these get injected during the build pipeline
#define CURRENT_VERSION "22.59.1-dev" // always append -dev to the current version for custom-builds
#define CURRENT_VERSION "22.60.0-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 9288
#define CURRENT_BINARY_DATABASE_VERSION 9286
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9045
#endif
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "eqemu-server",
"version": "22.59.1",
"version": "22.60.0",
"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.21.0 // indirect
golang.org/x/crypto v0.31.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.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
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/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,6 +142,7 @@ foreach my $table_to_generate (@tables) {
"guild_bank",
"inventory_versions",
"raid_leaders",
"sharedbank",
"trader_audit",
"eqtime",
"db_version",
+22 -16
View File
@@ -541,6 +541,17 @@ 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();
@@ -2369,26 +2380,21 @@ bool Client::StoreCharacter(
auto e = InventoryRepository::NewEntity();
e.character_id = character_id;
e.charid = 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.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();
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);
v.emplace_back(e);
}
+90 -66
View File
@@ -26,7 +26,6 @@
#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"
@@ -858,90 +857,115 @@ 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;
}
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
)
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
);
auto results = QueryDatabase(query);
if (!results.Success())
return false;
if (l.empty()) {
return true;
}
for (auto row = results.begin(); row != results.end(); ++row) {
int16 slot_id = Strings::ToInt(row[0]);
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 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 = content_db.GetItem(e.item_id);
if (!item) {
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;
}
EQ::ItemInstance *inst = content_db.CreateBaseItem(item, e.charges);
uint32 item_id = Strings::ToInt(row[1]);
int8 charges = Strings::ToInt(row[2]);
uint32 color = Strings::ToUnsignedInt(row[3]);
if (!inst) {
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]);
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)
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->SetCharges(e.charges);
inst->SetOrnamentIcon(ornament_icon);
inst->SetOrnamentationIDFile(ornament_idfile);
inst->SetOrnamentHeroModel(item->HerosForgeModel);
if (e.color > 0) {
inst->SetColor(e.color);
}
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 (augment_ids[i]) {
inst->PutAugment(this, i, augment_ids[i]);
}
if (aug[i])
inst->PutAugment(this, i, aug[i]);
}
}
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);
inv->PutItem(slot_id, *inst);
safe_delete(inst);
}
-5
View File
@@ -1564,11 +1564,6 @@ 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);
+7 -22
View File
@@ -1550,10 +1550,7 @@ 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(
"{} {}",
@@ -3078,10 +3075,7 @@ 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(
"{} {} {} {} {} {} {} {} {}",
@@ -3096,8 +3090,7 @@ 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)
@@ -4266,10 +4259,7 @@ 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(
"{} {} {} {} {} {} {} {} {}",
@@ -4284,17 +4274,13 @@ 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(
"{} {} {} {} {} {} {} {} {}",
@@ -4309,8 +4295,7 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
static_cast<int>(special)
);
},
0,
&args
0, &args
);
if (damage_override > 0) {
+4 -17
View File
@@ -1265,7 +1265,7 @@ void Bot::LoadAAs() {
}
while(current) {
if (!CanUseAlternateAdvancementRank(current)) {
if (current->level_req > GetLevel() || !CanUseAlternateAdvancementRank(current)) {
current = nullptr;
} else {
current = current->next;
@@ -3089,6 +3089,7 @@ bool Bot::Spawn(Client* botCharacterOwner) {
m_targetable = true;
entity_list.AddBot(this, true, true);
ClearDataBucketCache();
DataBucket::GetDataBuckets(this);
LoadBotSpellSettings();
if (!AI_AddBotSpells(GetBotSpellID())) {
@@ -4192,14 +4193,7 @@ 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) {
@@ -4264,14 +4258,7 @@ 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
+38 -38
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 = LDoNThemes::Unused;
adv_requested_theme = LDoNTheme::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 LDoNThemes::Unused: { // No theme, so distribute evenly across all
case LDoNTheme::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(LDoNThemes::Unused, split_points);
UpdateLDoNPoints(LDoNTheme::Unused, split_points);
}
break;
}
case LDoNThemes::GUK: {
case LDoNTheme::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 LDoNThemes::MIR: {
case LDoNTheme::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 LDoNThemes::MMC: {
case LDoNTheme::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 LDoNThemes::RUJ: {
case LDoNTheme::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 LDoNThemes::TAK: {
case LDoNTheme::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 LDoNThemes::GUK: {
case LDoNTheme::GUK: {
m_pp.ldon_points_guk = points;
break;
}
case LDoNThemes::MIR: {
case LDoNTheme::MIR: {
m_pp.ldon_points_mir = points;
break;
}
case LDoNThemes::MMC: {
case LDoNTheme::MMC: {
m_pp.ldon_points_mmc = points;
break;
}
case LDoNThemes::RUJ: {
case LDoNTheme::RUJ: {
m_pp.ldon_points_ruj = points;
break;
}
case LDoNThemes::TAK: {
case LDoNTheme::TAK: {
m_pp.ldon_points_tak = points;
break;
}
@@ -5676,15 +5676,15 @@ uint32 Client::GetLDoNPointsTheme(uint32 t)
{
switch(t)
{
case LDoNThemes::GUK:
case LDoNTheme::GUK:
return m_pp.ldon_points_guk;
case LDoNThemes::MIR:
case LDoNTheme::MIR:
return m_pp.ldon_points_mir;
case LDoNThemes::MMC:
case LDoNTheme::MMC:
return m_pp.ldon_points_mmc;
case LDoNThemes::RUJ:
case LDoNTheme::RUJ:
return m_pp.ldon_points_ruj;
case LDoNThemes::TAK:
case LDoNTheme::TAK:
return m_pp.ldon_points_tak;
default:
return 0;
@@ -5695,15 +5695,15 @@ uint32 Client::GetLDoNWinsTheme(uint32 t)
{
switch(t)
{
case LDoNThemes::GUK:
case LDoNTheme::GUK:
return m_pp.ldon_wins_guk;
case LDoNThemes::MIR:
case LDoNTheme::MIR:
return m_pp.ldon_wins_mir;
case LDoNThemes::MMC:
case LDoNTheme::MMC:
return m_pp.ldon_wins_mmc;
case LDoNThemes::RUJ:
case LDoNTheme::RUJ:
return m_pp.ldon_wins_ruj;
case LDoNThemes::TAK:
case LDoNTheme::TAK:
return m_pp.ldon_wins_tak;
default:
return 0;
@@ -5714,15 +5714,15 @@ uint32 Client::GetLDoNLossesTheme(uint32 t)
{
switch(t)
{
case LDoNThemes::GUK:
case LDoNTheme::GUK:
return m_pp.ldon_losses_guk;
case LDoNThemes::MIR:
case LDoNTheme::MIR:
return m_pp.ldon_losses_mir;
case LDoNThemes::MMC:
case LDoNTheme::MMC:
return m_pp.ldon_losses_mmc;
case LDoNThemes::RUJ:
case LDoNTheme::RUJ:
return m_pp.ldon_losses_ruj;
case LDoNThemes::TAK:
case LDoNTheme::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 LDoNThemes::GUK:
case LDoNTheme::GUK:
if (win) {
m_pp.ldon_wins_guk += (remove ? -1 : 1);
} else {
m_pp.ldon_losses_guk += (remove ? -1 : 1);
}
break;
case LDoNThemes::MIR:
case LDoNTheme::MIR:
if (win) {
m_pp.ldon_wins_mir += (remove ? -1 : 1);
} else {
m_pp.ldon_losses_mir += (remove ? -1 : 1);
}
break;
case LDoNThemes::MMC:
case LDoNTheme::MMC:
if (win) {
m_pp.ldon_wins_mmc += (remove ? -1 : 1);
} else {
m_pp.ldon_losses_mmc += (remove ? -1 : 1);
}
break;
case LDoNThemes::RUJ:
case LDoNTheme::RUJ:
if (win) {
m_pp.ldon_wins_ruj += (remove ? -1 : 1);
} else {
m_pp.ldon_losses_ruj += (remove ? -1 : 1);
}
break;
case LDoNThemes::TAK:
case LDoNTheme::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 = LDoNThemes::Unused;
adv_requested_theme = LDoNTheme::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(
"`character_id` = {} AND `slot_id` = {}",
"`charid` = {} AND `slotid` = {}",
character_id,
EQ::invslot::slotPrimary
)
@@ -9136,7 +9136,7 @@ void Client::SetPrimaryWeaponOrnamentation(uint32 model_id)
auto e = l.front();
e.ornament_idfile = model_id;
e.ornamentidfile = 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(
"`character_id` = {} AND `slot_id` = {}",
"`charid` = {} AND `slotid` = {}",
character_id,
EQ::invslot::slotSecondary
)
@@ -9169,7 +9169,7 @@ void Client::SetSecondaryWeaponOrnamentation(uint32 model_id)
auto e = l.front();
e.ornament_idfile = model_id;
e.ornamentidfile = model_id;
const int updated = InventoryRepository::UpdateOne(database, e);
+87 -148
View File
@@ -524,7 +524,6 @@ int Client::HandlePacket(const EQApplicationPacket *app)
// Finish client connecting state
void Client::CompleteConnect()
{
UpdateWho();
client_state = CLIENT_CONNECTED;
SendAllPackets();
@@ -913,10 +912,6 @@ 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()) {
@@ -1413,6 +1408,7 @@ 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
@@ -1639,6 +1635,11 @@ 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*/
@@ -2018,38 +2019,38 @@ void Client::Handle_OP_AdventureMerchantPurchase(const EQApplicationPacket *app)
return;
}
if (item->LDoNTheme <= LDoNThemeBits::TAKBit) {
if (item->LDoNTheme <= LDoNTheme::TAKBit) {
uint32 ldon_theme;
if (item->LDoNTheme & LDoNThemeBits::TAKBit) {
if (item->LDoNTheme & LDoNTheme::TAKBit) {
if (m_pp.ldon_points_tak < item_cost) {
cannot_afford = true;
ldon_theme = LDoNThemes::TAK;
ldon_theme = LDoNTheme::TAK;
}
} else if (item->LDoNTheme & LDoNThemeBits::RUJBit) {
} else if (item->LDoNTheme & LDoNTheme::RUJBit) {
if (m_pp.ldon_points_ruj < item_cost) {
cannot_afford = true;
ldon_theme = LDoNThemes::RUJ;
ldon_theme = LDoNTheme::RUJ;
}
} else if (item->LDoNTheme & LDoNThemeBits::MMCBit) {
} else if (item->LDoNTheme & LDoNTheme::MMCBit) {
if (m_pp.ldon_points_mmc < item_cost) {
cannot_afford = true;
ldon_theme = LDoNThemes::MMC;
ldon_theme = LDoNTheme::MMC;
}
} else if (item->LDoNTheme & LDoNThemeBits::MIRBit) {
} else if (item->LDoNTheme & LDoNTheme::MIRBit) {
if (m_pp.ldon_points_mir < item_cost) {
cannot_afford = true;
ldon_theme = LDoNThemes::MIR;
ldon_theme = LDoNTheme::MIR;
}
} else if (item->LDoNTheme & LDoNThemeBits::GUKBit) {
} else if (item->LDoNTheme & LDoNTheme::GUKBit) {
if (m_pp.ldon_points_guk < item_cost) {
cannot_afford = true;
ldon_theme = LDoNThemes::GUK;
ldon_theme = LDoNTheme::GUK;
}
}
merchant_type = fmt::format(
"{} Point{}",
EQ::constants::GetLDoNThemeName(ldon_theme),
LDoNTheme::GetName(ldon_theme),
item_cost != 1 ? "s" : ""
);
}
@@ -2193,19 +2194,19 @@ void Client::Handle_OP_AdventureMerchantRequest(const EQApplicationPacket *app)
item = database.GetItem(ml.item);
if (item) {
uint32 theme = LDoNThemes::Unused;
if (item->LDoNTheme > LDoNThemeBits::TAKBit) {
theme = LDoNThemes::Unused;
} else if (item->LDoNTheme & LDoNThemeBits::TAKBit) {
theme = LDoNThemes::TAK;
} else if (item->LDoNTheme & LDoNThemeBits::RUJBit) {
theme = LDoNThemes::RUJ;
} else if (item->LDoNTheme & LDoNThemeBits::MMCBit) {
theme = LDoNThemes::MMC;
} else if (item->LDoNTheme & LDoNThemeBits::MIRBit) {
theme = LDoNThemes::MIR;
} else if (item->LDoNTheme & LDoNThemeBits::GUKBit) {
theme = LDoNThemes::GUK;
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;
}
ss << "^" << item->Name << "|";
ss << item->ID << "|";
@@ -3246,30 +3247,14 @@ 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)) {
@@ -3301,29 +3286,13 @@ 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);
@@ -3393,30 +3362,14 @@ 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);
@@ -3481,30 +3434,14 @@ 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);
@@ -3980,6 +3917,10 @@ void Client::Handle_OP_BazaarSearch(const EQApplicationPacket *app)
SendBazaarWelcome();
break;
}
case FirstOpenSearch: {
SendBulkBazaarTraders();
break;
}
default: {
LogError("Malformed BazaarSearch_Struct packet received, ignoring\n");
}
@@ -4474,14 +4415,7 @@ 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)) {
@@ -4513,14 +4447,7 @@ 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)) {
@@ -9586,14 +9513,7 @@ 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)) {
@@ -9657,14 +9577,7 @@ 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)) {
@@ -10764,7 +10677,8 @@ void Client::Handle_OP_MoveCoin(const EQApplicationPacket *app)
void Client::Handle_OP_MoveItem(const EQApplicationPacket *app)
{
if (!CharacterID()) {
if (!CharacterID())
{
return;
}
@@ -10773,35 +10687,60 @@ 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)
+37 -57
View File
@@ -770,83 +770,65 @@ void Client::BulkSendInventoryItems()
EQ::OutBuffer ob;
EQ::OutBuffer::pos_type last_pos = ob.tellp();
// Equipment items
for (int16 slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; slot_id++) {
// Possessions items
for (int16 slot_id = EQ::invslot::POSSESSIONS_BEGIN; slot_id <= EQ::invslot::POSSESSIONS_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();
}
// 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;
}
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();
}
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;
}
// 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);
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;
}
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);
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);
@@ -858,8 +840,6 @@ 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;
+2 -2
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 + EQ::invbag::SLOT_COUNT) {
if (item->equip_slot >= bagstart && item->equip_slot < bagstart + 10) {
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[EQ::invbag::SLOT_COUNT] = {};
LootItem *item_data = nullptr, *bag_item_data[10] = {};
memset(bag_item_data, 0, sizeof(bag_item_data));
if (GetPlayerKillItem() > 1) {
+152 -274
View File
@@ -8,7 +8,7 @@
extern WorldServer worldserver;
std::vector<DataBucketCacheEntry> g_data_bucket_cache = {};
std::vector<DataBucketsRepository::DataBuckets> 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) {
// 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;
// update the cache if it exists
if (CanCache(k)) {
for (auto &e: g_data_bucket_cache) {
if (CheckBucketMatch(e, k)) {
e = b;
break;
}
}
}
@@ -74,28 +74,18 @@ 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)
{
DataBucketKey k = {};
k.key = bucket_key;
return GetData(k).value;
return GetData(DataBucketKey{.key = bucket_key}).value;
}
// GetData fetches bucket data from the database or cache if it exists
@@ -112,22 +102,27 @@ DataBucketsRepository::DataBuckets DataBucket::GetData(const DataBucketKey &k, b
k.npc_id
);
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();
}
bool can_cache = CanCache(k);
// 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();
}
// 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();
}
LogDataBuckets("Returning key [{}] value [{}] from cache", ce.e.key_, ce.e.value);
return ce.e;
// 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;
}
}
}
@@ -144,23 +139,21 @@ 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
if (!ignore_misses_cache) {
bool add_to_misses_cache = !ignore_misses_cache && can_cache;
if (add_to_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(
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()
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
}
);
@@ -178,60 +171,54 @@ DataBucketsRepository::DataBuckets DataBucket::GetData(const DataBucketKey &k, b
return {};
}
auto bucket = r.front();
// if the entry has expired, delete it
if (r[0].expires > 0 && r[0].expires < (long long) std::time(nullptr)) {
if (bucket.expires > 0 && bucket.expires < (long long) std::time(nullptr)) {
DeleteData(k);
return {};
}
bool has_cache = false;
for (auto &ce: g_data_bucket_cache) {
if (ce.e.id == r[0].id) {
has_cache = true;
break;
// 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);
}
}
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];
return bucket;
}
std::string DataBucket::GetDataExpires(const std::string &bucket_key)
{
DataBucketKey k = {};
k.key = bucket_key;
return GetDataExpires(k);
return GetDataExpires(DataBucketKey{.key = bucket_key});
}
std::string DataBucket::GetDataRemaining(const std::string &bucket_key)
{
DataBucketKey k = {};
k.key = bucket_key;
return GetDataRemaining(k);
return GetDataRemaining(DataBucketKey{.key = bucket_key});
}
bool DataBucket::DeleteData(const std::string &bucket_key)
{
DataBucketKey k = {};
k.key = bucket_key;
return DeleteData(k);
return DeleteData(DataBucketKey{.key = bucket_key});
}
// 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;
@@ -243,46 +230,39 @@ bool DataBucket::GetDataBuckets(Mob *mob)
else if (mob->IsClient()) {
t = DataBucketLoadType::Client;
}
else if (mob->IsNPC()) {
t = DataBucketLoadType::NPC;
}
BulkLoadEntities(t, {id});
BulkLoadEntitiesToCache(t, {id});
return true;
}
bool DataBucket::DeleteData(const DataBucketKey &k)
{
size_t size_before = g_data_bucket_cache.size();
if (CanCache(k)) {
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(),
[&](DataBucketCacheEntry &ce) {
bool match = CheckBucketMatch(ce.e, k);
if (match) {
ce.update_action = DataBucketCacheUpdateAction::Delete;
SendDataBucketCacheUpdate(ce);
// 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);
}
),
g_data_bucket_cache.end()
);
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()
);
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,
@@ -371,23 +351,21 @@ bool DataBucket::CheckBucketMatch(const DataBucketsRepository::DataBuckets &dbe,
);
}
void DataBucket::BulkLoadEntities(DataBucketLoadType::Type t, std::vector<uint32> ids)
void DataBucket::BulkLoadEntitiesToCache(DataBucketLoadType::Type t, std::vector<uint32> ids)
{
if (ids.empty()) {
return;
}
if (ids.size() == 1) {
bool has_cache = false;
for (const auto &ce: g_data_bucket_cache) {
bool has_cache = false;
for (const auto &e: g_data_bucket_cache) {
if (t == DataBucketLoadType::Bot) {
has_cache = ce.e.bot_id == ids[0];
has_cache = e.bot_id == ids[0];
}
else if (t == DataBucketLoadType::Client) {
has_cache = ce.e.character_id == ids[0];
}
else if (t == DataBucketLoadType::NPC) {
has_cache = ce.e.npc_id == ids[0];
has_cache = e.character_id == ids[0];
}
}
@@ -406,9 +384,6 @@ void DataBucket::BulkLoadEntities(DataBucketLoadType::Type t, std::vector<uint32
case DataBucketLoadType::Client:
column = "character_id";
break;
case DataBucketLoadType::NPC:
column = "npc_id";
break;
default:
LogError("Incorrect LoadType [{}]", static_cast<int>(t));
break;
@@ -442,12 +417,7 @@ void DataBucket::BulkLoadEntities(DataBucketLoadType::Type t, std::vector<uint32
if (!ExistsInCache(e)) {
LogDataBucketsDetail("bucket id [{}] bucket key [{}] bucket value [{}]", e.id, e.key_, e.value);
g_data_bucket_cache.emplace_back(
DataBucketCacheEntry{
.e = e,
.updated_time = GetCurrentTimeUNIX()
}
);
g_data_bucket_cache.emplace_back(e);
}
}
@@ -461,7 +431,7 @@ void DataBucket::BulkLoadEntities(DataBucketLoadType::Type t, std::vector<uint32
);
}
void DataBucket::DeleteCachedBuckets(DataBucketLoadType::Type t, uint32 id)
void DataBucket::DeleteCachedBuckets(DataBucketLoadType::Type type, uint32 id)
{
size_t size_before = g_data_bucket_cache.size();
@@ -469,11 +439,10 @@ void DataBucket::DeleteCachedBuckets(DataBucketLoadType::Type t, uint32 id)
std::remove_if(
g_data_bucket_cache.begin(),
g_data_bucket_cache.end(),
[&](DataBucketCacheEntry &ce) {
[&](DataBucketsRepository::DataBuckets &e) {
return (
(t == DataBucketLoadType::Bot && ce.e.bot_id == id) ||
(t == DataBucketLoadType::Client && ce.e.character_id == id) ||
(t == DataBucketLoadType::NPC && ce.e.npc_id == id)
(type == DataBucketLoadType::Bot && e.bot_id == id) ||
(type == DataBucketLoadType::Client && e.character_id == id)
);
}
),
@@ -482,24 +451,17 @@ void DataBucket::DeleteCachedBuckets(DataBucketLoadType::Type t, uint32 id)
LogDataBuckets(
"LoadType [{}] id [{}] cache size before [{}] after [{}]",
DataBucketLoadType::Name[t],
DataBucketLoadType::Name[type],
id,
size_before,
g_data_bucket_cache.size()
);
}
int64_t DataBucket::GetCurrentTimeUNIX()
bool DataBucket::ExistsInCache(const DataBucketsRepository::DataBuckets &entry)
{
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) {
for (const auto &e: g_data_bucket_cache) {
if (e.id == entry.id) {
return true;
}
}
@@ -507,134 +469,6 @@ bool DataBucket::ExistsInCache(const DataBucketsRepository::DataBuckets &e)
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
@@ -645,11 +479,11 @@ void DataBucket::DeleteFromMissesCache(DataBucketsRepository::DataBuckets e)
std::remove_if(
g_data_bucket_cache.begin(),
g_data_bucket_cache.end(),
[&](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;
[&](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;
}
),
g_data_bucket_cache.end()
@@ -667,3 +501,47 @@ 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;
}
+5 -34
View File
@@ -1,7 +1,3 @@
//
// Created by Akkadius on 7/7/18.
//
#ifndef EQEMU_DATABUCKET_H
#define EQEMU_DATABUCKET_H
@@ -12,27 +8,6 @@
#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;
@@ -46,14 +21,12 @@ namespace DataBucketLoadType {
enum Type : uint8 {
Bot,
Client,
NPC,
MaxType
};
static const std::string Name[Type::MaxType] = {
"Bot",
"Client",
"NPC",
};
}
@@ -68,8 +41,6 @@ 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);
@@ -80,15 +51,15 @@ public:
// bucket repository versus key matching
static bool CheckBucketMatch(const DataBucketsRepository::DataBuckets &dbe, const DataBucketKey &k);
static bool ExistsInCache(const DataBucketsRepository::DataBuckets &e);
static bool ExistsInCache(const DataBucketsRepository::DataBuckets &entry);
static void BulkLoadEntities(DataBucketLoadType::Type t, std::vector<uint32> ids);
static void DeleteCachedBuckets(DataBucketLoadType::Type t, uint32 id);
static void BulkLoadEntitiesToCache(DataBucketLoadType::Type t, std::vector<uint32> ids);
static void DeleteCachedBuckets(DataBucketLoadType::Type type, 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.arg[1]);
ExportVar(package_name.c_str(), "payload_value", sep.argplus[1]);
break;
}
+19 -19
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 + (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 == "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 == "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;
+2 -14
View File
@@ -1817,25 +1817,13 @@ 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);
}
}
+13
View File
@@ -1,6 +1,7 @@
#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"
@@ -11,6 +12,7 @@
#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"
@@ -47,6 +49,7 @@ 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",
@@ -65,6 +68,16 @@ 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
@@ -0,0 +1,95 @@
#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 '%%{}%%' ORDER BY `id` ASC LIMIT 50",
"LOWER(`name`) LIKE '%%{}%%' AND `name` NOT LIKE '%-deleted-%' 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
@@ -0,0 +1,65 @@
#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()
);
}
+15 -13
View File
@@ -3,20 +3,21 @@
void SetAdventurePoints(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
const uint16 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 : EQ::constants::GetLDoNThemeMap()) {
if (e.first != LDoNThemes::Unused) {
for (const auto& e : ldon_theme_names) {
if (e.first != LDoNTheme::Unused) {
c->Message(
Chat::White,
fmt::format(
"Theme {} | {}",
"Theme {} | {} ({})",
e.first,
e.second
e.second.first,
e.second.second
).c_str()
);
}
@@ -25,25 +26,26 @@ void SetAdventurePoints(Client *c, const Seperator *sep)
return;
}
auto t = c;
Client* 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 (!EQ::ValueWithin(theme_id, LDoNThemes::GUK, LDoNThemes::TAK)) {
if (!LDoNTheme::IsValid(theme_id)) {
c->Message(Chat::White, "Valid themes are as follows:");
for (const auto& e : EQ::constants::GetLDoNThemeMap()) {
if (e.first != LDoNThemes::Unused) {
for (const auto& e : ldon_theme_names) {
if (e.first != LDoNTheme::Unused) {
c->Message(
Chat::White,
fmt::format(
"Theme {} | {}",
"Theme {} | {} ({})",
e.first,
e.second
e.second.first,
e.second.second
).c_str()
);
}
@@ -56,7 +58,7 @@ void SetAdventurePoints(Client *c, const Seperator *sep)
Chat::White,
fmt::format(
"Set {} Points to {} for {}.",
EQ::constants::GetLDoNThemeName(theme_id),
LDoNTheme::GetName(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 : EQ::constants::GetLDoNThemeMap()) {
for (const auto& l : ldon_theme_names) {
const uint32 ldon_currency_value = t->GetLDoNPointsTheme(l.first);
if (ldon_currency_value) {
currency_table += DialogueWindow::TableRow(
DialogueWindow::TableCell(l.second) +
DialogueWindow::TableCell(l.second.first) +
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 {} | {} ({}){}",
(14000 + limboIndex),
(8000 + limboIndex),
item_data->ID,
linker.GenerateLink(),
(
@@ -339,7 +339,7 @@ void ShowInventory(Client *c, const Seperator *sep)
Chat::White,
fmt::format(
"Slot {} (Augment Slot {}) | {} ({}){}",
(14000 + limboIndex),
(8000 + 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 {} | {} ({}){}",
(14000 + limboIndex),
(8000 + 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 {}) | {} ({}){}",
(14000 + limboIndex),
(8000 + 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)MainTankName.compare(mob_name));
return !((bool)MainAssistName.compare(mob_name));
}
bool Group::AmIPuller(const char *mob_name)
-2
View File
@@ -63,7 +63,6 @@ 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);
@@ -73,7 +72,6 @@ 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);
+14 -40
View File
@@ -1909,20 +1909,13 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
return false;
}
//verify shared bank transactions in the database
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 (src_inst && src_slot_id >= EQ::invslot::SHARED_BANK_BEGIN && src_slot_id <= 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 (EQ::ValueWithin(src_slot_id, EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END) && src_inst->IsClassBag()){
if (src_slot_id >= EQ::invslot::SHARED_BANK_BEGIN && src_slot_id <= 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)){
@@ -1931,21 +1924,13 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
}
}
}
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 (dst_inst && dst_slot_id >= EQ::invslot::SHARED_BANK_BEGIN && dst_slot_id <= 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 (EQ::ValueWithin(dst_slot_id, EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END) && dst_inst->IsClassBag()){
if (dst_slot_id >= EQ::invslot::SHARED_BANK_BEGIN && dst_slot_id <= 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)){
@@ -1958,20 +1943,10 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
// Check for No Drop Hacks
Mob* with = trade->With();
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()
) {
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()) {
auto ndh_inst = m_inv[src_slot_id];
std::string ndh_item_data;
if (ndh_inst == nullptr) {
@@ -3666,7 +3641,7 @@ bool Client::InterrogateInventory(Client* requester, bool log, bool silent, bool
if (cursor_itr == m_inv.cursor_cbegin())
continue;
instmap[EQ::invbag::CURSOR_BAG_BEGIN + limbo] = *cursor_itr;
instmap[8000 + limbo] = *cursor_itr;
}
// call InterrogateInventory_ for error check
@@ -3769,12 +3744,11 @@ 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 (
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)
) {
(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)) {
switch (depth)
{
case 0: // requirement: inst is extant
+45 -32
View File
@@ -572,6 +572,8 @@ Mob::~Mob()
m_close_mobs.clear();
ClearDataBucketCache();
LeaveHealRotationTargetPool();
}
@@ -2048,19 +2050,19 @@ void Mob::SendStatsWindow(Client* c, bool use_window)
case 0: {
mod2a_name = "Avoidance";
mod2b_name = "Combat Effects";
mod2a_cap = Strings::Commify(RuleI(Character, ItemAvoidanceCap));
mod2b_cap = Strings::Commify(RuleI(Character, ItemCombatEffectsCap));
mod2a_cap = RuleI(Character, ItemAvoidanceCap);
mod2b_cap = RuleI(Character, ItemCombatEffectsCap);
if (IsBot()) {
mod2a = Strings::Commify(CastToBot()->GetAvoidance());
mod2a = CastToBot()->GetAvoidance();
} else if (IsClient()) {
mod2a = Strings::Commify(CastToClient()->GetAvoidance());
mod2a = CastToClient()->GetAvoidance();
}
if (IsBot()) {
mod2b = Strings::Commify(CastToBot()->GetCombatEffects());
mod2b = CastToBot()->GetCombatEffects();
} else if (IsClient()) {
mod2b = Strings::Commify(CastToClient()->GetCombatEffects());
mod2b = CastToClient()->GetCombatEffects();
}
break;
@@ -2068,19 +2070,19 @@ void Mob::SendStatsWindow(Client* c, bool use_window)
case 1: {
mod2a_name = "Accuracy";
mod2b_name = "Strikethrough";
mod2a_cap = Strings::Commify(RuleI(Character, ItemAccuracyCap));
mod2b_cap = Strings::Commify(RuleI(Character, ItemStrikethroughCap));
mod2a_cap = RuleI(Character, ItemAccuracyCap);
mod2b_cap = RuleI(Character, ItemStrikethroughCap);
if (IsBot()) {
mod2a = Strings::Commify(CastToBot()->GetAccuracy());
mod2a = CastToBot()->GetAccuracy();
} else if (IsClient()) {
mod2a = Strings::Commify(CastToClient()->GetAccuracy());
mod2a = CastToClient()->GetAccuracy();
}
if (IsBot()) {
mod2b = Strings::Commify(CastToBot()->GetStrikeThrough());
mod2b = CastToBot()->GetStrikeThrough();
} else if (IsClient()) {
mod2b = Strings::Commify(CastToClient()->GetStrikeThrough());
mod2b = CastToClient()->GetStrikeThrough();
}
break;
@@ -2088,20 +2090,20 @@ void Mob::SendStatsWindow(Client* c, bool use_window)
case 2: {
mod2a_name = "Shielding";
mod2b_name = "Spell Shielding";
mod2a_cap = Strings::Commify(RuleI(Character, ItemShieldingCap));
mod2b_cap = Strings::Commify(RuleI(Character, ItemSpellShieldingCap));
mod2a_cap = RuleI(Character, ItemShieldingCap);
mod2b_cap = RuleI(Character, ItemSpellShieldingCap);
if (IsBot()) {
mod2a = Strings::Commify(CastToBot()->GetShielding());
mod2a = CastToBot()->GetShielding();
} else if (IsClient()) {
mod2a = Strings::Commify(CastToClient()->GetShielding());
mod2a = CastToClient()->GetShielding();
}
if (IsBot()) {
mod2b = Strings::Commify(CastToBot()->GetSpellShield());
mod2b = CastToBot()->GetSpellShield();
} else if (IsClient()) {
mod2b = Strings::Commify(CastToClient()->GetSpellShield());
mod2b = CastToClient()->GetSpellShield();
}
break;
@@ -2109,19 +2111,19 @@ void Mob::SendStatsWindow(Client* c, bool use_window)
case 3: {
mod2a_name = "Stun Resist";
mod2b_name = "DOT Shielding";
mod2a_cap = Strings::Commify(RuleI(Character, ItemStunResistCap));
mod2b_cap = Strings::Commify(RuleI(Character, ItemDoTShieldingCap));
mod2a_cap = RuleI(Character, ItemStunResistCap);
mod2b_cap = RuleI(Character, ItemDoTShieldingCap);
if (IsBot()) {
mod2a = Strings::Commify(CastToBot()->GetStunResist());
mod2a = CastToBot()->GetStunResist();
} else if (IsClient()) {
mod2a = Strings::Commify(CastToClient()->GetStunResist());
mod2a = CastToClient()->GetStunResist();
}
if (IsBot()) {
mod2b = Strings::Commify(CastToBot()->GetDoTShield());
mod2b = CastToBot()->GetDoTShield();
} else if (IsClient()) {
mod2b = Strings::Commify(CastToClient()->GetDoTShield());
mod2b = CastToClient()->GetDoTShield();
}
break;
@@ -5325,14 +5327,7 @@ 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;
@@ -8613,3 +8608,21 @@ 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,6 +1491,8 @@ 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);
+11 -3
View File
@@ -1815,12 +1815,18 @@ 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) {
if (
CastToNPC()->GetCombatEvent() &&
GetHP() > 0 &&
entity_list.GetNPCByID(GetID())
) {
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_COMBAT)) {
parse->EventNPC(EVENT_COMBAT, CastToNPC(), nullptr, "0", 0);
}
const uint32 emote_id = CastToNPC()->GetEmoteID();
if (emote_id) {
CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::LeaveCombat, emote_id);
@@ -1829,6 +1835,8 @@ void Mob::AI_Event_NoLongerEngaged() {
m_combat_record.Stop();
CastToNPC()->SetCombatEvent(false);
}
} else {
parse->EventBotMerc(EVENT_COMBAT, this, nullptr, [&]() { return "0"; });
}
}
+34 -8
View File
@@ -3297,16 +3297,28 @@ uint32 NPC::GetSpawnKillCount()
return(0);
}
void NPC::DoQuestPause(Mob *other) {
if(IsMoving() && !IsOnHatelist(other)) {
PauseWandering(RuleI(NPC, SayPauseTimeInSec));
if (other && !other->sneaking)
FaceTarget(other);
} else if(!IsMoving()) {
if (other && !other->sneaking && GetAppearance() != eaSitting && GetAppearance() != eaDead)
FaceTarget(other);
void NPC::DoQuestPause(Mob* m)
{
if (!m) {
return;
}
if (IsMoving() && !IsOnHatelist(m)) {
PauseWandering(RuleI(NPC, SayPauseTimeInSec));
if (FacesTarget() && !m->sneaking) {
FaceTarget(m);
}
} else if (!IsMoving()) {
if (
FacesTarget() &&
!m->sneaking &&
GetAppearance() != eaSitting &&
GetAppearance() != eaDead
) {
FaceTarget(m);
}
}
}
void NPC::ChangeLastName(std::string last_name)
@@ -4238,3 +4250,17 @@ 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 -1
View File
@@ -482,7 +482,8 @@ 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 *other);
void DoQuestPause(Mob* m);
bool FacesTarget();
inline void SetSpellScale(float amt) { spellscale = amt; }
inline float GetSpellScale() { return spellscale; }
+13
View File
@@ -278,6 +278,19 @@ 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();
+13 -52
View File
@@ -91,13 +91,7 @@ void QuestManager::Process() {
if (cur->Timer_.Enabled() && cur->Timer_.Check()) {
if (cur->mob) {
if (cur->mob->IsEncounter()) {
parse->EventEncounter(
EVENT_TIMER,
cur->mob->CastToEncounter()->GetEncounterName(),
cur->name,
0,
nullptr
);
parse->EventEncounter(EVENT_TIMER, cur->mob->CastToEncounter()->GetEncounterName(), cur->name, 0, nullptr);
} else {
parse->EventMob(EVENT_TIMER, cur->mob, nullptr, [&]() { return cur->name; }, 0);
}
@@ -661,14 +655,7 @@ void QuestManager::stoptimer(const std::string& timer_name)
for (auto e = QTimerList.begin(); e != QTimerList.end(); ++e) {
if (e->mob && e->mob == owner && e->name == timer_name) {
parse->EventMob(
EVENT_TIMER_STOP,
owner,
nullptr,
[&]() {
return timer_name;
}
);
parse->EventMob(EVENT_TIMER_STOP, owner, nullptr, [&]() { return timer_name; });
QTimerList.erase(e);
break;
@@ -695,14 +682,7 @@ void QuestManager::stoptimer(const std::string& timer_name, Mob* m)
for (auto e = QTimerList.begin(); e != QTimerList.end();) {
if (e->mob && e->mob == m) {
parse->EventMob(
EVENT_TIMER_STOP,
m,
nullptr,
[&]() {
return timer_name;
}
);
parse->EventMob(EVENT_TIMER_STOP, m, nullptr, [&]() { return timer_name; });
QTimerList.erase(e);
break;
@@ -743,14 +723,7 @@ void QuestManager::stopalltimers()
for (auto e = QTimerList.begin(); e != QTimerList.end();) {
if (e->mob && e->mob == owner) {
parse->EventMob(
EVENT_TIMER_STOP,
owner,
nullptr,
[&]() {
return e->name;
}
);
parse->EventMob(EVENT_TIMER_STOP, owner, nullptr, [&]() { return e->name; });
e = QTimerList.erase(e);
} else {
@@ -792,14 +765,7 @@ void QuestManager::stopalltimers(Mob* m)
for (auto e = QTimerList.begin(); e != QTimerList.end();) {
if (e->mob && e->mob == m) {
parse->EventMob(
EVENT_TIMER_STOP,
m,
nullptr,
[&]() {
return e->name;
}
);
parse->EventMob(EVENT_TIMER_STOP, m, nullptr, [&]() { return e->name; });
e = QTimerList.erase(e);
} else {
@@ -853,18 +819,13 @@ void QuestManager::pausetimer(const std::string& timer_name, Mob* m)
}
);
parse->EventMob(
EVENT_TIMER_PAUSE,
mob,
nullptr,
[&]() {
return fmt::format(
"{} {}",
timer_name,
milliseconds
);
}
);
parse->EventMob(EVENT_TIMER_PAUSE, mob, nullptr, [&]() {
return fmt::format(
"{} {}",
timer_name,
milliseconds
);
});
LogQuests("Pausing timer [{}] for [{}] with [{}] ms remaining", timer_name, owner->GetName(), milliseconds);
}
@@ -1326,7 +1287,7 @@ std::string QuestManager::getskillname(int skill_id) {
}
std::string QuestManager::getldonthemename(uint32 theme_id) {
return EQ::constants::GetLDoNThemeName(theme_id);
return LDoNTheme::GetName(theme_id);
}
std::string QuestManager::getfactionname(int faction_id) {
+20 -38
View File
@@ -256,22 +256,15 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
Mob* spell_target = entity_list.GetMobID(target_id);
std::vector<std::any> args = { spell_target };
int return_value = parse->EventMob(
EVENT_CAST_BEGIN,
this,
nullptr,
[&]() {
return fmt::format(
"{} {} {} {}",
spell_id,
GetID(),
GetCasterLevel(spell_id),
target_id
);
},
0,
&args
);
int return_value = parse->EventMob(EVENT_CAST_BEGIN, this, nullptr, [&]() {
return fmt::format(
"{} {} {} {}",
spell_id,
GetID(),
GetCasterLevel(spell_id),
target_id
);
}, 0, &args);
if (IsClient() && return_value != 0) {
if (IsDiscipline(spell_id)) {
@@ -1804,22 +1797,15 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo
std::vector<std::any> args = { spell_target };
parse->EventMob(
EVENT_CAST,
this,
nullptr,
[&]() {
return fmt::format(
"{} {} {} {}",
spell_id,
GetID(),
GetCasterLevel(spell_id),
target_id
);
},
0,
&args
);
parse->EventMob(EVENT_CAST, this, nullptr, [&]() {
return fmt::format(
"{} {} {} {}",
spell_id,
GetID(),
GetCasterLevel(spell_id),
target_id
);
}, 0, &args);
if(bard_song_mode)
{
@@ -3965,10 +3951,7 @@ bool Mob::SpellOnTarget(
std::vector<std::any> args = { spelltar };
parse->EventMob(
EVENT_CAST_ON,
spelltar,
this,
parse->EventMob(EVENT_CAST_ON, spelltar, this,
[&]() {
return fmt::format(
"{} {} {} {}",
@@ -3978,8 +3961,7 @@ bool Mob::SpellOnTarget(
target_id
);
},
0,
&args
0, &args
);
if (!DoCastingChecksOnTarget(false, spell_id, spelltar)) {
+34 -26
View File
@@ -777,6 +777,8 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st
tradingWith->SayString(TRADE_BACK, GetCleanName());
PushItemOnCursor(*inst, true);
}
items.clear();
}
// Only enforce trade rules if the NPC doesn't have an EVENT_TRADE
// subroutine. That overrides all.
@@ -1091,15 +1093,16 @@ void Client::TraderStartTrader(const EQApplicationPacket *app)
inst->SetPrice(in->item_cost[i]);
TraderRepository::Trader trader_item{};
trader_item.id = 0;
trader_item.char_entity_id = GetID();
trader_item.char_id = CharacterID();
trader_item.char_zone_id = GetZoneID();
trader_item.item_charges = inst->GetCharges() == 0 ? 1 : inst->GetCharges();
trader_item.item_cost = inst->GetPrice();
trader_item.item_id = inst->GetID();
trader_item.item_sn = in->serial_number[i];
trader_item.slot_id = i;
trader_item.id = 0;
trader_item.char_entity_id = GetID();
trader_item.char_id = CharacterID();
trader_item.char_zone_id = GetZoneID();
trader_item.char_zone_instance_id = GetInstanceID();
trader_item.item_charges = inst->GetCharges() == 0 ? 1 : inst->GetCharges();
trader_item.item_cost = inst->GetPrice();
trader_item.item_id = inst->GetID();
trader_item.item_sn = in->serial_number[i];
trader_item.slot_id = i;
if (inst->IsAugmented()) {
auto augs = inst->GetAugmentIDs();
trader_item.aug_slot_1 = augs.at(0);
@@ -1794,7 +1797,7 @@ void Client::SendBarterWelcome()
void Client::DoBazaarSearch(BazaarSearchCriteria_Struct search_criteria)
{
auto results = Bazaar::GetSearchResults(database, search_criteria, GetZoneID());
auto results = Bazaar::GetSearchResults(database, search_criteria, GetZoneID(), GetInstanceID());
if (results.empty()) {
SendBazaarDone(GetID());
return;
@@ -2913,10 +2916,11 @@ void Client::SendBecomeTraderToWorld(Client *trader, BazaarTraderBarterActions a
auto outapp = new ServerPacket(ServerOP_TraderMessaging, sizeof(TraderMessaging_Struct));
auto data = (TraderMessaging_Struct *) outapp->pBuffer;
data->action = action;
data->entity_id = trader->GetID();
data->trader_id = trader->CharacterID();
data->zone_id = trader->GetZoneID();
data->action = action;
data->entity_id = trader->GetID();
data->trader_id = trader->CharacterID();
data->zone_id = trader->GetZoneID();
data->instance_id = trader->GetInstanceID();
strn0cpy(data->trader_name, trader->GetName(), sizeof(data->trader_name));
worldserver.SendPacket(outapp);
@@ -2937,9 +2941,11 @@ void Client::SendBecomeTrader(BazaarTraderBarterActions action, uint32 entity_id
auto outapp = new EQApplicationPacket(OP_BecomeTrader, sizeof(BecomeTrader_Struct));
auto data = (BecomeTrader_Struct *) outapp->pBuffer;
data->action = action;
data->entity_id = trader->GetID();
data->trader_id = trader->CharacterID();
data->action = action;
data->entity_id = trader->GetID();
data->trader_id = trader->CharacterID();
data->zone_id = trader->GetZoneID();
data->zone_instance_id = trader->GetInstanceID();
strn0cpy(data->trader_name, trader->GetCleanName(), sizeof(data->trader_name));
QueuePacket(outapp);
@@ -3085,14 +3091,15 @@ void Client::TraderPriceUpdate(const EQApplicationPacket *app)
auto item_detail = FindTraderItemBySerialNumber(newgis->serial_number[i]);
TraderRepository::Trader trader_item{};
trader_item.id = 0;
trader_item.char_entity_id = GetID();
trader_item.char_id = CharacterID();
trader_item.char_zone_id = GetZoneID();
trader_item.item_charges = newgis->charges[i];
trader_item.item_cost = tpus->NewPrice;
trader_item.item_id = newgis->items[i];
trader_item.item_sn = newgis->serial_number[i];
trader_item.id = 0;
trader_item.char_entity_id = GetID();
trader_item.char_id = CharacterID();
trader_item.char_zone_id = GetZoneID();
trader_item.char_zone_instance_id = GetInstanceID();
trader_item.item_charges = newgis->charges[i];
trader_item.item_cost = tpus->NewPrice;
trader_item.item_id = newgis->items[i];
trader_item.item_sn = newgis->serial_number[i];
if (item_detail->IsAugmented()) {
auto augs = item_detail->GetAugmentIDs();
trader_item.aug_slot_1 = augs.at(0);
@@ -3221,7 +3228,8 @@ void Client::SendBulkBazaarTraders()
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, results.count);
for (auto t : results.traders) {
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, t.zone_id);
VARSTRUCT_ENCODE_TYPE(uint16, bufptr, t.zone_id);
VARSTRUCT_ENCODE_TYPE(uint16, bufptr, t.zone_instance_id);
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, t.trader_id);
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, t.entity_id);
VARSTRUCT_ENCODE_STRING(bufptr, t.trader_name.c_str());
+7 -10
View File
@@ -3644,11 +3644,6 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
SharedTaskZoneMessaging::HandleWorldMessage(pack);
break;
}
case ServerOP_DataBucketCacheUpdate:
{
DataBucket::HandleWorldMessage(pack);
break;
}
case ServerOP_GuildTributeUpdate: {
GuildTributeUpdate* in = (GuildTributeUpdate*)pack->pBuffer;
@@ -3934,15 +3929,17 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
out->action = 0;
}
}
out->entity_id = in->entity_id;
out->zone_id = in->zone_id;
out->trader_id = in->trader_id;
out->entity_id = in->entity_id;
out->zone_id = in->zone_id;
out->zone_instance_id = in->instance_id;
out->trader_id = in->trader_id;
strn0cpy(out->trader_name, in->trader_name, sizeof(out->trader_name));
c.second->QueuePacket(outapp);
c.second->QueuePacket(outapp, true, Mob::CLIENT_CONNECTED);
safe_delete(outapp);
}
if (zone && zone->GetZoneID() == Zones::BAZAAR) {
if (zone && zone->GetZoneID() == Zones::BAZAAR && in->instance_id == zone->GetInstanceID()) {
if (in->action == TraderOn) {
c.second->SendBecomeTrader(TraderOn, in->entity_id);
}
-2
View File
@@ -1923,8 +1923,6 @@ const NPCType *ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load
}
}
DataBucket::BulkLoadEntities(DataBucketLoadType::NPC, npc_ids);
if (!npc_faction_ids.empty()) {
zone->LoadNPCFactions(npc_faction_ids);
zone->LoadNPCFactionAssociations(npc_faction_ids);
+4 -4
View File
@@ -208,10 +208,10 @@ struct ZoneSpellsBlocked {
};
struct TraderCharges_Struct {
uint32 ItemID[EQ::invtype::BAZAAR_SIZE];
int32 SerialNumber[EQ::invtype::BAZAAR_SIZE];
uint32 ItemCost[EQ::invtype::BAZAAR_SIZE];
int32 Charges[EQ::invtype::BAZAAR_SIZE];
uint32 ItemID[80];
int32 SerialNumber[80];
uint32 ItemCost[80];
int32 Charges[80];
};
const int MaxMercStanceID = 9;