mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-23 13:12:28 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 22fb7b22b4 |
-158
@@ -1,161 +1,3 @@
|
||||
## [23.0.2] 2/21/2025
|
||||
|
||||
### Bots
|
||||
|
||||
* Add checks to ensure bots and pets do not engage on ^pull ([#4708](https://github.com/EQEmu/Server/pull/4708)) @nytmyr 2025-02-22
|
||||
* Improve positioning ([#4709](https://github.com/EQEmu/Server/pull/4709)) @nytmyr 2025-02-22
|
||||
* Prevent medding in combat if any mob has bot targeted ([#4707](https://github.com/EQEmu/Server/pull/4707)) @nytmyr 2025-02-22
|
||||
|
||||
### Client Mod
|
||||
|
||||
* Adds a hacked fast camp rule for GMs ([#4697](https://github.com/EQEmu/Server/pull/4697)) @KimLS 2025-02-20
|
||||
|
||||
### Fixes
|
||||
|
||||
* Fix Lua Zone ID Exports ([#4700](https://github.com/EQEmu/Server/pull/4700)) @Kinglykrab 2025-02-22
|
||||
* Fix bad Mob reference in QuestManager::resumetimer() ([#4710](https://github.com/EQEmu/Server/pull/4710)) @zimp-wow 2025-02-22
|
||||
* Fix cursor load on zone ([#4704](https://github.com/EQEmu/Server/pull/4704)) @nytmyr 2025-02-22
|
||||
* Fix infinite loop in QuestManager::stoptimer() ([#4703](https://github.com/EQEmu/Server/pull/4703)) @zimp-wow 2025-02-21
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add GetSpawn() to Perl and Lua ([#4702](https://github.com/EQEmu/Server/pull/4702)) @Kinglykrab 2025-02-22
|
||||
|
||||
## [23.0.1] 2/20/2025
|
||||
|
||||
### Fixes
|
||||
|
||||
* Player event ordering merge fix ([#4699](https://github.com/EQEmu/Server/pull/4699)) @Akkadius 2025-02-20
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add DisableRespawnTimers to Perl and Lua ([#4691](https://github.com/EQEmu/Server/pull/4691)) @Kinglykrab 2025-02-20
|
||||
|
||||
## [23.0.0] 2/19/2025
|
||||
|
||||
### Bots
|
||||
|
||||
* Add AEHateLine to HateLine ParentType ([#4678](https://github.com/EQEmu/Server/pull/4678)) @nytmyr 2025-02-15
|
||||
* Add IsInRaidOrGroup checks to ^attack and ^pull ([#4654](https://github.com/EQEmu/Server/pull/4654)) @nytmyr 2025-02-07
|
||||
* Add missing stance options ([#4681](https://github.com/EQEmu/Server/pull/4681)) @nytmyr 2025-02-15
|
||||
* Bot Overhaul ([#4580](https://github.com/EQEmu/Server/pull/4580)) @nytmyr 2025-02-03
|
||||
* Command Cleanup ([#4676](https://github.com/EQEmu/Server/pull/4676)) @nytmyr 2025-02-15
|
||||
* Correct camp count on ^camp ([#4650](https://github.com/EQEmu/Server/pull/4650)) @nytmyr 2025-02-06
|
||||
* Correct helper message for forced casts ([#4656](https://github.com/EQEmu/Server/pull/4656)) @nytmyr 2025-02-07
|
||||
* Crash fixes related to GetNumberNeedingHealedInGroup ([#4684](https://github.com/EQEmu/Server/pull/4684)) @nytmyr 2025-02-15
|
||||
* Fix AE range calculation ([#4683](https://github.com/EQEmu/Server/pull/4683)) @nytmyr 2025-02-15
|
||||
* Fix Bards not casting ([#4638](https://github.com/EQEmu/Server/pull/4638)) @nytmyr 2025-02-03
|
||||
* Fix a couple potential crashes with GetNumberNeedingHealedInGroup ([#4652](https://github.com/EQEmu/Server/pull/4652)) @nytmyr 2025-02-07
|
||||
* Fix crash related to GetTempSpellType() ([#4649](https://github.com/EQEmu/Server/pull/4649)) @nytmyr 2025-02-06
|
||||
* Fix pets causing aggro ([#4677](https://github.com/EQEmu/Server/pull/4677)) @nytmyr 2025-02-15
|
||||
* Fix spell priority commands ([#4660](https://github.com/EQEmu/Server/pull/4660)) @nytmyr 2025-02-08
|
||||
* Fix typo in positioning ([#4659](https://github.com/EQEmu/Server/pull/4659)) @nytmyr 2025-02-08
|
||||
* Move BotGetSpellsByType to cache ([#4655](https://github.com/EQEmu/Server/pull/4655)) @nytmyr 2025-02-07
|
||||
* Prevents casting on ineligible targets due to target type, stacking, etc. ([#4680](https://github.com/EQEmu/Server/pull/4680)) @nytmyr 2025-02-15
|
||||
* Sanity checks for spell type updates ([#4641](https://github.com/EQEmu/Server/pull/4641)) @nytmyr 2025-02-05
|
||||
|
||||
### Bug
|
||||
|
||||
* Item Purchase Offset when multiple buyers are buying at the same time. ([#4628](https://github.com/EQEmu/Server/pull/4628)) @fryguy503 2025-02-06
|
||||
|
||||
### CI
|
||||
|
||||
* Fix database race condition ([#4646](https://github.com/EQEmu/Server/pull/4646)) @Akkadius 2025-02-06
|
||||
|
||||
### Client Mod
|
||||
|
||||
* Adds a hacked fast camp rule for GMs ([#4697](https://github.com/EQEmu/Server/pull/4697)) @KimLS 2025-02-20
|
||||
|
||||
### Code
|
||||
|
||||
* Bot RaidGroupSay ([#4653](https://github.com/EQEmu/Server/pull/4653)) @nytmyr 2025-02-07
|
||||
* Cleanup logic in cursor bag check ([#4642](https://github.com/EQEmu/Server/pull/4642)) @nytmyr 2025-02-04
|
||||
* Use Repositories for Titles ([#4608](https://github.com/EQEmu/Server/pull/4608)) @Kinglykrab 2025-02-07
|
||||
|
||||
### Commands
|
||||
|
||||
* Fix #goto not accepting proper heading ([#4685](https://github.com/EQEmu/Server/pull/4685)) @nytmyr 2025-02-15
|
||||
* Fix Illusion Block ([#4666](https://github.com/EQEmu/Server/pull/4666)) @nytmyr 2025-02-12
|
||||
|
||||
### Crash
|
||||
|
||||
* Fix raid/group crash regression ([#4671](https://github.com/EQEmu/Server/pull/4671)) @Akkadius 2025-02-12
|
||||
* Fix zone crash caused by NPC::MoveTo ([#4639](https://github.com/EQEmu/Server/pull/4639)) @catapultam-habeo 2025-02-03
|
||||
|
||||
### Databuckets
|
||||
|
||||
* Add Zone Scoped Databuckets ([#4690](https://github.com/EQEmu/Server/pull/4690)) @Akkadius 2025-02-18
|
||||
|
||||
### Expeditions
|
||||
|
||||
* Move expedition code into DynamicZone ([#4672](https://github.com/EQEmu/Server/pull/4672)) @hgtw 2025-02-16
|
||||
|
||||
### Feature
|
||||
|
||||
* Add Support for Tradeskill Recipe Inspect ([#4648](https://github.com/EQEmu/Server/pull/4648)) @Kinglykrab 2025-02-06
|
||||
* Add rule to allow /changepetname to function without being enabled by scripts. @catapultam-habeo 2025-02-05
|
||||
* GuildBank Updates ([#4674](https://github.com/EQEmu/Server/pull/4674)) @neckkola 2025-02-15
|
||||
* Implement Big Bags ([#4606](https://github.com/EQEmu/Server/pull/4606)) @Kinglykrab 2025-02-03
|
||||
|
||||
### Fixes
|
||||
|
||||
* #rq and #reload quest alias ([#4694](https://github.com/EQEmu/Server/pull/4694)) @Akkadius 2025-02-18
|
||||
* Always spawn zone controller first ([#4669](https://github.com/EQEmu/Server/pull/4669)) @Akkadius 2025-02-12
|
||||
* Big Bag Cleanup ([#4643](https://github.com/EQEmu/Server/pull/4643)) @fryguy503 2025-02-05
|
||||
* Big Bag additional fixes ([#4644](https://github.com/EQEmu/Server/pull/4644)) @fryguy503 2025-02-05
|
||||
* Change logging level for no items found in a bazaar search to reduce spam logs. ([#4675](https://github.com/EQEmu/Server/pull/4675)) @neckkola 2025-02-13
|
||||
* Find Zone - Expansion Settings ([#4692](https://github.com/EQEmu/Server/pull/4692)) @MortimerGreenwald 2025-02-18
|
||||
* Fix Beastlord Warder Size Modifier ([#4665](https://github.com/EQEmu/Server/pull/4665)) @Kinglykrab 2025-02-12
|
||||
* Fix CI since hand-ins are merged @Akkadius 2025-02-03
|
||||
* Fix Illusion Fade Texture Bug ([#4673](https://github.com/EQEmu/Server/pull/4673)) @Kinglykrab 2025-02-14
|
||||
* Fix Item Discovery ([#4663](https://github.com/EQEmu/Server/pull/4663)) @Kinglykrab 2025-02-10
|
||||
* Fix ST_GroupNoPets and ST_GroupClientAndPet ([#4667](https://github.com/EQEmu/Server/pull/4667)) @nytmyr 2025-02-10
|
||||
* Fix SendStatsWindow Mod2 Value Display ([#4658](https://github.com/EQEmu/Server/pull/4658)) @Kinglykrab 2025-02-07
|
||||
* Fix Tradeskill Queries ([#4661](https://github.com/EQEmu/Server/pull/4661)) @Kinglykrab 2025-02-09
|
||||
* Fix error in update manifest ([#4637](https://github.com/EQEmu/Server/pull/4637)) @nytmyr 2025-02-03
|
||||
* Fix issue with getting an unset nested databucket ([#4693](https://github.com/EQEmu/Server/pull/4693)) @Akkadius 2025-02-19
|
||||
* Fix non-error in player_event_logs ([#4695](https://github.com/EQEmu/Server/pull/4695)) @Akkadius 2025-02-18
|
||||
* GMMove Update Edge Case With Clients ([#4686](https://github.com/EQEmu/Server/pull/4686)) @Akkadius 2025-02-15
|
||||
* Item Handins to Pets ([#4687](https://github.com/EQEmu/Server/pull/4687)) @Akkadius 2025-02-15
|
||||
* Parcel Delivery Updates ([#4688](https://github.com/EQEmu/Server/pull/4688)) @neckkola 2025-02-16
|
||||
* Prevent zone from loading ETL ID's on bootup ([#4696](https://github.com/EQEmu/Server/pull/4696)) @Akkadius 2025-02-18
|
||||
* Update pre big bag corpse slot_id's to support big bags ([#4679](https://github.com/EQEmu/Server/pull/4679)) @nytmyr 2025-02-15
|
||||
|
||||
### Inventory
|
||||
|
||||
* Fix cursor bag saving to invalid slot_ids ([#4640](https://github.com/EQEmu/Server/pull/4640)) @nytmyr 2025-02-04
|
||||
|
||||
### Items
|
||||
|
||||
* Overhaul Item Hand-in System ([#4593](https://github.com/EQEmu/Server/pull/4593)) @Akkadius 2025-02-03
|
||||
|
||||
### Loginserver
|
||||
|
||||
* Fix iterator crash ([#4670](https://github.com/EQEmu/Server/pull/4670)) @Akkadius 2025-02-12
|
||||
* Modernize codebase ([#4647](https://github.com/EQEmu/Server/pull/4647)) @Akkadius 2025-02-06
|
||||
|
||||
### NPC Handins
|
||||
|
||||
* Fix MultiQuest Handins ([#4651](https://github.com/EQEmu/Server/pull/4651)) @Akkadius 2025-02-07
|
||||
|
||||
### Performance
|
||||
|
||||
* Server Reload Overhaul ([#4689](https://github.com/EQEmu/Server/pull/4689)) @Akkadius 2025-02-18
|
||||
|
||||
### Player Event Logs
|
||||
|
||||
* Migrate and Deprecate QS Legacy Logging ([#4542](https://github.com/EQEmu/Server/pull/4542)) @neckkola 2025-02-05
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add Bandolier Methods ([#4635](https://github.com/EQEmu/Server/pull/4635)) @Kinglykrab 2025-02-03
|
||||
* Add Potion Belt Methods ([#4634](https://github.com/EQEmu/Server/pull/4634)) @Kinglykrab 2025-02-04
|
||||
* Add Zone Support to Perl and Lua ([#4662](https://github.com/EQEmu/Server/pull/4662)) @Kinglykrab 2025-02-09
|
||||
|
||||
### Spells
|
||||
|
||||
* Add all types to checks for max_targets_allowed rule for AEs ([#4682](https://github.com/EQEmu/Server/pull/4682)) @nytmyr 2025-02-15
|
||||
|
||||
## [22.62.2] 2/1/2025
|
||||
|
||||
### Fixes
|
||||
|
||||
@@ -22,7 +22,6 @@ SET(common_sources
|
||||
dbcore.cpp
|
||||
deity.cpp
|
||||
dynamic_zone_base.cpp
|
||||
dynamic_zone_lockout.cpp
|
||||
emu_constants.cpp
|
||||
emu_limits.cpp
|
||||
emu_opcodes.cpp
|
||||
@@ -41,6 +40,7 @@ SET(common_sources
|
||||
events/player_event_logs.cpp
|
||||
events/player_event_discord_formatter.cpp
|
||||
evolving_items.cpp
|
||||
expedition_lockout_timer.cpp
|
||||
extprofile.cpp
|
||||
discord/discord_manager.cpp
|
||||
faction.cpp
|
||||
@@ -213,14 +213,16 @@ SET(repositories
|
||||
repositories/base/base_discovered_items_repository.h
|
||||
repositories/base/base_doors_repository.h
|
||||
repositories/base/base_dynamic_zones_repository.h
|
||||
repositories/base/base_dynamic_zone_lockouts_repository.h
|
||||
repositories/base/base_dynamic_zone_members_repository.h
|
||||
repositories/base/base_dynamic_zone_templates_repository.h
|
||||
repositories/base/base_expeditions_repository.h
|
||||
repositories/base/base_expedition_lockouts_repository.h
|
||||
repositories/base/base_faction_association_repository.h
|
||||
repositories/base/base_faction_base_data_repository.h
|
||||
repositories/base/base_faction_list_repository.h
|
||||
repositories/base/base_faction_list_mod_repository.h
|
||||
repositories/base/base_faction_values_repository.h
|
||||
repositories/base/base_find_location_repository.h
|
||||
repositories/base/base_fishing_repository.h
|
||||
repositories/base/base_forage_repository.h
|
||||
repositories/base/base_friends_repository.h
|
||||
@@ -409,14 +411,16 @@ SET(repositories
|
||||
repositories/discovered_items_repository.h
|
||||
repositories/doors_repository.h
|
||||
repositories/dynamic_zones_repository.h
|
||||
repositories/dynamic_zone_lockouts_repository.h
|
||||
repositories/dynamic_zone_members_repository.h
|
||||
repositories/dynamic_zone_templates_repository.h
|
||||
repositories/expeditions_repository.h
|
||||
repositories/expedition_lockouts_repository.h
|
||||
repositories/faction_association_repository.h
|
||||
repositories/faction_base_data_repository.h
|
||||
repositories/faction_list_repository.h
|
||||
repositories/faction_list_mod_repository.h
|
||||
repositories/faction_values_repository.h
|
||||
repositories/find_location_repository.h
|
||||
repositories/fishing_repository.h
|
||||
repositories/forage_repository.h
|
||||
repositories/friends_repository.h
|
||||
@@ -559,7 +563,6 @@ SET(common_headers
|
||||
discord/discord.h
|
||||
discord/discord_manager.h
|
||||
dynamic_zone_base.h
|
||||
dynamic_zone_lockout.h
|
||||
emu_constants.h
|
||||
emu_limits.h
|
||||
emu_opcodes.h
|
||||
@@ -586,6 +589,7 @@ SET(common_headers
|
||||
events/player_events.h
|
||||
event_sub.h
|
||||
evolving_items.h
|
||||
expedition_lockout_timer.h
|
||||
extprofile.h
|
||||
faction.h
|
||||
file.h
|
||||
@@ -645,7 +649,6 @@ SET(common_headers
|
||||
server_event_scheduler.h
|
||||
serverinfo.h
|
||||
servertalk.h
|
||||
server_reload_types.h
|
||||
shared_tasks.h
|
||||
shareddb.h
|
||||
skills.h
|
||||
|
||||
@@ -6770,107 +6770,7 @@ SET `aliases` =
|
||||
WHERE `command` = 'illusionblock'
|
||||
AND `aliases` NOT LIKE '%ib%';
|
||||
)",
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9303,
|
||||
.description = "2025_02_13_corpse_slot_fix.sql",
|
||||
.check = "SELECT * FROM `character_corpse_items` WHERE `equip_slot` BETWEEN 251 AND 350",
|
||||
.condition = "not_empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
UPDATE `character_corpse_items` SET `equip_slot` = ((`equip_slot` - 251) + 4010) WHERE `equip_slot` BETWEEN 251 AND 260; -- Bag 1
|
||||
UPDATE `character_corpse_items` SET `equip_slot` = ((`equip_slot` - 261) + 4210) WHERE `equip_slot` BETWEEN 261 AND 270; -- Bag 2
|
||||
UPDATE `character_corpse_items` SET `equip_slot` = ((`equip_slot` - 271) + 4410) WHERE `equip_slot` BETWEEN 271 AND 280; -- Bag 3
|
||||
UPDATE `character_corpse_items` SET `equip_slot` = ((`equip_slot` - 281) + 4610) WHERE `equip_slot` BETWEEN 281 AND 290; -- Bag 4
|
||||
UPDATE `character_corpse_items` SET `equip_slot` = ((`equip_slot` - 291) + 4810) WHERE `equip_slot` BETWEEN 291 AND 300; -- Bag 5
|
||||
UPDATE `character_corpse_items` SET `equip_slot` = ((`equip_slot` - 301) + 5010) WHERE `equip_slot` BETWEEN 301 AND 310; -- Bag 6
|
||||
UPDATE `character_corpse_items` SET `equip_slot` = ((`equip_slot` - 311) + 5210) WHERE `equip_slot` BETWEEN 311 AND 320; -- Bag 7
|
||||
UPDATE `character_corpse_items` SET `equip_slot` = ((`equip_slot` - 321) + 5410) WHERE `equip_slot` BETWEEN 321 AND 330; -- Bag 8
|
||||
UPDATE `character_corpse_items` SET `equip_slot` = ((`equip_slot` - 331) + 5610) WHERE `equip_slot` BETWEEN 331 AND 340; -- Bag 9
|
||||
UPDATE `character_corpse_items` SET `equip_slot` = ((`equip_slot` - 341) + 5810) WHERE `equip_slot` BETWEEN 341 AND 350; -- Bag 10
|
||||
)",
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9304,
|
||||
.description = "2024_12_01_2024_update_guild_bank",
|
||||
.check = "SHOW COLUMNS FROM `guild_bank` LIKE 'augment_one_id'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `guild_bank`
|
||||
DROP INDEX `guildid`,
|
||||
CHANGE COLUMN `guildid` `guild_id` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `id`,
|
||||
CHANGE COLUMN `itemid` `item_id` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `slot`,
|
||||
CHANGE COLUMN `whofor` `who_for` VARCHAR(64) NULL DEFAULT NULL COLLATE 'utf8_general_ci' AFTER `permissions`,
|
||||
ADD COLUMN `augment_one_id` INT UNSIGNED NULL DEFAULT '0' AFTER `item_id`,
|
||||
ADD COLUMN `augment_two_id` INT UNSIGNED NULL DEFAULT '0' AFTER `augment_one_id`,
|
||||
ADD COLUMN `augment_three_id` INT UNSIGNED NULL DEFAULT '0' AFTER `augment_two_id`,
|
||||
ADD COLUMN `augment_four_id` INT UNSIGNED NULL DEFAULT '0' AFTER `augment_three_id`,
|
||||
ADD COLUMN `augment_five_id` INT UNSIGNED NULL DEFAULT '0' AFTER `augment_four_id`,
|
||||
ADD COLUMN `augment_six_id` INT UNSIGNED NULL DEFAULT '0' AFTER `augment_five_id`,
|
||||
CHANGE COLUMN `qty` `quantity` INT(10) NOT NULL DEFAULT '0' AFTER `augment_six_id`;
|
||||
ALTER TABLE `guild_bank`
|
||||
ADD INDEX `guild_id` (`guild_id`);
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9305,
|
||||
.description = "2024_12_01_expedition_dz_merge.sql",
|
||||
.check = "SHOW COLUMNS FROM `dynamic_zones` LIKE 'is_locked'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `dynamic_zones`
|
||||
ADD COLUMN `is_locked` TINYINT NOT NULL DEFAULT '0' AFTER `has_zone_in`,
|
||||
ADD COLUMN `add_replay` TINYINT NOT NULL DEFAULT '1' AFTER `is_locked`;
|
||||
|
||||
ALTER TABLE `expedition_lockouts`
|
||||
CHANGE COLUMN `expedition_id` `dynamic_zone_id` INT(10) UNSIGNED NOT NULL AFTER `id`,
|
||||
DROP INDEX `expedition_id_event_name`,
|
||||
ADD UNIQUE INDEX `dz_id_event_name` (`dynamic_zone_id`, `event_name`) USING BTREE;
|
||||
|
||||
UPDATE expedition_lockouts lockouts
|
||||
INNER JOIN expeditions ON lockouts.dynamic_zone_id = expeditions.id
|
||||
SET lockouts.dynamic_zone_id = expeditions.dynamic_zone_id;
|
||||
|
||||
DROP TABLE `expeditions`;
|
||||
|
||||
RENAME TABLE `expedition_lockouts` TO `dynamic_zone_lockouts`;
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9306,
|
||||
.description = "2025_02_16_data_buckets_zone_id_instance_id.sql",
|
||||
.check = "SHOW COLUMNS FROM `data_buckets` LIKE 'zone_id'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
-- ✅ Drop old indexes
|
||||
DROP INDEX IF EXISTS `keys` ON `data_buckets`;
|
||||
DROP INDEX IF EXISTS `idx_npc_expires` ON `data_buckets`;
|
||||
DROP INDEX IF EXISTS `idx_bot_expires` ON `data_buckets`;
|
||||
|
||||
-- Add zone_id, instance_id
|
||||
ALTER TABLE `data_buckets`
|
||||
MODIFY COLUMN `npc_id` int(11) NOT NULL DEFAULT 0 AFTER `character_id`,
|
||||
MODIFY COLUMN `bot_id` int(11) NOT NULL DEFAULT 0 AFTER `npc_id`,
|
||||
ADD COLUMN `zone_id` smallint(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `bot_id`,
|
||||
ADD COLUMN `instance_id` smallint(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `zone_id`;
|
||||
|
||||
ALTER TABLE `data_buckets`
|
||||
MODIFY COLUMN `account_id` bigint(11) UNSIGNED NULL DEFAULT 0 AFTER `expires`,
|
||||
MODIFY COLUMN `character_id` bigint(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `account_id`,
|
||||
MODIFY COLUMN `npc_id` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `character_id`,
|
||||
MODIFY COLUMN `bot_id` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `npc_id`;
|
||||
|
||||
-- ✅ Create optimized unique index with `key` first
|
||||
CREATE UNIQUE INDEX `keys` ON data_buckets (`key`, character_id, npc_id, bot_id, account_id, zone_id, instance_id);
|
||||
|
||||
-- ✅ Create indexes for just instance_id (instance deletion)
|
||||
CREATE INDEX idx_instance_id ON data_buckets (instance_id);
|
||||
)",
|
||||
.content_schema_update = false
|
||||
},
|
||||
}
|
||||
// -- template; copy/paste this when you need to create a new entry
|
||||
// ManifestEntry{
|
||||
// .version = 9228,
|
||||
|
||||
@@ -30,7 +30,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "../common/repositories/respawn_times_repository.h"
|
||||
#include "../common/repositories/spawn_condition_values_repository.h"
|
||||
#include "repositories/spawn2_disabled_repository.h"
|
||||
#include "repositories/data_buckets_repository.h"
|
||||
|
||||
|
||||
#include "database.h"
|
||||
|
||||
@@ -479,7 +479,6 @@ void Database::DeleteInstance(uint16 instance_id)
|
||||
DynamicZoneMembersRepository::DeleteByInstance(*this, instance_id);
|
||||
DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id));
|
||||
CharacterCorpsesRepository::BuryInstance(*this, instance_id);
|
||||
DataBucketsRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id));
|
||||
}
|
||||
|
||||
void Database::FlagInstanceByGroupLeader(uint32 zone_id, int16 version, uint32 character_id, uint32 group_id)
|
||||
|
||||
@@ -311,9 +311,10 @@ namespace DatabaseSchema {
|
||||
"completed_shared_task_members",
|
||||
"completed_shared_tasks",
|
||||
"discord_webhooks",
|
||||
"dynamic_zone_lockouts",
|
||||
"dynamic_zone_members",
|
||||
"dynamic_zones",
|
||||
"expedition_lockouts",
|
||||
"expeditions",
|
||||
"gm_ips",
|
||||
"group_id",
|
||||
"group_leaders",
|
||||
|
||||
+64
-293
@@ -1,13 +1,11 @@
|
||||
#include "dynamic_zone_base.h"
|
||||
#include "database.h"
|
||||
#include "eqemu_logsys.h"
|
||||
#include "repositories/instance_list_repository.h"
|
||||
#include "repositories/instance_list_player_repository.h"
|
||||
#include "rulesys.h"
|
||||
#include "servertalk.h"
|
||||
#include "util/uuid.h"
|
||||
#include "repositories/character_expedition_lockouts_repository.h"
|
||||
#include "repositories/dynamic_zone_lockouts_repository.h"
|
||||
#include "repositories/instance_list_repository.h"
|
||||
#include "repositories/instance_list_player_repository.h"
|
||||
|
||||
DynamicZoneBase::DynamicZoneBase(DynamicZonesRepository::DynamicZoneInstance&& entry)
|
||||
{
|
||||
@@ -95,15 +93,13 @@ void DynamicZoneBase::LoadRepositoryResult(DynamicZonesRepository::DynamicZoneIn
|
||||
m_zonein.y = dz_entry.zone_in_y;
|
||||
m_zonein.z = dz_entry.zone_in_z;
|
||||
m_zonein.heading = dz_entry.zone_in_heading;
|
||||
m_has_zonein = dz_entry.has_zone_in != 0;
|
||||
m_is_locked = dz_entry.is_locked;
|
||||
m_add_replay = dz_entry.add_replay;
|
||||
m_has_zonein = (dz_entry.has_zone_in != 0);
|
||||
// instance_list portion
|
||||
m_zone_id = dz_entry.zone;
|
||||
m_zone_version = dz_entry.version;
|
||||
m_start_time = std::chrono::system_clock::from_time_t(dz_entry.start_time);
|
||||
m_duration = std::chrono::seconds(dz_entry.duration);
|
||||
m_never_expires = dz_entry.never_expires != 0;
|
||||
m_never_expires = (dz_entry.never_expires != 0);
|
||||
m_expire_time = m_start_time + m_duration;
|
||||
}
|
||||
|
||||
@@ -123,40 +119,37 @@ void DynamicZoneBase::AddMemberFromRepositoryResult(
|
||||
uint32_t DynamicZoneBase::SaveToDatabase()
|
||||
{
|
||||
LogDynamicZonesDetail("Saving dz instance [{}] to database", m_instance_id);
|
||||
if (m_instance_id == 0)
|
||||
|
||||
if (m_instance_id != 0)
|
||||
{
|
||||
return 0;
|
||||
auto insert_dz = DynamicZonesRepository::NewEntity();
|
||||
insert_dz.uuid = m_uuid;
|
||||
insert_dz.name = m_name;
|
||||
insert_dz.leader_id = m_leader.id;
|
||||
insert_dz.min_players = m_min_players;
|
||||
insert_dz.max_players = m_max_players;
|
||||
insert_dz.instance_id = m_instance_id,
|
||||
insert_dz.type = static_cast<int>(m_type);
|
||||
insert_dz.dz_switch_id = m_dz_switch_id;
|
||||
insert_dz.compass_zone_id = m_compass.zone_id;
|
||||
insert_dz.compass_x = m_compass.x;
|
||||
insert_dz.compass_y = m_compass.y;
|
||||
insert_dz.compass_z = m_compass.z;
|
||||
insert_dz.safe_return_zone_id = m_safereturn.zone_id;
|
||||
insert_dz.safe_return_x = m_safereturn.x;
|
||||
insert_dz.safe_return_y = m_safereturn.y;
|
||||
insert_dz.safe_return_z = m_safereturn.z;
|
||||
insert_dz.safe_return_heading = m_safereturn.heading;
|
||||
insert_dz.zone_in_x = m_zonein.x;
|
||||
insert_dz.zone_in_y = m_zonein.y;
|
||||
insert_dz.zone_in_z = m_zonein.z;
|
||||
insert_dz.zone_in_heading = m_zonein.heading;
|
||||
insert_dz.has_zone_in = m_has_zonein;
|
||||
|
||||
auto inserted_dz = DynamicZonesRepository::InsertOne(GetDatabase(), insert_dz);
|
||||
return inserted_dz.id;
|
||||
}
|
||||
|
||||
auto dz = DynamicZonesRepository::NewEntity();
|
||||
dz.uuid = m_uuid;
|
||||
dz.name = m_name;
|
||||
dz.leader_id = m_leader.id;
|
||||
dz.min_players = m_min_players;
|
||||
dz.max_players = m_max_players;
|
||||
dz.instance_id = static_cast<int32_t>(m_instance_id),
|
||||
dz.type = static_cast<uint8_t>(m_type);
|
||||
dz.dz_switch_id = m_dz_switch_id;
|
||||
dz.compass_zone_id = m_compass.zone_id;
|
||||
dz.compass_x = m_compass.x;
|
||||
dz.compass_y = m_compass.y;
|
||||
dz.compass_z = m_compass.z;
|
||||
dz.safe_return_zone_id = m_safereturn.zone_id;
|
||||
dz.safe_return_x = m_safereturn.x;
|
||||
dz.safe_return_y = m_safereturn.y;
|
||||
dz.safe_return_z = m_safereturn.z;
|
||||
dz.safe_return_heading = m_safereturn.heading;
|
||||
dz.zone_in_x = m_zonein.x;
|
||||
dz.zone_in_y = m_zonein.y;
|
||||
dz.zone_in_z = m_zonein.z;
|
||||
dz.zone_in_heading = m_zonein.heading;
|
||||
dz.has_zone_in = static_cast<uint8_t>(m_has_zonein);
|
||||
dz.is_locked = static_cast<int8_t>(m_is_locked);
|
||||
dz.add_replay = static_cast<int8_t>(m_add_replay);
|
||||
|
||||
dz = DynamicZonesRepository::InsertOne(GetDatabase(), std::move(dz));
|
||||
|
||||
return dz.id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool DynamicZoneBase::AddMember(const DynamicZoneMember& add_member)
|
||||
@@ -203,9 +196,10 @@ bool DynamicZoneBase::RemoveMember(const DynamicZoneMember& remove_member)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DynamicZoneBase::SwapMember(const DynamicZoneMember& add_member, const std::string& remove_name)
|
||||
bool DynamicZoneBase::SwapMember(
|
||||
const DynamicZoneMember& add_member, const std::string& remove_char_name)
|
||||
{
|
||||
auto remove_member = GetMemberData(remove_name);
|
||||
auto remove_member = GetMemberData(remove_char_name);
|
||||
if (!add_member.IsValid() || !remove_member.IsValid())
|
||||
{
|
||||
return false;
|
||||
@@ -236,18 +230,9 @@ void DynamicZoneBase::RemoveAllMembers()
|
||||
|
||||
void DynamicZoneBase::SaveMembers(const std::vector<DynamicZoneMember>& members)
|
||||
{
|
||||
if (members.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LogDynamicZonesDetail("Saving [{}] member(s) for dz [{}]", members.size(), m_id);
|
||||
|
||||
m_members = members;
|
||||
if (m_members.size() > m_max_players)
|
||||
{
|
||||
m_members.resize(m_max_players);
|
||||
}
|
||||
|
||||
// the lower level instance_list_players needs to be kept updated as well
|
||||
std::vector<DynamicZoneMembersRepository::DynamicZoneMembers> insert_members;
|
||||
@@ -257,12 +242,12 @@ void DynamicZoneBase::SaveMembers(const std::vector<DynamicZoneMember>& members)
|
||||
DynamicZoneMembersRepository::DynamicZoneMembers member_entry{};
|
||||
member_entry.dynamic_zone_id = m_id;
|
||||
member_entry.character_id = member.id;
|
||||
insert_members.push_back(member_entry);
|
||||
insert_members.emplace_back(member_entry);
|
||||
|
||||
InstanceListPlayerRepository::InstanceListPlayer player_entry{};
|
||||
player_entry.id = m_instance_id;
|
||||
player_entry.charid = member.id;
|
||||
insert_players.push_back(player_entry);
|
||||
InstanceListPlayerRepository::InstanceListPlayer player_entry;
|
||||
player_entry.id = static_cast<int>(m_instance_id);
|
||||
player_entry.charid = static_cast<int>(member.id);
|
||||
insert_players.emplace_back(player_entry);
|
||||
}
|
||||
|
||||
DynamicZoneMembersRepository::InsertOrUpdateMany(GetDatabase(), insert_members);
|
||||
@@ -354,44 +339,6 @@ void DynamicZoneBase::SetLeader(const DynamicZoneMember& new_leader, bool update
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicZoneBase::SetLocked(bool lock, bool update_db, DzLockMsg lock_msg, uint32_t color)
|
||||
{
|
||||
m_is_locked = lock;
|
||||
|
||||
if (update_db)
|
||||
{
|
||||
DynamicZonesRepository::UpdateLocked(GetDatabase(), m_id, lock);
|
||||
|
||||
ServerPacket pack(ServerOP_DzLock, sizeof(ServerDzLock_Struct));
|
||||
auto buf = reinterpret_cast<ServerDzLock_Struct*>(pack.pBuffer);
|
||||
buf->dz_id = GetID();
|
||||
buf->sender_zone_id = GetCurrentZoneID();
|
||||
buf->sender_instance_id = GetCurrentInstanceID();
|
||||
buf->lock = m_is_locked;
|
||||
buf->lock_msg = static_cast<uint8_t>(lock_msg);
|
||||
buf->color = color;
|
||||
SendServerPacket(&pack);
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicZoneBase::SetReplayOnJoin(bool enabled, bool update_db)
|
||||
{
|
||||
m_add_replay = enabled;
|
||||
|
||||
if (update_db)
|
||||
{
|
||||
DynamicZonesRepository::UpdateReplayOnJoin(GetDatabase(), m_id, enabled);
|
||||
|
||||
ServerPacket pack(ServerOP_DzReplayOnJoin, sizeof(ServerDzBool_Struct));
|
||||
auto buf = reinterpret_cast<ServerDzBool_Struct*>(pack.pBuffer);
|
||||
buf->dz_id = GetID();
|
||||
buf->sender_zone_id = GetCurrentZoneID();
|
||||
buf->sender_instance_id = GetCurrentInstanceID();
|
||||
buf->enabled = enabled;
|
||||
SendServerPacket(&pack);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t DynamicZoneBase::GetSecondsRemaining() const
|
||||
{
|
||||
auto remaining = std::chrono::duration_cast<std::chrono::seconds>(GetDurationRemaining()).count();
|
||||
@@ -531,13 +478,13 @@ void DynamicZoneBase::RemoveInternalMember(uint32_t character_id)
|
||||
), m_members.end());
|
||||
}
|
||||
|
||||
bool DynamicZoneBase::HasMember(uint32_t character_id) const
|
||||
bool DynamicZoneBase::HasMember(uint32_t character_id)
|
||||
{
|
||||
return std::any_of(m_members.begin(), m_members.end(),
|
||||
[&](const DynamicZoneMember& member) { return member.id == character_id; });
|
||||
}
|
||||
|
||||
bool DynamicZoneBase::HasMember(const std::string& character_name) const
|
||||
bool DynamicZoneBase::HasMember(const std::string& character_name)
|
||||
{
|
||||
return std::any_of(m_members.begin(), m_members.end(),
|
||||
[&](const DynamicZoneMember& member) {
|
||||
@@ -643,34 +590,35 @@ std::string DynamicZoneBase::GetDynamicZoneTypeName(DynamicZoneType dz_type)
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerPacket(uint16_t zone_id, uint16_t instance_id)
|
||||
EQ::Net::DynamicPacket DynamicZoneBase::GetSerializedDzPacket()
|
||||
{
|
||||
std::ostringstream ss = GetSerialized();
|
||||
std::string_view sv = ss.view();
|
||||
EQ::Net::DynamicPacket dyn_pack;
|
||||
dyn_pack.PutSerialize(0, *this);
|
||||
|
||||
auto pack_size = sizeof(ServerDzCreate_Struct) + sv.size();
|
||||
LogDynamicZonesDetail("Serialized server dz size [{}]", dyn_pack.Length());
|
||||
return dyn_pack;
|
||||
}
|
||||
|
||||
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerDzCreatePacket(
|
||||
uint16_t origin_zone_id, uint16_t origin_instance_id)
|
||||
{
|
||||
EQ::Net::DynamicPacket dyn_pack = GetSerializedDzPacket();
|
||||
|
||||
auto pack_size = sizeof(ServerDzCreateSerialized_Struct) + dyn_pack.Length();
|
||||
auto pack = std::make_unique<ServerPacket>(ServerOP_DzCreated, static_cast<uint32_t>(pack_size));
|
||||
auto buf = reinterpret_cast<ServerDzCreate_Struct*>(pack->pBuffer);
|
||||
buf->origin_zone_id = zone_id;
|
||||
buf->origin_instance_id = instance_id;
|
||||
buf->dz_id = GetID();
|
||||
buf->cereal_size = static_cast<uint32_t>(sv.size());
|
||||
memcpy(buf->cereal_data, sv.data(), sv.size());
|
||||
auto buf = reinterpret_cast<ServerDzCreateSerialized_Struct*>(pack->pBuffer);
|
||||
buf->origin_zone_id = origin_zone_id;
|
||||
buf->origin_instance_id = origin_instance_id;
|
||||
buf->cereal_size = static_cast<uint32_t>(dyn_pack.Length());
|
||||
memcpy(buf->cereal_data, dyn_pack.Data(), dyn_pack.Length());
|
||||
|
||||
return pack;
|
||||
}
|
||||
|
||||
std::ostringstream DynamicZoneBase::GetSerialized()
|
||||
void DynamicZoneBase::LoadSerializedDzPacket(char* cereal_data, uint32_t cereal_size)
|
||||
{
|
||||
std::ostringstream ss;
|
||||
cereal::BinaryOutputArchive archive(ss);
|
||||
archive(*this);
|
||||
return ss;
|
||||
}
|
||||
|
||||
void DynamicZoneBase::Unserialize(std::span<char> buf)
|
||||
{
|
||||
EQ::Util::MemoryStreamReader ss(buf.data(), buf.size());
|
||||
LogDynamicZonesDetail("Deserializing server dz size [{}]", cereal_size);
|
||||
EQ::Util::MemoryStreamReader ss(cereal_data, cereal_size);
|
||||
cereal::BinaryInputArchive archive(ss);
|
||||
archive(*this);
|
||||
}
|
||||
@@ -699,180 +647,3 @@ void DynamicZoneBase::LoadTemplate(const DynamicZoneTemplatesRepository::Dynamic
|
||||
m_zonein.z = dz_template.zone_in_z;
|
||||
m_zonein.heading = dz_template.zone_in_h;
|
||||
}
|
||||
|
||||
std::vector<uint32_t> DynamicZoneBase::GetMemberIds()
|
||||
{
|
||||
std::vector<uint32_t> ids;
|
||||
ids.reserve(m_members.size());
|
||||
for (const auto& member : m_members)
|
||||
{
|
||||
ids.push_back(member.id);
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
bool DynamicZoneBase::HasLockout(const std::string& event)
|
||||
{
|
||||
return std::ranges::any_of(m_lockouts, [&](const auto& l) { return l.IsEvent(event); });
|
||||
}
|
||||
|
||||
bool DynamicZoneBase::HasReplayLockout()
|
||||
{
|
||||
return HasLockout(DzLockout::ReplayTimer);
|
||||
}
|
||||
|
||||
void DynamicZoneBase::AddLockout(const std::string& event, uint32_t seconds)
|
||||
{
|
||||
auto lockout = DzLockout::Create(m_name, event, seconds, m_uuid);
|
||||
AddLockout(lockout);
|
||||
}
|
||||
|
||||
void DynamicZoneBase::AddLockout(const DzLockout& lockout, bool members_only)
|
||||
{
|
||||
if (!members_only)
|
||||
{
|
||||
DynamicZoneLockoutsRepository::InsertLockouts(GetDatabase(), GetID(), { lockout });
|
||||
}
|
||||
|
||||
CharacterExpeditionLockoutsRepository::InsertLockout(GetDatabase(), GetMemberIds(), lockout);
|
||||
|
||||
HandleLockoutUpdate(lockout, false, members_only);
|
||||
SendServerPacket(CreateLockoutPacket(lockout, false, members_only).get());
|
||||
}
|
||||
|
||||
void DynamicZoneBase::AddLockoutDuration(const std::string& event, int seconds, bool members_only)
|
||||
{
|
||||
auto lockout = DzLockout::Create(m_name, event, std::max(0, seconds), m_uuid);
|
||||
|
||||
// lockout has unsigned duration, pass original seconds to support reducing existing timers
|
||||
int secs = static_cast<int>(seconds * RuleR(Expedition, LockoutDurationMultiplier));
|
||||
CharacterExpeditionLockoutsRepository::AddLockoutDuration(GetDatabase(), GetMemberIds(), lockout, secs);
|
||||
|
||||
HandleLockoutDuration(lockout, seconds, members_only, true);
|
||||
SendServerPacket(CreateLockoutDurationPacket(lockout, seconds, members_only).get());
|
||||
}
|
||||
|
||||
void DynamicZoneBase::UpdateLockoutDuration(const std::string& event, uint32_t seconds, bool members_only)
|
||||
{
|
||||
// some live expeditions update existing lockout timers during progression
|
||||
auto it = std::ranges::find_if(m_lockouts, [&](const auto& l) { return l.IsEvent(event); });
|
||||
if (it != m_lockouts.end())
|
||||
{
|
||||
seconds = static_cast<uint32_t>(seconds * RuleR(Expedition, LockoutDurationMultiplier));
|
||||
DzLockout lockout(m_uuid, m_name, event, it->GetStartTime() + seconds, seconds);
|
||||
AddLockout(lockout, members_only);
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicZoneBase::RemoveLockout(const std::string& event)
|
||||
{
|
||||
DynamicZoneLockoutsRepository::DeleteWhere(GetDatabase(), fmt::format(
|
||||
"dynamic_zone_id = {} AND event_name = '{}'", GetID(), Strings::Escape(event)));
|
||||
|
||||
CharacterExpeditionLockoutsRepository::DeleteWhere(GetDatabase(), fmt::format(
|
||||
"character_id IN ({}) AND expedition_name = '{}' AND event_name = '{}'",
|
||||
fmt::join(GetMemberIds(), ","), Strings::Escape(m_name), Strings::Escape(event)));
|
||||
|
||||
DzLockout lockout{m_uuid, m_name, event, 0, 0};
|
||||
HandleLockoutUpdate(lockout, true, false);
|
||||
SendServerPacket(CreateLockoutPacket(lockout, true).get());
|
||||
}
|
||||
|
||||
void DynamicZoneBase::HandleLockoutUpdate(const DzLockout& lockout, bool remove, bool members_only)
|
||||
{
|
||||
if (!members_only)
|
||||
{
|
||||
std::erase_if(m_lockouts, [&](const auto& l) { return l.IsEvent(lockout.Event()); });
|
||||
if (!remove)
|
||||
{
|
||||
m_lockouts.push_back(lockout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicZoneBase::HandleLockoutDuration(const DzLockout& lockout, int seconds, bool members_only, bool insert_db)
|
||||
{
|
||||
if (!members_only)
|
||||
{
|
||||
auto it = std::ranges::find_if(m_lockouts, [&](const auto& l) { return l.IsEvent(lockout.Event()); });
|
||||
if (it != m_lockouts.end())
|
||||
{
|
||||
it->AddLockoutTime(seconds);
|
||||
}
|
||||
else
|
||||
{
|
||||
it = m_lockouts.insert(m_lockouts.end(), lockout);
|
||||
}
|
||||
|
||||
if (insert_db)
|
||||
{
|
||||
DynamicZoneLockoutsRepository::InsertLockouts(GetDatabase(), GetID(), { *it });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateLockoutPacket(const DzLockout& lockout, bool remove, bool members_only) const
|
||||
{
|
||||
uint32_t pack_size = sizeof(ServerDzLockout_Struct);
|
||||
auto pack = std::make_unique<ServerPacket>(ServerOP_DzLockout, pack_size);
|
||||
auto buf = reinterpret_cast<ServerDzLockout_Struct*>(pack->pBuffer);
|
||||
buf->dz_id = GetID();
|
||||
buf->expire_time = lockout.GetExpireTime();
|
||||
buf->duration = lockout.GetDuration();
|
||||
buf->sender_zone_id = GetCurrentZoneID();
|
||||
buf->sender_instance_id = GetCurrentInstanceID();
|
||||
buf->remove = remove;
|
||||
buf->members_only = members_only;
|
||||
strn0cpy(buf->event_name, lockout.Event().c_str(), sizeof(buf->event_name));
|
||||
return pack;
|
||||
}
|
||||
|
||||
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateLockoutDurationPacket(const DzLockout& lockout, int seconds, bool members_only) const
|
||||
{
|
||||
uint32_t pack_size = sizeof(ServerDzLockout_Struct);
|
||||
auto pack = std::make_unique<ServerPacket>(ServerOP_DzLockoutDuration, pack_size);
|
||||
auto buf = reinterpret_cast<ServerDzLockout_Struct*>(pack->pBuffer);
|
||||
buf->dz_id = GetID();
|
||||
buf->expire_time = lockout.GetExpireTime();
|
||||
buf->duration = lockout.GetDuration();
|
||||
buf->sender_zone_id = GetCurrentZoneID();
|
||||
buf->sender_instance_id = GetCurrentInstanceID();
|
||||
buf->members_only = members_only;
|
||||
buf->seconds = seconds;
|
||||
strn0cpy(buf->event_name, lockout.Event().c_str(), sizeof(buf->event_name));
|
||||
return pack;
|
||||
}
|
||||
|
||||
void DynamicZoneBase::SyncCharacterLockouts(uint32_t char_id, std::vector<DzLockout>& lockouts)
|
||||
{
|
||||
// adds missing event lockouts to client for this expedition and updates
|
||||
// client timers that are both shorter and from another expedition
|
||||
bool modified = false;
|
||||
|
||||
for (const auto& lockout : m_lockouts)
|
||||
{
|
||||
if (lockout.IsReplay() || lockout.IsExpired() || lockout.UUID() != m_uuid)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto it = std::find_if(lockouts.begin(), lockouts.end(), [&](const DzLockout& l) { return l.IsSame(lockout); });
|
||||
if (it == lockouts.end())
|
||||
{
|
||||
modified = true;
|
||||
lockouts.push_back(lockout); // insert missing
|
||||
}
|
||||
else if (it->GetSecondsRemaining() < lockout.GetSecondsRemaining() && it->UUID() != m_uuid)
|
||||
{
|
||||
// only update lockout timer not uuid so loot event apis still work
|
||||
modified = true;
|
||||
it->SetDuration(lockout.GetDuration());
|
||||
it->SetExpireTime(lockout.GetExpireTime());
|
||||
}
|
||||
}
|
||||
|
||||
if (modified)
|
||||
{
|
||||
CharacterExpeditionLockoutsRepository::InsertLockouts(GetDatabase(), char_id, lockouts);
|
||||
}
|
||||
}
|
||||
|
||||
+14
-68
@@ -1,8 +1,8 @@
|
||||
#ifndef COMMON_DYNAMIC_ZONE_BASE_H
|
||||
#define COMMON_DYNAMIC_ZONE_BASE_H
|
||||
|
||||
#include "dynamic_zone_lockout.h"
|
||||
#include "eq_constants.h"
|
||||
#include "net/packet.h"
|
||||
#include "repositories/dynamic_zones_repository.h"
|
||||
#include "repositories/dynamic_zone_members_repository.h"
|
||||
#include "repositories/dynamic_zone_templates_repository.h"
|
||||
@@ -10,40 +10,12 @@
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class Database;
|
||||
class ServerPacket;
|
||||
|
||||
// message string 8312 added in September 08 2020 Test patch (used by both dz and shared tasks)
|
||||
inline constexpr char DzNotAllAdded[] = "Not all players in your {0} were added to the {1}. The {1} can take a maximum of {2} players, and your {0} has {3}.";
|
||||
|
||||
enum class DzLockMsg : uint8_t
|
||||
{
|
||||
None = 0, Close, Begin
|
||||
};
|
||||
|
||||
enum class DynamicZoneType
|
||||
{
|
||||
None = 0,
|
||||
Expedition,
|
||||
Tutorial,
|
||||
Task,
|
||||
Mission, // Shared Task
|
||||
Quest
|
||||
};
|
||||
|
||||
enum class DynamicZoneMemberStatus
|
||||
{
|
||||
Unknown = 0,
|
||||
Online,
|
||||
Offline,
|
||||
InDynamicZone,
|
||||
LinkDead
|
||||
};
|
||||
|
||||
struct DynamicZoneMember
|
||||
{
|
||||
uint32_t id = 0;
|
||||
@@ -121,7 +93,6 @@ public:
|
||||
const std::string& GetName() const { return m_name; }
|
||||
const std::string& GetUUID() const { return m_uuid; }
|
||||
const DynamicZoneMember& GetLeader() const { return m_leader; }
|
||||
const std::vector<DzLockout>& GetLockouts() const { return m_lockouts; }
|
||||
const std::vector<DynamicZoneMember>& GetMembers() const { return m_members; }
|
||||
const DynamicZoneLocation& GetCompassLocation() const { return m_compass; }
|
||||
const DynamicZoneLocation& GetSafeReturnLocation() const { return m_safereturn; }
|
||||
@@ -133,34 +104,31 @@ public:
|
||||
uint32_t GetDatabaseMemberCount();
|
||||
DynamicZoneMember GetMemberData(uint32_t character_id);
|
||||
DynamicZoneMember GetMemberData(const std::string& character_name);
|
||||
std::vector<uint32_t> GetMemberIds();
|
||||
std::ostringstream GetSerialized();
|
||||
EQ::Net::DynamicPacket GetSerializedDzPacket();
|
||||
bool HasDatabaseMember(uint32_t character_id);
|
||||
bool HasMember(uint32_t character_id) const;
|
||||
bool HasMember(const std::string& character_name) const;
|
||||
bool HasMember(uint32_t character_id);
|
||||
bool HasMember(const std::string& character_name);
|
||||
bool HasMembers() const { return !m_members.empty(); }
|
||||
bool HasZoneInLocation() const { return m_has_zonein; }
|
||||
bool IsExpedition() const { return m_type == DynamicZoneType::Expedition; }
|
||||
bool IsExpired() const { return m_expire_time < std::chrono::system_clock::now(); }
|
||||
bool IsInstanceID(uint32_t instance_id) const { return (m_instance_id != 0 && m_instance_id == instance_id); }
|
||||
bool IsLocked() const { return m_is_locked; }
|
||||
bool IsValid() const { return m_instance_id != 0; }
|
||||
bool IsSameDz(uint32_t zone_id, uint32_t instance_id) const { return zone_id == m_zone_id && instance_id == m_instance_id; }
|
||||
void LoadSerializedDzPacket(char* cereal_data, uint32_t cereal_size);
|
||||
void LoadTemplate(const DynamicZoneTemplatesRepository::DynamicZoneTemplates& dz_template);
|
||||
void RemoveAllMembers();
|
||||
bool RemoveMember(uint32_t character_id);
|
||||
bool RemoveMember(const std::string& character_name);
|
||||
bool RemoveMember(const DynamicZoneMember& remove_member);
|
||||
void SaveMembers(const std::vector<DynamicZoneMember>& members);
|
||||
void SetCompass(const DynamicZoneLocation& location, bool update_db = false);
|
||||
void SetCompass(uint32_t zone_id, float x, float y, float z, bool update_db = false);
|
||||
void SetDuration(uint32_t seconds) { m_duration = std::chrono::seconds(seconds); }
|
||||
void SetLeader(const DynamicZoneMember& leader, bool update_db = false);
|
||||
void SetLocked(bool lock, bool update_db = false, DzLockMsg lock_msg = DzLockMsg::None, uint32_t color = Chat::Yellow);
|
||||
void SetMaxPlayers(uint32_t max_players) { m_max_players = max_players; }
|
||||
void SetMemberStatus(uint32_t character_id, DynamicZoneMemberStatus status);
|
||||
void SetMinPlayers(uint32_t min_players) { m_min_players = min_players; }
|
||||
void SetName(const std::string& name) { m_name = name; }
|
||||
void SetReplayOnJoin(bool enabled, bool update_db = false);
|
||||
void SetSafeReturn(const DynamicZoneLocation& location, bool update_db = false);
|
||||
void SetSafeReturn(uint32_t zone_id, float x, float y, float z, float heading, bool update_db = false);
|
||||
void SetSwitchID(int dz_switch_id, bool update_db = false);
|
||||
@@ -168,48 +136,34 @@ public:
|
||||
void SetUUID(std::string uuid) { m_uuid = std::move(uuid); }
|
||||
void SetZoneInLocation(const DynamicZoneLocation& location, bool update_db = false);
|
||||
void SetZoneInLocation(float x, float y, float z, float heading, bool update_db = false);
|
||||
bool SwapMember(const DynamicZoneMember& add_member, const std::string& remove_name);
|
||||
|
||||
void AddLockout(const std::string& event, uint32_t seconds);
|
||||
void AddLockoutDuration(const std::string& event, int seconds, bool members_only = true);
|
||||
bool HasLockout(const std::string& event);
|
||||
bool HasReplayLockout();
|
||||
void RemoveLockout(const std::string& event);
|
||||
void SyncCharacterLockouts(uint32_t char_id, std::vector<DzLockout>& lockouts);
|
||||
void UpdateLockoutDuration(const std::string& event, uint32_t seconds, bool members_only = true);
|
||||
bool SwapMember(const DynamicZoneMember& add_member, const std::string& remove_char_name);
|
||||
|
||||
protected:
|
||||
virtual uint16_t GetCurrentInstanceID() const { return 0; }
|
||||
virtual uint16_t GetCurrentZoneID() const { return 0; }
|
||||
virtual uint16_t GetCurrentInstanceID() { return 0; }
|
||||
virtual uint16_t GetCurrentZoneID() { return 0; }
|
||||
virtual Database& GetDatabase() = 0;
|
||||
virtual void HandleLockoutDuration(const DzLockout& lockout, int seconds, bool members_only, bool insert_db);
|
||||
virtual void HandleLockoutUpdate(const DzLockout& lockout, bool remove, bool members_only);
|
||||
virtual void ProcessCompassChange(const DynamicZoneLocation& location) { m_compass = location; }
|
||||
virtual void ProcessMemberAddRemove(const DynamicZoneMember& member, bool removed);
|
||||
virtual bool ProcessMemberStatusChange(uint32_t character_id, DynamicZoneMemberStatus status);
|
||||
virtual void ProcessRemoveAllMembers() { m_members.clear(); }
|
||||
virtual bool ProcessMemberStatusChange(uint32_t member_id, DynamicZoneMemberStatus status);
|
||||
virtual void ProcessRemoveAllMembers(bool silent = false) { m_members.clear(); }
|
||||
virtual void ProcessSetSwitchID(int dz_switch_id) { m_dz_switch_id = dz_switch_id; }
|
||||
virtual bool SendServerPacket(ServerPacket* packet) = 0;
|
||||
|
||||
void AddLockout(const DzLockout& lockout, bool members_only = false);
|
||||
void AddInternalMember(const DynamicZoneMember& member);
|
||||
uint32_t Create();
|
||||
uint32_t CreateInstance();
|
||||
void LoadRepositoryResult(DynamicZonesRepository::DynamicZoneInstance&& dz_entry);
|
||||
void RemoveInternalMember(uint32_t character_id);
|
||||
void SaveMembers(const std::vector<DynamicZoneMember>& members);
|
||||
uint32_t SaveToDatabase();
|
||||
bool SetInternalMemberStatus(uint32_t character_id, DynamicZoneMemberStatus status);
|
||||
|
||||
std::unique_ptr<ServerPacket> CreateServerPacket(uint16_t zone_id, uint16_t instance_id);
|
||||
std::unique_ptr<ServerPacket> CreateServerDzCreatePacket(uint16_t origin_zone_id, uint16_t origin_instance_id);
|
||||
std::unique_ptr<ServerPacket> CreateServerDzLocationPacket(uint16_t server_opcode, const DynamicZoneLocation& location);
|
||||
std::unique_ptr<ServerPacket> CreateServerDzSwitchIDPacket();
|
||||
std::unique_ptr<ServerPacket> CreateServerMemberAddRemovePacket(const DynamicZoneMember& member, bool removed);
|
||||
std::unique_ptr<ServerPacket> CreateServerMemberStatusPacket(uint32_t character_id, DynamicZoneMemberStatus status);
|
||||
std::unique_ptr<ServerPacket> CreateServerMemberSwapPacket(const DynamicZoneMember& remove_member, const DynamicZoneMember& add_member);
|
||||
std::unique_ptr<ServerPacket> CreateServerRemoveAllMembersPacket();
|
||||
std::unique_ptr<ServerPacket> CreateLockoutPacket(const DzLockout& lockout, bool remove, bool members_only = false) const;
|
||||
std::unique_ptr<ServerPacket> CreateLockoutDurationPacket(const DzLockout& lockout, int seconds, bool members_only = false) const;
|
||||
|
||||
uint32_t m_id = 0;
|
||||
uint32_t m_zone_id = 0;
|
||||
@@ -221,8 +175,6 @@ protected:
|
||||
bool m_never_expires = false;
|
||||
bool m_has_zonein = false;
|
||||
bool m_has_member_statuses = false;
|
||||
bool m_is_locked = false;
|
||||
bool m_add_replay = true;
|
||||
std::string m_name;
|
||||
std::string m_uuid;
|
||||
DynamicZoneMember m_leader;
|
||||
@@ -230,15 +182,12 @@ protected:
|
||||
DynamicZoneLocation m_compass;
|
||||
DynamicZoneLocation m_safereturn;
|
||||
DynamicZoneLocation m_zonein;
|
||||
std::chrono::seconds m_duration = {};
|
||||
std::chrono::seconds m_duration;
|
||||
std::chrono::time_point<std::chrono::system_clock> m_start_time;
|
||||
std::chrono::time_point<std::chrono::system_clock> m_expire_time;
|
||||
std::vector<DynamicZoneMember> m_members;
|
||||
std::vector<DzLockout> m_lockouts;
|
||||
|
||||
public:
|
||||
void Unserialize(std::span<char> buf);
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive& archive)
|
||||
{
|
||||
@@ -253,8 +202,6 @@ public:
|
||||
m_never_expires,
|
||||
m_has_zonein,
|
||||
m_has_member_statuses,
|
||||
m_is_locked,
|
||||
m_add_replay,
|
||||
m_name,
|
||||
m_uuid,
|
||||
m_leader,
|
||||
@@ -265,8 +212,7 @@ public:
|
||||
m_duration,
|
||||
m_start_time,
|
||||
m_expire_time,
|
||||
m_members,
|
||||
m_lockouts
|
||||
m_members
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
#include "dynamic_zone_lockout.h"
|
||||
#include "strings.h"
|
||||
#include "rulesys.h"
|
||||
#include "util/uuid.h"
|
||||
#include <fmt/format.h>
|
||||
#include <cereal/types/chrono.hpp>
|
||||
|
||||
DzLockout::DzLockout(std::string uuid, std::string expedition, std::string event, uint64_t expire_time, uint32_t duration)
|
||||
: m_uuid(std::move(uuid))
|
||||
, m_name(std::move(expedition))
|
||||
, m_event(std::move(event))
|
||||
, m_expire_time(std::chrono::system_clock::from_time_t(expire_time))
|
||||
, m_duration(duration)
|
||||
{
|
||||
m_is_replay = m_event == ReplayTimer;
|
||||
}
|
||||
|
||||
DzLockout::DzLockout(std::string_view name, BaseDynamicZoneLockoutsRepository::DynamicZoneLockouts&& lockout)
|
||||
: m_uuid(std::move(lockout.from_expedition_uuid))
|
||||
, m_name(name)
|
||||
, m_event(std::move(lockout.event_name))
|
||||
, m_expire_time(std::chrono::system_clock::from_time_t(lockout.expire_time))
|
||||
, m_duration(lockout.duration)
|
||||
{
|
||||
m_is_replay = m_event == ReplayTimer;
|
||||
}
|
||||
|
||||
DzLockout DzLockout::Create(const std::string& expedition, const std::string& event, uint32_t seconds, std::string uuid)
|
||||
{
|
||||
seconds = static_cast<uint32_t>(seconds * RuleR(Expedition, LockoutDurationMultiplier));
|
||||
|
||||
if (uuid.empty())
|
||||
{
|
||||
uuid = EQ::Util::UUID::Generate().ToString();
|
||||
}
|
||||
|
||||
DzLockout lockout{uuid, expedition, event, 0, seconds};
|
||||
lockout.Reset(); // sets expire time
|
||||
return lockout;
|
||||
}
|
||||
|
||||
uint32_t DzLockout::GetSecondsRemaining() const
|
||||
{
|
||||
auto now = std::chrono::system_clock::now();
|
||||
if (m_expire_time > now)
|
||||
{
|
||||
auto remaining = m_expire_time - now;
|
||||
return static_cast<uint32_t>(std::chrono::duration_cast<std::chrono::seconds>(remaining).count());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DzLockout::TimeStrings DzLockout::GetTimeRemainingStrs() const
|
||||
{
|
||||
auto seconds = GetSecondsRemaining();
|
||||
return DzLockout::TimeStrings{
|
||||
fmt::format_int(seconds / 86400).str(), // days
|
||||
fmt::format_int(seconds / 3600 % 24).str(), // hours
|
||||
fmt::format_int(seconds / 60 % 60).str(), // minutes
|
||||
fmt::format_int(seconds % 60).str() // seconds
|
||||
};
|
||||
}
|
||||
|
||||
bool DzLockout::IsSame(const DzLockout& other) const
|
||||
{
|
||||
return other.IsSame(m_name, m_event);
|
||||
}
|
||||
|
||||
bool DzLockout::IsSame(const std::string& expedition, const std::string& event) const
|
||||
{
|
||||
return m_name == expedition && m_event == event;
|
||||
}
|
||||
|
||||
void DzLockout::AddLockoutTime(int seconds)
|
||||
{
|
||||
seconds = static_cast<int>(seconds * RuleR(Expedition, LockoutDurationMultiplier));
|
||||
|
||||
auto new_duration = std::max(0, static_cast<int>(m_duration.count()) + seconds);
|
||||
|
||||
auto start_time = m_expire_time - m_duration;
|
||||
m_duration = std::chrono::seconds(new_duration);
|
||||
m_expire_time = start_time + m_duration;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void DzLockout::serialize(T& archive)
|
||||
{
|
||||
archive(m_is_replay, m_uuid, m_name, m_event, m_duration, m_expire_time);
|
||||
}
|
||||
|
||||
template void DzLockout::serialize(cereal::BinaryOutputArchive&);
|
||||
template void DzLockout::serialize(cereal::BinaryInputArchive&);
|
||||
@@ -1,56 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include "repositories/base/base_dynamic_zone_lockouts_repository.h"
|
||||
|
||||
class DzLockout
|
||||
{
|
||||
public:
|
||||
DzLockout() = default;
|
||||
DzLockout(std::string uuid, std::string expedition, std::string event, uint64_t expire_time, uint32_t duration);
|
||||
DzLockout(std::string_view name, BaseDynamicZoneLockoutsRepository::DynamicZoneLockouts&& lockout);
|
||||
|
||||
static constexpr char ReplayTimer[] = "Replay Timer";
|
||||
|
||||
static DzLockout Create(const std::string& expedition, const std::string& event, uint32_t seconds, std::string uuid = {});
|
||||
|
||||
struct TimeStrings
|
||||
{
|
||||
std::string days;
|
||||
std::string hours;
|
||||
std::string mins;
|
||||
std::string secs;
|
||||
};
|
||||
|
||||
void AddLockoutTime(int seconds);
|
||||
uint32_t GetDuration() const { return static_cast<uint32_t>(m_duration.count()); }
|
||||
uint64_t GetExpireTime() const { return std::chrono::system_clock::to_time_t(m_expire_time); }
|
||||
uint64_t GetStartTime() const { return std::chrono::system_clock::to_time_t(m_expire_time - m_duration); }
|
||||
uint32_t GetSecondsRemaining() const;
|
||||
TimeStrings GetTimeRemainingStrs() const;
|
||||
const std::string& DzName() const { return m_name; }
|
||||
const std::string& Event() const { return m_event; }
|
||||
const std::string& UUID() const { return m_uuid; }
|
||||
bool IsEvent(std::string_view event) const { return m_event == event; }
|
||||
bool IsExpired() const { return GetSecondsRemaining() == 0; }
|
||||
bool IsReplay() const { return m_is_replay; }
|
||||
bool IsSame(const DzLockout& other) const;
|
||||
bool IsSame(const std::string& expedition, const std::string& event) const;
|
||||
bool IsUUID(const std::string& uuid) const { return uuid == m_uuid; }
|
||||
void Reset() { m_expire_time = std::chrono::system_clock::now() + m_duration; }
|
||||
void SetDuration(uint32_t seconds) { m_duration = std::chrono::seconds(seconds); }
|
||||
void SetExpireTime(uint64_t expire_time) { m_expire_time = std::chrono::system_clock::from_time_t(expire_time); }
|
||||
void SetUUID(const std::string& uuid) { m_uuid = uuid; }
|
||||
|
||||
template <typename T>
|
||||
void serialize(T& archive);
|
||||
|
||||
private:
|
||||
bool m_is_replay = false;
|
||||
std::string m_uuid; // dz received in
|
||||
std::string m_name;
|
||||
std::string m_event;
|
||||
std::chrono::seconds m_duration = {};
|
||||
std::chrono::time_point<std::chrono::system_clock> m_expire_time;
|
||||
};
|
||||
@@ -130,8 +130,6 @@ namespace EQ
|
||||
using RoF2::invtype::MAIL_SIZE;
|
||||
using RoF2::invtype::GUILD_TROPHY_TRIBUTE_SIZE;
|
||||
using RoF2::invtype::KRONO_SIZE;
|
||||
using RoF2::invtype::GUILD_BANK_MAIN_SIZE;
|
||||
using RoF2::invtype::GUILD_BANK_DEPOSIT_SIZE;
|
||||
using RoF2::invtype::OTHER_SIZE;
|
||||
|
||||
using RoF2::invtype::TRADE_NPC_SIZE;
|
||||
|
||||
@@ -473,6 +473,7 @@ N(OP_SendAATable),
|
||||
N(OP_SendCharInfo),
|
||||
N(OP_SendExpZonein),
|
||||
N(OP_SendFindableNPCs),
|
||||
N(OP_SendFindableLocations),
|
||||
N(OP_SendGuildTributes),
|
||||
N(OP_SendLoginInfo),
|
||||
N(OP_SendMaxCharacters),
|
||||
|
||||
@@ -974,6 +974,25 @@ namespace ZoneBlockedSpellTypes {
|
||||
const uint8 Region = 2;
|
||||
};
|
||||
|
||||
enum class DynamicZoneType
|
||||
{
|
||||
None = 0,
|
||||
Expedition,
|
||||
Tutorial,
|
||||
Task,
|
||||
Mission, // Shared Task
|
||||
Quest
|
||||
};
|
||||
|
||||
enum class DynamicZoneMemberStatus : uint8_t
|
||||
{
|
||||
Unknown = 0,
|
||||
Online,
|
||||
Offline,
|
||||
InDynamicZone,
|
||||
LinkDead
|
||||
};
|
||||
|
||||
enum StartZoneIndex {
|
||||
Odus = 0,
|
||||
Qeynos,
|
||||
|
||||
+22
-22
@@ -173,7 +173,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
ClientUnknown::INULL, ClientUnknown::INULL, ClientUnknown::INULL,
|
||||
ClientUnknown::INULL, ClientUnknown::INULL, ClientUnknown::INULL,
|
||||
ClientUnknown::INULL, ClientUnknown::INULL, ClientUnknown::INULL,
|
||||
ClientUnknown::INULL, ClientUnknown::INULL, ClientUnknown::INULL
|
||||
ClientUnknown::INULL
|
||||
),
|
||||
|
||||
ClientUnknown::INULL,
|
||||
@@ -200,7 +200,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
Client62::INULL, Client62::INULL, Client62::INULL,
|
||||
Client62::INULL, Client62::INULL, Client62::INULL,
|
||||
Client62::INULL, Client62::INULL, Client62::INULL,
|
||||
Client62::INULL, Client62::INULL, Client62::INULL
|
||||
Client62::INULL
|
||||
),
|
||||
|
||||
Client62::INULL,
|
||||
@@ -227,7 +227,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
Titanium::invtype::VIEW_MOD_PC_SIZE, Titanium::invtype::VIEW_MOD_BANK_SIZE, Titanium::invtype::VIEW_MOD_SHARED_BANK_SIZE,
|
||||
Titanium::invtype::VIEW_MOD_LIMBO_SIZE, Titanium::invtype::ALT_STORAGE_SIZE, Titanium::invtype::ARCHIVED_SIZE,
|
||||
Titanium::INULL, Titanium::INULL, Titanium::INULL,
|
||||
Titanium::INULL, Titanium::INULL, Titanium::invtype::OTHER_SIZE
|
||||
Titanium::invtype::OTHER_SIZE
|
||||
),
|
||||
|
||||
Titanium::invslot::EQUIPMENT_BITMASK,
|
||||
@@ -254,7 +254,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
SoF::invtype::VIEW_MOD_PC_SIZE, SoF::invtype::VIEW_MOD_BANK_SIZE, SoF::invtype::VIEW_MOD_SHARED_BANK_SIZE,
|
||||
SoF::invtype::VIEW_MOD_LIMBO_SIZE, SoF::invtype::ALT_STORAGE_SIZE, SoF::invtype::ARCHIVED_SIZE,
|
||||
SoF::INULL, SoF::INULL, SoF::INULL,
|
||||
SoF::INULL, SoF::INULL, SoF::invtype::OTHER_SIZE
|
||||
SoF::invtype::OTHER_SIZE
|
||||
),
|
||||
|
||||
SoF::invslot::EQUIPMENT_BITMASK,
|
||||
@@ -281,7 +281,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
SoD::invtype::VIEW_MOD_PC_SIZE, SoD::invtype::VIEW_MOD_BANK_SIZE, SoD::invtype::VIEW_MOD_SHARED_BANK_SIZE,
|
||||
SoD::invtype::VIEW_MOD_LIMBO_SIZE, SoD::invtype::ALT_STORAGE_SIZE, SoD::invtype::ARCHIVED_SIZE,
|
||||
SoD::INULL, SoD::INULL, SoD::INULL,
|
||||
SoD::INULL, SoD::INULL, SoD::invtype::OTHER_SIZE
|
||||
SoD::invtype::OTHER_SIZE
|
||||
),
|
||||
|
||||
SoD::invslot::EQUIPMENT_BITMASK,
|
||||
@@ -308,7 +308,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
UF::invtype::VIEW_MOD_PC_SIZE, UF::invtype::VIEW_MOD_BANK_SIZE, UF::invtype::VIEW_MOD_SHARED_BANK_SIZE,
|
||||
UF::invtype::VIEW_MOD_LIMBO_SIZE, UF::invtype::ALT_STORAGE_SIZE, UF::invtype::ARCHIVED_SIZE,
|
||||
UF::INULL, UF::INULL, UF::INULL,
|
||||
UF::INULL, UF::INULL, UF::invtype::OTHER_SIZE
|
||||
UF::invtype::OTHER_SIZE
|
||||
),
|
||||
|
||||
UF::invslot::EQUIPMENT_BITMASK,
|
||||
@@ -335,7 +335,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
RoF::invtype::VIEW_MOD_PC_SIZE, RoF::invtype::VIEW_MOD_BANK_SIZE, RoF::invtype::VIEW_MOD_SHARED_BANK_SIZE,
|
||||
RoF::invtype::VIEW_MOD_LIMBO_SIZE, RoF::invtype::ALT_STORAGE_SIZE, RoF::invtype::ARCHIVED_SIZE,
|
||||
RoF::invtype::MAIL_SIZE, RoF::invtype::GUILD_TROPHY_TRIBUTE_SIZE, RoF::INULL,
|
||||
RoF::INULL,RoF::INULL,RoF::invtype::OTHER_SIZE
|
||||
RoF::invtype::OTHER_SIZE
|
||||
),
|
||||
|
||||
RoF::invslot::EQUIPMENT_BITMASK,
|
||||
@@ -362,7 +362,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
RoF2::invtype::VIEW_MOD_PC_SIZE, RoF2::invtype::VIEW_MOD_BANK_SIZE, RoF2::invtype::VIEW_MOD_SHARED_BANK_SIZE,
|
||||
RoF2::invtype::VIEW_MOD_LIMBO_SIZE, RoF2::invtype::ALT_STORAGE_SIZE, RoF2::invtype::ARCHIVED_SIZE,
|
||||
RoF2::invtype::MAIL_SIZE, RoF2::invtype::GUILD_TROPHY_TRIBUTE_SIZE, RoF2::invtype::KRONO_SIZE,
|
||||
RoF2::invtype::GUILD_BANK_MAIN_SIZE,RoF2::invtype::GUILD_BANK_DEPOSIT_SIZE, RoF2::invtype::OTHER_SIZE
|
||||
RoF2::invtype::OTHER_SIZE
|
||||
),
|
||||
|
||||
RoF2::invslot::EQUIPMENT_BITMASK,
|
||||
@@ -389,7 +389,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
EntityLimits::NPC::INULL, EntityLimits::NPC::INULL, EntityLimits::NPC::INULL,
|
||||
EntityLimits::NPC::INULL, EntityLimits::NPC::INULL, EntityLimits::NPC::INULL,
|
||||
EntityLimits::NPC::INULL, EntityLimits::NPC::INULL, EntityLimits::NPC::INULL,
|
||||
EntityLimits::NPC::INULL, EntityLimits::NPC::INULL,EntityLimits::NPC::INULL
|
||||
EntityLimits::NPC::INULL
|
||||
),
|
||||
|
||||
EntityLimits::NPC::INULL,
|
||||
@@ -416,7 +416,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
EntityLimits::NPCMerchant::INULL, EntityLimits::NPCMerchant::INULL, EntityLimits::NPCMerchant::INULL,
|
||||
EntityLimits::NPCMerchant::INULL, EntityLimits::NPCMerchant::INULL, EntityLimits::NPCMerchant::INULL,
|
||||
EntityLimits::NPCMerchant::INULL, EntityLimits::NPCMerchant::INULL, EntityLimits::NPCMerchant::INULL,
|
||||
EntityLimits::NPCMerchant::INULL, EntityLimits::NPCMerchant::INULL, EntityLimits::NPCMerchant::INULL
|
||||
EntityLimits::NPCMerchant::INULL
|
||||
),
|
||||
|
||||
EntityLimits::NPCMerchant::INULL,
|
||||
@@ -443,7 +443,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
EntityLimits::Merc::INULL, EntityLimits::Merc::INULL, EntityLimits::Merc::INULL,
|
||||
EntityLimits::Merc::INULL, EntityLimits::Merc::INULL, EntityLimits::Merc::INULL,
|
||||
EntityLimits::Merc::INULL, EntityLimits::Merc::INULL, EntityLimits::Merc::INULL,
|
||||
EntityLimits::Merc::INULL, EntityLimits::Merc::INULL, EntityLimits::Merc::INULL
|
||||
EntityLimits::Merc::INULL
|
||||
),
|
||||
|
||||
EntityLimits::Merc::INULL,
|
||||
@@ -470,7 +470,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
EntityLimits::Bot::INULL, EntityLimits::Bot::INULL, EntityLimits::Bot::INULL,
|
||||
EntityLimits::Bot::INULL, EntityLimits::Bot::INULL, EntityLimits::Bot::INULL,
|
||||
EntityLimits::Bot::INULL, EntityLimits::Bot::INULL, EntityLimits::Bot::INULL,
|
||||
EntityLimits::Bot::INULL, EntityLimits::Bot::INULL, EntityLimits::Bot::INULL
|
||||
EntityLimits::Bot::INULL
|
||||
),
|
||||
|
||||
EntityLimits::Bot::invslot::EQUIPMENT_BITMASK,
|
||||
@@ -497,7 +497,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
EntityLimits::ClientPet::INULL, EntityLimits::ClientPet::INULL, EntityLimits::ClientPet::INULL,
|
||||
EntityLimits::ClientPet::INULL, EntityLimits::ClientPet::INULL, EntityLimits::ClientPet::INULL,
|
||||
EntityLimits::ClientPet::INULL, EntityLimits::ClientPet::INULL, EntityLimits::ClientPet::INULL,
|
||||
EntityLimits::ClientPet::INULL, EntityLimits::ClientPet::INULL, EntityLimits::ClientPet::INULL
|
||||
EntityLimits::ClientPet::INULL
|
||||
),
|
||||
|
||||
EntityLimits::ClientPet::INULL,
|
||||
@@ -524,7 +524,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
EntityLimits::NPCPet::INULL, EntityLimits::NPCPet::INULL, EntityLimits::NPCPet::INULL,
|
||||
EntityLimits::NPCPet::INULL, EntityLimits::NPCPet::INULL, EntityLimits::NPCPet::INULL,
|
||||
EntityLimits::NPCPet::INULL, EntityLimits::NPCPet::INULL, EntityLimits::NPCPet::INULL,
|
||||
EntityLimits::NPCPet::INULL, EntityLimits::NPCPet::INULL, EntityLimits::NPCPet::INULL
|
||||
EntityLimits::NPCPet::INULL
|
||||
),
|
||||
|
||||
EntityLimits::NPCPet::INULL,
|
||||
@@ -551,7 +551,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
EntityLimits::MercPet::INULL, EntityLimits::MercPet::INULL, EntityLimits::MercPet::INULL,
|
||||
EntityLimits::MercPet::INULL, EntityLimits::MercPet::INULL, EntityLimits::MercPet::INULL,
|
||||
EntityLimits::MercPet::INULL, EntityLimits::MercPet::INULL, EntityLimits::MercPet::INULL,
|
||||
EntityLimits::MercPet::INULL, EntityLimits::MercPet::INULL, EntityLimits::MercPet::INULL
|
||||
EntityLimits::MercPet::INULL
|
||||
),
|
||||
|
||||
EntityLimits::MercPet::INULL,
|
||||
@@ -578,7 +578,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
EntityLimits::BotPet::INULL, EntityLimits::BotPet::INULL, EntityLimits::BotPet::INULL,
|
||||
EntityLimits::BotPet::INULL, EntityLimits::BotPet::INULL, EntityLimits::BotPet::INULL,
|
||||
EntityLimits::BotPet::INULL, EntityLimits::BotPet::INULL, EntityLimits::BotPet::INULL,
|
||||
EntityLimits::BotPet::INULL, EntityLimits::BotPet::INULL, EntityLimits::BotPet::INULL
|
||||
EntityLimits::BotPet::INULL
|
||||
),
|
||||
|
||||
EntityLimits::BotPet::INULL,
|
||||
@@ -605,7 +605,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
Titanium::invtype::VIEW_MOD_PC_SIZE, Titanium::invtype::VIEW_MOD_BANK_SIZE, Titanium::invtype::VIEW_MOD_SHARED_BANK_SIZE,
|
||||
Titanium::invtype::VIEW_MOD_LIMBO_SIZE, Titanium::INULL, Titanium::INULL,
|
||||
Titanium::INULL, Titanium::INULL, Titanium::INULL,
|
||||
Titanium::INULL, Titanium::INULL, Titanium::INULL
|
||||
Titanium::INULL
|
||||
),
|
||||
|
||||
Titanium::INULL,
|
||||
@@ -632,7 +632,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
SoF::invtype::VIEW_MOD_PC_SIZE, SoF::invtype::VIEW_MOD_BANK_SIZE, SoF::invtype::VIEW_MOD_SHARED_BANK_SIZE,
|
||||
SoF::invtype::VIEW_MOD_LIMBO_SIZE, SoF::INULL, SoF::INULL,
|
||||
SoF::INULL, SoF::INULL, SoF::INULL,
|
||||
SoF::INULL, SoF::INULL, SoF::INULL
|
||||
SoF::INULL
|
||||
),
|
||||
|
||||
SoF::INULL,
|
||||
@@ -659,7 +659,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
SoD::invtype::VIEW_MOD_PC_SIZE, SoD::invtype::VIEW_MOD_BANK_SIZE, SoD::invtype::VIEW_MOD_SHARED_BANK_SIZE,
|
||||
SoD::invtype::VIEW_MOD_LIMBO_SIZE, SoD::INULL, SoD::INULL,
|
||||
SoD::INULL, SoD::INULL, SoD::INULL,
|
||||
SoD::INULL, SoD::INULL, SoD::INULL
|
||||
SoD::INULL
|
||||
),
|
||||
|
||||
SoD::INULL,
|
||||
@@ -686,7 +686,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
UF::invtype::VIEW_MOD_PC_SIZE, UF::invtype::VIEW_MOD_BANK_SIZE, UF::invtype::VIEW_MOD_SHARED_BANK_SIZE,
|
||||
UF::invtype::VIEW_MOD_LIMBO_SIZE, UF::INULL, UF::INULL,
|
||||
UF::INULL, UF::INULL, UF::INULL,
|
||||
UF::INULL, UF::INULL, UF::INULL
|
||||
UF::INULL
|
||||
),
|
||||
|
||||
UF::INULL,
|
||||
@@ -713,7 +713,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
RoF::invtype::VIEW_MOD_PC_SIZE, RoF::invtype::VIEW_MOD_BANK_SIZE, RoF::invtype::VIEW_MOD_SHARED_BANK_SIZE,
|
||||
RoF::invtype::VIEW_MOD_LIMBO_SIZE, RoF::INULL, RoF::INULL,
|
||||
RoF::INULL, RoF::INULL, RoF::INULL,
|
||||
RoF::INULL, RoF::INULL, RoF::INULL
|
||||
RoF::INULL
|
||||
),
|
||||
|
||||
RoF::INULL,
|
||||
@@ -740,7 +740,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
||||
RoF2::invtype::VIEW_MOD_PC_SIZE, RoF2::invtype::VIEW_MOD_BANK_SIZE, RoF2::invtype::VIEW_MOD_SHARED_BANK_SIZE,
|
||||
RoF2::invtype::VIEW_MOD_LIMBO_SIZE, RoF2::INULL, RoF2::INULL,
|
||||
RoF2::INULL, RoF2::INULL, RoF2::INULL,
|
||||
RoF2::INULL, RoF2::INULL, RoF2::INULL
|
||||
RoF2::INULL
|
||||
),
|
||||
|
||||
RoF2::INULL,
|
||||
|
||||
+3
-3
@@ -87,7 +87,7 @@ namespace EQ
|
||||
int16 ViewMODPC, ViewMODBank, ViewMODSharedBank;
|
||||
int16 ViewMODLimbo, AltStorage, Archived;
|
||||
int16 Mail, GuildTrophyTribute, Krono;
|
||||
int16 GuildBankMain,GuildBankDeposit, Other;
|
||||
int16 Other;
|
||||
|
||||
InventoryTypeSize_Struct(
|
||||
int16 Possessions, int16 Bank, int16 SharedBank,
|
||||
@@ -98,7 +98,7 @@ namespace EQ
|
||||
int16 ViewMODPC, int16 ViewMODBank, int16 ViewMODSharedBank,
|
||||
int16 ViewMODLimbo, int16 AltStorage, int16 Archived,
|
||||
int16 Mail, int16 GuildTrophyTribute, int16 Krono,
|
||||
int16 GuildBankMain,int16 GuildBankDeposit, int16 Other
|
||||
int16 Other
|
||||
) :
|
||||
Possessions(Possessions), Bank(Bank), SharedBank(SharedBank),
|
||||
Trade(Trade), World(World), Limbo(Limbo),
|
||||
@@ -108,7 +108,7 @@ namespace EQ
|
||||
ViewMODPC(ViewMODPC), ViewMODBank(ViewMODBank), ViewMODSharedBank(ViewMODSharedBank),
|
||||
ViewMODLimbo(ViewMODLimbo), AltStorage(AltStorage), Archived(Archived),
|
||||
Mail(Mail), GuildTrophyTribute(GuildTrophyTribute), Krono(Krono),
|
||||
GuildBankMain(GuildBankMain), GuildBankDeposit(GuildBankDeposit), Other(Other)
|
||||
Other(Other)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
+44
-53
@@ -19,17 +19,17 @@
|
||||
#ifndef EQ_PACKET_STRUCTS_H
|
||||
#define EQ_PACKET_STRUCTS_H
|
||||
|
||||
#include <list>
|
||||
#include "types.h"
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <time.h>
|
||||
#include "../cereal/include/cereal/archives/binary.hpp"
|
||||
#include "../cereal/include/cereal/types/string.hpp"
|
||||
#include "../cereal/include/cereal/types/vector.hpp"
|
||||
#include "../common/version.h"
|
||||
#include "emu_constants.h"
|
||||
#include "textures.h"
|
||||
#include "types.h"
|
||||
#include "../cereal/include/cereal/archives/binary.hpp"
|
||||
#include "../cereal/include/cereal/types/string.hpp"
|
||||
#include "../cereal/include/cereal/types/vector.hpp"
|
||||
|
||||
static const uint32 BUFF_COUNT = 42;
|
||||
static const uint32 PET_BUFF_COUNT = 30;
|
||||
@@ -5529,65 +5529,56 @@ struct GuildBankWithdrawItem_Struct
|
||||
|
||||
struct GuildBankItemUpdate_Struct
|
||||
{
|
||||
void Init(
|
||||
uint32 inAction,
|
||||
uint32 inUnknown004,
|
||||
uint16 inSlotID,
|
||||
uint16 inArea,
|
||||
uint16 inUnknown012,
|
||||
uint32 inItemID,
|
||||
uint32 inIcon,
|
||||
uint32 inQuantity,
|
||||
uint32 inPermissions,
|
||||
uint32 inAllowMerge,
|
||||
bool inUseable)
|
||||
void Init(uint32 inAction, uint32 inUnknown004, uint16 inSlotID, uint16 inArea, uint16 inUnknown012, uint32 inItemID, uint32 inIcon, uint32 inQuantity,
|
||||
uint32 inPermissions, uint32 inAllowMerge, bool inUseable)
|
||||
{
|
||||
action = inAction;
|
||||
unknown004 = inUnknown004;
|
||||
slot_id = inSlotID;
|
||||
area = inArea;
|
||||
display = inUnknown012;
|
||||
item_id = inItemID;
|
||||
icon_id = inIcon;
|
||||
quantity = inQuantity;
|
||||
permissions = inPermissions;
|
||||
allow_merge = inAllowMerge;
|
||||
is_useable = inUseable;
|
||||
item_name[0] = '\0';
|
||||
donator[0] = '\0';
|
||||
who_for[0] = '\0';
|
||||
Action = inAction;
|
||||
Unknown004 = inUnknown004;
|
||||
SlotID = inSlotID;
|
||||
Area = inArea;
|
||||
Unknown012 = inUnknown012;
|
||||
ItemID = inItemID;
|
||||
Icon = inIcon;
|
||||
Quantity = inQuantity;
|
||||
Permissions = inPermissions;
|
||||
AllowMerge = inAllowMerge;
|
||||
Useable = inUseable;
|
||||
ItemName[0] = '\0';
|
||||
Donator[0] = '\0';
|
||||
WhoFor[0] = '\0';
|
||||
};
|
||||
|
||||
/*000*/ uint32 action;
|
||||
/*004*/ uint32 unknown004;
|
||||
/*008*/ uint16 slot_id;
|
||||
/*010*/ uint16 area;
|
||||
/*012*/ uint32 display;
|
||||
/*016*/ uint32 item_id;
|
||||
/*020*/ uint32 icon_id;
|
||||
/*024*/ uint32 quantity;
|
||||
/*028*/ uint32 permissions;
|
||||
/*032*/ uint8 allow_merge;
|
||||
/*033*/ uint8 is_useable; // Used in conjunction with the Public-if-useable permission.
|
||||
/*034*/ char item_name[64];
|
||||
/*098*/ char donator[64];
|
||||
/*162*/ char who_for[64];
|
||||
/*226*/ uint16 unknown226;
|
||||
/*000*/ uint32 Action;
|
||||
/*004*/ uint32 Unknown004;
|
||||
/*008*/ uint16 SlotID;
|
||||
/*010*/ uint16 Area;
|
||||
/*012*/ uint32 Unknown012;
|
||||
/*016*/ uint32 ItemID;
|
||||
/*020*/ uint32 Icon;
|
||||
/*024*/ uint32 Quantity;
|
||||
/*028*/ uint32 Permissions;
|
||||
/*032*/ uint8 AllowMerge;
|
||||
/*033*/ uint8 Useable; // Used in conjunction with the Public-if-useable permission.
|
||||
/*034*/ char ItemName[64];
|
||||
/*098*/ char Donator[64];
|
||||
/*162*/ char WhoFor[64];
|
||||
/*226*/ uint16 Unknown226;
|
||||
};
|
||||
|
||||
// newer clients (RoF+) send a list that contains 240 entries
|
||||
// The packets don't actually use all 64 chars in the strings, but we'll just overallocate for these
|
||||
struct GuildBankItemListEntry_Struct {
|
||||
uint8 vaild;
|
||||
struct GuildBankItemListEntry_Struct
|
||||
{
|
||||
uint8 vaild;
|
||||
uint32 permissions;
|
||||
char whofor[64];
|
||||
char donator[64];
|
||||
char whofor[64];
|
||||
char donator[64];
|
||||
uint32 item_id;
|
||||
uint32 item_icon;
|
||||
uint32 quantity;
|
||||
uint8 allow_merge; // 1 here for non-full stacks
|
||||
uint8 usable;
|
||||
char item_name[64];
|
||||
uint8 allow_merge; // 1 here for non-full stacks
|
||||
uint8 usable;
|
||||
char item_name[64];
|
||||
};
|
||||
|
||||
struct GuildBankClear_Struct
|
||||
|
||||
@@ -81,13 +81,14 @@ void PlayerEventLogs::Init()
|
||||
if (!settings_to_insert.empty()) {
|
||||
PlayerEventLogSettingsRepository::ReplaceMany(*m_database, settings_to_insert);
|
||||
}
|
||||
|
||||
|
||||
LoadEtlIds();
|
||||
|
||||
bool processing_in_world = !RuleB(Logging, PlayerEventsQSProcess) && IsWorld();
|
||||
bool processing_in_qs = RuleB(Logging, PlayerEventsQSProcess) && IsQueryServ();
|
||||
|
||||
// on initial boot process truncation
|
||||
if (processing_in_world || processing_in_qs) {
|
||||
LoadEtlIds();
|
||||
ProcessRetentionTruncation();
|
||||
}
|
||||
}
|
||||
@@ -401,7 +402,7 @@ void PlayerEventLogs::ProcessBatchQueue()
|
||||
r.event_data = "{}"; // Clear event data
|
||||
}
|
||||
else {
|
||||
LogPlayerEventsDetail("Non-Implemented ETL routing [{}]", r.event_type_id);
|
||||
LogError("Non-Implemented ETL routing [{}]", r.event_type_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,9 +65,6 @@ namespace PlayerEvent {
|
||||
BARTER_TRANSACTION,
|
||||
SPEECH,
|
||||
EVOLVE_ITEM,
|
||||
GUILD_BANK_DEPOSIT,
|
||||
GUILD_BANK_WITHDRAWAL,
|
||||
GUILD_BANK_MOVE_TO_BANK_AREA,
|
||||
MAX // dont remove
|
||||
};
|
||||
|
||||
@@ -132,10 +129,7 @@ namespace PlayerEvent {
|
||||
"Parcel Prune Routine",
|
||||
"Barter Transaction",
|
||||
"Player Speech",
|
||||
"Evolve Item Update",
|
||||
"Guild Bank Item Deposit",
|
||||
"Guild Bank Item Withdrawal",
|
||||
"Guild Bank Move From Deposit Area to Bank Area"
|
||||
"Evolve Item Update"
|
||||
};
|
||||
|
||||
// Generic struct used by all events
|
||||
@@ -881,9 +875,8 @@ namespace PlayerEvent {
|
||||
uint32 trader_id;
|
||||
std::string trader_name;
|
||||
uint32 price;
|
||||
uint32 quantity;
|
||||
int32 charges;
|
||||
uint64 total_cost;
|
||||
uint32 charges;
|
||||
uint32 total_cost;
|
||||
uint64 player_money_balance;
|
||||
|
||||
|
||||
@@ -903,7 +896,6 @@ namespace PlayerEvent {
|
||||
CEREAL_NVP(trader_id),
|
||||
CEREAL_NVP(trader_name),
|
||||
CEREAL_NVP(price),
|
||||
CEREAL_NVP(quantity),
|
||||
CEREAL_NVP(charges),
|
||||
CEREAL_NVP(total_cost),
|
||||
CEREAL_NVP(player_money_balance)
|
||||
@@ -923,9 +915,8 @@ namespace PlayerEvent {
|
||||
uint32 buyer_id;
|
||||
std::string buyer_name;
|
||||
uint32 price;
|
||||
uint32 quantity;
|
||||
int32 charges;
|
||||
uint64 total_cost;
|
||||
uint32 charges;
|
||||
uint32 total_cost;
|
||||
uint64 player_money_balance;
|
||||
|
||||
|
||||
@@ -945,7 +936,6 @@ namespace PlayerEvent {
|
||||
CEREAL_NVP(buyer_id),
|
||||
CEREAL_NVP(buyer_name),
|
||||
CEREAL_NVP(price),
|
||||
CEREAL_NVP(quantity),
|
||||
CEREAL_NVP(charges),
|
||||
CEREAL_NVP(total_cost),
|
||||
CEREAL_NVP(player_money_balance)
|
||||
@@ -1155,7 +1145,6 @@ namespace PlayerEvent {
|
||||
uint32 augment_5_id;
|
||||
uint32 augment_6_id;
|
||||
uint32 quantity;
|
||||
int32 charges;
|
||||
std::string from_player_name;
|
||||
std::string to_player_name;
|
||||
uint32 sent_date;
|
||||
@@ -1173,7 +1162,6 @@ namespace PlayerEvent {
|
||||
CEREAL_NVP(augment_5_id),
|
||||
CEREAL_NVP(augment_6_id),
|
||||
CEREAL_NVP(quantity),
|
||||
CEREAL_NVP(charges),
|
||||
CEREAL_NVP(from_player_name),
|
||||
CEREAL_NVP(to_player_name),
|
||||
CEREAL_NVP(sent_date)
|
||||
@@ -1286,38 +1274,6 @@ namespace PlayerEvent {
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
struct GuildBankTransaction {
|
||||
uint32 char_id;
|
||||
uint32 guild_id;
|
||||
uint32 item_id;
|
||||
uint32 aug_slot_one;
|
||||
uint32 aug_slot_two;
|
||||
uint32 aug_slot_three;
|
||||
uint32 aug_slot_four;
|
||||
uint32 aug_slot_five;
|
||||
uint32 aug_slot_six;
|
||||
uint32 quantity;
|
||||
uint32 permission;
|
||||
|
||||
// cereal
|
||||
template<class Archive>
|
||||
void serialize(Archive &ar)
|
||||
{
|
||||
ar(
|
||||
CEREAL_NVP(char_id),
|
||||
CEREAL_NVP(guild_id),
|
||||
CEREAL_NVP(item_id),
|
||||
CEREAL_NVP(aug_slot_one),
|
||||
CEREAL_NVP(aug_slot_two),
|
||||
CEREAL_NVP(aug_slot_three),
|
||||
CEREAL_NVP(aug_slot_four),
|
||||
CEREAL_NVP(aug_slot_five),
|
||||
CEREAL_NVP(aug_slot_six),
|
||||
CEREAL_NVP(quantity)
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif //EQEMU_PLAYER_EVENTS_H
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* EQEmulator: Everquest Server Emulator
|
||||
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
* are required to give you total support for your newly bought product;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "expedition_lockout_timer.h"
|
||||
#include "../common/strings.h"
|
||||
#include "../common/rulesys.h"
|
||||
#include "../common/util/uuid.h"
|
||||
#include <fmt/format.h>
|
||||
|
||||
const char* const DZ_REPLAY_TIMER_NAME = "Replay Timer"; // see December 14, 2016 patch notes
|
||||
|
||||
ExpeditionLockoutTimer::ExpeditionLockoutTimer(
|
||||
std::string expedition_uuid, std::string expedition_name,
|
||||
std::string event_name, uint64_t expire_time, uint32_t duration
|
||||
) :
|
||||
m_expedition_uuid{std::move(expedition_uuid)},
|
||||
m_expedition_name{std::move(expedition_name)},
|
||||
m_event_name{std::move(event_name)},
|
||||
m_expire_time(std::chrono::system_clock::from_time_t(expire_time)),
|
||||
m_duration(duration)
|
||||
{
|
||||
if (m_event_name == DZ_REPLAY_TIMER_NAME)
|
||||
{
|
||||
m_is_replay_timer = true;
|
||||
}
|
||||
}
|
||||
|
||||
ExpeditionLockoutTimer ExpeditionLockoutTimer::CreateLockout(
|
||||
const std::string& expedition_name, const std::string& event_name, uint32_t seconds, std::string uuid)
|
||||
{
|
||||
seconds = static_cast<uint32_t>(seconds * RuleR(Expedition, LockoutDurationMultiplier));
|
||||
|
||||
if (uuid.empty())
|
||||
{
|
||||
uuid = EQ::Util::UUID::Generate().ToString();
|
||||
}
|
||||
|
||||
ExpeditionLockoutTimer lockout{uuid, expedition_name, event_name, 0, seconds};
|
||||
lockout.Reset(); // sets expire time
|
||||
return lockout;
|
||||
}
|
||||
|
||||
uint32_t ExpeditionLockoutTimer::GetSecondsRemaining() const
|
||||
{
|
||||
auto now = std::chrono::system_clock::now();
|
||||
if (m_expire_time > now)
|
||||
{
|
||||
auto remaining = m_expire_time - now;
|
||||
return static_cast<uint32_t>(std::chrono::duration_cast<std::chrono::seconds>(remaining).count());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ExpeditionLockoutTimer::DaysHoursMinutes ExpeditionLockoutTimer::GetDaysHoursMinutesRemaining() const
|
||||
{
|
||||
auto seconds = GetSecondsRemaining();
|
||||
return ExpeditionLockoutTimer::DaysHoursMinutes{
|
||||
fmt::format_int(seconds / 86400).str(), // days
|
||||
fmt::format_int((seconds / 3600) % 24).str(), // hours
|
||||
fmt::format_int((seconds / 60) % 60).str() // minutes
|
||||
};
|
||||
}
|
||||
|
||||
bool ExpeditionLockoutTimer::IsSameLockout(const ExpeditionLockoutTimer& compare_lockout) const
|
||||
{
|
||||
return compare_lockout.IsSameLockout(GetExpeditionName(), GetEventName());
|
||||
}
|
||||
|
||||
bool ExpeditionLockoutTimer::IsSameLockout(
|
||||
const std::string& expedition_name, const std::string& event_name) const
|
||||
{
|
||||
return GetExpeditionName() == expedition_name && GetEventName() == event_name;
|
||||
}
|
||||
|
||||
void ExpeditionLockoutTimer::AddLockoutTime(int seconds)
|
||||
{
|
||||
seconds = static_cast<uint32_t>(seconds * RuleR(Expedition, LockoutDurationMultiplier));
|
||||
|
||||
auto new_duration = std::max(0, static_cast<int>(m_duration.count()) + seconds);
|
||||
|
||||
auto start_time = m_expire_time - m_duration;
|
||||
m_duration = std::chrono::seconds(new_duration);
|
||||
m_expire_time = start_time + m_duration;
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* EQEmulator: Everquest Server Emulator
|
||||
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
* are required to give you total support for your newly bought product;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EXPEDITION_LOCKOUT_TIMER_H
|
||||
#define EXPEDITION_LOCKOUT_TIMER_H
|
||||
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
|
||||
extern const char* const DZ_REPLAY_TIMER_NAME;
|
||||
|
||||
class ExpeditionLockoutTimer
|
||||
{
|
||||
public:
|
||||
ExpeditionLockoutTimer() = default;
|
||||
ExpeditionLockoutTimer(
|
||||
std::string expedition_uuid, std::string expedition_name,
|
||||
std::string event_name, uint64_t expire_time, uint32_t duration);
|
||||
|
||||
static ExpeditionLockoutTimer CreateLockout(
|
||||
const std::string& expedition_name, const std::string& event_name,
|
||||
uint32_t seconds, std::string uuid = {});
|
||||
|
||||
struct DaysHoursMinutes
|
||||
{
|
||||
std::string days;
|
||||
std::string hours;
|
||||
std::string mins;
|
||||
};
|
||||
|
||||
void AddLockoutTime(int seconds);
|
||||
uint32_t GetDuration() const { return static_cast<uint32_t>(m_duration.count()); }
|
||||
uint64_t GetExpireTime() const { return std::chrono::system_clock::to_time_t(m_expire_time); }
|
||||
uint64_t GetStartTime() const { return std::chrono::system_clock::to_time_t(m_expire_time - m_duration); }
|
||||
uint32_t GetSecondsRemaining() const;
|
||||
DaysHoursMinutes GetDaysHoursMinutesRemaining() const;
|
||||
const std::string& GetExpeditionName() const { return m_expedition_name; }
|
||||
const std::string& GetExpeditionUUID() const { return m_expedition_uuid; }
|
||||
const std::string& GetEventName() const { return m_event_name; }
|
||||
bool IsExpired() const { return GetSecondsRemaining() == 0; }
|
||||
bool IsFromExpedition(const std::string& uuid) const { return uuid == m_expedition_uuid; }
|
||||
bool IsReplayTimer() const { return m_is_replay_timer; }
|
||||
bool IsSameLockout(const ExpeditionLockoutTimer& compare_lockout) const;
|
||||
bool IsSameLockout(const std::string& expedition_name, const std::string& event_name) const;
|
||||
void Reset() { m_expire_time = std::chrono::system_clock::now() + m_duration; }
|
||||
void SetDuration(uint32_t seconds) { m_duration = std::chrono::seconds(seconds); }
|
||||
void SetExpireTime(uint64_t expire_time) { m_expire_time = std::chrono::system_clock::from_time_t(expire_time); }
|
||||
void SetUUID(const std::string& uuid) { m_expedition_uuid = uuid; }
|
||||
|
||||
private:
|
||||
bool m_is_replay_timer = false;
|
||||
std::string m_expedition_uuid; // expedition received in
|
||||
std::string m_expedition_name;
|
||||
std::string m_event_name;
|
||||
std::chrono::seconds m_duration;
|
||||
std::chrono::time_point<std::chrono::system_clock> m_expire_time;
|
||||
};
|
||||
|
||||
#endif
|
||||
+26
-28
@@ -547,62 +547,60 @@ uint32 BaseGuildManager::UpdateDbCreateGuild(std::string name, uint32 leader)
|
||||
|
||||
bool BaseGuildManager::UpdateDbDeleteGuild(uint32 guild_id, bool local_delete, bool db_delete)
|
||||
{
|
||||
auto const where_filter = fmt::format("guild_id = {}", guild_id);
|
||||
auto const bank_items = GuildBankRepository::GetWhere(*m_db, where_filter);
|
||||
|
||||
if (local_delete) {
|
||||
auto where_filter = fmt::format("guildid = {}", guild_id);
|
||||
auto bank_items = GuildBankRepository::GetWhere(*m_db, where_filter);
|
||||
if (!bank_items.empty()) {
|
||||
LogError(
|
||||
"Attempt to delete guild id [{}] that still has [{}] items in the bank. Please remove them and try "
|
||||
"again.",
|
||||
"Attempt to delete guild id [{}] that still has [{}] items in the bank. Please remove them and try again.",
|
||||
guild_id,
|
||||
bank_items.size()
|
||||
);
|
||||
LogGuilds(
|
||||
"Attempt to delete guild id [{}] that still has [{}] items in the bank. Please remove them and try "
|
||||
"again.",
|
||||
"Attempt to delete guild id [{}] that still has [{}] items in the bank. Please remove them and try again.",
|
||||
guild_id,
|
||||
bank_items.size()
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
auto res = m_guilds.find(guild_id);
|
||||
if (res != m_guilds.end()) {
|
||||
safe_delete(res->second);
|
||||
m_guilds.erase(res);
|
||||
LogGuilds("Deleted guild [{}] from memory", guild_id);
|
||||
// Does this need to be sent to world?
|
||||
else {
|
||||
std::map<uint32, GuildInfo *>::iterator res;
|
||||
res = m_guilds.find(guild_id);
|
||||
if (res != m_guilds.end()) {
|
||||
delete res->second;
|
||||
m_guilds.erase(res);
|
||||
LogGuilds("Deleted guild [{}] from memory", guild_id);
|
||||
//Does this need to be sent to world?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (db_delete) {
|
||||
auto where_filter = fmt::format("guildid = {}", guild_id);
|
||||
auto bank_items = GuildBankRepository::GetWhere(*m_db, where_filter);
|
||||
if (!bank_items.empty()) {
|
||||
LogError(
|
||||
"Attempt to delete guild id [{}] that still has [{}] items in the bank. Please remove them and try "
|
||||
"again.",
|
||||
"Attempt to delete guild id [{}] that still has [{}] items in the bank. Please remove them and try again.",
|
||||
guild_id,
|
||||
bank_items.size()
|
||||
);
|
||||
LogGuilds(
|
||||
"Attempt to delete guild id [{}] that still has [{}] items in the bank. Please remove them and try "
|
||||
"again.",
|
||||
"Attempt to delete guild id [{}] that still has [{}] items in the bank. Please remove them and try again.",
|
||||
guild_id,
|
||||
bank_items.size()
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
GuildTributesRepository::DeleteOne(*m_db, guild_id);
|
||||
GuildsRepository::DeleteOne(*m_db, guild_id);
|
||||
GuildRanksRepository::DeleteWhere(*m_db, where_filter);
|
||||
GuildPermissionsRepository::DeleteWhere(*m_db, where_filter);
|
||||
GuildMembersRepository::DeleteWhere(*m_db, where_filter);
|
||||
LogGuilds("Deleted guild [{}] from the database", guild_id);
|
||||
else {
|
||||
auto where_filter = fmt::format("guild_id = {}", guild_id);
|
||||
GuildTributesRepository::DeleteOne(*m_db, guild_id);
|
||||
GuildsRepository::DeleteOne(*m_db, guild_id);
|
||||
GuildRanksRepository::DeleteWhere(*m_db, where_filter);
|
||||
GuildPermissionsRepository::DeleteWhere(*m_db, where_filter);
|
||||
GuildMembersRepository::DeleteWhere(*m_db, where_filter);
|
||||
LogGuilds("Deleted guild [{}] from the database", guild_id);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -2028,57 +2028,3 @@ int16 EQ::InventoryProfile::_HasEvolvingItem(ItemInstQueue &iqueue, uint64 evolv
|
||||
|
||||
return INVALID_INDEX;
|
||||
}
|
||||
|
||||
|
||||
int16 EQ::InventoryProfile::FindFirstFreeSlotThatFitsItemWithStacking(ItemInstance *item_inst) const
|
||||
{
|
||||
auto item_data = item_inst->GetItem();
|
||||
if (!item_data) {
|
||||
return INVALID_INDEX;
|
||||
}
|
||||
|
||||
for (int16 i = invslot::GENERAL_BEGIN; i <= invslot::GENERAL_END; i++) {
|
||||
auto const inv_item = GetItem(i);
|
||||
if (!inv_item) {
|
||||
// Found available slot in personal inventory
|
||||
// Anything will fit here
|
||||
return i;
|
||||
}
|
||||
|
||||
if (item_data->IsClassBag() && item_inst->IsNoneEmptyContainer()) {
|
||||
// If the inbound item is a bag with items, it cannot be stored within a bag
|
||||
// Move to next potential slot
|
||||
continue;
|
||||
}
|
||||
|
||||
if (inv_item->GetID() == item_data->ID && item_data->Stackable) {
|
||||
if (item_inst->GetCharges() + inv_item->GetCharges() <= item_data->StackSize) {
|
||||
// Found a personal inventory slot that has room for a stackable addition
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
if (inv_item->IsClassBag() && CanItemFitInContainer(item_data, inv_item->GetItem())) {
|
||||
int16 const base_slot_id = CalcSlotId(i, invbag::SLOT_BEGIN);
|
||||
uint8 const bag_size = inv_item->GetItem()->BagSlots;
|
||||
uint8 const item_size = item_data->Size;
|
||||
|
||||
for (uint8 bag_slot = invbag::SLOT_BEGIN; bag_slot < bag_size; bag_slot++) {
|
||||
auto bag_item = GetItem(base_slot_id + bag_slot);
|
||||
if (!bag_item) {
|
||||
// Found available slot within bag that will hold inbound item
|
||||
return base_slot_id + bag_slot;
|
||||
}
|
||||
|
||||
if (bag_item && item_data->Stackable && bag_item->GetID() == item_data->ID) {
|
||||
if (item_inst->GetCharges() + bag_item->GetCharges() <= item_data->StackSize) {
|
||||
// Found a bag slot has room for a stackable addition
|
||||
return base_slot_id + bag_slot;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return INVALID_INDEX;
|
||||
}
|
||||
|
||||
@@ -179,7 +179,6 @@ namespace EQ
|
||||
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);
|
||||
int16 FindFirstFreeSlotThatFitsItem(const EQ::ItemData *inst);
|
||||
int16 FindFirstFreeSlotThatFitsItemWithStacking(ItemInstance *inst) const;
|
||||
|
||||
// Calculate slot_id for an item within a bag
|
||||
static int16 CalcSlotId(int16 slot_id); // Calc parent bag's slot_id
|
||||
|
||||
+16
-16
@@ -1213,22 +1213,22 @@ namespace RoF
|
||||
case 1: { // GuildBankItemUpdate
|
||||
auto emu = (GuildBankItemUpdate_Struct *)in->pBuffer;
|
||||
auto eq = (structs::GuildBankItemUpdate_Struct *)outapp->pBuffer;
|
||||
eq->action = 0;
|
||||
OUT(unknown004);
|
||||
eq->unknown008 = 0;
|
||||
OUT(slot_id);
|
||||
OUT(area);
|
||||
OUT(display);
|
||||
OUT(item_id);
|
||||
OUT(icon_id);
|
||||
OUT(quantity);
|
||||
OUT(permissions);
|
||||
OUT(allow_merge);
|
||||
OUT(is_useable);
|
||||
OUT_str(item_name);
|
||||
OUT_str(donator);
|
||||
OUT_str(who_for);
|
||||
OUT(unknown226);
|
||||
eq->Action = 0;
|
||||
OUT(Unknown004);
|
||||
eq->Unknown08 = 0;
|
||||
OUT(SlotID);
|
||||
OUT(Area);
|
||||
OUT(Unknown012);
|
||||
OUT(ItemID);
|
||||
OUT(Icon);
|
||||
OUT(Quantity);
|
||||
OUT(Permissions);
|
||||
OUT(AllowMerge);
|
||||
OUT(Useable);
|
||||
OUT_str(ItemName);
|
||||
OUT_str(Donator);
|
||||
OUT_str(WhoFor);
|
||||
OUT(Unknown226);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
+16
-13
@@ -1743,19 +1743,22 @@ namespace RoF2
|
||||
case 1: { // GuildBankItemUpdate
|
||||
auto emu = (GuildBankItemUpdate_Struct *)in->pBuffer;
|
||||
auto eq = (structs::GuildBankItemUpdate_Struct *)outapp->pBuffer;
|
||||
eq->action = 0;
|
||||
OUT(display);
|
||||
OUT(slot_id);
|
||||
OUT(area);
|
||||
OUT(item_id);
|
||||
OUT(icon_id);
|
||||
OUT(quantity);
|
||||
OUT(permissions);
|
||||
OUT(allow_merge);
|
||||
OUT(is_useable);
|
||||
OUT_str(item_name);
|
||||
OUT_str(donator);
|
||||
OUT_str(who_for);
|
||||
eq->Action = 0;
|
||||
OUT(Unknown004);
|
||||
eq->Unknown08 = 0;
|
||||
OUT(SlotID);
|
||||
OUT(Area);
|
||||
OUT(Unknown012);
|
||||
OUT(ItemID);
|
||||
OUT(Icon);
|
||||
OUT(Quantity);
|
||||
OUT(Permissions);
|
||||
OUT(AllowMerge);
|
||||
OUT(Useable);
|
||||
OUT_str(ItemName);
|
||||
OUT_str(Donator);
|
||||
OUT_str(WhoFor);
|
||||
OUT(Unknown226);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -101,8 +101,6 @@ namespace RoF2
|
||||
const int16 MAIL_SIZE = 0;//unknown
|
||||
const int16 GUILD_TROPHY_TRIBUTE_SIZE = 0;//unknown
|
||||
const int16 KRONO_SIZE = 0;//unknown
|
||||
const int16 GUILD_BANK_MAIN_SIZE = 200;
|
||||
const int16 GUILD_BANK_DEPOSIT_SIZE = 40;
|
||||
const int16 OTHER_SIZE = 0;//unknown
|
||||
|
||||
const int16 TRADE_NPC_SIZE = 4; // defined by implication
|
||||
|
||||
@@ -1965,39 +1965,41 @@ struct GuildBankWithdrawItem_Struct
|
||||
|
||||
struct GuildBankItemUpdate_Struct
|
||||
{
|
||||
void Init(uint32 inAction, uint32 inUnknown004, uint16 inSlotID, uint16 inArea, uint16 inUnknown016, uint32 inItemID, uint32 inIcon, uint32 inQuantity,
|
||||
void Init(uint32 inAction, uint32 inUnknown004, uint16 inSlotID, uint16 inArea, uint16 inUnknown012, uint32 inItemID, uint32 inIcon, uint32 inQuantity,
|
||||
uint32 inPermissions, uint32 inAllowMerge, bool inUseable)
|
||||
{
|
||||
action = inAction;
|
||||
slot_id = inSlotID;
|
||||
area = inArea;
|
||||
display = inUnknown016;
|
||||
item_id = inItemID;
|
||||
icon_id = inIcon;
|
||||
quantity = inQuantity;
|
||||
permissions = inPermissions;
|
||||
allow_merge = inAllowMerge;
|
||||
is_useable = inUseable;
|
||||
item_name[0] = '\0';
|
||||
donator[0] = '\0';
|
||||
who_for[0] = '\0';
|
||||
Action = inAction;
|
||||
Unknown004 = inUnknown004;
|
||||
SlotID = inSlotID;
|
||||
Area = inArea;
|
||||
Unknown012 = inUnknown012;
|
||||
ItemID = inItemID;
|
||||
Icon = inIcon;
|
||||
Quantity = inQuantity;
|
||||
Permissions = inPermissions;
|
||||
AllowMerge = inAllowMerge;
|
||||
Useable = inUseable;
|
||||
ItemName[0] = '\0';
|
||||
Donator[0] = '\0';
|
||||
WhoFor[0] = '\0';
|
||||
};
|
||||
|
||||
/*000*/ uint32 action;
|
||||
/*004*/ uint32 not_used004; //disassemble of client did not use this
|
||||
/*008*/ uint32 not_used008; //disassemble of client did not use this
|
||||
/*012*/ uint16 slot_id;
|
||||
/*014*/ uint16 area;
|
||||
/*016*/ uint32 display;
|
||||
/*020*/ uint32 item_id;
|
||||
/*024*/ uint32 icon_id;
|
||||
/*028*/ uint32 quantity;
|
||||
/*032*/ uint32 permissions;
|
||||
/*036*/ uint8 allow_merge;
|
||||
/*037*/ uint8 is_useable; // Used in conjunction with the Public-if-useable permission.
|
||||
/*038*/ char item_name[64];
|
||||
/*102*/ char donator[64];
|
||||
/*166*/ char who_for[64];
|
||||
/*000*/ uint32 Action;
|
||||
/*004*/ uint32 Unknown004;
|
||||
/*008*/ uint32 Unknown08;
|
||||
/*012*/ uint16 SlotID;
|
||||
/*014*/ uint16 Area;
|
||||
/*016*/ uint32 Unknown012;
|
||||
/*020*/ uint32 ItemID;
|
||||
/*024*/ uint32 Icon;
|
||||
/*028*/ uint32 Quantity;
|
||||
/*032*/ uint32 Permissions;
|
||||
/*036*/ uint8 AllowMerge;
|
||||
/*037*/ uint8 Useable; // Used in conjunction with the Public-if-useable permission.
|
||||
/*038*/ char ItemName[64];
|
||||
/*102*/ char Donator[64];
|
||||
/*166*/ char WhoFor[64];
|
||||
/*230*/ uint16 Unknown226;
|
||||
};
|
||||
|
||||
struct GuildBankClear_Struct
|
||||
|
||||
@@ -1946,38 +1946,38 @@ struct GuildBankItemUpdate_Struct
|
||||
void Init(uint32 inAction, uint32 inUnknown004, uint16 inSlotID, uint16 inArea, uint16 inUnknown012, uint32 inItemID, uint32 inIcon, uint32 inQuantity,
|
||||
uint32 inPermissions, uint32 inAllowMerge, bool inUseable)
|
||||
{
|
||||
action = inAction;
|
||||
unknown004 = inUnknown004;
|
||||
slot_id = inSlotID;
|
||||
area = inArea;
|
||||
display = inUnknown012;
|
||||
item_id = inItemID;
|
||||
icon_id = inIcon;
|
||||
quantity = inQuantity;
|
||||
permissions = inPermissions;
|
||||
allow_merge = inAllowMerge;
|
||||
is_useable = inUseable;
|
||||
item_name[0] = '\0';
|
||||
donator[0] = '\0';
|
||||
who_for[0] = '\0';
|
||||
Action = inAction;
|
||||
Unknown004 = inUnknown004;
|
||||
SlotID = inSlotID;
|
||||
Area = inArea;
|
||||
Unknown012 = inUnknown012;
|
||||
ItemID = inItemID;
|
||||
Icon = inIcon;
|
||||
Quantity = inQuantity;
|
||||
Permissions = inPermissions;
|
||||
AllowMerge = inAllowMerge;
|
||||
Useable = inUseable;
|
||||
ItemName[0] = '\0';
|
||||
Donator[0] = '\0';
|
||||
WhoFor[0] = '\0';
|
||||
};
|
||||
|
||||
/*000*/ uint32 action;
|
||||
/*004*/ uint32 unknown004;
|
||||
/*008*/ uint32 unknown008;
|
||||
/*012*/ uint16 slot_id;
|
||||
/*014*/ uint16 area;
|
||||
/*016*/ uint32 display;
|
||||
/*020*/ uint32 item_id;
|
||||
/*024*/ uint32 icon_id;
|
||||
/*028*/ uint32 quantity;
|
||||
/*032*/ uint32 permissions;
|
||||
/*036*/ uint8 allow_merge;
|
||||
/*037*/ uint8 is_useable; // Used in conjunction with the Public-if-useable permission.
|
||||
/*038*/ char item_name[64];
|
||||
/*102*/ char donator[64];
|
||||
/*166*/ char who_for[64];
|
||||
/*230*/ uint16 unknown226;
|
||||
/*000*/ uint32 Action;
|
||||
/*004*/ uint32 Unknown004;
|
||||
/*008*/ uint32 Unknown08;
|
||||
/*012*/ uint16 SlotID;
|
||||
/*014*/ uint16 Area;
|
||||
/*016*/ uint32 Unknown012;
|
||||
/*020*/ uint32 ItemID;
|
||||
/*024*/ uint32 Icon;
|
||||
/*028*/ uint32 Quantity;
|
||||
/*032*/ uint32 Permissions;
|
||||
/*036*/ uint8 AllowMerge;
|
||||
/*037*/ uint8 Useable; // Used in conjunction with the Public-if-useable permission.
|
||||
/*038*/ char ItemName[64];
|
||||
/*102*/ char Donator[64];
|
||||
/*166*/ char WhoFor[64];
|
||||
/*230*/ uint16 Unknown226;
|
||||
};
|
||||
|
||||
struct GuildBankClear_Struct
|
||||
|
||||
@@ -23,12 +23,10 @@ public:
|
||||
std::string key_;
|
||||
std::string value;
|
||||
uint32_t expires;
|
||||
uint64_t account_id;
|
||||
uint64_t character_id;
|
||||
uint32_t npc_id;
|
||||
uint32_t bot_id;
|
||||
uint16_t zone_id;
|
||||
uint16_t instance_id;
|
||||
int64_t account_id;
|
||||
int64_t character_id;
|
||||
int64_t npc_id;
|
||||
int64_t bot_id;
|
||||
|
||||
// cereal
|
||||
template<class Archive>
|
||||
@@ -42,9 +40,7 @@ public:
|
||||
CEREAL_NVP(account_id),
|
||||
CEREAL_NVP(character_id),
|
||||
CEREAL_NVP(npc_id),
|
||||
CEREAL_NVP(bot_id),
|
||||
CEREAL_NVP(zone_id),
|
||||
CEREAL_NVP(instance_id)
|
||||
CEREAL_NVP(bot_id)
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -65,8 +61,6 @@ public:
|
||||
"character_id",
|
||||
"npc_id",
|
||||
"bot_id",
|
||||
"zone_id",
|
||||
"instance_id",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -81,8 +75,6 @@ public:
|
||||
"character_id",
|
||||
"npc_id",
|
||||
"bot_id",
|
||||
"zone_id",
|
||||
"instance_id",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -131,8 +123,6 @@ public:
|
||||
e.character_id = 0;
|
||||
e.npc_id = 0;
|
||||
e.bot_id = 0;
|
||||
e.zone_id = 0;
|
||||
e.instance_id = 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -173,12 +163,10 @@ public:
|
||||
e.key_ = row[1] ? row[1] : "";
|
||||
e.value = row[2] ? row[2] : "";
|
||||
e.expires = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.account_id = row[4] ? strtoull(row[4], nullptr, 10) : 0;
|
||||
e.character_id = row[5] ? strtoull(row[5], nullptr, 10) : 0;
|
||||
e.npc_id = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.bot_id = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.zone_id = row[8] ? static_cast<uint16_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.instance_id = row[9] ? static_cast<uint16_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.account_id = row[4] ? strtoll(row[4], nullptr, 10) : 0;
|
||||
e.character_id = row[5] ? strtoll(row[5], nullptr, 10) : 0;
|
||||
e.npc_id = row[6] ? strtoll(row[6], nullptr, 10) : 0;
|
||||
e.bot_id = row[7] ? strtoll(row[7], nullptr, 10) : 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -219,8 +207,6 @@ public:
|
||||
v.push_back(columns[5] + " = " + std::to_string(e.character_id));
|
||||
v.push_back(columns[6] + " = " + std::to_string(e.npc_id));
|
||||
v.push_back(columns[7] + " = " + std::to_string(e.bot_id));
|
||||
v.push_back(columns[8] + " = " + std::to_string(e.zone_id));
|
||||
v.push_back(columns[9] + " = " + std::to_string(e.instance_id));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -250,8 +236,6 @@ public:
|
||||
v.push_back(std::to_string(e.character_id));
|
||||
v.push_back(std::to_string(e.npc_id));
|
||||
v.push_back(std::to_string(e.bot_id));
|
||||
v.push_back(std::to_string(e.zone_id));
|
||||
v.push_back(std::to_string(e.instance_id));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -289,8 +273,6 @@ public:
|
||||
v.push_back(std::to_string(e.character_id));
|
||||
v.push_back(std::to_string(e.npc_id));
|
||||
v.push_back(std::to_string(e.bot_id));
|
||||
v.push_back(std::to_string(e.zone_id));
|
||||
v.push_back(std::to_string(e.instance_id));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
@@ -328,12 +310,10 @@ public:
|
||||
e.key_ = row[1] ? row[1] : "";
|
||||
e.value = row[2] ? row[2] : "";
|
||||
e.expires = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.account_id = row[4] ? strtoull(row[4], nullptr, 10) : 0;
|
||||
e.character_id = row[5] ? strtoull(row[5], nullptr, 10) : 0;
|
||||
e.npc_id = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.bot_id = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.zone_id = row[8] ? static_cast<uint16_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.instance_id = row[9] ? static_cast<uint16_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.account_id = row[4] ? strtoll(row[4], nullptr, 10) : 0;
|
||||
e.character_id = row[5] ? strtoll(row[5], nullptr, 10) : 0;
|
||||
e.npc_id = row[6] ? strtoll(row[6], nullptr, 10) : 0;
|
||||
e.bot_id = row[7] ? strtoll(row[7], nullptr, 10) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -362,12 +342,10 @@ public:
|
||||
e.key_ = row[1] ? row[1] : "";
|
||||
e.value = row[2] ? row[2] : "";
|
||||
e.expires = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.account_id = row[4] ? strtoull(row[4], nullptr, 10) : 0;
|
||||
e.character_id = row[5] ? strtoull(row[5], nullptr, 10) : 0;
|
||||
e.npc_id = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.bot_id = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.zone_id = row[8] ? static_cast<uint16_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.instance_id = row[9] ? static_cast<uint16_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.account_id = row[4] ? strtoll(row[4], nullptr, 10) : 0;
|
||||
e.character_id = row[5] ? strtoll(row[5], nullptr, 10) : 0;
|
||||
e.npc_id = row[6] ? strtoll(row[6], nullptr, 10) : 0;
|
||||
e.bot_id = row[7] ? strtoll(row[7], nullptr, 10) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -450,8 +428,6 @@ public:
|
||||
v.push_back(std::to_string(e.character_id));
|
||||
v.push_back(std::to_string(e.npc_id));
|
||||
v.push_back(std::to_string(e.bot_id));
|
||||
v.push_back(std::to_string(e.zone_id));
|
||||
v.push_back(std::to_string(e.instance_id));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -482,8 +458,6 @@ public:
|
||||
v.push_back(std::to_string(e.character_id));
|
||||
v.push_back(std::to_string(e.npc_id));
|
||||
v.push_back(std::to_string(e.bot_id));
|
||||
v.push_back(std::to_string(e.zone_id));
|
||||
v.push_back(std::to_string(e.instance_id));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
@@ -42,8 +42,6 @@ public:
|
||||
float zone_in_z;
|
||||
float zone_in_heading;
|
||||
uint8_t has_zone_in;
|
||||
int8_t is_locked;
|
||||
int8_t add_replay;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
@@ -77,8 +75,6 @@ public:
|
||||
"zone_in_z",
|
||||
"zone_in_heading",
|
||||
"has_zone_in",
|
||||
"is_locked",
|
||||
"add_replay",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -108,8 +104,6 @@ public:
|
||||
"zone_in_z",
|
||||
"zone_in_heading",
|
||||
"has_zone_in",
|
||||
"is_locked",
|
||||
"add_replay",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -173,8 +167,6 @@ public:
|
||||
e.zone_in_z = 0;
|
||||
e.zone_in_heading = 0;
|
||||
e.has_zone_in = 0;
|
||||
e.is_locked = 0;
|
||||
e.add_replay = 1;
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -234,8 +226,6 @@ public:
|
||||
e.zone_in_z = row[20] ? strtof(row[20], nullptr) : 0;
|
||||
e.zone_in_heading = row[21] ? strtof(row[21], nullptr) : 0;
|
||||
e.has_zone_in = row[22] ? static_cast<uint8_t>(strtoul(row[22], nullptr, 10)) : 0;
|
||||
e.is_locked = row[23] ? static_cast<int8_t>(atoi(row[23])) : 0;
|
||||
e.add_replay = row[24] ? static_cast<int8_t>(atoi(row[24])) : 1;
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -291,8 +281,6 @@ public:
|
||||
v.push_back(columns[20] + " = " + std::to_string(e.zone_in_z));
|
||||
v.push_back(columns[21] + " = " + std::to_string(e.zone_in_heading));
|
||||
v.push_back(columns[22] + " = " + std::to_string(e.has_zone_in));
|
||||
v.push_back(columns[23] + " = " + std::to_string(e.is_locked));
|
||||
v.push_back(columns[24] + " = " + std::to_string(e.add_replay));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -337,8 +325,6 @@ public:
|
||||
v.push_back(std::to_string(e.zone_in_z));
|
||||
v.push_back(std::to_string(e.zone_in_heading));
|
||||
v.push_back(std::to_string(e.has_zone_in));
|
||||
v.push_back(std::to_string(e.is_locked));
|
||||
v.push_back(std::to_string(e.add_replay));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -391,8 +377,6 @@ public:
|
||||
v.push_back(std::to_string(e.zone_in_z));
|
||||
v.push_back(std::to_string(e.zone_in_heading));
|
||||
v.push_back(std::to_string(e.has_zone_in));
|
||||
v.push_back(std::to_string(e.is_locked));
|
||||
v.push_back(std::to_string(e.add_replay));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
@@ -449,8 +433,6 @@ public:
|
||||
e.zone_in_z = row[20] ? strtof(row[20], nullptr) : 0;
|
||||
e.zone_in_heading = row[21] ? strtof(row[21], nullptr) : 0;
|
||||
e.has_zone_in = row[22] ? static_cast<uint8_t>(strtoul(row[22], nullptr, 10)) : 0;
|
||||
e.is_locked = row[23] ? static_cast<int8_t>(atoi(row[23])) : 0;
|
||||
e.add_replay = row[24] ? static_cast<int8_t>(atoi(row[24])) : 1;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -498,8 +480,6 @@ public:
|
||||
e.zone_in_z = row[20] ? strtof(row[20], nullptr) : 0;
|
||||
e.zone_in_heading = row[21] ? strtof(row[21], nullptr) : 0;
|
||||
e.has_zone_in = row[22] ? static_cast<uint8_t>(strtoul(row[22], nullptr, 10)) : 0;
|
||||
e.is_locked = row[23] ? static_cast<int8_t>(atoi(row[23])) : 0;
|
||||
e.add_replay = row[24] ? static_cast<int8_t>(atoi(row[24])) : 1;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -597,8 +577,6 @@ public:
|
||||
v.push_back(std::to_string(e.zone_in_z));
|
||||
v.push_back(std::to_string(e.zone_in_heading));
|
||||
v.push_back(std::to_string(e.has_zone_in));
|
||||
v.push_back(std::to_string(e.is_locked));
|
||||
v.push_back(std::to_string(e.add_replay));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -644,8 +622,6 @@ public:
|
||||
v.push_back(std::to_string(e.zone_in_z));
|
||||
v.push_back(std::to_string(e.zone_in_heading));
|
||||
v.push_back(std::to_string(e.has_zone_in));
|
||||
v.push_back(std::to_string(e.is_locked));
|
||||
v.push_back(std::to_string(e.add_replay));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
+44
-44
@@ -9,18 +9,18 @@
|
||||
* @docs https://docs.eqemu.io/developer/repositories
|
||||
*/
|
||||
|
||||
#ifndef EQEMU_BASE_DYNAMIC_ZONE_LOCKOUTS_REPOSITORY_H
|
||||
#define EQEMU_BASE_DYNAMIC_ZONE_LOCKOUTS_REPOSITORY_H
|
||||
#ifndef EQEMU_BASE_EXPEDITION_LOCKOUTS_REPOSITORY_H
|
||||
#define EQEMU_BASE_EXPEDITION_LOCKOUTS_REPOSITORY_H
|
||||
|
||||
#include "../../database.h"
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
class BaseDynamicZoneLockoutsRepository {
|
||||
class BaseExpeditionLockoutsRepository {
|
||||
public:
|
||||
struct DynamicZoneLockouts {
|
||||
struct ExpeditionLockouts {
|
||||
uint32_t id;
|
||||
uint32_t dynamic_zone_id;
|
||||
uint32_t expedition_id;
|
||||
std::string event_name;
|
||||
time_t expire_time;
|
||||
uint32_t duration;
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"dynamic_zone_id",
|
||||
"expedition_id",
|
||||
"event_name",
|
||||
"expire_time",
|
||||
"duration",
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"dynamic_zone_id",
|
||||
"expedition_id",
|
||||
"event_name",
|
||||
"UNIX_TIMESTAMP(expire_time)",
|
||||
"duration",
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
|
||||
static std::string TableName()
|
||||
{
|
||||
return std::string("dynamic_zone_lockouts");
|
||||
return std::string("expedition_lockouts");
|
||||
}
|
||||
|
||||
static std::string BaseSelect()
|
||||
@@ -89,12 +89,12 @@ public:
|
||||
);
|
||||
}
|
||||
|
||||
static DynamicZoneLockouts NewEntity()
|
||||
static ExpeditionLockouts NewEntity()
|
||||
{
|
||||
DynamicZoneLockouts e{};
|
||||
ExpeditionLockouts e{};
|
||||
|
||||
e.id = 0;
|
||||
e.dynamic_zone_id = 0;
|
||||
e.expedition_id = 0;
|
||||
e.event_name = "";
|
||||
e.expire_time = std::time(nullptr);
|
||||
e.duration = 0;
|
||||
@@ -103,23 +103,23 @@ public:
|
||||
return e;
|
||||
}
|
||||
|
||||
static DynamicZoneLockouts GetDynamicZoneLockouts(
|
||||
const std::vector<DynamicZoneLockouts> &dynamic_zone_lockoutss,
|
||||
int dynamic_zone_lockouts_id
|
||||
static ExpeditionLockouts GetExpeditionLockouts(
|
||||
const std::vector<ExpeditionLockouts> &expedition_lockoutss,
|
||||
int expedition_lockouts_id
|
||||
)
|
||||
{
|
||||
for (auto &dynamic_zone_lockouts : dynamic_zone_lockoutss) {
|
||||
if (dynamic_zone_lockouts.id == dynamic_zone_lockouts_id) {
|
||||
return dynamic_zone_lockouts;
|
||||
for (auto &expedition_lockouts : expedition_lockoutss) {
|
||||
if (expedition_lockouts.id == expedition_lockouts_id) {
|
||||
return expedition_lockouts;
|
||||
}
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static DynamicZoneLockouts FindOne(
|
||||
static ExpeditionLockouts FindOne(
|
||||
Database& db,
|
||||
int dynamic_zone_lockouts_id
|
||||
int expedition_lockouts_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
@@ -127,16 +127,16 @@ public:
|
||||
"{} WHERE {} = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
PrimaryKey(),
|
||||
dynamic_zone_lockouts_id
|
||||
expedition_lockouts_id
|
||||
)
|
||||
);
|
||||
|
||||
auto row = results.begin();
|
||||
if (results.RowCount() == 1) {
|
||||
DynamicZoneLockouts e{};
|
||||
ExpeditionLockouts e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.dynamic_zone_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.expedition_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.event_name = row[2] ? row[2] : "";
|
||||
e.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10);
|
||||
e.duration = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
@@ -150,7 +150,7 @@ public:
|
||||
|
||||
static int DeleteOne(
|
||||
Database& db,
|
||||
int dynamic_zone_lockouts_id
|
||||
int expedition_lockouts_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
@@ -158,7 +158,7 @@ public:
|
||||
"DELETE FROM {} WHERE {} = {}",
|
||||
TableName(),
|
||||
PrimaryKey(),
|
||||
dynamic_zone_lockouts_id
|
||||
expedition_lockouts_id
|
||||
)
|
||||
);
|
||||
|
||||
@@ -167,14 +167,14 @@ public:
|
||||
|
||||
static int UpdateOne(
|
||||
Database& db,
|
||||
const DynamicZoneLockouts &e
|
||||
const ExpeditionLockouts &e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto columns = Columns();
|
||||
|
||||
v.push_back(columns[1] + " = " + std::to_string(e.dynamic_zone_id));
|
||||
v.push_back(columns[1] + " = " + std::to_string(e.expedition_id));
|
||||
v.push_back(columns[2] + " = '" + Strings::Escape(e.event_name) + "'");
|
||||
v.push_back(columns[3] + " = FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")");
|
||||
v.push_back(columns[4] + " = " + std::to_string(e.duration));
|
||||
@@ -193,15 +193,15 @@ public:
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static DynamicZoneLockouts InsertOne(
|
||||
static ExpeditionLockouts InsertOne(
|
||||
Database& db,
|
||||
DynamicZoneLockouts e
|
||||
ExpeditionLockouts e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.dynamic_zone_id));
|
||||
v.push_back(std::to_string(e.expedition_id));
|
||||
v.push_back("'" + Strings::Escape(e.event_name) + "'");
|
||||
v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")");
|
||||
v.push_back(std::to_string(e.duration));
|
||||
@@ -227,7 +227,7 @@ public:
|
||||
|
||||
static int InsertMany(
|
||||
Database& db,
|
||||
const std::vector<DynamicZoneLockouts> &entries
|
||||
const std::vector<ExpeditionLockouts> &entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
@@ -236,7 +236,7 @@ public:
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.dynamic_zone_id));
|
||||
v.push_back(std::to_string(e.expedition_id));
|
||||
v.push_back("'" + Strings::Escape(e.event_name) + "'");
|
||||
v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")");
|
||||
v.push_back(std::to_string(e.duration));
|
||||
@@ -258,9 +258,9 @@ public:
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static std::vector<DynamicZoneLockouts> All(Database& db)
|
||||
static std::vector<ExpeditionLockouts> All(Database& db)
|
||||
{
|
||||
std::vector<DynamicZoneLockouts> all_entries;
|
||||
std::vector<ExpeditionLockouts> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -272,10 +272,10 @@ public:
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
DynamicZoneLockouts e{};
|
||||
ExpeditionLockouts e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.dynamic_zone_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.expedition_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.event_name = row[2] ? row[2] : "";
|
||||
e.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10);
|
||||
e.duration = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
@@ -287,9 +287,9 @@ public:
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static std::vector<DynamicZoneLockouts> GetWhere(Database& db, const std::string &where_filter)
|
||||
static std::vector<ExpeditionLockouts> GetWhere(Database& db, const std::string &where_filter)
|
||||
{
|
||||
std::vector<DynamicZoneLockouts> all_entries;
|
||||
std::vector<ExpeditionLockouts> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -302,10 +302,10 @@ public:
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
DynamicZoneLockouts e{};
|
||||
ExpeditionLockouts e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.dynamic_zone_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.expedition_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.event_name = row[2] ? row[2] : "";
|
||||
e.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10);
|
||||
e.duration = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
@@ -379,13 +379,13 @@ public:
|
||||
|
||||
static int ReplaceOne(
|
||||
Database& db,
|
||||
const DynamicZoneLockouts &e
|
||||
const ExpeditionLockouts &e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.dynamic_zone_id));
|
||||
v.push_back(std::to_string(e.expedition_id));
|
||||
v.push_back("'" + Strings::Escape(e.event_name) + "'");
|
||||
v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")");
|
||||
v.push_back(std::to_string(e.duration));
|
||||
@@ -404,7 +404,7 @@ public:
|
||||
|
||||
static int ReplaceMany(
|
||||
Database& db,
|
||||
const std::vector<DynamicZoneLockouts> &entries
|
||||
const std::vector<ExpeditionLockouts> &entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
@@ -413,7 +413,7 @@ public:
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.dynamic_zone_id));
|
||||
v.push_back(std::to_string(e.expedition_id));
|
||||
v.push_back("'" + Strings::Escape(e.event_name) + "'");
|
||||
v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")");
|
||||
v.push_back(std::to_string(e.duration));
|
||||
@@ -436,4 +436,4 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#endif //EQEMU_BASE_DYNAMIC_ZONE_LOCKOUTS_REPOSITORY_H
|
||||
#endif //EQEMU_BASE_EXPEDITION_LOCKOUTS_REPOSITORY_H
|
||||
@@ -0,0 +1,415 @@
|
||||
/**
|
||||
* 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_EXPEDITIONS_REPOSITORY_H
|
||||
#define EQEMU_BASE_EXPEDITIONS_REPOSITORY_H
|
||||
|
||||
#include "../../database.h"
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
class BaseExpeditionsRepository {
|
||||
public:
|
||||
struct Expeditions {
|
||||
uint32_t id;
|
||||
uint32_t dynamic_zone_id;
|
||||
uint8_t add_replay_on_join;
|
||||
uint8_t is_locked;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
{
|
||||
return std::string("id");
|
||||
}
|
||||
|
||||
static std::vector<std::string> Columns()
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"dynamic_zone_id",
|
||||
"add_replay_on_join",
|
||||
"is_locked",
|
||||
};
|
||||
}
|
||||
|
||||
static std::vector<std::string> SelectColumns()
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"dynamic_zone_id",
|
||||
"add_replay_on_join",
|
||||
"is_locked",
|
||||
};
|
||||
}
|
||||
|
||||
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("expeditions");
|
||||
}
|
||||
|
||||
static std::string BaseSelect()
|
||||
{
|
||||
return fmt::format(
|
||||
"SELECT {} FROM {}",
|
||||
SelectColumnsRaw(),
|
||||
TableName()
|
||||
);
|
||||
}
|
||||
|
||||
static std::string BaseInsert()
|
||||
{
|
||||
return fmt::format(
|
||||
"INSERT INTO {} ({}) ",
|
||||
TableName(),
|
||||
ColumnsRaw()
|
||||
);
|
||||
}
|
||||
|
||||
static Expeditions NewEntity()
|
||||
{
|
||||
Expeditions e{};
|
||||
|
||||
e.id = 0;
|
||||
e.dynamic_zone_id = 0;
|
||||
e.add_replay_on_join = 1;
|
||||
e.is_locked = 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static Expeditions GetExpeditions(
|
||||
const std::vector<Expeditions> &expeditionss,
|
||||
int expeditions_id
|
||||
)
|
||||
{
|
||||
for (auto &expeditions : expeditionss) {
|
||||
if (expeditions.id == expeditions_id) {
|
||||
return expeditions;
|
||||
}
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static Expeditions FindOne(
|
||||
Database& db,
|
||||
int expeditions_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE {} = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
PrimaryKey(),
|
||||
expeditions_id
|
||||
)
|
||||
);
|
||||
|
||||
auto row = results.begin();
|
||||
if (results.RowCount() == 1) {
|
||||
Expeditions e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.dynamic_zone_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.add_replay_on_join = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 1;
|
||||
e.is_locked = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static int DeleteOne(
|
||||
Database& db,
|
||||
int expeditions_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"DELETE FROM {} WHERE {} = {}",
|
||||
TableName(),
|
||||
PrimaryKey(),
|
||||
expeditions_id
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int UpdateOne(
|
||||
Database& db,
|
||||
const Expeditions &e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto columns = Columns();
|
||||
|
||||
v.push_back(columns[1] + " = " + std::to_string(e.dynamic_zone_id));
|
||||
v.push_back(columns[2] + " = " + std::to_string(e.add_replay_on_join));
|
||||
v.push_back(columns[3] + " = " + std::to_string(e.is_locked));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"UPDATE {} SET {} WHERE {} = {}",
|
||||
TableName(),
|
||||
Strings::Implode(", ", v),
|
||||
PrimaryKey(),
|
||||
e.id
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static Expeditions InsertOne(
|
||||
Database& db,
|
||||
Expeditions e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.dynamic_zone_id));
|
||||
v.push_back(std::to_string(e.add_replay_on_join));
|
||||
v.push_back(std::to_string(e.is_locked));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES ({})",
|
||||
BaseInsert(),
|
||||
Strings::Implode(",", v)
|
||||
)
|
||||
);
|
||||
|
||||
if (results.Success()) {
|
||||
e.id = results.LastInsertedID();
|
||||
return e;
|
||||
}
|
||||
|
||||
e = NewEntity();
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static int InsertMany(
|
||||
Database& db,
|
||||
const std::vector<Expeditions> &entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &e: entries) {
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.dynamic_zone_id));
|
||||
v.push_back(std::to_string(e.add_replay_on_join));
|
||||
v.push_back(std::to_string(e.is_locked));
|
||||
|
||||
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<Expeditions> All(Database& db)
|
||||
{
|
||||
std::vector<Expeditions> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{}",
|
||||
BaseSelect()
|
||||
)
|
||||
);
|
||||
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
Expeditions e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.dynamic_zone_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.add_replay_on_join = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 1;
|
||||
e.is_locked = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static std::vector<Expeditions> GetWhere(Database& db, const std::string &where_filter)
|
||||
{
|
||||
std::vector<Expeditions> 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) {
|
||||
Expeditions e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.dynamic_zone_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.add_replay_on_join = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 1;
|
||||
e.is_locked = row[3] ? static_cast<uint8_t>(strtoul(row[3], 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 Expeditions &e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.dynamic_zone_id));
|
||||
v.push_back(std::to_string(e.add_replay_on_join));
|
||||
v.push_back(std::to_string(e.is_locked));
|
||||
|
||||
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<Expeditions> &entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &e: entries) {
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.dynamic_zone_id));
|
||||
v.push_back(std::to_string(e.add_replay_on_join));
|
||||
v.push_back(std::to_string(e.is_locked));
|
||||
|
||||
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_EXPEDITIONS_REPOSITORY_H
|
||||
@@ -0,0 +1,511 @@
|
||||
/**
|
||||
* 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_FIND_LOCATION_REPOSITORY_H
|
||||
#define EQEMU_BASE_FIND_LOCATION_REPOSITORY_H
|
||||
|
||||
#include "../../database.h"
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
class BaseFindLocationRepository {
|
||||
public:
|
||||
struct FindLocation {
|
||||
uint32_t id;
|
||||
std::string zone;
|
||||
int32_t version;
|
||||
int8_t min_expansion;
|
||||
int8_t max_expansion;
|
||||
std::string content_flags;
|
||||
std::string content_flags_disabled;
|
||||
int32_t type;
|
||||
int32_t zone_id;
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
{
|
||||
return std::string("id");
|
||||
}
|
||||
|
||||
static std::vector<std::string> Columns()
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"zone",
|
||||
"version",
|
||||
"min_expansion",
|
||||
"max_expansion",
|
||||
"content_flags",
|
||||
"content_flags_disabled",
|
||||
"type",
|
||||
"zone_id",
|
||||
"x",
|
||||
"y",
|
||||
"z",
|
||||
};
|
||||
}
|
||||
|
||||
static std::vector<std::string> SelectColumns()
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"zone",
|
||||
"version",
|
||||
"min_expansion",
|
||||
"max_expansion",
|
||||
"content_flags",
|
||||
"content_flags_disabled",
|
||||
"type",
|
||||
"zone_id",
|
||||
"x",
|
||||
"y",
|
||||
"z",
|
||||
};
|
||||
}
|
||||
|
||||
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("find_location");
|
||||
}
|
||||
|
||||
static std::string BaseSelect()
|
||||
{
|
||||
return fmt::format(
|
||||
"SELECT {} FROM {}",
|
||||
SelectColumnsRaw(),
|
||||
TableName()
|
||||
);
|
||||
}
|
||||
|
||||
static std::string BaseInsert()
|
||||
{
|
||||
return fmt::format(
|
||||
"INSERT INTO {} ({}) ",
|
||||
TableName(),
|
||||
ColumnsRaw()
|
||||
);
|
||||
}
|
||||
|
||||
static FindLocation NewEntity()
|
||||
{
|
||||
FindLocation e{};
|
||||
|
||||
e.id = 0;
|
||||
e.zone = "";
|
||||
e.version = 0;
|
||||
e.min_expansion = -1;
|
||||
e.max_expansion = -1;
|
||||
e.content_flags = "";
|
||||
e.content_flags_disabled = "";
|
||||
e.type = 0;
|
||||
e.zone_id = 0;
|
||||
e.x = 0;
|
||||
e.y = 0;
|
||||
e.z = 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static FindLocation GetFindLocation(
|
||||
const std::vector<FindLocation> &find_locations,
|
||||
int find_location_id
|
||||
)
|
||||
{
|
||||
for (auto &find_location : find_locations) {
|
||||
if (find_location.id == find_location_id) {
|
||||
return find_location;
|
||||
}
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static FindLocation FindOne(
|
||||
Database& db,
|
||||
int find_location_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE {} = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
PrimaryKey(),
|
||||
find_location_id
|
||||
)
|
||||
);
|
||||
|
||||
auto row = results.begin();
|
||||
if (results.RowCount() == 1) {
|
||||
FindLocation e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.zone = row[1] ? row[1] : "";
|
||||
e.version = row[2] ? static_cast<int32_t>(atoi(row[2])) : 0;
|
||||
e.min_expansion = row[3] ? static_cast<int8_t>(atoi(row[3])) : -1;
|
||||
e.max_expansion = row[4] ? static_cast<int8_t>(atoi(row[4])) : -1;
|
||||
e.content_flags = row[5] ? row[5] : "";
|
||||
e.content_flags_disabled = row[6] ? row[6] : "";
|
||||
e.type = row[7] ? static_cast<int32_t>(atoi(row[7])) : 0;
|
||||
e.zone_id = row[8] ? static_cast<int32_t>(atoi(row[8])) : 0;
|
||||
e.x = row[9] ? strtof(row[9], nullptr) : 0;
|
||||
e.y = row[10] ? strtof(row[10], nullptr) : 0;
|
||||
e.z = row[11] ? strtof(row[11], nullptr) : 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static int DeleteOne(
|
||||
Database& db,
|
||||
int find_location_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"DELETE FROM {} WHERE {} = {}",
|
||||
TableName(),
|
||||
PrimaryKey(),
|
||||
find_location_id
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int UpdateOne(
|
||||
Database& db,
|
||||
const FindLocation &e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto columns = Columns();
|
||||
|
||||
v.push_back(columns[1] + " = '" + Strings::Escape(e.zone) + "'");
|
||||
v.push_back(columns[2] + " = " + std::to_string(e.version));
|
||||
v.push_back(columns[3] + " = " + std::to_string(e.min_expansion));
|
||||
v.push_back(columns[4] + " = " + std::to_string(e.max_expansion));
|
||||
v.push_back(columns[5] + " = '" + Strings::Escape(e.content_flags) + "'");
|
||||
v.push_back(columns[6] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
|
||||
v.push_back(columns[7] + " = " + std::to_string(e.type));
|
||||
v.push_back(columns[8] + " = " + std::to_string(e.zone_id));
|
||||
v.push_back(columns[9] + " = " + std::to_string(e.x));
|
||||
v.push_back(columns[10] + " = " + std::to_string(e.y));
|
||||
v.push_back(columns[11] + " = " + std::to_string(e.z));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"UPDATE {} SET {} WHERE {} = {}",
|
||||
TableName(),
|
||||
Strings::Implode(", ", v),
|
||||
PrimaryKey(),
|
||||
e.id
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static FindLocation InsertOne(
|
||||
Database& db,
|
||||
FindLocation e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back("'" + Strings::Escape(e.zone) + "'");
|
||||
v.push_back(std::to_string(e.version));
|
||||
v.push_back(std::to_string(e.min_expansion));
|
||||
v.push_back(std::to_string(e.max_expansion));
|
||||
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
|
||||
v.push_back(std::to_string(e.type));
|
||||
v.push_back(std::to_string(e.zone_id));
|
||||
v.push_back(std::to_string(e.x));
|
||||
v.push_back(std::to_string(e.y));
|
||||
v.push_back(std::to_string(e.z));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES ({})",
|
||||
BaseInsert(),
|
||||
Strings::Implode(",", v)
|
||||
)
|
||||
);
|
||||
|
||||
if (results.Success()) {
|
||||
e.id = results.LastInsertedID();
|
||||
return e;
|
||||
}
|
||||
|
||||
e = NewEntity();
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static int InsertMany(
|
||||
Database& db,
|
||||
const std::vector<FindLocation> &entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &e: entries) {
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back("'" + Strings::Escape(e.zone) + "'");
|
||||
v.push_back(std::to_string(e.version));
|
||||
v.push_back(std::to_string(e.min_expansion));
|
||||
v.push_back(std::to_string(e.max_expansion));
|
||||
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
|
||||
v.push_back(std::to_string(e.type));
|
||||
v.push_back(std::to_string(e.zone_id));
|
||||
v.push_back(std::to_string(e.x));
|
||||
v.push_back(std::to_string(e.y));
|
||||
v.push_back(std::to_string(e.z));
|
||||
|
||||
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<FindLocation> All(Database& db)
|
||||
{
|
||||
std::vector<FindLocation> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{}",
|
||||
BaseSelect()
|
||||
)
|
||||
);
|
||||
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
FindLocation e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.zone = row[1] ? row[1] : "";
|
||||
e.version = row[2] ? static_cast<int32_t>(atoi(row[2])) : 0;
|
||||
e.min_expansion = row[3] ? static_cast<int8_t>(atoi(row[3])) : -1;
|
||||
e.max_expansion = row[4] ? static_cast<int8_t>(atoi(row[4])) : -1;
|
||||
e.content_flags = row[5] ? row[5] : "";
|
||||
e.content_flags_disabled = row[6] ? row[6] : "";
|
||||
e.type = row[7] ? static_cast<int32_t>(atoi(row[7])) : 0;
|
||||
e.zone_id = row[8] ? static_cast<int32_t>(atoi(row[8])) : 0;
|
||||
e.x = row[9] ? strtof(row[9], nullptr) : 0;
|
||||
e.y = row[10] ? strtof(row[10], nullptr) : 0;
|
||||
e.z = row[11] ? strtof(row[11], nullptr) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static std::vector<FindLocation> GetWhere(Database& db, const std::string &where_filter)
|
||||
{
|
||||
std::vector<FindLocation> 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) {
|
||||
FindLocation e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.zone = row[1] ? row[1] : "";
|
||||
e.version = row[2] ? static_cast<int32_t>(atoi(row[2])) : 0;
|
||||
e.min_expansion = row[3] ? static_cast<int8_t>(atoi(row[3])) : -1;
|
||||
e.max_expansion = row[4] ? static_cast<int8_t>(atoi(row[4])) : -1;
|
||||
e.content_flags = row[5] ? row[5] : "";
|
||||
e.content_flags_disabled = row[6] ? row[6] : "";
|
||||
e.type = row[7] ? static_cast<int32_t>(atoi(row[7])) : 0;
|
||||
e.zone_id = row[8] ? static_cast<int32_t>(atoi(row[8])) : 0;
|
||||
e.x = row[9] ? strtof(row[9], nullptr) : 0;
|
||||
e.y = row[10] ? strtof(row[10], nullptr) : 0;
|
||||
e.z = row[11] ? strtof(row[11], nullptr) : 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 FindLocation &e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back("'" + Strings::Escape(e.zone) + "'");
|
||||
v.push_back(std::to_string(e.version));
|
||||
v.push_back(std::to_string(e.min_expansion));
|
||||
v.push_back(std::to_string(e.max_expansion));
|
||||
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
|
||||
v.push_back(std::to_string(e.type));
|
||||
v.push_back(std::to_string(e.zone_id));
|
||||
v.push_back(std::to_string(e.x));
|
||||
v.push_back(std::to_string(e.y));
|
||||
v.push_back(std::to_string(e.z));
|
||||
|
||||
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<FindLocation> &entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &e: entries) {
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back("'" + Strings::Escape(e.zone) + "'");
|
||||
v.push_back(std::to_string(e.version));
|
||||
v.push_back(std::to_string(e.min_expansion));
|
||||
v.push_back(std::to_string(e.max_expansion));
|
||||
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
|
||||
v.push_back(std::to_string(e.type));
|
||||
v.push_back(std::to_string(e.zone_id));
|
||||
v.push_back(std::to_string(e.x));
|
||||
v.push_back(std::to_string(e.y));
|
||||
v.push_back(std::to_string(e.z));
|
||||
|
||||
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_FIND_LOCATION_REPOSITORY_H
|
||||
@@ -6,7 +6,7 @@
|
||||
* 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
|
||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
||||
*/
|
||||
|
||||
#ifndef EQEMU_BASE_GUILD_BANK_REPOSITORY_H
|
||||
@@ -16,24 +16,19 @@
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
|
||||
class BaseGuildBankRepository {
|
||||
public:
|
||||
struct GuildBank {
|
||||
uint32_t id;
|
||||
uint32_t guild_id;
|
||||
uint32_t guildid;
|
||||
uint8_t area;
|
||||
uint32_t slot;
|
||||
uint32_t item_id;
|
||||
uint32_t augment_one_id;
|
||||
uint32_t augment_two_id;
|
||||
uint32_t augment_three_id;
|
||||
uint32_t augment_four_id;
|
||||
uint32_t augment_five_id;
|
||||
uint32_t augment_six_id;
|
||||
int32_t quantity;
|
||||
uint32_t itemid;
|
||||
uint32_t qty;
|
||||
std::string donator;
|
||||
uint8_t permissions;
|
||||
std::string who_for;
|
||||
std::string whofor;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
@@ -45,20 +40,14 @@ public:
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"guild_id",
|
||||
"guildid",
|
||||
"area",
|
||||
"slot",
|
||||
"item_id",
|
||||
"augment_one_id",
|
||||
"augment_two_id",
|
||||
"augment_three_id",
|
||||
"augment_four_id",
|
||||
"augment_five_id",
|
||||
"augment_six_id",
|
||||
"quantity",
|
||||
"itemid",
|
||||
"qty",
|
||||
"donator",
|
||||
"permissions",
|
||||
"who_for",
|
||||
"whofor",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -66,20 +55,14 @@ public:
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"guild_id",
|
||||
"guildid",
|
||||
"area",
|
||||
"slot",
|
||||
"item_id",
|
||||
"augment_one_id",
|
||||
"augment_two_id",
|
||||
"augment_three_id",
|
||||
"augment_four_id",
|
||||
"augment_five_id",
|
||||
"augment_six_id",
|
||||
"quantity",
|
||||
"itemid",
|
||||
"qty",
|
||||
"donator",
|
||||
"permissions",
|
||||
"who_for",
|
||||
"whofor",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -120,21 +103,15 @@ public:
|
||||
{
|
||||
GuildBank e{};
|
||||
|
||||
e.id = 0;
|
||||
e.guild_id = 0;
|
||||
e.area = 0;
|
||||
e.slot = 0;
|
||||
e.item_id = 0;
|
||||
e.augment_one_id = 0;
|
||||
e.augment_two_id = 0;
|
||||
e.augment_three_id = 0;
|
||||
e.augment_four_id = 0;
|
||||
e.augment_five_id = 0;
|
||||
e.augment_six_id = 0;
|
||||
e.quantity = 0;
|
||||
e.donator = "";
|
||||
e.permissions = 0;
|
||||
e.who_for = "";
|
||||
e.id = 0;
|
||||
e.guildid = 0;
|
||||
e.area = 0;
|
||||
e.slot = 0;
|
||||
e.itemid = 0;
|
||||
e.qty = 0;
|
||||
e.donator = "";
|
||||
e.permissions = 0;
|
||||
e.whofor = "";
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -171,21 +148,15 @@ public:
|
||||
if (results.RowCount() == 1) {
|
||||
GuildBank e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.guild_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.area = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.slot = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.item_id = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.augment_one_id = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.augment_two_id = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.augment_three_id = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.augment_four_id = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.augment_five_id = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.augment_six_id = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
|
||||
e.quantity = row[11] ? static_cast<int32_t>(atoi(row[11])) : 0;
|
||||
e.donator = row[12] ? row[12] : "";
|
||||
e.permissions = row[13] ? static_cast<uint8_t>(strtoul(row[13], nullptr, 10)) : 0;
|
||||
e.who_for = row[14] ? row[14] : "";
|
||||
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.guildid = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.area = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
|
||||
e.slot = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
|
||||
e.itemid = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
|
||||
e.qty = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
|
||||
e.donator = row[6] ? row[6] : "";
|
||||
e.permissions = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
|
||||
e.whofor = row[8] ? row[8] : "";
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -219,20 +190,14 @@ public:
|
||||
|
||||
auto columns = Columns();
|
||||
|
||||
v.push_back(columns[1] + " = " + std::to_string(e.guild_id));
|
||||
v.push_back(columns[1] + " = " + std::to_string(e.guildid));
|
||||
v.push_back(columns[2] + " = " + std::to_string(e.area));
|
||||
v.push_back(columns[3] + " = " + std::to_string(e.slot));
|
||||
v.push_back(columns[4] + " = " + std::to_string(e.item_id));
|
||||
v.push_back(columns[5] + " = " + std::to_string(e.augment_one_id));
|
||||
v.push_back(columns[6] + " = " + std::to_string(e.augment_two_id));
|
||||
v.push_back(columns[7] + " = " + std::to_string(e.augment_three_id));
|
||||
v.push_back(columns[8] + " = " + std::to_string(e.augment_four_id));
|
||||
v.push_back(columns[9] + " = " + std::to_string(e.augment_five_id));
|
||||
v.push_back(columns[10] + " = " + std::to_string(e.augment_six_id));
|
||||
v.push_back(columns[11] + " = " + std::to_string(e.quantity));
|
||||
v.push_back(columns[12] + " = '" + Strings::Escape(e.donator) + "'");
|
||||
v.push_back(columns[13] + " = " + std::to_string(e.permissions));
|
||||
v.push_back(columns[14] + " = '" + Strings::Escape(e.who_for) + "'");
|
||||
v.push_back(columns[4] + " = " + std::to_string(e.itemid));
|
||||
v.push_back(columns[5] + " = " + std::to_string(e.qty));
|
||||
v.push_back(columns[6] + " = '" + Strings::Escape(e.donator) + "'");
|
||||
v.push_back(columns[7] + " = " + std::to_string(e.permissions));
|
||||
v.push_back(columns[8] + " = '" + Strings::Escape(e.whofor) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -255,20 +220,14 @@ public:
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.guild_id));
|
||||
v.push_back(std::to_string(e.guildid));
|
||||
v.push_back(std::to_string(e.area));
|
||||
v.push_back(std::to_string(e.slot));
|
||||
v.push_back(std::to_string(e.item_id));
|
||||
v.push_back(std::to_string(e.augment_one_id));
|
||||
v.push_back(std::to_string(e.augment_two_id));
|
||||
v.push_back(std::to_string(e.augment_three_id));
|
||||
v.push_back(std::to_string(e.augment_four_id));
|
||||
v.push_back(std::to_string(e.augment_five_id));
|
||||
v.push_back(std::to_string(e.augment_six_id));
|
||||
v.push_back(std::to_string(e.quantity));
|
||||
v.push_back(std::to_string(e.itemid));
|
||||
v.push_back(std::to_string(e.qty));
|
||||
v.push_back("'" + Strings::Escape(e.donator) + "'");
|
||||
v.push_back(std::to_string(e.permissions));
|
||||
v.push_back("'" + Strings::Escape(e.who_for) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.whofor) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -299,20 +258,14 @@ public:
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.guild_id));
|
||||
v.push_back(std::to_string(e.guildid));
|
||||
v.push_back(std::to_string(e.area));
|
||||
v.push_back(std::to_string(e.slot));
|
||||
v.push_back(std::to_string(e.item_id));
|
||||
v.push_back(std::to_string(e.augment_one_id));
|
||||
v.push_back(std::to_string(e.augment_two_id));
|
||||
v.push_back(std::to_string(e.augment_three_id));
|
||||
v.push_back(std::to_string(e.augment_four_id));
|
||||
v.push_back(std::to_string(e.augment_five_id));
|
||||
v.push_back(std::to_string(e.augment_six_id));
|
||||
v.push_back(std::to_string(e.quantity));
|
||||
v.push_back(std::to_string(e.itemid));
|
||||
v.push_back(std::to_string(e.qty));
|
||||
v.push_back("'" + Strings::Escape(e.donator) + "'");
|
||||
v.push_back(std::to_string(e.permissions));
|
||||
v.push_back("'" + Strings::Escape(e.who_for) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.whofor) + "'");
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
@@ -346,21 +299,15 @@ public:
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
GuildBank e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.guild_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.area = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.slot = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.item_id = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.augment_one_id = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.augment_two_id = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.augment_three_id = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.augment_four_id = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.augment_five_id = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.augment_six_id = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
|
||||
e.quantity = row[11] ? static_cast<int32_t>(atoi(row[11])) : 0;
|
||||
e.donator = row[12] ? row[12] : "";
|
||||
e.permissions = row[13] ? static_cast<uint8_t>(strtoul(row[13], nullptr, 10)) : 0;
|
||||
e.who_for = row[14] ? row[14] : "";
|
||||
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.guildid = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.area = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
|
||||
e.slot = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
|
||||
e.itemid = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
|
||||
e.qty = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
|
||||
e.donator = row[6] ? row[6] : "";
|
||||
e.permissions = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
|
||||
e.whofor = row[8] ? row[8] : "";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -385,21 +332,15 @@ public:
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
GuildBank e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.guild_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.area = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.slot = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.item_id = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.augment_one_id = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.augment_two_id = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.augment_three_id = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.augment_four_id = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.augment_five_id = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.augment_six_id = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
|
||||
e.quantity = row[11] ? static_cast<int32_t>(atoi(row[11])) : 0;
|
||||
e.donator = row[12] ? row[12] : "";
|
||||
e.permissions = row[13] ? static_cast<uint8_t>(strtoul(row[13], nullptr, 10)) : 0;
|
||||
e.who_for = row[14] ? row[14] : "";
|
||||
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.guildid = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.area = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
|
||||
e.slot = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
|
||||
e.itemid = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
|
||||
e.qty = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
|
||||
e.donator = row[6] ? row[6] : "";
|
||||
e.permissions = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
|
||||
e.whofor = row[8] ? row[8] : "";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -458,90 +399,6 @@ public:
|
||||
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 GuildBank &e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.guild_id));
|
||||
v.push_back(std::to_string(e.area));
|
||||
v.push_back(std::to_string(e.slot));
|
||||
v.push_back(std::to_string(e.item_id));
|
||||
v.push_back(std::to_string(e.augment_one_id));
|
||||
v.push_back(std::to_string(e.augment_two_id));
|
||||
v.push_back(std::to_string(e.augment_three_id));
|
||||
v.push_back(std::to_string(e.augment_four_id));
|
||||
v.push_back(std::to_string(e.augment_five_id));
|
||||
v.push_back(std::to_string(e.augment_six_id));
|
||||
v.push_back(std::to_string(e.quantity));
|
||||
v.push_back("'" + Strings::Escape(e.donator) + "'");
|
||||
v.push_back(std::to_string(e.permissions));
|
||||
v.push_back("'" + Strings::Escape(e.who_for) + "'");
|
||||
|
||||
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<GuildBank> &entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &e: entries) {
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.guild_id));
|
||||
v.push_back(std::to_string(e.area));
|
||||
v.push_back(std::to_string(e.slot));
|
||||
v.push_back(std::to_string(e.item_id));
|
||||
v.push_back(std::to_string(e.augment_one_id));
|
||||
v.push_back(std::to_string(e.augment_two_id));
|
||||
v.push_back(std::to_string(e.augment_three_id));
|
||||
v.push_back(std::to_string(e.augment_four_id));
|
||||
v.push_back(std::to_string(e.augment_five_id));
|
||||
v.push_back(std::to_string(e.augment_six_id));
|
||||
v.push_back(std::to_string(e.quantity));
|
||||
v.push_back("'" + Strings::Escape(e.donator) + "'");
|
||||
v.push_back(std::to_string(e.permissions));
|
||||
v.push_back("'" + Strings::Escape(e.who_for) + "'");
|
||||
|
||||
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_GUILD_BANK_REPOSITORY_H
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define EQEMU_CHARACTER_EXPEDITION_LOCKOUTS_REPOSITORY_H
|
||||
|
||||
#include "../database.h"
|
||||
#include "../dynamic_zone_lockout.h"
|
||||
#include "../expedition_lockout_timer.h"
|
||||
#include "../strings.h"
|
||||
#include "base/base_character_expedition_lockouts_repository.h"
|
||||
#include <unordered_map>
|
||||
@@ -47,8 +47,33 @@ public:
|
||||
|
||||
// Custom extended repository methods here
|
||||
|
||||
static std::unordered_map<uint32_t, std::vector<DzLockout>> GetLockouts(
|
||||
Database& db, const std::vector<uint32_t>& char_ids, const std::string& expedition)
|
||||
struct CharacterExpeditionLockoutsTimeStamp {
|
||||
int id;
|
||||
int character_id;
|
||||
std::string expedition_name;
|
||||
std::string event_name;
|
||||
time_t expire_time;
|
||||
int duration;
|
||||
std::string from_expedition_uuid;
|
||||
};
|
||||
|
||||
static ExpeditionLockoutTimer GetExpeditionLockoutTimerFromEntry(
|
||||
CharacterExpeditionLockoutsTimeStamp&& entry)
|
||||
{
|
||||
ExpeditionLockoutTimer lockout_timer{
|
||||
std::move(entry.from_expedition_uuid),
|
||||
std::move(entry.expedition_name),
|
||||
std::move(entry.event_name),
|
||||
static_cast<uint64_t>(entry.expire_time),
|
||||
static_cast<uint32_t>(entry.duration)
|
||||
};
|
||||
|
||||
return lockout_timer;
|
||||
}
|
||||
|
||||
static std::unordered_map<uint32_t, std::vector<ExpeditionLockoutTimer>> GetManyCharacterLockoutTimers(
|
||||
Database& db, const std::vector<uint32_t>& character_ids,
|
||||
const std::string& expedition_name, const std::string& ordered_event_name)
|
||||
{
|
||||
auto results = db.QueryDatabase(fmt::format(SQL(
|
||||
SELECT
|
||||
@@ -59,171 +84,39 @@ public:
|
||||
from_expedition_uuid
|
||||
FROM character_expedition_lockouts
|
||||
WHERE
|
||||
character_id IN ({0})
|
||||
character_id IN ({})
|
||||
AND expire_time > NOW()
|
||||
AND expedition_name = '{1}'
|
||||
AND expedition_name = '{}'
|
||||
ORDER BY
|
||||
FIELD(character_id, {0}),
|
||||
FIELD(event_name, '{2}') DESC
|
||||
FIELD(character_id, {}),
|
||||
FIELD(event_name, '{}') DESC
|
||||
),
|
||||
fmt::join(char_ids, ","),
|
||||
Strings::Escape(expedition),
|
||||
Strings::Escape(DzLockout::ReplayTimer)
|
||||
fmt::join(character_ids, ","),
|
||||
Strings::Escape(expedition_name),
|
||||
fmt::join(character_ids, ","),
|
||||
Strings::Escape(ordered_event_name)
|
||||
));
|
||||
|
||||
std::unordered_map<uint32_t, std::vector<DzLockout>> lockouts;
|
||||
std::unordered_map<uint32_t, std::vector<ExpeditionLockoutTimer>> lockouts;
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row)
|
||||
{
|
||||
CharacterExpeditionLockoutsTimeStamp entry{};
|
||||
|
||||
int col = 0;
|
||||
uint32_t char_id = std::strtoul(row[col++], nullptr, 10);
|
||||
time_t expire_time = std::strtoull(row[col++], nullptr, 10);
|
||||
uint32_t duration = std::strtoul(row[col++], nullptr, 10);
|
||||
std::string event = row[col++];
|
||||
std::string uuid = row[col++];
|
||||
entry.character_id = std::strtoul(row[col++], nullptr, 10);
|
||||
entry.expire_time = std::strtoull(row[col++], nullptr, 10);
|
||||
entry.duration = std::strtoul(row[col++], nullptr, 10);
|
||||
entry.event_name = row[col++];
|
||||
entry.expedition_name = expedition_name;
|
||||
entry.from_expedition_uuid = row[col++];
|
||||
|
||||
lockouts[char_id].emplace_back(std::move(uuid), expedition, std::move(event), expire_time, duration);
|
||||
auto lockout = GetExpeditionLockoutTimerFromEntry(std::move(entry));
|
||||
lockouts[entry.character_id].emplace_back(std::move(lockout));
|
||||
}
|
||||
|
||||
return lockouts;
|
||||
}
|
||||
|
||||
static std::vector<DzLockout> GetLockouts(Database& db, uint32_t char_id)
|
||||
{
|
||||
std::vector<DzLockout> lockouts;
|
||||
|
||||
auto rows = GetWhere(db, fmt::format("character_id = {} AND expire_time > NOW()", char_id));
|
||||
lockouts.reserve(rows.size());
|
||||
|
||||
for (auto& row : rows)
|
||||
{
|
||||
lockouts.emplace_back(
|
||||
std::move(row.from_expedition_uuid),
|
||||
std::move(row.expedition_name),
|
||||
std::move(row.event_name),
|
||||
row.expire_time,
|
||||
row.duration
|
||||
);
|
||||
}
|
||||
|
||||
return lockouts;
|
||||
}
|
||||
|
||||
static std::vector<CharacterExpeditionLockouts> GetLockouts(Database& db, const std::vector<std::string>& names, const std::string& expedition, const std::string& event)
|
||||
{
|
||||
if (names.empty())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return GetWhere(db, fmt::format(
|
||||
"character_id IN (select id from character_data where name IN ('{}')) AND expire_time > NOW() AND expedition_name = '{}' AND event_name = '{}' LIMIT 1",
|
||||
fmt::join(names, "','"), Strings::Escape(expedition), Strings::Escape(event)));
|
||||
}
|
||||
|
||||
static void InsertLockouts(Database& db, uint32_t char_id, const std::vector<DzLockout>& lockouts)
|
||||
{
|
||||
std::string insert_values;
|
||||
for (const auto& lockout : lockouts)
|
||||
{
|
||||
fmt::format_to(std::back_inserter(insert_values),
|
||||
"({}, FROM_UNIXTIME({}), {}, '{}', '{}', '{}'),",
|
||||
char_id,
|
||||
lockout.GetExpireTime(),
|
||||
lockout.GetDuration(),
|
||||
Strings::Escape(lockout.UUID()),
|
||||
Strings::Escape(lockout.DzName()),
|
||||
Strings::Escape(lockout.Event())
|
||||
);
|
||||
}
|
||||
|
||||
if (!insert_values.empty())
|
||||
{
|
||||
insert_values.pop_back(); // trailing comma
|
||||
|
||||
auto query = fmt::format(SQL(
|
||||
INSERT INTO character_expedition_lockouts
|
||||
(character_id, expire_time, duration, from_expedition_uuid, expedition_name, event_name)
|
||||
VALUES {}
|
||||
ON DUPLICATE KEY UPDATE
|
||||
from_expedition_uuid = VALUES(from_expedition_uuid),
|
||||
expire_time = VALUES(expire_time),
|
||||
duration = VALUES(duration);
|
||||
), insert_values);
|
||||
|
||||
db.QueryDatabase(query);
|
||||
}
|
||||
}
|
||||
|
||||
static void InsertLockout(Database& db, const std::vector<uint32_t>& char_ids, const DzLockout& lockout)
|
||||
{
|
||||
std::string insert_values;
|
||||
for (const auto& char_id : char_ids)
|
||||
{
|
||||
fmt::format_to(std::back_inserter(insert_values),
|
||||
"({}, FROM_UNIXTIME({}), {}, '{}', '{}', '{}'),",
|
||||
char_id,
|
||||
lockout.GetExpireTime(),
|
||||
lockout.GetDuration(),
|
||||
Strings::Escape(lockout.UUID()),
|
||||
Strings::Escape(lockout.DzName()),
|
||||
Strings::Escape(lockout.Event())
|
||||
);
|
||||
}
|
||||
|
||||
if (!insert_values.empty())
|
||||
{
|
||||
insert_values.pop_back(); // trailing comma
|
||||
|
||||
auto query = fmt::format(SQL(
|
||||
INSERT INTO character_expedition_lockouts
|
||||
(character_id, expire_time, duration, from_expedition_uuid, expedition_name, event_name)
|
||||
VALUES {}
|
||||
ON DUPLICATE KEY UPDATE
|
||||
from_expedition_uuid = VALUES(from_expedition_uuid),
|
||||
expire_time = VALUES(expire_time),
|
||||
duration = VALUES(duration);
|
||||
), insert_values);
|
||||
|
||||
db.QueryDatabase(query);
|
||||
}
|
||||
}
|
||||
|
||||
// inserts a new lockout or updates existing lockout with seconds added to current time
|
||||
static void AddLockoutDuration(Database& db, const std::vector<uint32_t>& char_ids, const DzLockout& lockout, int seconds)
|
||||
{
|
||||
std::string insert_values;
|
||||
for (const auto& char_id : char_ids)
|
||||
{
|
||||
fmt::format_to(std::back_inserter(insert_values),
|
||||
"({}, FROM_UNIXTIME({}), {}, '{}', '{}', '{}'),",
|
||||
char_id,
|
||||
lockout.GetExpireTime(),
|
||||
lockout.GetDuration(),
|
||||
Strings::Escape(lockout.UUID()),
|
||||
Strings::Escape(lockout.DzName()),
|
||||
Strings::Escape(lockout.Event())
|
||||
);
|
||||
}
|
||||
|
||||
if (!insert_values.empty())
|
||||
{
|
||||
insert_values.pop_back(); // trailing comma
|
||||
|
||||
auto query = fmt::format(SQL(
|
||||
INSERT INTO character_expedition_lockouts
|
||||
(character_id, expire_time, duration, from_expedition_uuid, expedition_name, event_name)
|
||||
VALUES {0}
|
||||
ON DUPLICATE KEY UPDATE
|
||||
from_expedition_uuid = VALUES(from_expedition_uuid),
|
||||
expire_time = DATE_ADD(expire_time, INTERVAL {1} SECOND),
|
||||
duration = GREATEST(0, CAST(duration AS SIGNED) + {1});
|
||||
), insert_values, seconds);
|
||||
|
||||
db.QueryDatabase(query);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif //EQEMU_CHARACTER_EXPEDITION_LOCKOUTS_REPOSITORY_H
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
#ifndef EQEMU_DYNAMIC_ZONE_LOCKOUTS_REPOSITORY_H
|
||||
#define EQEMU_DYNAMIC_ZONE_LOCKOUTS_REPOSITORY_H
|
||||
|
||||
#include "../database.h"
|
||||
#include "../strings.h"
|
||||
#include "../dynamic_zone_lockout.h"
|
||||
#include "base/base_dynamic_zone_lockouts_repository.h"
|
||||
|
||||
class DynamicZoneLockoutsRepository: public BaseDynamicZoneLockoutsRepository {
|
||||
public:
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* DynamicZoneLockoutsRepository::GetByZoneAndVersion(int zone_id, int zone_version)
|
||||
* DynamicZoneLockoutsRepository::GetWhereNeverExpires()
|
||||
* DynamicZoneLockoutsRepository::GetWhereXAndY()
|
||||
* DynamicZoneLockoutsRepository::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
|
||||
*/
|
||||
|
||||
// Custom extended repository methods here
|
||||
|
||||
static void InsertLockouts(Database& db, uint32_t dz_id, const std::vector<DzLockout>& lockouts)
|
||||
{
|
||||
std::string insert_values;
|
||||
for (const auto& lockout : lockouts)
|
||||
{
|
||||
fmt::format_to(std::back_inserter(insert_values),
|
||||
"({}, '{}', '{}', FROM_UNIXTIME({}), {}),",
|
||||
dz_id,
|
||||
Strings::Escape(lockout.UUID()),
|
||||
Strings::Escape(lockout.Event()),
|
||||
lockout.GetExpireTime(),
|
||||
lockout.GetDuration()
|
||||
);
|
||||
}
|
||||
|
||||
if (!insert_values.empty())
|
||||
{
|
||||
insert_values.pop_back(); // trailing comma
|
||||
|
||||
auto query = fmt::format(SQL(
|
||||
INSERT INTO dynamic_zone_lockouts
|
||||
(dynamic_zone_id, from_expedition_uuid, event_name, expire_time, duration)
|
||||
VALUES {}
|
||||
ON DUPLICATE KEY UPDATE
|
||||
from_expedition_uuid = VALUES(from_expedition_uuid),
|
||||
expire_time = VALUES(expire_time),
|
||||
duration = VALUES(duration);
|
||||
), insert_values);
|
||||
|
||||
db.QueryDatabase(query);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif //EQEMU_DYNAMIC_ZONE_LOCKOUTS_REPOSITORY_H
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
));
|
||||
}
|
||||
|
||||
static std::vector<MemberWithName> AllWithNames(Database& db)
|
||||
static std::vector<MemberWithName> GetAllWithNames(Database& db)
|
||||
{
|
||||
std::vector<MemberWithName> all_entries;
|
||||
|
||||
@@ -146,34 +146,65 @@ public:
|
||||
|
||||
static void RemoveMember(Database& db, uint32_t dynamic_zone_id, uint32_t character_id)
|
||||
{
|
||||
DeleteWhere(db, fmt::format("dynamic_zone_id = {} AND character_id = {}", dynamic_zone_id, character_id));
|
||||
db.QueryDatabase(fmt::format(SQL(
|
||||
DELETE FROM {}
|
||||
WHERE dynamic_zone_id = {} AND character_id = {};
|
||||
),
|
||||
TableName(), dynamic_zone_id, character_id
|
||||
));
|
||||
}
|
||||
|
||||
static void RemoveAllMembers(Database& db, uint32_t dynamic_zone_id)
|
||||
{
|
||||
DeleteWhere(db, fmt::format("dynamic_zone_id = {}", dynamic_zone_id));
|
||||
db.QueryDatabase(fmt::format(SQL(
|
||||
DELETE FROM {}
|
||||
WHERE dynamic_zone_id = {};
|
||||
),
|
||||
TableName(), dynamic_zone_id
|
||||
));
|
||||
}
|
||||
|
||||
static uint32_t InsertOrUpdateMany(Database& db, const std::vector<DynamicZoneMembers>& entries)
|
||||
static void RemoveAllMembers(Database& db, std::vector<uint32_t> dynamic_zone_ids)
|
||||
{
|
||||
if (entries.empty())
|
||||
if (!dynamic_zone_ids.empty())
|
||||
{
|
||||
return 0;
|
||||
db.QueryDatabase(fmt::format(SQL(
|
||||
DELETE FROM {}
|
||||
WHERE dynamic_zone_id IN ({});
|
||||
),
|
||||
TableName(), Strings::Join(dynamic_zone_ids, ",")
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
static int InsertOrUpdateMany(Database& db,
|
||||
const std::vector<DynamicZoneMembers>& dynamic_zone_members_entries)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &dynamic_zone_members_entry: dynamic_zone_members_entries)
|
||||
{
|
||||
std::vector<std::string> insert_values;
|
||||
|
||||
insert_values.push_back(std::to_string(dynamic_zone_members_entry.id));
|
||||
insert_values.push_back(std::to_string(dynamic_zone_members_entry.dynamic_zone_id));
|
||||
insert_values.push_back(std::to_string(dynamic_zone_members_entry.character_id));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", insert_values) + ")");
|
||||
}
|
||||
|
||||
std::vector<std::string> values;
|
||||
values.reserve(entries.size());
|
||||
std::vector<std::string> insert_values;
|
||||
|
||||
for (const auto& entry : entries)
|
||||
{
|
||||
values.push_back(fmt::format("({},{},{})", entry.id, entry.dynamic_zone_id, entry.character_id));
|
||||
}
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"INSERT INTO {} ({}) VALUES {} ON DUPLICATE KEY UPDATE id = id;",
|
||||
TableName(),
|
||||
ColumnsRaw(),
|
||||
Strings::Implode(",", insert_chunks)
|
||||
)
|
||||
);
|
||||
|
||||
auto results = db.QueryDatabase(fmt::format(
|
||||
"INSERT INTO {} ({}) VALUES {} ON DUPLICATE KEY UPDATE id = id;",
|
||||
TableName(), ColumnsRaw(), fmt::join(values, ",")));
|
||||
|
||||
return results.Success() ? results.RowsAffected() : 0;
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -70,8 +70,6 @@ public:
|
||||
float zone_in_z;
|
||||
float zone_in_heading;
|
||||
int has_zone_in;
|
||||
int8_t is_locked;
|
||||
int8_t add_replay;
|
||||
int zone;
|
||||
int version;
|
||||
int is_global;
|
||||
@@ -107,8 +105,6 @@ public:
|
||||
dynamic_zones.zone_in_z,
|
||||
dynamic_zones.zone_in_heading,
|
||||
dynamic_zones.has_zone_in,
|
||||
dynamic_zones.is_locked,
|
||||
dynamic_zones.add_replay,
|
||||
instance_list.zone,
|
||||
instance_list.version,
|
||||
instance_list.is_global,
|
||||
@@ -148,8 +144,6 @@ public:
|
||||
entry.zone_in_z = strtof(row[col++], nullptr);
|
||||
entry.zone_in_heading = strtof(row[col++], nullptr);
|
||||
entry.has_zone_in = strtol(row[col++], nullptr, 10) != 0;
|
||||
entry.is_locked = static_cast<int8_t>(strtol(row[col++], nullptr, 10));
|
||||
entry.add_replay = static_cast<int8_t>(strtol(row[col++], nullptr, 10));
|
||||
// from instance_list
|
||||
entry.zone = strtol(row[col++], nullptr, 10);
|
||||
entry.version = strtol(row[col++], nullptr, 10);
|
||||
@@ -250,22 +244,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdateLocked(Database& db, uint32_t dz_id, bool lock)
|
||||
{
|
||||
if (dz_id != 0)
|
||||
{
|
||||
db.QueryDatabase(fmt::format("UPDATE dynamic_zones SET is_locked = {} WHERE id = {}", lock, dz_id));
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdateReplayOnJoin(Database& db, uint32_t dz_id, bool enabled)
|
||||
{
|
||||
if (dz_id != 0)
|
||||
{
|
||||
db.QueryDatabase(fmt::format("UPDATE dynamic_zones SET add_replay = {} WHERE id = {}", enabled, dz_id));
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdateSwitchID(Database& db, uint32_t dz_id, int dz_switch_id)
|
||||
{
|
||||
if (dz_id != 0)
|
||||
@@ -373,59 +351,6 @@ public:
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
struct CharacterDz
|
||||
{
|
||||
uint32_t id;
|
||||
std::string name;
|
||||
uint32_t dz_id;
|
||||
};
|
||||
|
||||
// get character ids with possible active dz id by type
|
||||
static std::vector<CharacterDz> GetCharactersWithDz(Database& db, const std::vector<std::string>& names, int type)
|
||||
{
|
||||
if (names.empty())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<CharacterDz> entries;
|
||||
entries.reserve(names.size());
|
||||
|
||||
auto results = db.QueryDatabase(fmt::format(SQL(
|
||||
SELECT
|
||||
character_data.id,
|
||||
character_data.name,
|
||||
MAX(dynamic_zones.id)
|
||||
FROM character_data
|
||||
LEFT JOIN dynamic_zone_members
|
||||
ON character_data.id = dynamic_zone_members.character_id
|
||||
LEFT JOIN dynamic_zones
|
||||
ON dynamic_zone_members.dynamic_zone_id = dynamic_zones.id
|
||||
AND dynamic_zones.`type` = {0}
|
||||
WHERE character_data.name IN ('{1}')
|
||||
GROUP BY character_data.id
|
||||
ORDER BY FIELD(character_data.name, '{1}')
|
||||
),
|
||||
type,
|
||||
fmt::join(names, "','")
|
||||
));
|
||||
|
||||
if (results.Success())
|
||||
{
|
||||
for (auto row = results.begin(); row != results.end(); ++row)
|
||||
{
|
||||
CharacterDz entry{};
|
||||
entry.id = std::strtoul(row[0], nullptr, 10);
|
||||
entry.name = row[1];
|
||||
entry.dz_id = row[2] ? std::strtoul(row[2], nullptr, 10) : 0;
|
||||
|
||||
entries.push_back(std::move(entry));
|
||||
}
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //EQEMU_DYNAMIC_ZONES_REPOSITORY_H
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
#ifndef EQEMU_EXPEDITION_LOCKOUTS_REPOSITORY_H
|
||||
#define EQEMU_EXPEDITION_LOCKOUTS_REPOSITORY_H
|
||||
|
||||
#include "../database.h"
|
||||
#include "../strings.h"
|
||||
#include "base/base_expedition_lockouts_repository.h"
|
||||
|
||||
class ExpeditionLockoutsRepository: public BaseExpeditionLockoutsRepository {
|
||||
public:
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* ExpeditionLockoutsRepository::GetByZoneAndVersion(int zone_id, int zone_version)
|
||||
* ExpeditionLockoutsRepository::GetWhereNeverExpires()
|
||||
* ExpeditionLockoutsRepository::GetWhereXAndY()
|
||||
* ExpeditionLockoutsRepository::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
|
||||
*/
|
||||
|
||||
// Custom extended repository methods here
|
||||
|
||||
struct ExpeditionLockoutsWithTimestamp {
|
||||
uint32_t id;
|
||||
uint32_t expedition_id;
|
||||
std::string event_name;
|
||||
time_t expire_time;
|
||||
int duration;
|
||||
std::string from_expedition_uuid;
|
||||
};
|
||||
|
||||
static std::vector<ExpeditionLockoutsWithTimestamp> GetWithTimestamp(
|
||||
Database& db, const std::vector<uint32_t>& expedition_ids)
|
||||
{
|
||||
if (expedition_ids.empty())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<ExpeditionLockoutsWithTimestamp> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(fmt::format(SQL(
|
||||
SELECT
|
||||
id,
|
||||
expedition_id,
|
||||
event_name,
|
||||
UNIX_TIMESTAMP(expire_time),
|
||||
duration,
|
||||
from_expedition_uuid
|
||||
FROM expedition_lockouts
|
||||
WHERE expedition_id IN ({})
|
||||
),
|
||||
Strings::Join(expedition_ids, ",")
|
||||
));
|
||||
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row)
|
||||
{
|
||||
ExpeditionLockoutsWithTimestamp entry{};
|
||||
|
||||
int col = 0;
|
||||
entry.id = strtoul(row[col++], nullptr, 10);
|
||||
entry.expedition_id = strtoul(row[col++], nullptr, 10);
|
||||
entry.event_name = row[col++];
|
||||
entry.expire_time = strtoull(row[col++], nullptr, 10);
|
||||
entry.duration = strtol(row[col++], nullptr, 10);
|
||||
entry.from_expedition_uuid = row[col++];
|
||||
|
||||
all_entries.emplace_back(std::move(entry));
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //EQEMU_EXPEDITION_LOCKOUTS_REPOSITORY_H
|
||||
@@ -0,0 +1,134 @@
|
||||
#ifndef EQEMU_EXPEDITIONS_REPOSITORY_H
|
||||
#define EQEMU_EXPEDITIONS_REPOSITORY_H
|
||||
|
||||
#include "../database.h"
|
||||
#include "../strings.h"
|
||||
#include "base/base_expeditions_repository.h"
|
||||
|
||||
class ExpeditionsRepository: public BaseExpeditionsRepository {
|
||||
public:
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* ExpeditionsRepository::GetByZoneAndVersion(int zone_id, int zone_version)
|
||||
* ExpeditionsRepository::GetWhereNeverExpires()
|
||||
* ExpeditionsRepository::GetWhereXAndY()
|
||||
* ExpeditionsRepository::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
|
||||
*/
|
||||
|
||||
// Custom extended repository methods here
|
||||
|
||||
struct CharacterExpedition
|
||||
{
|
||||
uint32_t id;
|
||||
std::string name;
|
||||
uint32_t expedition_id;
|
||||
};
|
||||
|
||||
static std::vector<CharacterExpedition> GetCharactersWithExpedition(
|
||||
Database& db, const std::vector<std::string>& character_names)
|
||||
{
|
||||
if (character_names.empty())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<CharacterExpedition> entries;
|
||||
|
||||
auto joined_character_names = fmt::format("'{}'", Strings::Join(character_names, "','"));
|
||||
|
||||
auto results = db.QueryDatabase(fmt::format(SQL(
|
||||
SELECT
|
||||
character_data.id,
|
||||
character_data.name,
|
||||
MAX(expeditions.id)
|
||||
FROM character_data
|
||||
LEFT JOIN dynamic_zone_members
|
||||
ON character_data.id = dynamic_zone_members.character_id
|
||||
LEFT JOIN expeditions
|
||||
ON dynamic_zone_members.dynamic_zone_id = expeditions.dynamic_zone_id
|
||||
WHERE character_data.name IN ({})
|
||||
GROUP BY character_data.id
|
||||
ORDER BY FIELD(character_data.name, {})
|
||||
),
|
||||
joined_character_names,
|
||||
joined_character_names
|
||||
));
|
||||
|
||||
if (results.Success())
|
||||
{
|
||||
entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row)
|
||||
{
|
||||
CharacterExpedition entry{};
|
||||
entry.id = std::strtoul(row[0], nullptr, 10);
|
||||
entry.name = row[1];
|
||||
entry.expedition_id = row[2] ? std::strtoul(row[2], nullptr, 10) : 0;
|
||||
|
||||
entries.emplace_back(std::move(entry));
|
||||
}
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
static uint32_t GetIDByMemberID(Database& db, uint32_t character_id)
|
||||
{
|
||||
if (character_id == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t expedition_id = 0;
|
||||
|
||||
auto results = db.QueryDatabase(fmt::format(SQL(
|
||||
SELECT
|
||||
expeditions.id
|
||||
FROM expeditions
|
||||
INNER JOIN dynamic_zone_members
|
||||
ON expeditions.dynamic_zone_id = dynamic_zone_members.dynamic_zone_id
|
||||
WHERE
|
||||
dynamic_zone_members.character_id = {}
|
||||
),
|
||||
character_id
|
||||
));
|
||||
|
||||
if (results.Success() && results.RowCount() > 0)
|
||||
{
|
||||
auto row = results.begin();
|
||||
expedition_id = std::strtoul(row[0], nullptr, 10);
|
||||
}
|
||||
|
||||
return expedition_id;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //EQEMU_EXPEDITIONS_REPOSITORY_H
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef EQEMU_FIND_LOCATION_REPOSITORY_H
|
||||
#define EQEMU_FIND_LOCATION_REPOSITORY_H
|
||||
|
||||
#include "../database.h"
|
||||
#include "../strings.h"
|
||||
#include "base/base_find_location_repository.h"
|
||||
|
||||
class FindLocationRepository: public BaseFindLocationRepository {
|
||||
public:
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* FindLocationRepository::GetByZoneAndVersion(int zone_id, int zone_version)
|
||||
* FindLocationRepository::GetWhereNeverExpires()
|
||||
* FindLocationRepository::GetWhereXAndY()
|
||||
* FindLocationRepository::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
|
||||
*/
|
||||
|
||||
// Custom extended repository methods here
|
||||
|
||||
};
|
||||
|
||||
#endif //EQEMU_FIND_LOCATION_REPOSITORY_H
|
||||
@@ -45,26 +45,33 @@ public:
|
||||
|
||||
// Custom extended repository methods here
|
||||
|
||||
static uint32_t InsertOrUpdateMany(Database& db, const std::vector<InstanceListPlayer>& entries)
|
||||
static int InsertOrUpdateMany(Database& db,
|
||||
const std::vector<InstanceListPlayer>& instance_list_player_entries)
|
||||
{
|
||||
if (entries.empty())
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &instance_list_player_entry: instance_list_player_entries)
|
||||
{
|
||||
return 0;
|
||||
std::vector<std::string> insert_values;
|
||||
|
||||
insert_values.push_back(std::to_string(instance_list_player_entry.id));
|
||||
insert_values.push_back(std::to_string(instance_list_player_entry.charid));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", insert_values) + ")");
|
||||
}
|
||||
|
||||
std::vector<std::string> values;
|
||||
values.reserve(entries.size());
|
||||
std::vector<std::string> insert_values;
|
||||
|
||||
for (const auto& entry : entries)
|
||||
{
|
||||
values.push_back(fmt::format("({},{})", entry.id, entry.charid));
|
||||
}
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"INSERT INTO {} ({}) VALUES {} ON DUPLICATE KEY UPDATE id = VALUES(id)",
|
||||
TableName(),
|
||||
ColumnsRaw(),
|
||||
Strings::Implode(",", insert_chunks)
|
||||
)
|
||||
);
|
||||
|
||||
auto results = db.QueryDatabase(fmt::format(
|
||||
"INSERT INTO {} ({}) VALUES {} ON DUPLICATE KEY UPDATE id = VALUES(id)",
|
||||
TableName(), ColumnsRaw(), fmt::join(values, ",")));
|
||||
|
||||
return results.Success() ? results.RowsAffected() : 0;
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static bool ReplaceOne(Database& db, InstanceListPlayer e)
|
||||
|
||||
+3
-5
@@ -230,7 +230,6 @@ RULE_BOOL(Character, PlayerTradingLoreFeedback, true, "If enabled, during a play
|
||||
RULE_INT(Character, MendAlwaysSucceedValue, 199, "Value at which mend will always succeed its skill check. Default: 199")
|
||||
RULE_BOOL(Character, SneakAlwaysSucceedOver100, false, "When sneak skill is over 100, always succeed sneak/hide. Default: false")
|
||||
RULE_INT(Character, BandolierSwapDelay, 0, "Bandolier swap delay in milliseconds, default is 0")
|
||||
RULE_BOOL(Character, EnableHackedFastCampForGM, false, "Enables hacked fast camp for GM clients, if the GM doesn't have a hacked client they'll camp like normal")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Mercs)
|
||||
@@ -714,7 +713,6 @@ RULE_INT(Aggro, BardAggroCap, 40, "per song bard aggro cap.")
|
||||
RULE_INT(Aggro, InitialAggroBonus, 100, "Initial Aggro Bonus, Default: 100")
|
||||
RULE_INT(Aggro, InitialPetAggroBonus, 100, "Initial Pet Aggro Bonus, Default 100")
|
||||
RULE_STRING(Aggro, ExcludedFleeAllyFactionIDs, "0|5013|5014|5023|5032", "Common Faction IDs that are excluded from faction checks in EntityList::FleeAllyCount")
|
||||
RULE_BOOL(Aggro, AggroBotPets, false, "If enabled, NPCs will aggro bot pets")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(TaskSystem)
|
||||
@@ -819,11 +817,11 @@ RULE_INT(Bots, MinDelayBetweenInCombatCastAttempts, 500, "The minimum delay in m
|
||||
RULE_INT(Bots, MaxDelayBetweenInCombatCastAttempts, 2000, "The maximum delay in milliseconds between cast attempts while in-combat. This is rolled between the min and max. Default 2500ms.")
|
||||
RULE_INT(Bots, MinDelayBetweenOutCombatCastAttempts, 1000, "The minimum delay in milliseconds between cast attempts while out-of-combat. This is rolled between the min and max. Default 1000ms.")
|
||||
RULE_INT(Bots, MaxDelayBetweenOutCombatCastAttempts, 2500, "The maximum delay in milliseconds between cast attempts while out-of-combat. This is rolled between the min and max. Default 2500ms.")
|
||||
RULE_INT(Bots, MezChance, 60, "60 Default. Chance for a bot to attempt to Mez a target after validating it is eligible.")
|
||||
RULE_INT(Bots, MezChance, 35, "35 Default. Chance for a bot to attempt to Mez a target after validating it is eligible.")
|
||||
RULE_INT(Bots, AEMezChance, 35, "35 Default. Chance for a bot to attempt to AE Mez targets after validating they are eligible.")
|
||||
RULE_INT(Bots, MezSuccessDelay, 2500, "2500 (2.5 sec) Default. Delay between successful Mez attempts.")
|
||||
RULE_INT(Bots, MezSuccessDelay, 3500, "3500 (3.5 sec) Default. Delay between successful Mez attempts.")
|
||||
RULE_INT(Bots, AEMezSuccessDelay, 5000, "5000 (5 sec) Default. Delay between successful AEMez attempts.")
|
||||
RULE_INT(Bots, MezFailDelay, 1250, "1250 (1.25 sec) Default. Delay between failed Mez attempts.")
|
||||
RULE_INT(Bots, MezFailDelay, 2000, "2000 (2 sec) Default. Delay between failed Mez attempts.")
|
||||
RULE_INT(Bots, MezAEFailDelay, 4000, "4000 (4 sec) Default. Delay between failed AEMez attempts.")
|
||||
RULE_INT(Bots, MinGroupHealTargets, 3, "Minimum number of targets in valid range that are required for a group heal to cast. Default 3.")
|
||||
RULE_INT(Bots, MinGroupCureTargets, 3, "Minimum number of targets in valid range that are required for a cure heal to cast. Default 3.")
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
#ifndef EQEMU_SERVER_RELOAD_TYPES_H
|
||||
#define EQEMU_SERVER_RELOAD_TYPES_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
namespace ServerReload {
|
||||
enum Type {
|
||||
ReloadTypeNone = 0,
|
||||
AAData,
|
||||
AlternateCurrencies,
|
||||
BaseData,
|
||||
BlockedSpells,
|
||||
Commands,
|
||||
ContentFlags,
|
||||
DataBucketsCache,
|
||||
Doors,
|
||||
DzTemplates,
|
||||
Factions,
|
||||
GroundSpawns,
|
||||
LevelEXPMods,
|
||||
Logs,
|
||||
Loot,
|
||||
Merchants,
|
||||
NPCEmotes,
|
||||
NPCSpells,
|
||||
Objects,
|
||||
Opcodes,
|
||||
PerlExportSettings,
|
||||
Quests,
|
||||
QuestsTimerReset,
|
||||
Rules,
|
||||
SkillCaps,
|
||||
StaticZoneData,
|
||||
Tasks,
|
||||
Titles,
|
||||
Traps,
|
||||
Variables,
|
||||
VeteranRewards,
|
||||
WorldRepop,
|
||||
WorldWithRespawn,
|
||||
ZoneData,
|
||||
ZonePoints,
|
||||
Max
|
||||
};
|
||||
|
||||
static const char *Name[ServerReload::Max] = {
|
||||
"None",
|
||||
"AA Data",
|
||||
"Alternate Currencies",
|
||||
"Base Data",
|
||||
"Blocked Spells",
|
||||
"Commands",
|
||||
"Content Flags",
|
||||
"Data Buckets Cache",
|
||||
"Doors",
|
||||
"DZ Templates",
|
||||
"Factions",
|
||||
"Ground Spawns",
|
||||
"Level EXP Mods",
|
||||
"Logs",
|
||||
"Loot",
|
||||
"Merchants",
|
||||
"NPC Emotes",
|
||||
"NPC Spells",
|
||||
"Objects",
|
||||
"Opcodes",
|
||||
"Perl Event Export Settings",
|
||||
"Quest",
|
||||
"Quests With Timer (Resets timer events)",
|
||||
"Rules",
|
||||
"Skill Caps",
|
||||
"Static Zone Data",
|
||||
"Tasks",
|
||||
"Titles",
|
||||
"Traps",
|
||||
"Variables",
|
||||
"Veteran Rewards",
|
||||
"World Repop",
|
||||
"World Repop Timers (Clear Respawn Timers)",
|
||||
"Zone Data",
|
||||
"Zone Points"
|
||||
};
|
||||
|
||||
inline std::string GetName(int reload_type)
|
||||
{
|
||||
if (reload_type < 0 || reload_type >= ServerReload::Type::Max) {
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
return ServerReload::Name[reload_type];
|
||||
}
|
||||
|
||||
// Get a clean name without spaces or special characters
|
||||
inline std::string GetNameClean(int reload_type)
|
||||
{
|
||||
if (reload_type < 0 || reload_type >= ServerReload::Type::Max) {
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
// get the name before parentheses
|
||||
std::string name = ServerReload::Name[reload_type];
|
||||
size_t pos = name.find('(');
|
||||
if (pos != std::string::npos) {
|
||||
name = name.substr(0, pos);
|
||||
}
|
||||
|
||||
// Trim leading spaces
|
||||
size_t start = name.find_first_not_of(' ');
|
||||
if (start == std::string::npos) {
|
||||
return ""; // If all spaces, return empty string
|
||||
}
|
||||
|
||||
// Trim trailing spaces
|
||||
size_t end = name.find_last_not_of(' ');
|
||||
|
||||
// Extract trimmed substring
|
||||
return name.substr(start, end - start + 1);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
inline std::vector<ServerReload::Type> GetTypes()
|
||||
{
|
||||
std::vector<ServerReload::Type> types;
|
||||
types.reserve(ServerReload::Type::Max);
|
||||
for (int i = 1; i < ServerReload::Type::Max; i++) {
|
||||
types.push_back(static_cast<ServerReload::Type>(i));
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
struct Request {
|
||||
int type = 0;
|
||||
bool requires_zone_booted = false;
|
||||
int64 reload_at_unix = 0;
|
||||
int32 opt_param = 0;
|
||||
uint32_t zone_server_id = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //EQEMU_SERVER_RELOAD_TYPES_H
|
||||
+67
-30
@@ -170,6 +170,18 @@
|
||||
#define ServerOP_LFPMatches 0x0214
|
||||
#define ServerOP_ClientVersionSummary 0x0215
|
||||
|
||||
// expedition
|
||||
#define ServerOP_ExpeditionCreate 0x0400
|
||||
#define ServerOP_ExpeditionLockout 0x0403
|
||||
#define ServerOP_ExpeditionDzAddPlayer 0x0408
|
||||
#define ServerOP_ExpeditionDzMakeLeader 0x0409
|
||||
#define ServerOP_ExpeditionCharacterLockout 0x040d
|
||||
#define ServerOP_ExpeditionSaveInvite 0x040e
|
||||
#define ServerOP_ExpeditionRequestInvite 0x040f
|
||||
#define ServerOP_ExpeditionReplayOnJoin 0x0410
|
||||
#define ServerOP_ExpeditionLockState 0x0411
|
||||
#define ServerOP_ExpeditionLockoutDuration 0x0414
|
||||
|
||||
// dz
|
||||
#define ServerOP_DzAddRemoveMember 0x0450
|
||||
#define ServerOP_DzRemoveAllMembers 0x0451
|
||||
@@ -187,15 +199,6 @@
|
||||
#define ServerOP_DzDeleted 0x045d
|
||||
#define ServerOP_DzSetSwitchID 0x045e
|
||||
#define ServerOP_DzMovePC 0x045f
|
||||
#define ServerOP_DzLock 0x0460
|
||||
#define ServerOP_DzReplayOnJoin 0x0461
|
||||
#define ServerOP_DzLockout 0x0462
|
||||
#define ServerOP_DzLockoutDuration 0x0463
|
||||
#define ServerOP_DzCharacterLockout 0x0464
|
||||
#define ServerOP_DzAddPlayer 0x0465
|
||||
#define ServerOP_DzSaveInvite 0x0466
|
||||
#define ServerOP_DzRequestInvite 0x0467
|
||||
#define ServerOP_DzMakeLeader 0x0468
|
||||
|
||||
#define ServerOP_LSInfo 0x1000
|
||||
#define ServerOP_LSStatus 0x1001
|
||||
@@ -248,7 +251,37 @@
|
||||
#define ServerOP_UpdateSchedulerEvents 0x4007
|
||||
#define ServerOP_DiscordWebhookMessage 0x4008
|
||||
|
||||
#define ServerOP_ServerReloadRequest 0x4100
|
||||
#define ServerOP_ReloadAAData 0x4100
|
||||
#define ServerOP_ReloadAlternateCurrencies 0x4101
|
||||
#define ServerOP_ReloadBlockedSpells 0x4102
|
||||
#define ServerOP_ReloadCommands 0x4103
|
||||
#define ServerOP_ReloadContentFlags 0x4104
|
||||
#define ServerOP_ReloadDoors 0x4105
|
||||
#define ServerOP_ReloadGroundSpawns 0x4106
|
||||
#define ServerOP_ReloadLevelEXPMods 0x4107
|
||||
#define ServerOP_ReloadLogs 0x4108
|
||||
#define ServerOP_ReloadMerchants 0x4109
|
||||
#define ServerOP_ReloadNPCEmotes 0x4110
|
||||
#define ServerOP_ReloadObjects 0x4111
|
||||
#define ServerOP_ReloadOpcodes 0x4112
|
||||
#define ServerOP_ReloadPerlExportSettings 0x4113
|
||||
#define ServerOP_ReloadRules 0x4114
|
||||
#define ServerOP_ReloadStaticZoneData 0x4115
|
||||
#define ServerOP_ReloadTasks 0x4116
|
||||
#define ServerOP_ReloadTitles 0x4117
|
||||
#define ServerOP_ReloadTraps 0x4118
|
||||
#define ServerOP_ReloadVariables 0x4119
|
||||
#define ServerOP_ReloadVeteranRewards 0x4120
|
||||
#define ServerOP_ReloadWorld 0x4121
|
||||
#define ServerOP_ReloadZonePoints 0x4122
|
||||
#define ServerOP_ReloadDzTemplates 0x4123
|
||||
#define ServerOP_ReloadZoneData 0x4124
|
||||
#define ServerOP_ReloadDataBucketsCache 0x4125
|
||||
#define ServerOP_ReloadFactions 0x4126
|
||||
#define ServerOP_ReloadLoot 0x4127
|
||||
#define ServerOP_ReloadBaseData 0x4128
|
||||
#define ServerOP_ReloadSkillCaps 0x4129
|
||||
#define ServerOP_ReloadNPCSpells 0x4130
|
||||
|
||||
#define ServerOP_CZDialogueWindow 0x4500
|
||||
#define ServerOP_CZLDoNUpdate 0x4501
|
||||
@@ -1510,8 +1543,10 @@ struct UCSServerStatus_Struct {
|
||||
};
|
||||
};
|
||||
|
||||
struct ServerCharacterID_Struct {
|
||||
uint32_t char_id;
|
||||
struct ServerExpeditionID_Struct {
|
||||
uint32 expedition_id;
|
||||
uint32 sender_zone_id;
|
||||
uint32 sender_instance_id;
|
||||
};
|
||||
|
||||
struct ServerDzLeaderID_Struct {
|
||||
@@ -1545,42 +1580,45 @@ struct ServerDzMovePC_Struct {
|
||||
uint32 character_id;
|
||||
};
|
||||
|
||||
struct ServerDzLockout_Struct {
|
||||
uint32 dz_id;
|
||||
struct ServerExpeditionLockout_Struct {
|
||||
uint32 expedition_id;
|
||||
uint64 expire_time;
|
||||
uint32 duration;
|
||||
uint32 sender_zone_id;
|
||||
uint16 sender_instance_id;
|
||||
uint8 remove;
|
||||
uint8 members_only;
|
||||
int seconds;
|
||||
int seconds_adjust;
|
||||
char event_name[256];
|
||||
};
|
||||
|
||||
struct ServerDzLock_Struct {
|
||||
uint32 dz_id;
|
||||
struct ServerExpeditionLockState_Struct {
|
||||
uint32 expedition_id;
|
||||
uint32 sender_zone_id;
|
||||
uint16 sender_instance_id;
|
||||
bool lock;
|
||||
uint8 enabled;
|
||||
uint8 lock_msg; // 0: none, 1: closing 2: trial begin
|
||||
uint32 color;
|
||||
};
|
||||
|
||||
struct ServerDzBool_Struct {
|
||||
uint32 dz_id;
|
||||
struct ServerExpeditionSetting_Struct {
|
||||
uint32 expedition_id;
|
||||
uint32 sender_zone_id;
|
||||
uint16 sender_instance_id;
|
||||
bool enabled;
|
||||
uint8 enabled;
|
||||
};
|
||||
|
||||
struct ServerDzCharacterLockout_Struct {
|
||||
struct ServerExpeditionCharacterLockout_Struct {
|
||||
uint8 remove;
|
||||
uint32 char_id;
|
||||
uint32 character_id;
|
||||
uint64 expire_time;
|
||||
uint32 duration;
|
||||
char uuid[37];
|
||||
char expedition[128];
|
||||
char event[256];
|
||||
char expedition_name[128];
|
||||
char event_name[256];
|
||||
};
|
||||
|
||||
struct ServerExpeditionCharacterID_Struct {
|
||||
uint32_t character_id;
|
||||
};
|
||||
|
||||
struct ServerDzExpireWarning_Struct {
|
||||
@@ -1589,7 +1627,7 @@ struct ServerDzExpireWarning_Struct {
|
||||
};
|
||||
|
||||
struct ServerDzCommand_Struct {
|
||||
uint32 dz_id;
|
||||
uint32 expedition_id;
|
||||
uint8 is_char_online; // 0: target name is offline, 1: online
|
||||
char requester_name[64];
|
||||
char target_name[64];
|
||||
@@ -1658,12 +1696,11 @@ struct ServerDzSetDuration_Struct {
|
||||
uint32 seconds;
|
||||
};
|
||||
|
||||
struct ServerDzCreate_Struct {
|
||||
struct ServerDzCreateSerialized_Struct {
|
||||
uint16_t origin_zone_id;
|
||||
uint16_t origin_instance_id;
|
||||
uint32_t dz_id;
|
||||
uint32_t cereal_size;
|
||||
char cereal_data[1];
|
||||
char cereal_data[0];
|
||||
};
|
||||
|
||||
struct ServerSendPlayerEvent_Struct {
|
||||
|
||||
+14
-23
@@ -93,14 +93,7 @@ bool IsTargetableAESpell(uint16 spell_id)
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
spells[spell_id].target_type == ST_AETarget ||
|
||||
spells[spell_id].target_type == ST_TargetAETap ||
|
||||
spells[spell_id].target_type == ST_AETargetHateList ||
|
||||
spells[spell_id].target_type == ST_TargetAENoPlayersPets ||
|
||||
spells[spell_id].target_type == ST_UndeadAE ||
|
||||
spells[spell_id].target_type == ST_SummonedAE
|
||||
);
|
||||
return spells[spell_id].target_type == ST_AETarget;
|
||||
}
|
||||
|
||||
bool IsSacrificeSpell(uint16 spell_id)
|
||||
@@ -682,19 +675,17 @@ bool IsAnyNukeOrStunSpell(uint16 spell_id) {
|
||||
}
|
||||
|
||||
bool IsAnyAESpell(uint16 spell_id) {
|
||||
if (!IsValidSpell(spell_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
IsTargetableAESpell(spell_id) ||
|
||||
IsAESpell(spell_id) ||
|
||||
IsPBAESpell(spell_id) ||
|
||||
IsAEDurationSpell(spell_id) ||
|
||||
IsAERainNukeSpell(spell_id) ||
|
||||
IsAERainSpell(spell_id) ||
|
||||
IsPBAENukeSpell(spell_id)
|
||||
);
|
||||
return (
|
||||
IsValidSpell(spell_id) &&
|
||||
(
|
||||
IsAEDurationSpell(spell_id) ||
|
||||
IsAESpell(spell_id) ||
|
||||
IsAERainNukeSpell(spell_id) ||
|
||||
IsAERainSpell(spell_id) ||
|
||||
IsPBAESpell(spell_id) ||
|
||||
IsPBAENukeSpell(spell_id)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
bool IsAESpell(uint16 spell_id)
|
||||
@@ -749,8 +740,8 @@ bool IsPBAESpell(uint16 spell_id)
|
||||
|
||||
if (
|
||||
spell.aoe_range > 0 &&
|
||||
!IsTargetRequiredForSpell(spell_id)
|
||||
) {
|
||||
spell.target_type == ST_AECaster
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -743,7 +743,7 @@ namespace BotSpellTypes
|
||||
constexpr uint16 DISCIPLINE_END = BotSpellTypes::DiscUtility; // Do not remove this, increment as needed
|
||||
}
|
||||
|
||||
static std::map<uint16, std::string> spell_type_names = {
|
||||
static std::map<uint16, std::string> spellType_names = {
|
||||
{ BotSpellTypes::Nuke, "Nuke" },
|
||||
{ BotSpellTypes::RegularHeal, "Regular Heal" },
|
||||
{ BotSpellTypes::Root, "Root" },
|
||||
@@ -818,7 +818,7 @@ static std::map<uint16, std::string> spell_type_names = {
|
||||
{ BotSpellTypes::AELull, "AE Lull" }
|
||||
};
|
||||
|
||||
static std::map<uint16, std::string> spell_type_short_names = {
|
||||
static std::map<uint16, std::string> spellType_shortNames = {
|
||||
{ BotSpellTypes::Nuke, "nukes" },
|
||||
{ BotSpellTypes::RegularHeal, "regularheals" },
|
||||
{ BotSpellTypes::Root, "roots" },
|
||||
@@ -900,7 +900,7 @@ const uint32 SPELL_TYPES_INNATE = (SpellType_Nuke | SpellType_Lifetap | SpellTyp
|
||||
// Bot related functions
|
||||
bool IsBotSpellTypeDetrimental (uint16 spell_type);
|
||||
bool IsBotSpellTypeBeneficial (uint16 spell_type);
|
||||
bool BotSpellTypeUsesTargetSettings(uint16 spell_type);
|
||||
bool IsBotSpellTypeOtherBeneficial(uint16 spell_type);
|
||||
bool IsBotSpellTypeInnate (uint16 spell_type);
|
||||
bool IsAEBotSpellType(uint16 spell_type);
|
||||
bool IsGroupBotSpellType(uint16 spell_type);
|
||||
|
||||
@@ -90,7 +90,7 @@ bool IsBotSpellTypeBeneficial(uint16 spell_type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BotSpellTypeUsesTargetSettings(uint16 spell_type) {
|
||||
bool IsBotSpellTypeOtherBeneficial(uint16 spell_type) {
|
||||
switch (spell_type) {
|
||||
case BotSpellTypes::RegularHeal:
|
||||
case BotSpellTypes::CompleteHeal:
|
||||
|
||||
@@ -912,27 +912,3 @@ std::string Strings::ZoneTime(const uint8 hours, const uint8 minutes)
|
||||
hours >= 13 ? "PM" : "AM"
|
||||
);
|
||||
}
|
||||
|
||||
std::string Strings::Slugify(const std::string& input, const std::string& separator) {
|
||||
std::string slug;
|
||||
bool last_was_hyphen = false;
|
||||
|
||||
for (char c : input) {
|
||||
if (std::isalnum(c)) {
|
||||
slug += std::tolower(c);
|
||||
last_was_hyphen = false;
|
||||
} else if (c == ' ' || c == '_' || c == '-') {
|
||||
if (!last_was_hyphen && !slug.empty()) {
|
||||
slug += separator;
|
||||
last_was_hyphen = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove trailing hyphen if present
|
||||
if (!slug.empty() && slug.back() == '-') {
|
||||
slug.pop_back();
|
||||
}
|
||||
|
||||
return slug;
|
||||
}
|
||||
|
||||
@@ -186,8 +186,6 @@ public:
|
||||
value = strtod(tmp_str.data(), nullptr);
|
||||
return res;
|
||||
}
|
||||
|
||||
static std::string Slugify(const std::string &input, const std::string &separator = "-");
|
||||
};
|
||||
|
||||
const std::string StringFormat(const char *format, ...);
|
||||
|
||||
+2
-2
@@ -25,7 +25,7 @@
|
||||
|
||||
// Build variables
|
||||
// these get injected during the build pipeline
|
||||
#define CURRENT_VERSION "23.0.2-dev" // always append -dev to the current version for custom-builds
|
||||
#define CURRENT_VERSION "22.62.2-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 9306
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9302
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9054
|
||||
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "eqemu-server",
|
||||
"version": "23.0.2",
|
||||
"version": "22.62.2",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/EQEmu/Server.git"
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "worldserver.h"
|
||||
#include "../common/events/player_events.h"
|
||||
#include "../common/events/player_event_logs.h"
|
||||
#include "../common/server_reload_types.h"
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <stdarg.h>
|
||||
@@ -73,13 +72,9 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
||||
case 0: {
|
||||
break;
|
||||
}
|
||||
case ServerOP_ServerReloadRequest: {
|
||||
auto o = (ServerReload::Request*) p.Data();
|
||||
if (o->type == ServerReload::Type::Logs) {
|
||||
LogSys.LoadLogDatabaseSettings();
|
||||
player_event_logs.ReloadSettings();
|
||||
}
|
||||
|
||||
case ServerOP_ReloadLogs: {
|
||||
LogSys.LoadLogDatabaseSettings();
|
||||
player_event_logs.ReloadSettings();
|
||||
break;
|
||||
}
|
||||
case ServerOP_QueryServGeneric: {
|
||||
|
||||
+3
-8
@@ -28,7 +28,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "database.h"
|
||||
#include "../common/discord/discord_manager.h"
|
||||
#include "../common/events/player_event_logs.h"
|
||||
#include "../common/server_reload_types.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
@@ -76,13 +75,9 @@ void WorldServer::ProcessMessage(uint16 opcode, EQ::Net::Packet &p)
|
||||
{
|
||||
break;
|
||||
}
|
||||
case ServerOP_ServerReloadRequest: {
|
||||
auto o = (ServerReload::Request*) pack->pBuffer;
|
||||
if (o->type == ServerReload::Type::Logs) {
|
||||
LogSys.LoadLogDatabaseSettings();
|
||||
player_event_logs.ReloadSettings();
|
||||
}
|
||||
|
||||
case ServerOP_ReloadLogs: {
|
||||
LogSys.LoadLogDatabaseSettings();
|
||||
player_event_logs.ReloadSettings();
|
||||
break;
|
||||
}
|
||||
case ServerOP_PlayerEvent: {
|
||||
|
||||
@@ -11,6 +11,8 @@ SET(world_sources
|
||||
dynamic_zone_manager.cpp
|
||||
eql_config.cpp
|
||||
eqemu_api_world_data_service.cpp
|
||||
expedition_database.cpp
|
||||
expedition_message.cpp
|
||||
launcher_link.cpp
|
||||
launcher_list.cpp
|
||||
lfplist.cpp
|
||||
@@ -46,6 +48,8 @@ SET(world_headers
|
||||
dynamic_zone_manager.h
|
||||
eql_config.h
|
||||
eqemu_api_world_data_service.h
|
||||
expedition_database.h
|
||||
expedition_message.h
|
||||
launcher_link.h
|
||||
launcher_list.h
|
||||
lfplist.h
|
||||
|
||||
+3
-3
@@ -127,8 +127,8 @@ public:
|
||||
inline void PushToTellQueue(ServerChannelMessage_Struct *scm) { tell_queue.push_back(scm); }
|
||||
void ProcessTellQueue();
|
||||
|
||||
void SetPendingDzInvite(ServerPacket* pack) { m_dz_invite.reset(pack->Copy()); };
|
||||
std::unique_ptr<ServerPacket> GetPendingDzInvite() { return std::move(m_dz_invite); }
|
||||
void SetPendingExpeditionInvite(ServerPacket* pack) { p_pending_expedition_invite.reset(pack->Copy()); };
|
||||
std::unique_ptr<ServerPacket> GetPendingExpeditionInvite() { return std::move(p_pending_expedition_invite); }
|
||||
|
||||
private:
|
||||
void ClearVars(bool iAll = false);
|
||||
@@ -176,7 +176,7 @@ private:
|
||||
// Tell Queue -- really a vector :D
|
||||
std::vector<ServerChannelMessage_Struct *> tell_queue;
|
||||
|
||||
std::unique_ptr<ServerPacket> m_dz_invite;
|
||||
std::unique_ptr<ServerPacket> p_pending_expedition_invite = nullptr;
|
||||
};
|
||||
|
||||
#endif /*CLIENTENTRY_H_*/
|
||||
|
||||
@@ -1717,13 +1717,13 @@ void ClientList::SendCharacterMessageID(ClientListEntry* character,
|
||||
return;
|
||||
}
|
||||
|
||||
SerializeBuffer argbuf;
|
||||
SerializeBuffer serialized_args;
|
||||
for (const auto& arg : args)
|
||||
{
|
||||
argbuf.WriteString(arg);
|
||||
serialized_args.WriteString(arg);
|
||||
}
|
||||
|
||||
uint32_t args_size = static_cast<uint32_t>(argbuf.size());
|
||||
uint32_t args_size = static_cast<uint32_t>(serialized_args.size());
|
||||
uint32_t pack_size = sizeof(CZClientMessageString_Struct) + args_size;
|
||||
auto pack = std::make_unique<ServerPacket>(ServerOP_CZClientMessageString, pack_size);
|
||||
auto buf = reinterpret_cast<CZClientMessageString_Struct*>(pack->pBuffer);
|
||||
@@ -1731,10 +1731,7 @@ void ClientList::SendCharacterMessageID(ClientListEntry* character,
|
||||
buf->chat_type = chat_type;
|
||||
strn0cpy(buf->client_name, character->name(), sizeof(buf->client_name));
|
||||
buf->args_size = args_size;
|
||||
if (argbuf.size() > 0)
|
||||
{
|
||||
memcpy(buf->args, argbuf.buffer(), argbuf.size());
|
||||
}
|
||||
memcpy(buf->args, serialized_args.buffer(), serialized_args.size());
|
||||
|
||||
character->Server()->SendPacket(pack.get());
|
||||
}
|
||||
|
||||
+5
-1
@@ -911,7 +911,11 @@ void ConsoleReloadWorld(
|
||||
)
|
||||
{
|
||||
connection->SendLine("Reloading World...");
|
||||
zoneserver_list.SendServerReload(ServerReload::Type::WorldRepop, nullptr);
|
||||
auto pack = new ServerPacket(ServerOP_ReloadWorld, sizeof(ReloadWorld_Struct));
|
||||
ReloadWorld_Struct *RW = (ReloadWorld_Struct *) pack->pBuffer;
|
||||
RW->global_repop = ReloadWorld::Repop;
|
||||
zoneserver_list.SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
}
|
||||
|
||||
auto debounce_reload = std::chrono::system_clock::now();
|
||||
|
||||
+128
-2
@@ -164,6 +164,132 @@ void DynamicZone::SendZonesLeaderChanged()
|
||||
zoneserver_list.SendPacket(pack.get());
|
||||
}
|
||||
|
||||
void DynamicZone::HandleZoneMessage(ServerPacket* pack)
|
||||
{
|
||||
switch (pack->opcode)
|
||||
{
|
||||
case ServerOP_DzCreated:
|
||||
{
|
||||
dynamic_zone_manager.CacheNewDynamicZone(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzSetCompass:
|
||||
case ServerOP_DzSetSafeReturn:
|
||||
case ServerOP_DzSetZoneIn:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzLocation_Struct*>(pack->pBuffer);
|
||||
auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id);
|
||||
if (dz)
|
||||
{
|
||||
if (pack->opcode == ServerOP_DzSetCompass)
|
||||
{
|
||||
dz->SetCompass(buf->zone_id, buf->x, buf->y, buf->z, false);
|
||||
}
|
||||
else if (pack->opcode == ServerOP_DzSetSafeReturn)
|
||||
{
|
||||
dz->SetSafeReturn(buf->zone_id, buf->x, buf->y, buf->z, buf->heading, false);
|
||||
}
|
||||
else if (pack->opcode == ServerOP_DzSetZoneIn)
|
||||
{
|
||||
dz->SetZoneInLocation(buf->x, buf->y, buf->z, buf->heading, false);
|
||||
}
|
||||
}
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzSetSwitchID:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzSwitchID_Struct*>(pack->pBuffer);
|
||||
auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id);
|
||||
if (dz)
|
||||
{
|
||||
dz->ProcessSetSwitchID(buf->dz_switch_id);
|
||||
}
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzAddRemoveMember:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzMember_Struct*>(pack->pBuffer);
|
||||
auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id);
|
||||
if (dz)
|
||||
{
|
||||
auto status = static_cast<DynamicZoneMemberStatus>(buf->character_status);
|
||||
dz->ProcessMemberAddRemove({ buf->character_id, buf->character_name, status }, buf->removed);
|
||||
}
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzSwapMembers:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzMemberSwap_Struct*>(pack->pBuffer);
|
||||
auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id);
|
||||
if (dz)
|
||||
{
|
||||
// we add first in world so new member can be chosen if leader is removed
|
||||
auto status = static_cast<DynamicZoneMemberStatus>(buf->add_character_status);
|
||||
dz->ProcessMemberAddRemove({ buf->add_character_id, buf->add_character_name, status }, false);
|
||||
dz->ProcessMemberAddRemove({ buf->remove_character_id, buf->remove_character_name }, true);
|
||||
}
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzRemoveAllMembers:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzID_Struct*>(pack->pBuffer);
|
||||
auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id);
|
||||
if (dz)
|
||||
{
|
||||
dz->ProcessRemoveAllMembers();
|
||||
}
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzSetSecondsRemaining:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzSetDuration_Struct*>(pack->pBuffer);
|
||||
auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id);
|
||||
if (dz)
|
||||
{
|
||||
dz->SetSecondsRemaining(buf->seconds);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzGetMemberStatuses:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzID_Struct*>(pack->pBuffer);
|
||||
auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id);
|
||||
if (dz)
|
||||
{
|
||||
dz->SendZoneMemberStatuses(buf->sender_zone_id, buf->sender_instance_id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzUpdateMemberStatus:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzMemberStatus_Struct*>(pack->pBuffer);
|
||||
auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id);
|
||||
if (dz)
|
||||
{
|
||||
auto status = static_cast<DynamicZoneMemberStatus>(buf->status);
|
||||
dz->ProcessMemberStatusChange(buf->character_id, status);
|
||||
}
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzMovePC:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzMovePC_Struct*>(pack->pBuffer);
|
||||
auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id);
|
||||
if (dz && dz->HasMember(buf->character_id))
|
||||
{
|
||||
zoneserver_list.SendPacket(buf->sender_zone_id, buf->sender_instance_id, pack);
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void DynamicZone::ProcessMemberAddRemove(const DynamicZoneMember& member, bool removed)
|
||||
{
|
||||
DynamicZoneBase::ProcessMemberAddRemove(member, removed);
|
||||
@@ -219,13 +345,13 @@ void DynamicZone::SendZoneMemberStatuses(uint16_t zone_id, uint16_t instance_id)
|
||||
|
||||
void DynamicZone::CacheMemberStatuses()
|
||||
{
|
||||
if (m_has_member_statuses || m_members.empty())
|
||||
if (m_has_member_statuses)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// called when a new dz is cached to fill member statuses
|
||||
std::string zone_name;
|
||||
std::string zone_name{};
|
||||
std::vector<ClientListEntry*> all_clients;
|
||||
all_clients.reserve(client_list.GetClientCount());
|
||||
client_list.GetClients(zone_name.c_str(), all_clients);
|
||||
|
||||
@@ -22,6 +22,7 @@ public:
|
||||
using DynamicZoneBase::DynamicZoneBase; // inherit base constructors
|
||||
|
||||
static DynamicZone* FindDynamicZoneByID(uint32_t dz_id);
|
||||
static void HandleZoneMessage(ServerPacket* pack);
|
||||
|
||||
void SetSecondsRemaining(uint32_t seconds_remaining) override;
|
||||
|
||||
@@ -32,7 +33,7 @@ public:
|
||||
protected:
|
||||
Database& GetDatabase() override;
|
||||
void ProcessMemberAddRemove(const DynamicZoneMember& member, bool removed) override;
|
||||
bool ProcessMemberStatusChange(uint32_t character_id, DynamicZoneMemberStatus status) override;
|
||||
bool ProcessMemberStatusChange(uint32_t member_id, DynamicZoneMemberStatus status) override;
|
||||
bool SendServerPacket(ServerPacket* packet) override;
|
||||
|
||||
private:
|
||||
|
||||
+39
-280
@@ -1,14 +1,12 @@
|
||||
#include "dynamic_zone_manager.h"
|
||||
#include "dynamic_zone.h"
|
||||
#include "cliententry.h"
|
||||
#include "clientlist.h"
|
||||
#include "worlddb.h"
|
||||
#include "zonelist.h"
|
||||
#include "zoneserver.h"
|
||||
#include "../common/rulesys.h"
|
||||
#include "../common/repositories/dynamic_zone_lockouts_repository.h"
|
||||
#include "../common/repositories/expeditions_repository.h"
|
||||
#include "../common/repositories/expedition_lockouts_repository.h"
|
||||
|
||||
extern ClientList client_list;
|
||||
extern ZSList zoneserver_list;
|
||||
|
||||
DynamicZoneManager dynamic_zone_manager;
|
||||
@@ -29,8 +27,6 @@ void DynamicZoneManager::PurgeExpiredDynamicZones()
|
||||
{
|
||||
LogDynamicZones("Purging [{}] dynamic zone(s)", dz_ids.size());
|
||||
|
||||
DynamicZoneLockoutsRepository::DeleteWhere(database,
|
||||
fmt::format("dynamic_zone_id IN ({})", fmt::join(dz_ids, ",")));
|
||||
DynamicZoneMembersRepository::DeleteWhere(database,
|
||||
fmt::format("dynamic_zone_id IN ({})", Strings::Join(dz_ids, ",")));
|
||||
DynamicZonesRepository::DeleteWhere(database,
|
||||
@@ -38,7 +34,8 @@ void DynamicZoneManager::PurgeExpiredDynamicZones()
|
||||
}
|
||||
}
|
||||
|
||||
DynamicZone* DynamicZoneManager::TryCreate(DynamicZone& dz_request, const std::vector<DynamicZoneMember>& members)
|
||||
DynamicZone* DynamicZoneManager::CreateNew(
|
||||
DynamicZone& dz_request, const std::vector<DynamicZoneMember>& members)
|
||||
{
|
||||
// this creates a new dz instance and saves it to both db and cache
|
||||
uint32_t dz_id = dz_request.Create();
|
||||
@@ -49,12 +46,15 @@ DynamicZone* DynamicZoneManager::TryCreate(DynamicZone& dz_request, const std::v
|
||||
}
|
||||
|
||||
auto dz = std::make_unique<DynamicZone>(dz_request);
|
||||
dz->SaveMembers(members);
|
||||
dz->CacheMemberStatuses();
|
||||
if (!members.empty())
|
||||
{
|
||||
dz->SaveMembers(members);
|
||||
dz->CacheMemberStatuses();
|
||||
}
|
||||
|
||||
LogDynamicZones("Created new dz [{}] for zone [{}]", dz_id, dz_request.GetZoneID());
|
||||
|
||||
auto pack = dz->CreateServerPacket(0, 0);
|
||||
auto pack = dz->CreateServerDzCreatePacket(0, 0);
|
||||
zoneserver_list.SendPacket(pack.get());
|
||||
|
||||
auto inserted = dynamic_zone_cache.emplace(dz_id, std::move(dz));
|
||||
@@ -63,17 +63,18 @@ DynamicZone* DynamicZoneManager::TryCreate(DynamicZone& dz_request, const std::v
|
||||
|
||||
void DynamicZoneManager::CacheNewDynamicZone(ServerPacket* pack)
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzCreate_Struct*>(pack->pBuffer);
|
||||
auto buf = reinterpret_cast<ServerDzCreateSerialized_Struct*>(pack->pBuffer);
|
||||
|
||||
auto new_dz = std::make_unique<DynamicZone>();
|
||||
new_dz->Unserialize({ buf->cereal_data, buf->cereal_size });
|
||||
new_dz->LoadSerializedDzPacket(buf->cereal_data, buf->cereal_size);
|
||||
new_dz->CacheMemberStatuses();
|
||||
|
||||
// reserialize with member statuses cached before forwarding (restore origin zone)
|
||||
auto repack = new_dz->CreateServerPacket(buf->origin_zone_id, buf->origin_instance_id);
|
||||
auto repack = new_dz->CreateServerDzCreatePacket(buf->origin_zone_id, buf->origin_instance_id);
|
||||
|
||||
dynamic_zone_cache.emplace(buf->dz_id, std::move(new_dz));
|
||||
LogDynamicZones("Cached new dynamic zone [{}]", buf->dz_id);
|
||||
uint32_t dz_id = new_dz->GetID();
|
||||
dynamic_zone_cache.emplace(dz_id, std::move(new_dz));
|
||||
LogDynamicZones("Cached new dynamic zone [{}]", dz_id);
|
||||
|
||||
zoneserver_list.SendPacket(repack.get());
|
||||
}
|
||||
@@ -82,19 +83,18 @@ void DynamicZoneManager::CacheAllFromDatabase()
|
||||
{
|
||||
BenchTimer bench;
|
||||
|
||||
auto dzs = DynamicZonesRepository::AllWithInstanceNotExpired(database);
|
||||
auto members = DynamicZoneMembersRepository::AllWithNames(database);
|
||||
auto lockouts = DynamicZoneLockoutsRepository::All(database);
|
||||
auto dynamic_zones = DynamicZonesRepository::AllWithInstanceNotExpired(database);
|
||||
auto dynamic_zone_members = DynamicZoneMembersRepository::GetAllWithNames(database);
|
||||
|
||||
dynamic_zone_cache.clear();
|
||||
dynamic_zone_cache.reserve(dzs.size());
|
||||
dynamic_zone_cache.reserve(dynamic_zones.size());
|
||||
|
||||
for (auto& entry : dzs)
|
||||
for (auto& entry : dynamic_zones)
|
||||
{
|
||||
uint32_t dz_id = entry.id;
|
||||
auto dz = std::make_unique<DynamicZone>(std::move(entry));
|
||||
|
||||
for (auto& member : members)
|
||||
for (auto& member : dynamic_zone_members)
|
||||
{
|
||||
if (member.dynamic_zone_id == dz_id)
|
||||
{
|
||||
@@ -102,14 +102,6 @@ void DynamicZoneManager::CacheAllFromDatabase()
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& lockout : lockouts)
|
||||
{
|
||||
if (lockout.dynamic_zone_id == dz->GetID())
|
||||
{
|
||||
dz->m_lockouts.emplace_back(dz->GetName(), std::move(lockout));
|
||||
}
|
||||
}
|
||||
|
||||
// note leader status won't be updated here until leader is set by owning system (expeditions)
|
||||
dz->CacheMemberStatuses();
|
||||
|
||||
@@ -150,10 +142,24 @@ void DynamicZoneManager::Process()
|
||||
dynamic_zone_cache.erase(dz_id);
|
||||
}
|
||||
|
||||
DynamicZoneLockoutsRepository::DeleteWhere(database,
|
||||
fmt::format("dynamic_zone_id IN ({})", fmt::join(dynamic_zone_ids, ",")));
|
||||
DynamicZoneMembersRepository::DeleteWhere(database,
|
||||
fmt::format("dynamic_zone_id IN ({})", fmt::join(dynamic_zone_ids, ",")));
|
||||
// need to look up expedition ids until lockouts are moved to dynamic zones
|
||||
std::vector<uint32_t> expedition_ids;
|
||||
auto expeditions = ExpeditionsRepository::GetWhere(database,
|
||||
fmt::format("dynamic_zone_id IN ({})", Strings::Join(dynamic_zone_ids, ",")));
|
||||
|
||||
if (!expeditions.empty())
|
||||
{
|
||||
for (const auto& expedition : expeditions)
|
||||
{
|
||||
expedition_ids.emplace_back(expedition.id);
|
||||
}
|
||||
ExpeditionLockoutsRepository::DeleteWhere(database,
|
||||
fmt::format("expedition_id IN ({})", Strings::Join(expedition_ids, ",")));
|
||||
}
|
||||
|
||||
ExpeditionsRepository::DeleteWhere(database,
|
||||
fmt::format("dynamic_zone_id IN ({})", Strings::Join(dynamic_zone_ids, ",")));
|
||||
DynamicZoneMembersRepository::RemoveAllMembers(database, dynamic_zone_ids);
|
||||
DynamicZonesRepository::DeleteWhere(database,
|
||||
fmt::format("id IN ({})", Strings::Join(dynamic_zone_ids, ",")));
|
||||
}
|
||||
@@ -168,250 +174,3 @@ void DynamicZoneManager::LoadTemplates()
|
||||
m_dz_templates[dz_template.id] = dz_template;
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicZoneManager::HandleZoneMessage(ServerPacket* pack)
|
||||
{
|
||||
switch (pack->opcode)
|
||||
{
|
||||
case ServerOP_DzCreated:
|
||||
{
|
||||
CacheNewDynamicZone(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzAddPlayer:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzCommand_Struct*>(pack->pBuffer);
|
||||
|
||||
ClientListEntry* cle = client_list.FindCharacter(buf->target_name);
|
||||
if (cle && cle->Server())
|
||||
{
|
||||
// continue in the add target's zone
|
||||
buf->is_char_online = true;
|
||||
cle->Server()->SendPacket(pack);
|
||||
}
|
||||
else
|
||||
{
|
||||
// add target not online, return to inviter
|
||||
ClientListEntry* inviter_cle = client_list.FindCharacter(buf->requester_name);
|
||||
if (inviter_cle && inviter_cle->Server())
|
||||
{
|
||||
inviter_cle->Server()->SendPacket(pack);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzSaveInvite:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzCommand_Struct*>(pack->pBuffer);
|
||||
if (ClientListEntry* cle = client_list.FindCharacter(buf->target_name))
|
||||
{
|
||||
// store packet on cle and re-send it when client requests it
|
||||
buf->is_char_online = true;
|
||||
pack->opcode = ServerOP_DzAddPlayer;
|
||||
cle->SetPendingDzInvite(pack);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzRequestInvite:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerCharacterID_Struct*>(pack->pBuffer);
|
||||
if (ClientListEntry* cle = client_list.FindCLEByCharacterID(buf->char_id))
|
||||
{
|
||||
auto invite_pack = cle->GetPendingDzInvite();
|
||||
if (invite_pack && cle->Server())
|
||||
{
|
||||
cle->Server()->SendPacket(invite_pack.get());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzMakeLeader:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzCommandMakeLeader_Struct*>(pack->pBuffer);
|
||||
|
||||
// notify requester (old leader) and new leader of the result
|
||||
ZoneServer* new_leader_zs = nullptr;
|
||||
ClientListEntry* leader_cle = client_list.FindCharacter(buf->new_leader_name);
|
||||
if (leader_cle && leader_cle->Server())
|
||||
{
|
||||
auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id);
|
||||
if (dz && dz->GetLeaderID() == buf->requester_id)
|
||||
{
|
||||
buf->is_success = dz->SetNewLeader(leader_cle->CharID());
|
||||
}
|
||||
|
||||
buf->is_online = true;
|
||||
new_leader_zs = leader_cle->Server();
|
||||
new_leader_zs->SendPacket(pack);
|
||||
}
|
||||
|
||||
// if old and new leader are in the same zone only send one message
|
||||
ClientListEntry* requester_cle = client_list.FindCLEByCharacterID(buf->requester_id);
|
||||
if (requester_cle && requester_cle->Server() && requester_cle->Server() != new_leader_zs)
|
||||
{
|
||||
requester_cle->Server()->SendPacket(pack);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzSetCompass:
|
||||
case ServerOP_DzSetSafeReturn:
|
||||
case ServerOP_DzSetZoneIn:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzLocation_Struct*>(pack->pBuffer);
|
||||
if (auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id))
|
||||
{
|
||||
if (pack->opcode == ServerOP_DzSetCompass)
|
||||
{
|
||||
dz->SetCompass(buf->zone_id, buf->x, buf->y, buf->z, false);
|
||||
}
|
||||
else if (pack->opcode == ServerOP_DzSetSafeReturn)
|
||||
{
|
||||
dz->SetSafeReturn(buf->zone_id, buf->x, buf->y, buf->z, buf->heading, false);
|
||||
}
|
||||
else if (pack->opcode == ServerOP_DzSetZoneIn)
|
||||
{
|
||||
dz->SetZoneInLocation(buf->x, buf->y, buf->z, buf->heading, false);
|
||||
}
|
||||
}
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzSetSwitchID:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzSwitchID_Struct*>(pack->pBuffer);
|
||||
if (auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id))
|
||||
{
|
||||
dz->ProcessSetSwitchID(buf->dz_switch_id);
|
||||
}
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzAddRemoveMember:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzMember_Struct*>(pack->pBuffer);
|
||||
if (auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id))
|
||||
{
|
||||
auto status = static_cast<DynamicZoneMemberStatus>(buf->character_status);
|
||||
dz->ProcessMemberAddRemove({ buf->character_id, buf->character_name, status }, buf->removed);
|
||||
}
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzSwapMembers:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzMemberSwap_Struct*>(pack->pBuffer);
|
||||
if (auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id))
|
||||
{
|
||||
// we add first in world so new member can be chosen if leader is removed
|
||||
auto status = static_cast<DynamicZoneMemberStatus>(buf->add_character_status);
|
||||
dz->ProcessMemberAddRemove({ buf->add_character_id, buf->add_character_name, status }, false);
|
||||
dz->ProcessMemberAddRemove({ buf->remove_character_id, buf->remove_character_name }, true);
|
||||
}
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzRemoveAllMembers:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzID_Struct*>(pack->pBuffer);
|
||||
if (auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id))
|
||||
{
|
||||
dz->ProcessRemoveAllMembers();
|
||||
}
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzSetSecondsRemaining:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzSetDuration_Struct*>(pack->pBuffer);
|
||||
if (auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id))
|
||||
{
|
||||
dz->SetSecondsRemaining(buf->seconds);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzGetMemberStatuses:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzID_Struct*>(pack->pBuffer);
|
||||
if (auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id))
|
||||
{
|
||||
dz->SendZoneMemberStatuses(buf->sender_zone_id, buf->sender_instance_id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzUpdateMemberStatus:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzMemberStatus_Struct*>(pack->pBuffer);
|
||||
if (auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id))
|
||||
{
|
||||
auto status = static_cast<DynamicZoneMemberStatus>(buf->status);
|
||||
dz->ProcessMemberStatusChange(buf->character_id, status);
|
||||
}
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzMovePC:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzMovePC_Struct*>(pack->pBuffer);
|
||||
auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id);
|
||||
if (dz && dz->HasMember(buf->character_id))
|
||||
{
|
||||
zoneserver_list.SendPacket(buf->sender_zone_id, buf->sender_instance_id, pack);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzLock:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzLock_Struct*>(pack->pBuffer);
|
||||
if (auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id))
|
||||
{
|
||||
dz->SetLocked(buf->lock);
|
||||
}
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzReplayOnJoin:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzBool_Struct*>(pack->pBuffer);
|
||||
if (auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id))
|
||||
{
|
||||
dz->SetReplayOnJoin(buf->enabled);
|
||||
}
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzLockout:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzLockout_Struct*>(pack->pBuffer);
|
||||
if (auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id))
|
||||
{
|
||||
DzLockout lockout{ dz->GetUUID(), dz->GetName(), buf->event_name, buf->expire_time, buf->duration };
|
||||
dz->HandleLockoutUpdate(lockout, buf->remove, buf->members_only);
|
||||
}
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzLockoutDuration:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzLockout_Struct*>(pack->pBuffer);
|
||||
if (auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id))
|
||||
{
|
||||
DzLockout lockout{ dz->GetUUID(), dz->GetName(), buf->event_name, buf->expire_time, buf->duration };
|
||||
dz->HandleLockoutDuration(lockout, buf->seconds, buf->members_only, false);
|
||||
}
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzCharacterLockout:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzCharacterLockout_Struct*>(pack->pBuffer);
|
||||
auto cle = client_list.FindCLEByCharacterID(buf->char_id);
|
||||
if (cle && cle->Server())
|
||||
{
|
||||
cle->Server()->SendPacket(pack);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -20,8 +20,7 @@ public:
|
||||
|
||||
void CacheAllFromDatabase();
|
||||
void CacheNewDynamicZone(ServerPacket* pack);
|
||||
DynamicZone* TryCreate(DynamicZone& dz_request, const std::vector<DynamicZoneMember>& members);
|
||||
void HandleZoneMessage(ServerPacket* pack);
|
||||
DynamicZone* CreateNew(DynamicZone& dz_request, const std::vector<DynamicZoneMember>& members);
|
||||
void LoadTemplates();
|
||||
void Process();
|
||||
void PurgeExpiredDynamicZones();
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "zoneserver.h"
|
||||
#include "zonelist.h"
|
||||
#include "../common/database_schema.h"
|
||||
#include "../common/server_reload_types.h"
|
||||
#include "../common/zone_store.h"
|
||||
#include "worlddb.h"
|
||||
#include "wguild_mgr.h"
|
||||
@@ -114,47 +113,136 @@ void callGetClientList(Json::Value &response)
|
||||
client_list.GetClientList(response);
|
||||
}
|
||||
|
||||
|
||||
struct Reload {
|
||||
std::string command{};
|
||||
uint16 opcode;
|
||||
std::string desc{};
|
||||
};
|
||||
|
||||
std::vector<Reload> reload_types = {
|
||||
Reload{.command = "aa", .opcode = ServerOP_ReloadAAData, .desc = "Alternate Advancement"},
|
||||
Reload{.command = "alternate_currencies", .opcode = ServerOP_ReloadAlternateCurrencies, .desc = "Alternate Currencies"},
|
||||
Reload{.command = "base_data", .opcode = ServerOP_ReloadBaseData, .desc = "Base Data"},
|
||||
Reload{.command = "blocked_spells", .opcode = ServerOP_ReloadBlockedSpells, .desc = "Blocked Spells"},
|
||||
Reload{.command = "commands", .opcode = ServerOP_ReloadCommands, .desc = "Commands"},
|
||||
Reload{.command = "content_flags", .opcode = ServerOP_ReloadContentFlags, .desc = "Content Flags"},
|
||||
Reload{.command = "data_buckets_cache", .opcode = ServerOP_ReloadDataBucketsCache, .desc = "Data Buckets Cache"},
|
||||
Reload{.command = "doors", .opcode = ServerOP_ReloadDoors, .desc = "Doors"},
|
||||
Reload{.command = "dztemplates", .opcode = ServerOP_ReloadDzTemplates, .desc = "Dynamic Zone Templates"},
|
||||
Reload{.command = "ground_spawns", .opcode = ServerOP_ReloadGroundSpawns, .desc = "Ground Spawns"},
|
||||
Reload{.command = "level_mods", .opcode = ServerOP_ReloadLevelEXPMods, .desc = "Level Mods"},
|
||||
Reload{.command = "logs", .opcode = ServerOP_ReloadLogs, .desc = "Log Settings"},
|
||||
Reload{.command = "loot", .opcode = ServerOP_ReloadLoot, .desc = "Loot"},
|
||||
Reload{.command = "merchants", .opcode = ServerOP_ReloadMerchants, .desc = "Merchants"},
|
||||
Reload{.command = "npc_emotes", .opcode = ServerOP_ReloadNPCEmotes, .desc = "NPC Emotes"},
|
||||
Reload{.command = "npc_spells", .opcode = ServerOP_ReloadNPCSpells, .desc = "NPC Spells"},
|
||||
Reload{.command = "objects", .opcode = ServerOP_ReloadObjects, .desc = "Objects"},
|
||||
Reload{.command = "opcodes", .opcode = ServerOP_ReloadOpcodes, .desc = "Opcodes"},
|
||||
Reload{.command = "perl_export", .opcode = ServerOP_ReloadPerlExportSettings, .desc = "Perl Event Export Settings"},
|
||||
Reload{.command = "rules", .opcode = ServerOP_ReloadRules, .desc = "Rules"},
|
||||
Reload{.command = "skill_caps", .opcode = ServerOP_ReloadSkillCaps, .desc = "Skill Caps"},
|
||||
Reload{.command = "static", .opcode = ServerOP_ReloadStaticZoneData, .desc = "Static Zone Data"},
|
||||
Reload{.command = "tasks", .opcode = ServerOP_ReloadTasks, .desc = "Tasks"},
|
||||
Reload{.command = "titles", .opcode = ServerOP_ReloadTitles, .desc = "Titles"},
|
||||
Reload{.command = "traps", .opcode = ServerOP_ReloadTraps, .desc = "Traps"},
|
||||
Reload{.command = "variables", .opcode = ServerOP_ReloadVariables, .desc = "Variables"},
|
||||
Reload{.command = "veteran_rewards", .opcode = ServerOP_ReloadVeteranRewards, .desc = "Veteran Rewards"},
|
||||
Reload{.command = "world", .opcode = ServerOP_ReloadWorld, .desc = "World"},
|
||||
Reload{.command = "zone_points", .opcode = ServerOP_ReloadZonePoints, .desc = "Zone Points"},
|
||||
};
|
||||
|
||||
void getReloadTypes(Json::Value &response)
|
||||
{
|
||||
for (auto &t: ServerReload::GetTypes()) {
|
||||
for (auto &c: reload_types) {
|
||||
Json::Value v;
|
||||
|
||||
v["command"] = std::to_string(t);
|
||||
v["description"] = ServerReload::GetName(t);
|
||||
v["command"] = c.command;
|
||||
v["opcode"] = c.opcode;
|
||||
v["description"] = c.desc;
|
||||
response.append(v);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EQEmuApiWorldDataService::reload(Json::Value &r, const std::vector<std::string> &args)
|
||||
{
|
||||
std::vector<std::string> commands{};
|
||||
commands.reserve(ServerReload::GetTypes().size());
|
||||
for (auto &c: ServerReload::GetTypes()) {
|
||||
commands.emplace_back(std::to_string(c));
|
||||
commands.reserve(reload_types.size());
|
||||
for (auto &c: reload_types) {
|
||||
commands.emplace_back(c.command);
|
||||
}
|
||||
|
||||
std::string command = !args[1].empty() ? args[1] : "";
|
||||
if (command.empty()) {
|
||||
message(r, fmt::format("Need to provide a type ID to reload. Example(s) [{}]", Strings::Implode("|", commands)));
|
||||
message(r, fmt::format("Need to provide a type to reload. Example(s) [{}]", Strings::Implode("|", commands)));
|
||||
return;
|
||||
}
|
||||
|
||||
ServerPacket *pack = nullptr;
|
||||
|
||||
bool found_command = false;
|
||||
bool found_command = false;
|
||||
for (auto &c: reload_types) {
|
||||
if (command == c.command) {
|
||||
if (c.command == "world") {
|
||||
uint8 global_repop = ReloadWorld::NoRepop;
|
||||
|
||||
for (auto &t: ServerReload::GetTypes()) {
|
||||
if (std::to_string(t) == command || Strings::ToLower(ServerReload::GetName(t)) == command) {
|
||||
message(r, fmt::format("Reloading [{}] globally", ServerReload::GetName(t)));
|
||||
zoneserver_list.SendServerReload(t, nullptr);
|
||||
if (Strings::IsNumber(args[2])) {
|
||||
global_repop = static_cast<uint8>(Strings::ToUnsignedInt(args[2]));
|
||||
|
||||
if (global_repop > ReloadWorld::ForceRepop) {
|
||||
global_repop = ReloadWorld::ForceRepop;
|
||||
}
|
||||
}
|
||||
|
||||
message(
|
||||
r,
|
||||
fmt::format(
|
||||
"Attempting to reload Quests {}worldwide.",
|
||||
(
|
||||
global_repop ?
|
||||
(
|
||||
global_repop == ReloadWorld::Repop ?
|
||||
"and repop NPCs " :
|
||||
"and forcefully repop NPCs "
|
||||
) :
|
||||
""
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
pack = new ServerPacket(ServerOP_ReloadWorld, sizeof(ReloadWorld_Struct));
|
||||
auto RW = (ReloadWorld_Struct *) pack->pBuffer;
|
||||
RW->global_repop = global_repop;
|
||||
}
|
||||
else {
|
||||
pack = new ServerPacket(c.opcode, 0);
|
||||
message(r, fmt::format("Reloading [{}] globally", c.desc));
|
||||
|
||||
if (c.opcode == ServerOP_ReloadLogs) {
|
||||
LogSys.LoadLogDatabaseSettings();
|
||||
QSLink.SendPacket(pack);
|
||||
UCSLink.SendPacket(pack);
|
||||
}
|
||||
else if (c.opcode == ServerOP_ReloadRules) {
|
||||
RuleManager::Instance()->LoadRules(&database, RuleManager::Instance()->GetActiveRuleset(), true);
|
||||
}
|
||||
}
|
||||
|
||||
found_command = true;
|
||||
}
|
||||
found_command = true;
|
||||
}
|
||||
|
||||
if (!found_command) {
|
||||
message(r, fmt::format("Need to provide a type to reload. Example(s) [{}]", Strings::Implode("|", commands)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (pack) {
|
||||
zoneserver_list.SendPacket(pack);
|
||||
}
|
||||
|
||||
safe_delete(pack);
|
||||
}
|
||||
|
||||
void EQEmuApiWorldDataService::message(Json::Value &r, const std::string &message)
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* EQEmulator: Everquest Server Emulator
|
||||
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
* are required to give you total support for your newly bought product;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "expedition_database.h"
|
||||
#include "worlddb.h"
|
||||
#include "../common/repositories/expeditions_repository.h"
|
||||
#include "../common/repositories/expedition_lockouts_repository.h"
|
||||
#include "../common/repositories/dynamic_zone_members_repository.h"
|
||||
|
||||
void ExpeditionDatabase::PurgeExpiredExpeditions()
|
||||
{
|
||||
std::string query = SQL(
|
||||
SELECT
|
||||
expeditions.id,
|
||||
expeditions.dynamic_zone_id
|
||||
FROM expeditions
|
||||
LEFT JOIN dynamic_zones ON expeditions.dynamic_zone_id = dynamic_zones.id
|
||||
LEFT JOIN instance_list ON dynamic_zones.instance_id = instance_list.id
|
||||
LEFT JOIN
|
||||
(
|
||||
SELECT dynamic_zone_id, COUNT(*) member_count
|
||||
FROM dynamic_zone_members
|
||||
GROUP BY dynamic_zone_id
|
||||
) dynamic_zone_members
|
||||
ON dynamic_zone_members.dynamic_zone_id = expeditions.dynamic_zone_id
|
||||
WHERE
|
||||
instance_list.id IS NULL
|
||||
OR dynamic_zone_members.member_count IS NULL
|
||||
OR dynamic_zone_members.member_count = 0
|
||||
OR (instance_list.start_time + instance_list.duration) <= UNIX_TIMESTAMP();
|
||||
);
|
||||
|
||||
auto results = database.QueryDatabase(query);
|
||||
if (results.Success())
|
||||
{
|
||||
std::vector<std::string> expedition_ids;
|
||||
std::vector<uint32_t> dynamic_zone_ids;
|
||||
for (auto row = results.begin(); row != results.end(); ++row)
|
||||
{
|
||||
expedition_ids.emplace_back(row[0]);
|
||||
dynamic_zone_ids.emplace_back(static_cast<uint32_t>(strtoul(row[1], nullptr, 10)));
|
||||
}
|
||||
|
||||
if (!expedition_ids.empty())
|
||||
{
|
||||
ExpeditionsRepository::DeleteWhere(database, fmt::format("id IN ({})", fmt::join(expedition_ids, ",")));
|
||||
ExpeditionLockoutsRepository::DeleteWhere(database, fmt::format("expedition_id IN ({})", fmt::join(expedition_ids, ",")));
|
||||
DynamicZoneMembersRepository::RemoveAllMembers(database, dynamic_zone_ids);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExpeditionDatabase::PurgeExpiredCharacterLockouts()
|
||||
{
|
||||
std::string query = SQL(
|
||||
DELETE FROM character_expedition_lockouts
|
||||
WHERE expire_time <= NOW();
|
||||
);
|
||||
|
||||
database.QueryDatabase(query);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* EQEmulator: Everquest Server Emulator
|
||||
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
* are required to give you total support for your newly bought product;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WORLD_EXPEDITION_DATABASE_H
|
||||
#define WORLD_EXPEDITION_DATABASE_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
class Expedition;
|
||||
|
||||
namespace ExpeditionDatabase
|
||||
{
|
||||
void PurgeExpiredExpeditions();
|
||||
void PurgeExpiredCharacterLockouts();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,151 @@
|
||||
/**
|
||||
* EQEmulator: Everquest Server Emulator
|
||||
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
* are required to give you total support for your newly bought product;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "dynamic_zone.h"
|
||||
#include "expedition_message.h"
|
||||
#include "cliententry.h"
|
||||
#include "clientlist.h"
|
||||
#include "zonelist.h"
|
||||
#include "zoneserver.h"
|
||||
#include "../common/servertalk.h"
|
||||
#include <algorithm>
|
||||
|
||||
extern ClientList client_list;
|
||||
extern ZSList zoneserver_list;
|
||||
|
||||
void ExpeditionMessage::HandleZoneMessage(ServerPacket* pack)
|
||||
{
|
||||
switch (pack->opcode)
|
||||
{
|
||||
case ServerOP_ExpeditionCreate:
|
||||
{
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_ExpeditionDzAddPlayer:
|
||||
{
|
||||
ExpeditionMessage::AddPlayer(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_ExpeditionDzMakeLeader:
|
||||
{
|
||||
ExpeditionMessage::MakeLeader(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_ExpeditionCharacterLockout:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerExpeditionCharacterLockout_Struct*>(pack->pBuffer);
|
||||
auto cle = client_list.FindCLEByCharacterID(buf->character_id);
|
||||
if (cle && cle->Server())
|
||||
{
|
||||
cle->Server()->SendPacket(pack);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_ExpeditionSaveInvite:
|
||||
{
|
||||
ExpeditionMessage::SaveInvite(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_ExpeditionRequestInvite:
|
||||
{
|
||||
ExpeditionMessage::RequestInvite(pack);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExpeditionMessage::AddPlayer(ServerPacket* pack)
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzCommand_Struct*>(pack->pBuffer);
|
||||
|
||||
ClientListEntry* invited_cle = client_list.FindCharacter(buf->target_name);
|
||||
if (invited_cle && invited_cle->Server())
|
||||
{
|
||||
// continue in the add target's zone
|
||||
buf->is_char_online = true;
|
||||
invited_cle->Server()->SendPacket(pack);
|
||||
}
|
||||
else
|
||||
{
|
||||
// add target not online, return to inviter
|
||||
ClientListEntry* inviter_cle = client_list.FindCharacter(buf->requester_name);
|
||||
if (inviter_cle && inviter_cle->Server())
|
||||
{
|
||||
inviter_cle->Server()->SendPacket(pack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExpeditionMessage::MakeLeader(ServerPacket* pack)
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzCommandMakeLeader_Struct*>(pack->pBuffer);
|
||||
|
||||
// notify requester (old leader) and new leader of the result
|
||||
ZoneServer* new_leader_zs = nullptr;
|
||||
ClientListEntry* new_leader_cle = client_list.FindCharacter(buf->new_leader_name);
|
||||
if (new_leader_cle && new_leader_cle->Server())
|
||||
{
|
||||
auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id);
|
||||
if (dz && dz->GetLeaderID() == buf->requester_id)
|
||||
{
|
||||
buf->is_success = dz->SetNewLeader(new_leader_cle->CharID());
|
||||
}
|
||||
|
||||
buf->is_online = true;
|
||||
new_leader_zs = new_leader_cle->Server();
|
||||
new_leader_zs->SendPacket(pack);
|
||||
}
|
||||
|
||||
// if old and new leader are in the same zone only send one message
|
||||
ClientListEntry* requester_cle = client_list.FindCLEByCharacterID(buf->requester_id);
|
||||
if (requester_cle && requester_cle->Server() && requester_cle->Server() != new_leader_zs)
|
||||
{
|
||||
requester_cle->Server()->SendPacket(pack);
|
||||
}
|
||||
}
|
||||
|
||||
void ExpeditionMessage::SaveInvite(ServerPacket* pack)
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerDzCommand_Struct*>(pack->pBuffer);
|
||||
|
||||
ClientListEntry* invited_cle = client_list.FindCharacter(buf->target_name);
|
||||
if (invited_cle)
|
||||
{
|
||||
// store packet on cle and re-send it when client requests it
|
||||
buf->is_char_online = true;
|
||||
pack->opcode = ServerOP_ExpeditionDzAddPlayer;
|
||||
invited_cle->SetPendingExpeditionInvite(pack);
|
||||
}
|
||||
}
|
||||
|
||||
void ExpeditionMessage::RequestInvite(ServerPacket* pack)
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerExpeditionCharacterID_Struct*>(pack->pBuffer);
|
||||
ClientListEntry* cle = client_list.FindCLEByCharacterID(buf->character_id);
|
||||
if (cle)
|
||||
{
|
||||
auto invite_pack = cle->GetPendingExpeditionInvite();
|
||||
if (invite_pack && cle->Server())
|
||||
{
|
||||
cle->Server()->SendPacket(invite_pack.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* EQEmulator: Everquest Server Emulator
|
||||
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
* are required to give you total support for your newly bought product;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WORLD_EXPEDITION_MESSAGE_H
|
||||
#define WORLD_EXPEDITION_MESSAGE_H
|
||||
|
||||
class ServerPacket;
|
||||
|
||||
namespace ExpeditionMessage
|
||||
{
|
||||
void AddPlayer(ServerPacket* pack);
|
||||
void HandleZoneMessage(ServerPacket* pack);
|
||||
void MakeLeader(ServerPacket* pack);
|
||||
void RequestInvite(ServerPacket* pack);
|
||||
void SaveInvite(ServerPacket* pack);
|
||||
};
|
||||
|
||||
#endif
|
||||
+2
-2
@@ -76,10 +76,10 @@
|
||||
#include "web_interface.h"
|
||||
#include "console.h"
|
||||
#include "dynamic_zone_manager.h"
|
||||
#include "expedition_database.h"
|
||||
|
||||
#include "world_server_cli.h"
|
||||
#include "../common/content/world_content_service.h"
|
||||
#include "../common/repositories/character_expedition_lockouts_repository.h"
|
||||
#include "../common/repositories/character_task_timers_repository.h"
|
||||
#include "../common/zone_store.h"
|
||||
#include "world_event_scheduler.h"
|
||||
@@ -449,7 +449,7 @@ int main(int argc, char **argv)
|
||||
if (PurgeInstanceTimer.Check()) {
|
||||
database.PurgeExpiredInstances();
|
||||
database.PurgeAllDeletedDataBuckets();
|
||||
CharacterExpeditionLockoutsRepository::DeleteWhere(database, "expire_time <= NOW()");
|
||||
ExpeditionDatabase::PurgeExpiredCharacterLockouts();
|
||||
CharacterTaskTimersRepository::DeleteWhere(database, "expire_time <= NOW()");
|
||||
}
|
||||
|
||||
|
||||
@@ -1172,7 +1172,7 @@ void SharedTaskManager::CreateDynamicZone(SharedTask *shared_task, DynamicZone &
|
||||
}
|
||||
}
|
||||
|
||||
auto new_dz = dynamic_zone_manager.TryCreate(dz_request, dz_members);
|
||||
auto new_dz = dynamic_zone_manager.CreateNew(dz_request, dz_members);
|
||||
if (new_dz) {
|
||||
auto shared_task_dz = SharedTaskDynamicZonesRepository::NewEntity();
|
||||
shared_task_dz.shared_task_id = shared_task->GetDbSharedTask().id;
|
||||
|
||||
@@ -283,7 +283,7 @@ void SharedTaskWorldMessaging::HandleZoneMessage(ServerPacket *pack)
|
||||
auto t = shared_task_manager.FindSharedTaskByTaskIdAndCharacterId(buf->task_id, buf->source_character_id);
|
||||
if (t) {
|
||||
DynamicZone dz;
|
||||
dz.Unserialize({ buf->cereal_data, buf->cereal_size });
|
||||
dz.LoadSerializedDzPacket(buf->cereal_data, buf->cereal_size);
|
||||
|
||||
shared_task_manager.CreateDynamicZone(t, dz);
|
||||
}
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
#include "../common/http/uri.h"
|
||||
#include "../common/net/console_server.h"
|
||||
#include "../common/net/servertalk_server.h"
|
||||
#include "../common/repositories/character_expedition_lockouts_repository.h"
|
||||
#include "../common/repositories/character_task_timers_repository.h"
|
||||
#include "../common/rulesys.h"
|
||||
#include "../common/strings.h"
|
||||
#include "adventure_manager.h"
|
||||
#include "dynamic_zone_manager.h"
|
||||
#include "expedition_database.h"
|
||||
#include "login_server_list.h"
|
||||
#include "shared_task_manager.h"
|
||||
#include "ucs.h"
|
||||
@@ -367,8 +367,9 @@ bool WorldBoot::DatabaseLoadRoutines(int argc, char **argv)
|
||||
LogInfo("Purging expired dynamic zones and members");
|
||||
dynamic_zone_manager.PurgeExpiredDynamicZones();
|
||||
|
||||
LogInfo("Purging expired character expedition lockouts");
|
||||
CharacterExpeditionLockoutsRepository::DeleteWhere(database, "expire_time <= NOW()");
|
||||
LogInfo("Purging expired expeditions");
|
||||
ExpeditionDatabase::PurgeExpiredExpeditions();
|
||||
ExpeditionDatabase::PurgeExpiredCharacterLockouts();
|
||||
|
||||
LogInfo("Purging expired character task timers");
|
||||
CharacterTaskTimersRepository::DeleteWhere(database, "expire_time <= NOW()");
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <string>
|
||||
#include "../common/types.h"
|
||||
#include "../common/discord/discord.h"
|
||||
#include "ucs.h"
|
||||
|
||||
extern UCSConnection UCSLink;
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include "../common/servertalk.h"
|
||||
#include <ctime>
|
||||
#include "../common/rulesys.h"
|
||||
#include "../common/server_reload_types.h"
|
||||
|
||||
void WorldEventScheduler::Process(ZSList *zs_list)
|
||||
{
|
||||
@@ -56,7 +55,11 @@ void WorldEventScheduler::Process(ZSList *zs_list)
|
||||
if (e.event_type == ServerEvents::EVENT_TYPE_RELOAD_WORLD) {
|
||||
LogScheduler("Sending reload world event [{}]", e.event_data.c_str());
|
||||
|
||||
zs_list->SendServerReload(ServerReload::Type::WorldRepop, nullptr);
|
||||
auto pack = new ServerPacket(ServerOP_ReloadWorld, sizeof(ReloadWorld_Struct));
|
||||
auto *reload_world = (ReloadWorld_Struct *) pack->pBuffer;
|
||||
reload_world->global_repop = ReloadWorld::Repop;
|
||||
zs_list->SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,19 +28,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "../common/event_sub.h"
|
||||
#include "web_interface.h"
|
||||
#include "../common/zone_store.h"
|
||||
#include "../common/events/player_event_logs.h"
|
||||
#include "../common/patches/patches.h"
|
||||
#include "../common/skill_caps.h"
|
||||
#include "../common/content/world_content_service.h"
|
||||
#include "world_boot.h"
|
||||
#include "shared_task_manager.h"
|
||||
#include "dynamic_zone_manager.h"
|
||||
#include "ucs.h"
|
||||
|
||||
extern uint32 numzones;
|
||||
extern EQ::Random emu_random;
|
||||
extern WebInterfaceList web_interface;
|
||||
extern SharedTaskManager shared_task_manager;
|
||||
volatile bool UCSServerAvailable_ = false;
|
||||
void CatchSignal(int sig_num);
|
||||
|
||||
@@ -870,76 +861,3 @@ bool ZSList::SendPacketToBootedZones(ServerPacket* pack)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ZSList::SendServerReload(ServerReload::Type type, uchar *packet)
|
||||
{
|
||||
static auto pack = ServerPacket(ServerOP_ServerReloadRequest, sizeof(ServerReload::Request));
|
||||
auto r = (ServerReload::Request *) pack.pBuffer;
|
||||
|
||||
// Copy the packet data if it exists
|
||||
if (packet) {
|
||||
memcpy(pack.pBuffer, packet, sizeof(ServerReload::Request));
|
||||
}
|
||||
|
||||
r->type = type;
|
||||
r->requires_zone_booted = true;
|
||||
|
||||
LogInfo("Sending reload to all zones for type [{}]", ServerReload::GetName(type));
|
||||
|
||||
static const std::unordered_set<ServerReload::Type> no_zone_boot_required = {
|
||||
ServerReload::Type::Opcodes,
|
||||
ServerReload::Type::Rules,
|
||||
ServerReload::Type::ContentFlags,
|
||||
ServerReload::Type::Logs,
|
||||
ServerReload::Type::Commands,
|
||||
ServerReload::Type::PerlExportSettings,
|
||||
ServerReload::Type::DataBucketsCache,
|
||||
ServerReload::Type::WorldRepop
|
||||
};
|
||||
|
||||
// Set requires_zone_booted flag before executing reload logic
|
||||
if (no_zone_boot_required.contains(type)) {
|
||||
r->requires_zone_booted = false;
|
||||
}
|
||||
|
||||
// reload at the world level
|
||||
if (type == ServerReload::Type::Opcodes) {
|
||||
ReloadAllPatches();
|
||||
} else if (type == ServerReload::Type::Rules) {
|
||||
RuleManager::Instance()->LoadRules(&database, RuleManager::Instance()->GetActiveRuleset(), true);
|
||||
} else if (type == ServerReload::Type::SkillCaps) {
|
||||
skill_caps.ReloadSkillCaps();
|
||||
} else if (type == ServerReload::Type::ContentFlags) {
|
||||
content_service.SetExpansionContext()->ReloadContentFlags();
|
||||
} else if (type == ServerReload::Type::Logs) {
|
||||
LogSys.LoadLogDatabaseSettings();
|
||||
player_event_logs.ReloadSettings();
|
||||
UCSLink.SendPacket(&pack);
|
||||
} else if (type == ServerReload::Type::Tasks) {
|
||||
shared_task_manager.LoadTaskData();
|
||||
} else if (type == ServerReload::Type::DzTemplates) {
|
||||
dynamic_zone_manager.LoadTemplates();
|
||||
}
|
||||
|
||||
// Send the packet to all zones with staggered delays
|
||||
// to prevent all zones from reloading at the same time
|
||||
// and causing a massive spike in CPU usage
|
||||
// This is especially important for large servers
|
||||
// with many zones
|
||||
// we reload 10 zones every second
|
||||
int counter = 0;
|
||||
|
||||
for (auto &z: zone_server_list) {
|
||||
bool is_local = r->zone_server_id != 0;
|
||||
|
||||
// if the zone reload is local to a specific zone
|
||||
if (r->zone_server_id != 0 && r->zone_server_id != z->GetID()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// if the reload is local, we don't need to stagger the reloads
|
||||
r->reload_at_unix = is_local ? 0 : (std::time(nullptr) + 1) + (counter / 10);
|
||||
z->SendPacket(&pack);
|
||||
++counter;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "../common/eqtime.h"
|
||||
#include "../common/timer.h"
|
||||
#include "../common/event/timer.h"
|
||||
#include "../common/server_reload_types.h"
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <deque>
|
||||
@@ -70,7 +69,6 @@ public:
|
||||
ZoneServer* FindByZoneID(uint32 ZoneID);
|
||||
|
||||
const std::list<std::unique_ptr<ZoneServer>> &getZoneServerList() const;
|
||||
void SendServerReload(ServerReload::Type type, uchar *packet = nullptr);
|
||||
|
||||
private:
|
||||
void OnTick(EQ::Timer *t);
|
||||
|
||||
+75
-14
@@ -39,6 +39,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "../common/zone_store.h"
|
||||
#include "dynamic_zone.h"
|
||||
#include "dynamic_zone_manager.h"
|
||||
#include "expedition_message.h"
|
||||
#include "shared_task_world_messaging.h"
|
||||
#include "../common/shared_tasks.h"
|
||||
#include "shared_task_manager.h"
|
||||
@@ -49,7 +50,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "../zone/data_bucket.h"
|
||||
#include "../common/repositories/guild_tributes_repository.h"
|
||||
#include "../common/skill_caps.h"
|
||||
#include "../common/server_reload_types.h"
|
||||
|
||||
extern ClientList client_list;
|
||||
extern GroupLFPList LFPGroupList;
|
||||
@@ -1357,6 +1357,11 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
QSLink.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_ReloadOpcodes: {
|
||||
ReloadAllPatches();
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_CZDialogueWindow:
|
||||
case ServerOP_CZLDoNUpdate:
|
||||
case ServerOP_CZMarquee:
|
||||
@@ -1370,6 +1375,10 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
case ServerOP_Consent:
|
||||
case ServerOP_DepopAllPlayersCorpses:
|
||||
case ServerOP_DepopPlayerCorpse:
|
||||
case ServerOP_ExpeditionLockState:
|
||||
case ServerOP_ExpeditionLockout:
|
||||
case ServerOP_ExpeditionLockoutDuration:
|
||||
case ServerOP_ExpeditionReplayOnJoin:
|
||||
case ServerOP_GuildRankUpdate:
|
||||
case ServerOP_ItemStatus:
|
||||
case ServerOP_KickPlayer:
|
||||
@@ -1380,6 +1389,30 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
case ServerOP_RaidGroupSay:
|
||||
case ServerOP_RaidSay:
|
||||
case ServerOP_RefreshCensorship:
|
||||
case ServerOP_ReloadAAData:
|
||||
case ServerOP_ReloadAlternateCurrencies:
|
||||
case ServerOP_ReloadBaseData:
|
||||
case ServerOP_ReloadBlockedSpells:
|
||||
case ServerOP_ReloadCommands:
|
||||
case ServerOP_ReloadDoors:
|
||||
case ServerOP_ReloadDataBucketsCache:
|
||||
case ServerOP_ReloadFactions:
|
||||
case ServerOP_ReloadGroundSpawns:
|
||||
case ServerOP_ReloadLevelEXPMods:
|
||||
case ServerOP_ReloadMerchants:
|
||||
case ServerOP_ReloadNPCEmotes:
|
||||
case ServerOP_ReloadNPCSpells:
|
||||
case ServerOP_ReloadObjects:
|
||||
case ServerOP_ReloadPerlExportSettings:
|
||||
case ServerOP_ReloadStaticZoneData:
|
||||
case ServerOP_ReloadTitles:
|
||||
case ServerOP_ReloadTraps:
|
||||
case ServerOP_ReloadVariables:
|
||||
case ServerOP_ReloadVeteranRewards:
|
||||
case ServerOP_ReloadWorld:
|
||||
case ServerOP_ReloadZonePoints:
|
||||
case ServerOP_ReloadZoneData:
|
||||
case ServerOP_ReloadLoot:
|
||||
case ServerOP_RezzPlayerAccept:
|
||||
case ServerOP_SpawnStatusChange:
|
||||
case ServerOP_TraderMessaging:
|
||||
@@ -1397,9 +1430,14 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_ServerReloadRequest: {
|
||||
auto o = (ServerReload::Request*) pack->pBuffer;
|
||||
zoneserver_list.SendServerReload((ServerReload::Type) o->type, pack->pBuffer);
|
||||
case ServerOP_ReloadSkillCaps: {
|
||||
zoneserver_list.SendPacket(pack);
|
||||
skill_caps.ReloadSkillCaps();
|
||||
break;
|
||||
}
|
||||
case ServerOP_ReloadRules: {
|
||||
zoneserver_list.SendPacket(pack);
|
||||
RuleManager::Instance()->LoadRules(&database, "default", true);
|
||||
break;
|
||||
}
|
||||
case ServerOP_IsOwnerOnline: {
|
||||
@@ -1427,6 +1465,29 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_ReloadContentFlags: {
|
||||
zoneserver_list.SendPacket(pack);
|
||||
content_service.SetExpansionContext()->ReloadContentFlags();
|
||||
break;
|
||||
}
|
||||
case ServerOP_ReloadLogs: {
|
||||
zoneserver_list.SendPacket(pack);
|
||||
QSLink.SendPacket(pack);
|
||||
UCSLink.SendPacket(pack);
|
||||
LogSys.LoadLogDatabaseSettings();
|
||||
player_event_logs.ReloadSettings();
|
||||
break;
|
||||
}
|
||||
case ServerOP_ReloadTasks: {
|
||||
shared_task_manager.LoadTaskData();
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_ReloadDzTemplates: {
|
||||
dynamic_zone_manager.LoadTemplates();
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_ChangeSharedMem: {
|
||||
auto hotfix_name = std::string((char*) pack->pBuffer);
|
||||
|
||||
@@ -1471,11 +1532,16 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
SharedTaskWorldMessaging::HandleZoneMessage(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_ExpeditionCreate:
|
||||
case ServerOP_ExpeditionDzAddPlayer:
|
||||
case ServerOP_ExpeditionDzMakeLeader:
|
||||
case ServerOP_ExpeditionCharacterLockout:
|
||||
case ServerOP_ExpeditionSaveInvite:
|
||||
case ServerOP_ExpeditionRequestInvite: {
|
||||
ExpeditionMessage::HandleZoneMessage(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_DzCreated:
|
||||
case ServerOP_DzAddPlayer:
|
||||
case ServerOP_DzSaveInvite:
|
||||
case ServerOP_DzRequestInvite:
|
||||
case ServerOP_DzMakeLeader:
|
||||
case ServerOP_DzAddRemoveMember:
|
||||
case ServerOP_DzSwapMembers:
|
||||
case ServerOP_DzRemoveAllMembers:
|
||||
@@ -1486,13 +1552,8 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
case ServerOP_DzSetZoneIn:
|
||||
case ServerOP_DzSetSwitchID:
|
||||
case ServerOP_DzMovePC:
|
||||
case ServerOP_DzLock:
|
||||
case ServerOP_DzReplayOnJoin:
|
||||
case ServerOP_DzLockout:
|
||||
case ServerOP_DzLockoutDuration:
|
||||
case ServerOP_DzCharacterLockout:
|
||||
case ServerOP_DzUpdateMemberStatus: {
|
||||
dynamic_zone_manager.HandleZoneMessage(pack);
|
||||
DynamicZone::HandleZoneMessage(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_GuildTributeUpdate: {
|
||||
|
||||
@@ -36,6 +36,8 @@ SET(zone_sources
|
||||
encounter.cpp
|
||||
entity.cpp
|
||||
exp.cpp
|
||||
expedition.cpp
|
||||
expedition_database.cpp
|
||||
expedition_request.cpp
|
||||
fastmath.cpp
|
||||
fearpath.cpp
|
||||
@@ -203,6 +205,8 @@ SET(zone_headers
|
||||
encounter.h
|
||||
entity.h
|
||||
event_codes.h
|
||||
expedition.h
|
||||
expedition_database.h
|
||||
expedition_request.h
|
||||
fastmath.h
|
||||
forage.h
|
||||
|
||||
+11
-34
@@ -405,12 +405,17 @@ bool Mob::CheckWillAggro(Mob *mob) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Mob* pet_owner = mob->GetOwner();
|
||||
|
||||
if (pet_owner && pet_owner->IsOfClientBot()) {
|
||||
if (mob->IsPetAggroExempt(pet_owner)) {
|
||||
return false;
|
||||
}
|
||||
Mob *pet_owner = mob->GetOwner();
|
||||
if (
|
||||
pet_owner &&
|
||||
pet_owner->IsClient() &&
|
||||
(
|
||||
!RuleB(Aggro, AggroPlayerPets) ||
|
||||
pet_owner->CastToClient()->GetGM() ||
|
||||
mob->GetSpecialAbility(SpecialAbility::AggroImmunity)
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsNPC() && mob->IsNPC() && mob->GetSpecialAbility(SpecialAbility::NPCAggroImmunity)) {
|
||||
@@ -577,34 +582,6 @@ bool Mob::CheckWillAggro(Mob *mob) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Mob::IsPetAggroExempt(Mob* pet_owner) {
|
||||
if (!pet_owner) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool exempt_client_pet = pet_owner->IsClient() && !RuleB(Aggro, AggroPlayerPets);
|
||||
bool exempt_bot_pet = pet_owner->IsBot() && !RuleB(Aggro, AggroBotPets);
|
||||
|
||||
if (exempt_client_pet || exempt_bot_pet) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Mob* ultimate_owner = GetUltimateOwner();
|
||||
Client* client_owner = (ultimate_owner && ultimate_owner->IsClient())
|
||||
? ultimate_owner->CastToClient()
|
||||
: nullptr;
|
||||
|
||||
if (client_owner && client_owner->GetGM()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (GetSpecialAbility(SpecialAbility::AggroImmunity)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int EntityList::FleeAllyCount(Mob* attacker, Mob* skipped)
|
||||
{
|
||||
// Return a list of how many NPCs of the same faction or race are within aggro range of the given exclude Mob.
|
||||
|
||||
+344
-258
@@ -1856,7 +1856,6 @@ bool Bot::BotRangedAttack(Mob* other, bool can_double_attack) {
|
||||
|
||||
if (
|
||||
!GetPullingFlag() &&
|
||||
!GetReturningFlag() &&
|
||||
(
|
||||
(
|
||||
GetBotStance() != Stance::Aggressive &&
|
||||
@@ -2116,10 +2115,8 @@ void Bot::SetHoldMode() {
|
||||
void Bot::AI_Process()
|
||||
{
|
||||
|
||||
#define PULLING_BOT (GetPullingFlag())
|
||||
#define NOT_PULLING_BOT (!GetPullingFlag())
|
||||
#define RETURNING_BOT (GetReturningFlag())
|
||||
#define NOT_RETURNING_BOT (!GetReturningFlag())
|
||||
#define PULLING_BOT (GetPullingFlag() || GetReturningFlag())
|
||||
#define NOT_PULLING_BOT (!GetPullingFlag() && !GetReturningFlag())
|
||||
#define GUARDING (GetGuardFlag())
|
||||
#define NOT_GUARDING (!GetGuardFlag())
|
||||
#define HOLDING (GetHoldFlag())
|
||||
@@ -2227,7 +2224,7 @@ void Bot::AI_Process()
|
||||
|
||||
// PULLING FLAG (TARGET VALIDATION)
|
||||
|
||||
if (PULLING_BOT) {
|
||||
if (GetPullingFlag()) {
|
||||
if (!PullingFlagChecks(bot_owner)) {
|
||||
return;
|
||||
}
|
||||
@@ -2235,10 +2232,10 @@ void Bot::AI_Process()
|
||||
|
||||
// RETURNING FLAG
|
||||
|
||||
if (RETURNING_BOT) {
|
||||
if (ReturningFlagChecks(bot_owner, leash_owner, fm_distance)) {
|
||||
return;
|
||||
}
|
||||
if (GetReturningFlag()) {
|
||||
ReturningFlagChecks(bot_owner, leash_owner, fm_distance);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// DEFAULT (ACQUIRE TARGET)
|
||||
@@ -2271,7 +2268,7 @@ void Bot::AI_Process()
|
||||
}
|
||||
|
||||
// This causes conflicts with default pet handler (bounces between targets)
|
||||
if (NOT_PULLING_BOT && NOT_RETURNING_BOT && HasPet() && (GetClass() != Class::Enchanter || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 2)) {
|
||||
if (NOT_PULLING_BOT && HasPet() && (GetClass() != Class::Enchanter || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 2)) {
|
||||
// We don't add to hate list here because it's assumed to already be on the list
|
||||
GetPet()->SetTarget(tar);
|
||||
}
|
||||
@@ -2312,7 +2309,7 @@ void Bot::AI_Process()
|
||||
|
||||
// PULLING FLAG (ACTIONABLE RANGE)
|
||||
|
||||
if (PULLING_BOT || RETURNING_BOT) {
|
||||
if (GetPullingFlag()) {
|
||||
if (!TargetValidation(tar)) { return; }
|
||||
|
||||
if (!DoLosChecks(tar)) {
|
||||
@@ -2371,11 +2368,7 @@ void Bot::AI_Process()
|
||||
// ENGAGED AT COMBAT RANGE
|
||||
|
||||
// We can fight
|
||||
bool other_bot_pulling =
|
||||
(bot_owner->GetBotPulling() && NOT_PULLING_BOT) &&
|
||||
(bot_owner->GetBotPulling() && NOT_RETURNING_BOT);
|
||||
|
||||
if (!other_bot_pulling && at_combat_range) {
|
||||
if (at_combat_range) {
|
||||
bool jitter_cooldown = false;
|
||||
|
||||
if (m_combat_jitter_timer.GetRemainingTime() > 1 && m_combat_jitter_timer.Enabled()) {
|
||||
@@ -2466,20 +2459,60 @@ void Bot::AI_Process()
|
||||
|
||||
// ENGAGED NOT AT COMBAT RANGE
|
||||
|
||||
else if (!other_bot_pulling && !TryPursueTarget(leash_distance, Goal)) {
|
||||
else if (!TryPursueTarget(leash_distance, Goal)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// End not in combat range
|
||||
if (bot_owner->GetBotPulling() && HasPet()) {
|
||||
GetPet()->WipeHateList();
|
||||
GetPet()->SetTarget(nullptr);
|
||||
}
|
||||
|
||||
TryMeditate();
|
||||
}
|
||||
else { // Out-of-combat behavior
|
||||
DoOutOfCombatChecks(bot_owner, follow_mob, Goal, leash_distance, fm_distance);
|
||||
SetAttackFlag(false);
|
||||
SetCombatRoundForAlerts(false);
|
||||
SetAttackingFlag(false);
|
||||
|
||||
if (!bot_owner->GetBotPulling()) {
|
||||
SetPullingFlag(false);
|
||||
SetReturningFlag(false);
|
||||
}
|
||||
|
||||
// AUTO DEFEND
|
||||
|
||||
if (TryAutoDefend(bot_owner, leash_distance) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetTarget(nullptr);
|
||||
|
||||
if (
|
||||
HasPet() &&
|
||||
(
|
||||
GetClass() != Class::Enchanter ||
|
||||
GetPet()->GetPetType() != petAnimation ||
|
||||
GetAA(aaAnimationEmpathy) >= 1
|
||||
)
|
||||
) {
|
||||
GetPet()->WipeHateList();
|
||||
GetPet()->SetTarget(nullptr);
|
||||
}
|
||||
|
||||
if (m_PlayerState & static_cast<uint32>(PlayerState::Aggressive)) {
|
||||
SendRemovePlayerState(PlayerState::Aggressive);
|
||||
}
|
||||
|
||||
// OK TO IDLE
|
||||
|
||||
// Ok to idle
|
||||
if (TryNonCombatMovementChecks(bot_owner, follow_mob, Goal)) {
|
||||
return;
|
||||
}
|
||||
if (!IsBotNonSpellFighter() && AI_HasSpells() && TryIdleChecks(fm_distance)) {
|
||||
return;
|
||||
}
|
||||
if (GetClass() == Class::Bard && AI_HasSpells() && TryBardMovementCasts()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2507,7 +2540,7 @@ bool Bot::TryNonCombatMovementChecks(Client* bot_owner, const Mob* follow_mob, g
|
||||
|
||||
float destination_distance = DistanceSquared(GetPosition(), Goal);
|
||||
|
||||
if (destination_distance > GetFollowDistance()) {
|
||||
if ((!bot_owner->GetBotPulling() || PULLING_BOT) && (destination_distance > GetFollowDistance())) {
|
||||
if (!IsRooted()) {
|
||||
if (rest_timer.Enabled()) {
|
||||
rest_timer.Disable();
|
||||
@@ -2547,56 +2580,9 @@ bool Bot::TryIdleChecks(float fm_distance) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Bot::DoOutOfCombatChecks(Client* bot_owner, Mob* follow_mob, glm::vec3& Goal, float leash_distance, float fm_distance) {
|
||||
SetAttackFlag(false);
|
||||
SetCombatRoundForAlerts(false);
|
||||
SetAttackingFlag(false);
|
||||
|
||||
if (PULLING_BOT || RETURNING_BOT || !bot_owner->GetBotPulling()) {
|
||||
SetPullingFlag(false);
|
||||
SetReturningFlag(false);
|
||||
}
|
||||
|
||||
if (TryAutoDefend(bot_owner, leash_distance) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetTarget(nullptr);
|
||||
|
||||
if (
|
||||
HasPet() &&
|
||||
(
|
||||
GetClass() != Class::Enchanter ||
|
||||
GetPet()->GetPetType() != petAnimation ||
|
||||
GetAA(aaAnimationEmpathy) >= 1
|
||||
)
|
||||
) {
|
||||
GetPet()->WipeHateList();
|
||||
GetPet()->SetTarget(nullptr);
|
||||
}
|
||||
|
||||
if (m_PlayerState & static_cast<uint32>(PlayerState::Aggressive)) {
|
||||
SendRemovePlayerState(PlayerState::Aggressive);
|
||||
}
|
||||
|
||||
// Ok to idle
|
||||
if (TryNonCombatMovementChecks(bot_owner, follow_mob, Goal)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsBotNonSpellFighter() && AI_HasSpells() && TryIdleChecks(fm_distance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetClass() == Class::Bard && AI_HasSpells() && TryBardMovementCasts()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// This is as close as I could get without modifying the aggro mechanics and making it an expensive process...
|
||||
// 'class Client' doesn't make use of hate_list
|
||||
bool Bot::TryAutoDefend(Client* bot_owner, float leash_distance) {
|
||||
@@ -2760,26 +2746,11 @@ bool Bot::TryAutoDefend(Client* bot_owner, float leash_distance) {
|
||||
|
||||
bool Bot::TryMeditate() {
|
||||
if (!IsMoving() && !spellend_timer.Enabled()) {
|
||||
if (IsEngaged()) {
|
||||
if (HasOrMayGetAggro(IsSitting())) {
|
||||
if (IsSitting()) {
|
||||
Stand();
|
||||
}
|
||||
|
||||
if (IsEngaged() && HasOrMayGetAggro(IsSitting())) {
|
||||
if (IsSitting()) {
|
||||
Stand();
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto mob : hate_list.GetHateList()) {
|
||||
auto tar = mob->entity_on_hatelist;
|
||||
|
||||
if (tar) {
|
||||
Mob* tar_target = tar->GetTarget();
|
||||
|
||||
if (tar_target && tar_target == this) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BotMeditate(IsSitting());
|
||||
@@ -2787,7 +2758,6 @@ bool Bot::TryMeditate() {
|
||||
if (!(GetPlayerState() & static_cast<uint32>(PlayerState::Aggressive))) {
|
||||
SendAddPlayerState(PlayerState::Aggressive);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3244,7 +3214,7 @@ bool Bot::IsValidTarget(
|
||||
SetCombatRoundForAlerts(false);
|
||||
SetAttackingFlag(false);
|
||||
|
||||
if (PULLING_BOT || RETURNING_BOT) {
|
||||
if (PULLING_BOT) {
|
||||
SetPullingFlag(false);
|
||||
SetReturningFlag(false);
|
||||
bot_owner->SetBotPulling(false);
|
||||
@@ -3277,7 +3247,7 @@ Mob* Bot::GetBotTarget(Client* bot_owner)
|
||||
SetAttackFlag(false);
|
||||
SetAttackingFlag(false);
|
||||
|
||||
if (PULLING_BOT || RETURNING_BOT) {
|
||||
if (PULLING_BOT) {
|
||||
// 'Flags' should only be set on the bot that is pulling
|
||||
SetPullingFlag(false);
|
||||
SetReturningFlag(false);
|
||||
@@ -3295,11 +3265,7 @@ Mob* Bot::GetBotTarget(Client* bot_owner)
|
||||
}
|
||||
|
||||
bool Bot::TargetValidation(Mob* other) {
|
||||
if (GetAppearance() == eaDead || GetHP() < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!other || other->GetAppearance() == eaDead || other->GetHP() < 0) {
|
||||
if (!other || GetAppearance() == eaDead) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3307,33 +3273,23 @@ bool Bot::TargetValidation(Mob* other) {
|
||||
}
|
||||
|
||||
bool Bot::ReturningFlagChecks(Client* bot_owner, Mob* leash_owner, float fm_distance) {
|
||||
auto engage_range = (GetBotDistanceRanged() < 30 ? 30 : GetBotDistanceRanged());
|
||||
|
||||
if (
|
||||
(GetTarget() && Distance(GetPosition(), GetTarget()->GetPosition()) <= engage_range) &&
|
||||
(
|
||||
(NOT_GUARDING && fm_distance <= GetFollowDistance()) ||
|
||||
(GUARDING && DistanceSquared(GetPosition(), GetGuardPoint()) <= GetFollowDistance())
|
||||
)
|
||||
(NOT_GUARDING && fm_distance <= GetFollowDistance()) ||
|
||||
(GUARDING && DistanceSquared(GetPosition(), GetGuardPoint()) <= GetFollowDistance())
|
||||
) { // Once we're back, clear blocking flags so everyone else can join in
|
||||
WipeHateList();
|
||||
SetTarget(nullptr);
|
||||
SetPullingFlag(false);
|
||||
SetReturningFlag(false);
|
||||
bot_owner->SetBotPulling(false);
|
||||
|
||||
if (GetPet()) {
|
||||
GetPet()->SetPetOrder(m_previous_pet_order);
|
||||
|
||||
if (GetClass() != Class::Enchanter || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 1) {
|
||||
GetPet()->WipeHateList();
|
||||
GetPet()->SetTarget(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Need to keep puller out of combat until they reach their 'return to' destination
|
||||
WipeHateList();
|
||||
|
||||
if (!IsMoving()) {
|
||||
glm::vec3 Goal(0, 0, 0);
|
||||
|
||||
@@ -3372,6 +3328,8 @@ bool Bot::PullingFlagChecks(Client* bot_owner) {
|
||||
return false;
|
||||
}
|
||||
else if (GetTarget()->GetHateList().size()) {
|
||||
WipeHateList();
|
||||
SetTarget(nullptr);
|
||||
SetPullingFlag(false);
|
||||
SetReturningFlag();
|
||||
|
||||
@@ -3385,8 +3343,6 @@ bool Bot::PullingFlagChecks(Client* bot_owner) {
|
||||
if (GetPlayerState() & static_cast<uint32>(PlayerState::Aggressive)) {
|
||||
SendRemovePlayerState(PlayerState::Aggressive);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -3540,7 +3496,7 @@ Client* Bot::SetLeashOwner(Client* bot_owner, Group* bot_group, Raid* raid, uint
|
||||
}
|
||||
|
||||
void Bot::SetOwnerTarget(Client* bot_owner) {
|
||||
if (GetPet() && (PULLING_BOT || RETURNING_BOT)) {
|
||||
if (GetPet() && PULLING_BOT) {
|
||||
GetPet()->SetPetOrder(m_previous_pet_order);
|
||||
}
|
||||
|
||||
@@ -4983,7 +4939,7 @@ bool Bot::Death(Mob *killer_mob, int64 damage, uint16 spell_id, EQ::skills::Skil
|
||||
|
||||
LeaveHealRotationMemberPool();
|
||||
|
||||
if ((PULLING_BOT || RETURNING_BOT) && my_owner && my_owner->IsClient()) {
|
||||
if ((GetPullingFlag() || GetReturningFlag()) && my_owner && my_owner->IsClient()) {
|
||||
my_owner->CastToClient()->SetBotPulling(false);
|
||||
}
|
||||
|
||||
@@ -7728,21 +7684,15 @@ void EntityList::ShowSpawnWindow(Client* client, int Distance, bool NamedOnly) {
|
||||
}
|
||||
|
||||
uint8 Bot::GetNumberNeedingHealedInGroup(Mob* tar, uint16 spell_type, uint16 spell_id, float range) {
|
||||
if (!TargetValidation(tar)) {
|
||||
if (!tar) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8 count = 0;
|
||||
std::vector<Mob*> target_list = tar->IsClient() ? GatherSpellTargets(false, tar) : tar->CastToBot()->GetSpellTargetList();
|
||||
auto target_list = tar->IsClient() ? GatherSpellTargets(false, tar) : tar->CastToBot()->GetSpellTargetList();
|
||||
|
||||
for (auto* m : target_list) {
|
||||
if (
|
||||
m &&
|
||||
entity_list.IsMobInZone(m) &&
|
||||
TargetValidation(m) &&
|
||||
tar->CalculateDistance(m) < range &&
|
||||
CastChecks(spell_id, m, spell_type, true, IsGroupBotSpellType(spell_type))
|
||||
) {
|
||||
for (Mob* m : target_list) {
|
||||
if (m && tar->CalculateDistance(m) < range && CastChecks(spell_id, m, spell_type, true, IsGroupBotSpellType(spell_type))) {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
@@ -8403,13 +8353,12 @@ void Bot::ListBotSpells(uint8 min_level)
|
||||
bot_owner->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Spell {} | Spell: {} (ID: {}) | Add Spell: {}",
|
||||
"Spell {} | Spell: {} | Add Spell: {}",
|
||||
spell_number,
|
||||
Saylink::Silent(
|
||||
fmt::format("^spellinfo {}", s.spellid),
|
||||
spells[s.spellid].name
|
||||
),
|
||||
s.spellid,
|
||||
Saylink::Silent(
|
||||
fmt::format("^spellsettingsadd {} {} {} {}", s.spellid, s.priority, s.min_hp, s.max_hp), "Add")
|
||||
).c_str()
|
||||
@@ -9454,7 +9403,7 @@ void Bot::DoItemClick(const EQ::ItemData *item, uint16 slot_id)
|
||||
uint8 Bot::spell_casting_chances[SPELL_TYPE_COUNT][Class::PLAYER_CLASS_COUNT][Stance::AEBurn][cntHSND] = { 0 };
|
||||
|
||||
bool Bot::PrecastChecks(Mob* tar, uint16 spell_type) {
|
||||
if (!TargetValidation(tar)) {
|
||||
if (!tar) {
|
||||
LogBotSpellChecksDetail("{} says, 'Cancelling cast due to PrecastChecks !tar.'", GetCleanName());
|
||||
return false;
|
||||
}
|
||||
@@ -9476,18 +9425,24 @@ bool Bot::PrecastChecks(Mob* tar, uint16 spell_type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!EQ::ValueWithin(GetManaRatio(), GetSpellTypeMinManaLimit(spell_type), GetSpellTypeMaxManaLimit(spell_type))) {
|
||||
if (
|
||||
GetManaRatio() < GetSpellTypeMinManaLimit(spell_type) ||
|
||||
GetManaRatio() > GetSpellTypeMaxManaLimit(spell_type)
|
||||
) {
|
||||
LogBotSpellChecksDetail("{} says, 'Cancelling cast of [{}] on [{}] due to GetSpellTypeMinManaLimit or GetSpellTypeMaxManaLimit.'", GetCleanName(), GetSpellTypeNameByID(spell_type), tar->GetCleanName());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!EQ::ValueWithin(GetHPRatio(), GetSpellTypeMinHPLimit(spell_type), GetSpellTypeMaxHPLimit(spell_type))) {
|
||||
if (
|
||||
GetHPRatio() < GetSpellTypeMinHPLimit(spell_type) ||
|
||||
GetHPRatio() > GetSpellTypeMaxHPLimit(spell_type)
|
||||
) {
|
||||
LogBotSpellChecksDetail("{} says, 'Cancelling cast of [{}] on [{}] due to GetSpellTypeMinHPLimit or GetSpellTypeMaxHPLimit.'", GetCleanName(), GetSpellTypeNameByID(spell_type), tar->GetCleanName());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!GetUltimateSpellTypeRecastCheck(spell_type, tar)) {
|
||||
LogBotSpellChecksDetail("{} says, 'Cancelling cast of [{}] on [{}] due to GetUltimateSpellTypeRecastCheck.'", GetCleanName(), GetSpellTypeNameByID(spell_type), tar->GetCleanName());
|
||||
if (!GetUltimateSpellTypeDelayCheck(spell_type, tar)) {
|
||||
LogBotSpellChecksDetail("{} says, 'Cancelling cast of [{}] on [{}] due to GetUltimateSpellTypeDelayCheck.'", GetCleanName(), GetSpellTypeNameByID(spell_type), tar->GetCleanName());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -9496,7 +9451,10 @@ bool Bot::PrecastChecks(Mob* tar, uint16 spell_type) {
|
||||
case BotSpellTypes::AEMez:
|
||||
return true;
|
||||
default:
|
||||
if (!EQ::ValueWithin(GetHPRatioForSpellType(spell_type, tar), GetUltimateSpellTypeMinThreshold(spell_type, tar), GetUltimateSpellTypeMaxThreshold(spell_type, tar))) {
|
||||
if (
|
||||
GetHPRatioForSpellType(spell_type, tar) < GetUltimateSpellTypeMinThreshold(spell_type, tar) ||
|
||||
GetHPRatioForSpellType(spell_type, tar) > GetUltimateSpellTypeMaxThreshold(spell_type, tar)
|
||||
) {
|
||||
LogBotSpellChecksDetail("{} says, 'Cancelling cast of [{}] on [{}] due to GetUltimateSpellTypeMinThreshold or GetUltimateSpellTypeMaxThreshold.'", GetCleanName(), GetSpellTypeNameByID(spell_type), tar->GetCleanName());
|
||||
return false;
|
||||
}
|
||||
@@ -9507,7 +9465,7 @@ bool Bot::PrecastChecks(Mob* tar, uint16 spell_type) {
|
||||
|
||||
bool Bot::CastChecks(uint16 spell_id, Mob* tar, uint16 spell_type, bool prechecks, bool ae_check) {
|
||||
if (prechecks) {
|
||||
if (!tar || tar->GetAppearance() == eaDead || tar->GetHP() < 0) {
|
||||
if (!tar) {
|
||||
LogBotSpellChecksDetail("{} says, 'Cancelling cast due to CastChecks !tar.'", GetCleanName());
|
||||
return false;
|
||||
}
|
||||
@@ -9658,7 +9616,7 @@ bool Bot::CastChecks(uint16 spell_id, Mob* tar, uint16 spell_type, bool precheck
|
||||
|
||||
if (
|
||||
BotSpellTypeRequiresTarget(spell_type) &&
|
||||
!TargetValidation(tar)
|
||||
!tar
|
||||
) {
|
||||
LogBotSpellChecksDetail("{} says, 'Cancelling cast due to CastChecks !tar.'", GetCleanName());
|
||||
return false;
|
||||
@@ -9748,10 +9706,13 @@ bool Bot::CastChecks(uint16 spell_id, Mob* tar, uint16 spell_type, bool precheck
|
||||
}
|
||||
//LogBotSpellChecksDetail("{} says, 'Doing CanCastSpellType checks of {} on {}.'", GetCleanName(), GetSpellName(spell_id), tar->GetCleanName());
|
||||
if (!CanCastSpellType(spell_type, spell_id, tar)) {
|
||||
LogBotSpellChecksDetail("{} says, 'Cancelling cast of {} on {} due to CanCastSpellType.'", GetCleanName(), GetSpellName(spell_id), tar->GetCleanName());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsCommandedSpell()) { //stop checks here for commanded spells
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!IsValidTargetType(spell_id, GetSpellTargetType(spell_id), tar->GetBodyType())) {
|
||||
LogBotSpellChecksDetail("{} says, 'Cancelling cast of {} on {} due to IsValidTargetType.'", GetCleanName(), GetSpellName(spell_id), tar->GetCleanName());
|
||||
return false;
|
||||
@@ -9788,7 +9749,7 @@ bool Bot::CastChecks(uint16 spell_id, Mob* tar, uint16 spell_type, bool precheck
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsCommandedSpell() || spell_type == UINT16_MAX) { //AA/Forced cast checks, return here
|
||||
if (spell_type == UINT16_MAX) { //AA/Forced cast checks, return here
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -10559,7 +10520,7 @@ void Bot::SetBotSpellRecastTimer(uint16 spell_type, Mob* tar, bool precast) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!precast && BotSpellTypeUsesTargetSettings(spell_type)) {
|
||||
if (!precast && IsBotSpellTypeOtherBeneficial(spell_type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -10584,7 +10545,7 @@ void Bot::SetBotSpellRecastTimer(uint16 spell_type, Mob* tar, bool precast) {
|
||||
owner->CastToBot()->SetSpellTypeRecastTimer(spell_type, (GetUltimateSpellTypeDelay(spell_type, tar) + added_delay));
|
||||
}
|
||||
}
|
||||
else if (BotSpellTypeUsesTargetSettings(spell_type)) {
|
||||
else if (IsBotSpellTypeOtherBeneficial(spell_type)) {
|
||||
if (tar->IsClient()) {
|
||||
tar->CastToClient()->SetSpellTypeRecastTimer(spell_type, (GetUltimateSpellTypeDelay(spell_type, tar) + added_delay));
|
||||
}
|
||||
@@ -10598,12 +10559,6 @@ void Bot::SetBotSpellRecastTimer(uint16 spell_type, Mob* tar, bool precast) {
|
||||
}
|
||||
|
||||
BotSpell Bot::GetSpellByHealType(uint16 spell_type, Mob* tar) {
|
||||
if (!TargetValidation(tar)) {
|
||||
BotSpell result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
switch (spell_type) {
|
||||
case BotSpellTypes::VeryFastHeals:
|
||||
case BotSpellTypes::PetVeryFastHeals:
|
||||
@@ -10803,7 +10758,6 @@ bool Bot::GetDefaultSpellTypeHold(uint16 spell_type, uint8 stance) {
|
||||
switch (stance) {
|
||||
case Stance::AEBurn:
|
||||
case Stance::Burn:
|
||||
case Stance::Assist:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -11083,36 +11037,31 @@ bool Bot::GetDefaultSpellTypeAggroCheck(uint16 spell_type, uint8 stance) {
|
||||
switch (stance) {
|
||||
case Stance::AEBurn:
|
||||
case Stance::Burn:
|
||||
case Stance::Aggressive:
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (spell_type) {
|
||||
case BotSpellTypes::AEDebuff:
|
||||
case BotSpellTypes::AEDispel:
|
||||
case BotSpellTypes::AEDoT:
|
||||
case BotSpellTypes::AEFear:
|
||||
case BotSpellTypes::AEHateLine:
|
||||
case BotSpellTypes::AELifetap:
|
||||
case BotSpellTypes::Nuke:
|
||||
case BotSpellTypes::Root:
|
||||
case BotSpellTypes::Snare:
|
||||
case BotSpellTypes::DOT:
|
||||
case BotSpellTypes::Slow:
|
||||
case BotSpellTypes::Debuff:
|
||||
case BotSpellTypes::Fear:
|
||||
case BotSpellTypes::Stun:
|
||||
case BotSpellTypes::AENukes:
|
||||
case BotSpellTypes::AERains:
|
||||
case BotSpellTypes::AERoot:
|
||||
case BotSpellTypes::AEStun:
|
||||
case BotSpellTypes::AEDebuff:
|
||||
case BotSpellTypes::AESlow:
|
||||
case BotSpellTypes::AESnare:
|
||||
case BotSpellTypes::AEStun:
|
||||
case BotSpellTypes::DOT:
|
||||
case BotSpellTypes::Debuff:
|
||||
case BotSpellTypes::Dispel:
|
||||
case BotSpellTypes::Fear:
|
||||
case BotSpellTypes::HateLine:
|
||||
case BotSpellTypes::Nuke:
|
||||
case BotSpellTypes::AEFear:
|
||||
case BotSpellTypes::AEDispel:
|
||||
case BotSpellTypes::AERoot:
|
||||
case BotSpellTypes::AEDoT:
|
||||
case BotSpellTypes::PBAENuke:
|
||||
case BotSpellTypes::Root:
|
||||
case BotSpellTypes::Slow:
|
||||
case BotSpellTypes::Snare:
|
||||
case BotSpellTypes::Stun:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -11193,7 +11142,7 @@ uint16 Bot::GetDefaultSpellTypeAnnounceCast(uint16 spell_type, uint8 stance) {
|
||||
}
|
||||
|
||||
bool Bot::GetUltimateSpellTypeHold(uint16 spell_type, Mob* tar) {
|
||||
if (!TargetValidation(tar)) {
|
||||
if (!tar) {
|
||||
return GetSpellTypeHold(spell_type);
|
||||
}
|
||||
|
||||
@@ -11570,12 +11519,11 @@ uint16 Bot::GetParentSpellType(uint16 spell_type) {
|
||||
case BotSpellTypes::AELull:
|
||||
case BotSpellTypes::Lull:
|
||||
return BotSpellTypes::Lull;
|
||||
case BotSpellTypes::HateLine:
|
||||
case BotSpellTypes::AEHateLine:
|
||||
return BotSpellTypes::HateLine;
|
||||
case BotSpellTypes::Charm:
|
||||
case BotSpellTypes::Escape:
|
||||
case BotSpellTypes::HateRedux:
|
||||
case BotSpellTypes::HateLine:
|
||||
case BotSpellTypes::AEHateLine:
|
||||
case BotSpellTypes::InCombatBuff:
|
||||
case BotSpellTypes::InCombatBuffSong:
|
||||
case BotSpellTypes::OutOfCombatBuffSong:
|
||||
@@ -11854,15 +11802,15 @@ void Bot::DoCombatPositioning(
|
||||
}
|
||||
else if (tar->IsRooted() && !IsTaunting()) { // Move non-taunters out of range - Above already checks if bot is targeted, otherwise they would stay
|
||||
if (tar_distance <= melee_distance_max) {
|
||||
if (PlotBotPositionAroundTarget(tar, Goal.x, Goal.y, Goal.z, (melee_distance_max + 1), (melee_distance_max * 2), GetBehindMob(), false)) {
|
||||
if (PlotBotPositionAroundTarget(tar, Goal.x, Goal.y, Goal.z, (melee_distance_max + 1), (melee_distance_max * 2), false, IsTaunting())) {
|
||||
RunToGoalWithJitter(Goal);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (tar_distance < melee_distance_min || (!front_mob && IsTaunting())) { // Back up any bots that are too close
|
||||
if (PlotBotPositionAroundTarget(tar, Goal.x, Goal.y, Goal.z, melee_distance_min, melee_distance, GetBehindMob(), (IsTaunting() || !GetBehindMob()))) {
|
||||
else if (IsTaunting() && ((tar_distance < melee_distance_min) || !front_mob)) { // Back up any bots that are too close
|
||||
if (PlotBotPositionAroundTarget(tar, Goal.x, Goal.y, Goal.z, melee_distance_min, melee_distance, false, IsTaunting())) {
|
||||
RunToGoalWithJitter(Goal);
|
||||
|
||||
return;
|
||||
@@ -11897,8 +11845,8 @@ void Bot::DoCombatPositioning(
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (tar_distance < melee_distance_min || (GetBehindMob() && !behind_mob) || (IsTaunting() && !front_mob) || !HasRequiredLoSForPositioning(tar)) { // Regular adjustment
|
||||
if (PlotBotPositionAroundTarget(tar, Goal.x, Goal.y, Goal.z, melee_distance_min, melee_distance, GetBehindMob(), (IsTaunting() || !GetBehindMob()))) {
|
||||
else if (tar_distance < melee_distance_min || (GetBehindMob() && !behind_mob) || (IsTaunting() && !front_mob)|| !HasRequiredLoSForPositioning(tar)) { // Regular adjustment
|
||||
if (PlotBotPositionAroundTarget(tar, Goal.x, Goal.y, Goal.z, melee_distance_min, melee_distance, GetBehindMob(), IsTaunting())) {
|
||||
RunToGoalWithJitter(Goal);
|
||||
|
||||
return;
|
||||
@@ -12035,7 +11983,7 @@ bool Bot::HasRequiredLoSForPositioning(Mob* tar) {
|
||||
|
||||
bool Bot::HasValidAETarget(Bot* caster, uint16 spell_id, uint16 spell_type, Mob* tar) {
|
||||
int spell_range = caster->GetActSpellRange(spell_id, spells[spell_id].range);
|
||||
int spell_ae_range = caster->GetAOERange(spell_id);
|
||||
int spell_ae_range = caster->GetActSpellRange(spell_id, spells[spell_id].aoe_range);
|
||||
int target_count = 0;
|
||||
|
||||
for (auto& close_mob : caster->m_close_mobs) {
|
||||
@@ -12046,18 +11994,6 @@ bool Bot::HasValidAETarget(Bot* caster, uint16 spell_id, uint16 spell_type, Mob*
|
||||
}
|
||||
|
||||
switch (spell_type) {
|
||||
case BotSpellTypes::AELull:
|
||||
if (m->GetSpecialAbility(SpecialAbility::PacifyImmunity)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
case BotSpellTypes::AEMez:
|
||||
if (m->GetSpecialAbility(SpecialAbility::MesmerizeImmunity)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
case BotSpellTypes::AEDispel:
|
||||
if (m->GetSpecialAbility(SpecialAbility::DispellImmunity)) {
|
||||
continue;
|
||||
@@ -12141,6 +12077,182 @@ bool Bot::HasValidAETarget(Bot* caster, uint16 spell_id, uint16 spell_type, Mob*
|
||||
return true;
|
||||
}
|
||||
|
||||
void Bot::CopySettings(Bot* to, uint8 setting_type, uint16 spell_type) {
|
||||
switch (setting_type) {
|
||||
case BotSettingCategories::BaseSetting:
|
||||
for (uint16 i = BotBaseSettings::START; i <= BotBaseSettings::END; ++i) {
|
||||
to->SetBotBaseSetting(i, GetBotBaseSetting(i));
|
||||
}
|
||||
|
||||
break;
|
||||
case BotSettingCategories::SpellHold:
|
||||
if (spell_type != UINT16_MAX) {
|
||||
to->SetSpellTypeHold(spell_type, GetSpellTypeHold(spell_type));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
to->SetSpellTypeHold(i, GetSpellTypeHold(i));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case BotSettingCategories::SpellDelay:
|
||||
if (spell_type != UINT16_MAX) {
|
||||
to->SetSpellTypeDelay(spell_type, GetSpellTypeDelay(spell_type));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
to->SetSpellTypeDelay(i, GetSpellTypeDelay(i));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case BotSettingCategories::SpellMinThreshold:
|
||||
if (spell_type != UINT16_MAX) {
|
||||
to->SetSpellTypeMinThreshold(spell_type, GetSpellTypeMinThreshold(spell_type));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
to->SetSpellTypeMinThreshold(i, GetSpellTypeMinThreshold(i));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case BotSettingCategories::SpellMaxThreshold:
|
||||
if (spell_type != UINT16_MAX) {
|
||||
to->SetSpellTypeMaxThreshold(spell_type, GetSpellTypeMaxThreshold(spell_type));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
to->SetSpellTypeMaxThreshold(i, GetSpellTypeMaxThreshold(i));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case BotSettingCategories::SpellTypeAggroCheck:
|
||||
if (spell_type != UINT16_MAX) {
|
||||
to->SetSpellTypeAggroCheck(spell_type, GetSpellTypeAggroCheck(spell_type));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
to->SetSpellTypeAggroCheck(i, GetSpellTypeAggroCheck(i));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case BotSettingCategories::SpellTypeResistLimit:
|
||||
if (spell_type != UINT16_MAX) {
|
||||
to->SetSpellTypeResistLimit(spell_type, GetSpellTypeResistLimit(spell_type));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
to->SetSpellTypeResistLimit(i, GetSpellTypeResistLimit(i));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case BotSettingCategories::SpellTypeMinManaPct:
|
||||
if (spell_type != UINT16_MAX) {
|
||||
to->SetSpellTypeMinManaLimit(spell_type, GetSpellTypeMinManaLimit(spell_type));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
to->SetSpellTypeMinManaLimit(i, GetSpellTypeMinManaLimit(i));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case BotSettingCategories::SpellTypeMaxManaPct:
|
||||
if (spell_type != UINT16_MAX) {
|
||||
to->SetSpellTypeMaxManaLimit(spell_type, GetSpellTypeMaxManaLimit(spell_type));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
to->SetSpellTypeMaxManaLimit(i, GetSpellTypeMaxManaLimit(i));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case BotSettingCategories::SpellTypeMinHPPct:
|
||||
if (spell_type != UINT16_MAX) {
|
||||
to->SetSpellTypeMinHPLimit(spell_type, GetSpellTypeMinHPLimit(spell_type));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
to->SetSpellTypeMinHPLimit(i, GetSpellTypeMinHPLimit(i));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case BotSettingCategories::SpellTypeMaxHPPct:
|
||||
if (spell_type != UINT16_MAX) {
|
||||
to->SetSpellTypeMaxHPLimit(spell_type, GetSpellTypeMaxHPLimit(spell_type));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
to->SetSpellTypeMaxHPLimit(i, GetSpellTypeMaxHPLimit(i));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case BotSettingCategories::SpellTypeIdlePriority:
|
||||
if (spell_type != UINT16_MAX) {
|
||||
to->SetSpellTypePriority(spell_type, BotPriorityCategories::Idle, GetSpellTypePriority(spell_type, BotPriorityCategories::Idle));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
to->SetSpellTypePriority(i, BotPriorityCategories::Idle, GetSpellTypePriority(i, BotPriorityCategories::Idle));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case BotSettingCategories::SpellTypeEngagedPriority:
|
||||
if (spell_type != UINT16_MAX) {
|
||||
to->SetSpellTypePriority(spell_type, BotPriorityCategories::Engaged, GetSpellTypePriority(spell_type, BotPriorityCategories::Engaged));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
to->SetSpellTypePriority(i, BotPriorityCategories::Engaged, GetSpellTypePriority(i, BotPriorityCategories::Engaged));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case BotSettingCategories::SpellTypePursuePriority:
|
||||
if (spell_type != UINT16_MAX) {
|
||||
to->SetSpellTypePriority(spell_type, BotPriorityCategories::Pursue, GetSpellTypePriority(spell_type, BotPriorityCategories::Pursue));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
to->SetSpellTypePriority(i, BotPriorityCategories::Pursue, GetSpellTypePriority(i, BotPriorityCategories::Pursue));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case BotSettingCategories::SpellTypeAEOrGroupTargetCount:
|
||||
if (spell_type != UINT16_MAX) {
|
||||
to->SetSpellTypeAEOrGroupTargetCount(spell_type, GetSpellTypeAEOrGroupTargetCount(spell_type));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
to->SetSpellTypeAEOrGroupTargetCount(i, GetSpellTypeAEOrGroupTargetCount(i));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case BotSettingCategories::SpellTypeAnnounceCast:
|
||||
if (spell_type != UINT16_MAX) {
|
||||
to->SetSpellTypeAnnounceCast(spell_type, GetSpellTypeAnnounceCast(spell_type));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
to->SetSpellTypeAnnounceCast(i, GetSpellTypeAnnounceCast(i));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Bot::CopyBotSpellSettings(Bot* to)
|
||||
{
|
||||
if (!to) {
|
||||
@@ -12689,16 +12801,12 @@ bool Bot::IsValidBotSpellCategory(uint8 setting_type) {
|
||||
}
|
||||
|
||||
std::string Bot::GetBotSpellCategoryName(uint8 setting_type) {
|
||||
return Bot::IsValidBotSpellCategory(setting_type) ? bot_setting_category_names[setting_type] : "UNKNOWN CATEGORY";
|
||||
}
|
||||
|
||||
std::string Bot::GetBotSpellCategoryShortName(uint8 setting_type) {
|
||||
return Bot::IsValidBotSpellCategory(setting_type) ? bot_setting_category_short_names[setting_type] : "UNKNOWN CATEGORY";
|
||||
return Bot::IsValidBotSpellCategory(setting_type) ? botSpellCategory_names[setting_type] : "UNKNOWN CATEGORY";
|
||||
}
|
||||
|
||||
uint16 Bot::GetBotSpellCategoryIDByShortName(std::string setting_string) {
|
||||
for (int i = BotSettingCategories::START; i <= BotSettingCategories::END; ++i) {
|
||||
if (!Strings::ToLower(setting_string).compare(Strings::ToLower(GetBotSpellCategoryShortName(i)))) {
|
||||
if (!Strings::ToLower(setting_string).compare(Strings::ToLower(GetBotSpellCategoryName(i)))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@@ -12725,11 +12833,11 @@ uint16 Bot::GetBaseSettingIDByShortName(std::string setting_string) {
|
||||
}
|
||||
|
||||
std::string Bot::GetSpellTypeShortNameByID(uint16 spell_type) {
|
||||
return IsValidBotSpellType(spell_type) ? spell_type_short_names[spell_type] : "UNKNOWN SPELLTYPE";
|
||||
return IsValidBotSpellType(spell_type) ? spellType_shortNames[spell_type] : "UNKNOWN SPELLTYPE";
|
||||
}
|
||||
|
||||
std::string Bot::GetSpellTypeNameByID(uint16 spell_type) {
|
||||
return IsValidBotSpellType(spell_type) ? spell_type_names[spell_type] : "UNKNOWN SPELLTYPE";
|
||||
return IsValidBotSpellType(spell_type) ? spellType_names[spell_type] : "UNKNOWN SPELLTYPE";
|
||||
}
|
||||
|
||||
bool Bot::IsValidSubType(uint16 sub_type) {
|
||||
@@ -12893,7 +13001,7 @@ uint8 Bot::GetDefaultSpellTypeMaxThreshold(uint16 spell_type, uint8 stance) {
|
||||
}
|
||||
case BotSpellTypes::GroupHeals:
|
||||
case BotSpellTypes::RegularHeal:
|
||||
if (bot_class == Class::Necromancer || bot_class == Class::Shaman) {
|
||||
if (bot_class == Class::Necromancer || (bot_class == Class::Shaman && !GetSpellTypeHold(BotSpellTypes::InCombatBuff))) {
|
||||
return 60;
|
||||
}
|
||||
|
||||
@@ -13022,88 +13130,81 @@ uint8 Bot::GetDefaultSpellTypeMaxThreshold(uint16 spell_type, uint8 stance) {
|
||||
}
|
||||
|
||||
uint16 Bot::GetUltimateSpellTypeDelay(uint16 spell_type, Mob* tar) {
|
||||
if (!TargetValidation(tar)) {
|
||||
if (!tar) {
|
||||
return GetSpellTypeDelay(spell_type);
|
||||
}
|
||||
|
||||
Mob* owner = tar->IsPet() ? tar->GetOwner() : nullptr;
|
||||
if (tar->IsPet() && tar->GetOwner() && tar->GetOwner()->IsOfClientBot()) {
|
||||
Mob* owner = tar->GetOwner();
|
||||
|
||||
if (owner && owner->IsOfClientBot()) {
|
||||
return owner->IsClient()
|
||||
? owner->CastToClient()->GetSpellTypeDelay(GetPetBotSpellType(spell_type))
|
||||
: owner->CastToBot()->GetSpellTypeDelay(GetPetBotSpellType(spell_type));
|
||||
return owner->IsClient() ? owner->CastToClient()->GetSpellTypeDelay(GetPetBotSpellType(spell_type)) : owner->CastToBot()->GetSpellTypeDelay(
|
||||
GetPetBotSpellType(spell_type));
|
||||
}
|
||||
|
||||
if (BotSpellTypeUsesTargetSettings(spell_type) && tar->IsOfClientBot()) {
|
||||
return tar->IsClient()
|
||||
? tar->CastToClient()->GetSpellTypeDelay(spell_type)
|
||||
: tar->CastToBot()->GetSpellTypeDelay(spell_type);
|
||||
if (IsBotSpellTypeOtherBeneficial(spell_type) && tar->IsOfClientBot()) {
|
||||
return tar->IsClient() ? tar->CastToClient()->GetSpellTypeDelay(spell_type) : tar->CastToBot()->GetSpellTypeDelay(
|
||||
spell_type
|
||||
);
|
||||
}
|
||||
|
||||
return GetSpellTypeDelay(spell_type);
|
||||
}
|
||||
|
||||
bool Bot::GetUltimateSpellTypeRecastCheck(uint16 spell_type, Mob* tar) {
|
||||
if (!TargetValidation(tar)) {
|
||||
bool Bot::GetUltimateSpellTypeDelayCheck(uint16 spell_type, Mob* tar) {
|
||||
if (!tar) {
|
||||
return SpellTypeRecastCheck(spell_type);
|
||||
}
|
||||
|
||||
Mob* owner = tar->IsPet() ? tar->GetOwner() : nullptr;
|
||||
if (tar->IsPet() && tar->GetOwner() && tar->GetOwner()->IsOfClientBot()) {
|
||||
Mob* owner = tar->GetOwner();
|
||||
|
||||
if (owner && owner->IsOfClientBot()) {
|
||||
return owner->IsClient()
|
||||
? owner->CastToClient()->SpellTypeRecastCheck(GetPetBotSpellType(spell_type))
|
||||
: owner->CastToBot()->SpellTypeRecastCheck(GetPetBotSpellType(spell_type));
|
||||
return owner->IsClient() ? owner->CastToClient()->SpellTypeRecastCheck(GetPetBotSpellType(spell_type)) : owner->CastToBot()->SpellTypeRecastCheck(GetPetBotSpellType(spell_type));
|
||||
}
|
||||
|
||||
if (BotSpellTypeUsesTargetSettings(spell_type) && tar->IsOfClientBot()) {
|
||||
return tar->IsClient()
|
||||
? tar->CastToClient()->SpellTypeRecastCheck(spell_type)
|
||||
: tar->CastToBot()->SpellTypeRecastCheck(spell_type);
|
||||
if (IsBotSpellTypeOtherBeneficial(spell_type) && tar->IsOfClientBot()) {
|
||||
return tar->IsClient() ? tar->CastToClient()->SpellTypeRecastCheck(spell_type) : tar->CastToBot()->SpellTypeRecastCheck(spell_type);
|
||||
}
|
||||
|
||||
return SpellTypeRecastCheck(spell_type);
|
||||
}
|
||||
|
||||
uint8 Bot::GetUltimateSpellTypeMinThreshold(uint16 spell_type, Mob* tar) {
|
||||
if (!TargetValidation(tar)) {
|
||||
if (!tar) {
|
||||
return GetSpellTypeMinThreshold(spell_type);
|
||||
}
|
||||
|
||||
Mob* owner = tar->IsPet() ? tar->GetOwner() : nullptr;
|
||||
if (tar->IsPet() && tar->GetOwner() && tar->GetOwner()->IsOfClientBot()) {
|
||||
Mob* owner = tar->GetOwner();
|
||||
|
||||
if (owner && owner->IsOfClientBot()) {
|
||||
return owner->IsClient()
|
||||
? owner->CastToClient()->GetSpellTypeMinThreshold(GetPetBotSpellType(spell_type))
|
||||
: owner->CastToBot()->GetSpellTypeMinThreshold(GetPetBotSpellType(spell_type));
|
||||
return owner->IsClient() ? owner->CastToClient()->GetSpellTypeMinThreshold(GetPetBotSpellType(spell_type)) : owner->CastToBot()->GetSpellTypeMinThreshold(
|
||||
GetPetBotSpellType(spell_type));
|
||||
}
|
||||
|
||||
if (BotSpellTypeUsesTargetSettings(spell_type) && tar->IsOfClientBot()) {
|
||||
return tar->IsClient()
|
||||
? tar->CastToClient()->GetSpellTypeMinThreshold(spell_type)
|
||||
: tar->CastToBot()->GetSpellTypeMinThreshold(spell_type);
|
||||
if (IsBotSpellTypeOtherBeneficial(spell_type) && tar->IsOfClientBot()) {
|
||||
return tar->IsClient() ? tar->CastToClient()->GetSpellTypeMinThreshold(spell_type) : tar->CastToBot()->GetSpellTypeMinThreshold(
|
||||
spell_type
|
||||
);
|
||||
}
|
||||
|
||||
return GetSpellTypeMinThreshold(spell_type);
|
||||
}
|
||||
|
||||
uint8 Bot::GetUltimateSpellTypeMaxThreshold(uint16 spell_type, Mob* tar) {
|
||||
if (!TargetValidation(tar)) {
|
||||
if (!tar) {
|
||||
return GetSpellTypeMaxThreshold(spell_type);
|
||||
}
|
||||
|
||||
Mob* owner = tar->IsPet() ? tar->GetOwner() : nullptr;
|
||||
if (tar->IsPet() && tar->GetOwner() && tar->GetOwner()->IsOfClientBot()) {
|
||||
Mob* owner = tar->GetOwner();
|
||||
|
||||
if (owner && owner->IsOfClientBot()) {
|
||||
return owner->IsClient()
|
||||
? owner->CastToClient()->GetSpellTypeMaxThreshold(GetPetBotSpellType(spell_type))
|
||||
: owner->CastToBot()->GetSpellTypeMaxThreshold(GetPetBotSpellType(spell_type));
|
||||
return owner->IsClient() ? owner->CastToClient()->GetSpellTypeMaxThreshold(GetPetBotSpellType(spell_type)) : owner->CastToBot()->GetSpellTypeMaxThreshold(
|
||||
GetPetBotSpellType(spell_type));
|
||||
}
|
||||
|
||||
if (BotSpellTypeUsesTargetSettings(spell_type) && tar->IsOfClientBot()) {
|
||||
return tar->IsClient()
|
||||
? tar->CastToClient()->GetSpellTypeMaxThreshold(spell_type)
|
||||
: tar->CastToBot()->GetSpellTypeMaxThreshold(spell_type);
|
||||
if (IsBotSpellTypeOtherBeneficial(spell_type) && tar->IsOfClientBot()) {
|
||||
return tar->IsClient() ? tar->CastToClient()->GetSpellTypeMaxThreshold(spell_type) : tar->CastToBot()->GetSpellTypeMaxThreshold(
|
||||
spell_type
|
||||
);
|
||||
}
|
||||
|
||||
return GetSpellTypeMaxThreshold(spell_type);
|
||||
@@ -13187,9 +13288,11 @@ bool Bot::IsImmuneToBotSpell(uint16 spell_id, Mob* caster) {
|
||||
(
|
||||
IsEffectInSpell(spell_id, SE_Root) ||
|
||||
IsEffectInSpell(spell_id, SE_MovementSpeed)
|
||||
)
|
||||
) {
|
||||
return true;
|
||||
)
|
||||
) {
|
||||
if (GetSpecialAbility(SpecialAbility::SnareImmunity)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsLifetapSpell(spell_id)) {
|
||||
@@ -13217,20 +13320,3 @@ std::vector<Mob*> Bot::GetSpellTargetList(bool entire_raid) {
|
||||
|
||||
return entire_raid ? _spell_target_list : _group_spell_target_list;
|
||||
}
|
||||
|
||||
bool Bot::IsValidBotStance(uint8 stance) {
|
||||
switch (stance) {
|
||||
case Stance::Passive:
|
||||
case Stance::Balanced:
|
||||
case Stance::Efficient:
|
||||
case Stance::Aggressive:
|
||||
case Stance::Assist:
|
||||
case Stance::Burn:
|
||||
case Stance::AEBurn:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
+6
-27
@@ -93,7 +93,7 @@ enum BotCastingChanceConditional : uint8
|
||||
cntHSND = 16
|
||||
};
|
||||
|
||||
namespace BotSettingCategories {
|
||||
namespace BotSettingCategories { // Update GetBotSpellCategoryName as needed
|
||||
constexpr uint8 BaseSetting = 0;
|
||||
constexpr uint8 SpellHold = 1;
|
||||
constexpr uint8 SpellDelay = 2;
|
||||
@@ -118,32 +118,13 @@ namespace BotSettingCategories {
|
||||
constexpr uint16 END = BotSettingCategories::SpellTypeAnnounceCast;
|
||||
};
|
||||
|
||||
static std::map<uint8, std::string> bot_setting_category_names = {
|
||||
{ BotSettingCategories::BaseSetting, "Base Setting" },
|
||||
{ BotSettingCategories::SpellHold, "Spell Holds" },
|
||||
{ BotSettingCategories::SpellDelay, "Spell Delays" },
|
||||
{ BotSettingCategories::SpellMinThreshold, "Spell Minimum Thresholds" },
|
||||
{ BotSettingCategories::SpellMaxThreshold, "Spell Maximum Thresholds" },
|
||||
{ BotSettingCategories::SpellTypeResistLimit, "Spell Resist Limits" },
|
||||
{ BotSettingCategories::SpellTypeAggroCheck, "Spell Aggro Checks" },
|
||||
{ BotSettingCategories::SpellTypeMinManaPct, "Spell Min Mana Percent" },
|
||||
{ BotSettingCategories::SpellTypeMaxManaPct, "Spell Max Mana Percent" },
|
||||
{ BotSettingCategories::SpellTypeMinHPPct, "Spell Min HP Percent" },
|
||||
{ BotSettingCategories::SpellTypeMaxHPPct, "Spell Max HP Percent" },
|
||||
{ BotSettingCategories::SpellTypeIdlePriority, "Spell Idle Priority" },
|
||||
{ BotSettingCategories::SpellTypeEngagedPriority, "Spell Engaged Priority" },
|
||||
{ BotSettingCategories::SpellTypePursuePriority, "Spell Pursue Priority" },
|
||||
{ BotSettingCategories::SpellTypeAEOrGroupTargetCount, "Spell Target Counts" },
|
||||
{ BotSettingCategories::SpellTypeAnnounceCast, "Spell Announce Casts" }
|
||||
};
|
||||
|
||||
static std::map<uint8, std::string> bot_setting_category_short_names = {
|
||||
static std::map<uint8, std::string> botSpellCategory_names = {
|
||||
{ BotSettingCategories::BaseSetting, "BaseSetting" },
|
||||
{ BotSettingCategories::SpellHold, "SpellHolds" },
|
||||
{ BotSettingCategories::SpellDelay, "SpellDelays" },
|
||||
{ BotSettingCategories::SpellMinThreshold, "SpellMinThresholds" },
|
||||
{ BotSettingCategories::SpellMaxThreshold, "SpellMaxThresholds" },
|
||||
{ BotSettingCategories::SpellTypeResistLimit, "SpellResistLimits" },
|
||||
{ BotSettingCategories::SpellTypeResistLimit, "SpellResistLimit" },
|
||||
{ BotSettingCategories::SpellTypeAggroCheck, "SpellAggroChecks" },
|
||||
{ BotSettingCategories::SpellTypeMinManaPct, "SpellMinManaPct" },
|
||||
{ BotSettingCategories::SpellTypeMaxManaPct, "SpellMaxManaPct" },
|
||||
@@ -156,7 +137,7 @@ static std::map<uint8, std::string> bot_setting_category_short_names = {
|
||||
{ BotSettingCategories::SpellTypeAnnounceCast, "SpellAnnounceCasts" }
|
||||
};
|
||||
|
||||
namespace BotPriorityCategories {
|
||||
namespace BotPriorityCategories { // Update GetBotSpellCategoryName as needed
|
||||
constexpr uint8 Idle = 0;
|
||||
constexpr uint8 Engaged = 1;
|
||||
constexpr uint8 Pursue = 2;
|
||||
@@ -610,6 +591,7 @@ public:
|
||||
void SetBotBaseSetting(uint16 bot_setting, int setting_value);
|
||||
int GetSetting(uint16 setting_category, uint16 setting_type);
|
||||
void SetBotSetting(uint8 setting_type, uint16 bot_setting, int setting_value);
|
||||
void CopySettings(Bot* to, uint8 setting_type, uint16 spell_type = UINT16_MAX);
|
||||
void CopyBotSpellSettings(Bot* to);
|
||||
void ResetBotSpellSettings();
|
||||
|
||||
@@ -661,7 +643,7 @@ public:
|
||||
uint8 GetDefaultSpellTypeMinThreshold(uint16 spell_type, uint8 stance = Stance::Balanced);
|
||||
uint8 GetDefaultSpellTypeMaxThreshold(uint16 spell_type, uint8 stance = Stance::Balanced);
|
||||
uint16 GetUltimateSpellTypeDelay(uint16 spell_type, Mob* tar);
|
||||
bool GetUltimateSpellTypeRecastCheck(uint16 spell_type, Mob* tar);
|
||||
bool GetUltimateSpellTypeDelayCheck(uint16 spell_type, Mob* tar);
|
||||
uint8 GetUltimateSpellTypeMinThreshold(uint16 spell_type, Mob* tar);
|
||||
uint8 GetUltimateSpellTypeMaxThreshold(uint16 spell_type, Mob* tar);
|
||||
void SetIllusionBlock(bool value) { _illusionBlock = value; }
|
||||
@@ -695,7 +677,6 @@ public:
|
||||
bool IsValidSpellTypeSubType(uint16 spell_type, uint16 sub_type, uint16 spell_id);
|
||||
static bool IsValidBotSpellCategory(uint8 setting_type);
|
||||
static std::string GetBotSpellCategoryName(uint8 setting_type);
|
||||
static std::string GetBotSpellCategoryShortName(uint8 setting_type);
|
||||
static uint16 GetBotSpellCategoryIDByShortName(std::string setting_string);
|
||||
void AssignBotSpellsToTypes(std::vector<BotSpells>& AIBot_spells, std::unordered_map<uint16, std::vector<BotSpells_wIndex>>& AIBot_spells_by_type);
|
||||
uint16 GetSpellByAA(int id, AA::Rank*& rank);
|
||||
@@ -816,7 +797,6 @@ public:
|
||||
|
||||
bool GetRangerAutoWeaponSelect() { return _rangerAutoWeaponSelect; }
|
||||
uint8 GetBotStance() { return _botStance; }
|
||||
static bool IsValidBotStance(uint8 stance);
|
||||
uint8 GetChanceToCastBySpellType(uint16 spell_type);
|
||||
bool IsGroupHealer() const { return m_CastingRoles.GroupHealer; }
|
||||
bool IsGroupSlower() const { return m_CastingRoles.GroupSlower; }
|
||||
@@ -1127,7 +1107,6 @@ public:
|
||||
bool TryAutoDefend(Client* bot_owner, float leash_distance);
|
||||
bool TryIdleChecks(float fm_distance);
|
||||
bool TryNonCombatMovementChecks(Client* bot_owner, const Mob* follow_mob, glm::vec3& Goal);
|
||||
void DoOutOfCombatChecks(Client* bot_owner, Mob* follow_mob, glm::vec3& Goal, float leash_distance, float fm_distance);
|
||||
bool TryBardMovementCasts();
|
||||
bool BotRangedAttack(Mob* other, bool can_double_attack = false);
|
||||
bool CheckDoubleRangedAttack();
|
||||
|
||||
@@ -53,7 +53,6 @@ void bot_command_attack(Client *c, const Seperator *sep)
|
||||
size_t attacker_count = 0;
|
||||
Bot *first_attacker = nullptr;
|
||||
sbl.erase(std::remove(sbl.begin(), sbl.end(), nullptr), sbl.end());
|
||||
|
||||
for (auto bot_iter : sbl) {
|
||||
if (!bot_iter->ValidStateCheck(c)) {
|
||||
continue;
|
||||
|
||||
@@ -12,7 +12,6 @@ void bot_command_behind_mob(Client* c, const Seperator* sep)
|
||||
BotCommandHelpParams p;
|
||||
|
||||
p.description = { "Toggles whether or not bots will stay behind the mob during combat." };
|
||||
p.notes = { "- Bots that are taunting will remain in front of their target"};
|
||||
p.example_format = { fmt::format("{} [value] [actionable]", sep->arg[0]) };
|
||||
p.examples_one =
|
||||
{
|
||||
@@ -85,7 +84,6 @@ void bot_command_behind_mob(Client* c, const Seperator* sep)
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ void bot_command_blocked_buffs(Client* c, const Seperator* sep)
|
||||
}
|
||||
|
||||
if (helper_command_alias_fail(c, "bot_command_blocked_buffs", sep->arg[0], "blockedbuffs")) {
|
||||
c->Message(Chat::White, "note: Allows you to set, view and wipe beneficial blocked buffs for the selected bots.");
|
||||
c->Message(Chat::White, "note: Allows you to set, view and wipe blocked buffs for the selected bots.");
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -17,7 +17,7 @@ void bot_command_blocked_buffs(Client* c, const Seperator* sep)
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
BotCommandHelpParams p;
|
||||
|
||||
p.description = { "Allows you to set, view and wipe beneficial blocked buffs for the selected bots." };
|
||||
p.description = { "Allows you to set, view and wipe blocked buffs for the selected bots." };
|
||||
p.notes = { "- You can 'set' spells to be blocked, 'remove' spells from the blocked list, 'list' the current blocked spells or 'wipe' the entire list." };
|
||||
p.example_format = { fmt::format("{} [add [ID] | remove [ID] | list | wipe] [actionable, default: target]", sep->arg[0]) };
|
||||
p.examples_one =
|
||||
@@ -231,7 +231,7 @@ void bot_command_blocked_pet_buffs(Client* c, const Seperator* sep)
|
||||
}
|
||||
|
||||
if (helper_command_alias_fail(c, "bot_command_blocked_pet_buffs", sep->arg[0], "blockedpetbuffs")) {
|
||||
c->Message(Chat::White, "note: Allows you to set, view and wipe beneficial blocked pet buffs for the selected bots.");
|
||||
c->Message(Chat::White, "note: Allows you to set, view and wipe blocked pet buffs for the selected bots.");
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -239,7 +239,7 @@ void bot_command_blocked_pet_buffs(Client* c, const Seperator* sep)
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
BotCommandHelpParams p;
|
||||
|
||||
p.description = { "Allows you to set, view and wipe beneficial blocked pet buffs for the selected bots." };
|
||||
p.description = { "Allows you to set, view and wipe blocked pet buffs for the selected bots." };
|
||||
p.notes =
|
||||
{
|
||||
"- You can 'set' spells to be blocked, 'remove' spells from the blocked list, 'list' the current blocked spells or 'wipe' the entire list.",
|
||||
|
||||
@@ -480,7 +480,7 @@ void bot_command_follow_distance(Client *c, const Seperator *sep)
|
||||
p.description = { "Sets or resets the follow distance of the selected bots." };
|
||||
p.notes =
|
||||
{
|
||||
fmt::format("[Default]: {}", RuleI(Bots, DefaultFollowDistance)),
|
||||
fmt::format("[Default]: {}", RuleI(Bots, MaxFollowDistance)),
|
||||
fmt::format("- You must use a value between 1 and {}.", RuleI(Bots, MaxFollowDistance))
|
||||
};
|
||||
p.example_format = { fmt::format("{} [reset]/[set [value]] [actionable]", sep->arg[0]) };
|
||||
@@ -1154,7 +1154,7 @@ void bot_command_stance(Client *c, const Seperator *sep)
|
||||
p.description = { "Change a bot's stance to control the way it behaves." };
|
||||
p.notes =
|
||||
{
|
||||
"- Changing a stance will reset all settings to match that stance type.",
|
||||
"- <b>Changing a stance will reset all settings to match that stance type.</b>",
|
||||
"- Any changes made will only save to that stance for future use.",
|
||||
fmt::format(
|
||||
"- {} (#{}) will tell Non-Warrior classes to taunt automatically.",
|
||||
@@ -1181,16 +1181,16 @@ void bot_command_stance(Client *c, const Seperator *sep)
|
||||
Stance::AEBurn
|
||||
),
|
||||
"<br>",
|
||||
fmt::format(
|
||||
"- {} (#{}) - Idle. Does not cast or engage in combat.",
|
||||
Stance::GetName(Stance::Passive),
|
||||
Stance::Passive
|
||||
),
|
||||
fmt::format(
|
||||
"- {} (#{}) [Default] - Overall balance and casts most spell types by default.",
|
||||
Stance::GetName(Stance::Balanced),
|
||||
Stance::Balanced
|
||||
),
|
||||
fmt::format(
|
||||
"- {} (#{}) - Idle. Does not cast or engage in combat.",
|
||||
Stance::GetName(Stance::Passive),
|
||||
Stance::Passive
|
||||
),
|
||||
fmt::format(
|
||||
"- {} (#{}) - More mana and aggro efficient (SKs will still cast hate line). Longer delays between detrimental spells, thresholds adjusted to cast less often.",
|
||||
Stance::GetName(Stance::Efficient),
|
||||
@@ -1263,7 +1263,12 @@ void bot_command_stance(Client *c, const Seperator *sep)
|
||||
if (sep->IsNumber(1)) {
|
||||
++ab_arg;
|
||||
value = atoi(sep->arg[1]);
|
||||
if (!Bot::IsValidBotStance(value)) {
|
||||
if (
|
||||
value < Stance::Passive ||
|
||||
value > Stance::AEBurn ||
|
||||
value == Stance::Reactive ||
|
||||
value == Stance::Assist
|
||||
) {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
|
||||
+172
-163
@@ -52,7 +52,7 @@ void bot_command_copy_settings(Client* c, const Seperator* sep)
|
||||
),
|
||||
};
|
||||
p.actionables = { "target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned" };
|
||||
p.options = { "all, misc, spellsettings, spelltypesettings, spellholds, spelldelays, spellminthresholds, spellmaxthresholds, spellresistlimits, spellaggrochecks, spellminmanapct, spellmaxmanapct, spellminhppct, spellmaxhppct, spellidlepriority, spellengagedpriority, spellpursuepriority, spelltargetcounts, spellannouncecasts, blockedbuffs, blockedpetbuffs" };
|
||||
p.options = { "all, misc, spellsettings, spelltypesettings, spellholds, spelldelays, spellminthresholds, spellmaxthresholds, spellminmanapct, spellmaxmanapct, spellminhppct, spellmaxhppct, spellidlepriority, spellengagedpriority, spellpursuepriority, spellaggrochecks, spelltargetcounts, spellresistlimits, spellannouncecasts, blockedbuffs, blockedpetbuffs" };
|
||||
p.options_one =
|
||||
{
|
||||
"[spellsettings] will copy ^spellsettings options",
|
||||
@@ -85,6 +85,12 @@ void bot_command_copy_settings(Client* c, const Seperator* sep)
|
||||
return;
|
||||
}
|
||||
|
||||
int spell_type_arg_int = 4;
|
||||
std::string spell_type_arg = sep->arg[spell_type_arg_int];
|
||||
int ab_arg = 2;
|
||||
bool valid_option = false;
|
||||
uint16 spell_type = UINT16_MAX;
|
||||
uint16 setting_type = UINT16_MAX;
|
||||
std::vector<std::string> options =
|
||||
{
|
||||
"all",
|
||||
@@ -94,79 +100,63 @@ void bot_command_copy_settings(Client* c, const Seperator* sep)
|
||||
"spellholds",
|
||||
"spelldelays",
|
||||
"spellminthresholds",
|
||||
"spellmaxthresholds",
|
||||
"spellresistlimits",
|
||||
"spellaggrochecks",
|
||||
"spellmaxthresholds",
|
||||
"spellminmanapct",
|
||||
"spellmaxmanapct",
|
||||
"spellminhppct",
|
||||
"spellmaxhppct",
|
||||
"spellidlepriority",
|
||||
"spellengagedpriority",
|
||||
"spellpursuepriority",
|
||||
"spellpursuepriority",
|
||||
"spellaggrochecks",
|
||||
"spelltargetcounts",
|
||||
"spellresistlimits",
|
||||
"spellannouncecasts",
|
||||
"blockedbuffs",
|
||||
"blockedpetbuffs"
|
||||
};
|
||||
|
||||
std::string option_arg = Strings::ToLower(sep->arg[3]);
|
||||
bool valid_option = false;
|
||||
bool copy_all = false;
|
||||
bool copy_misc = false;
|
||||
bool copy_spell_settings = false;
|
||||
bool copy_spell_type_settings = false;
|
||||
bool copy_blocked_buffs = false;
|
||||
bool copy_blocked_pet_buffs = false;
|
||||
uint16 setting_type = UINT16_MAX;
|
||||
if (sep->IsNumber(spell_type_arg_int)) {
|
||||
spell_type = atoi(sep->arg[spell_type_arg_int]);
|
||||
|
||||
if (!Bot::IsValidBotSpellType(spell_type)) {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"You must choose a valid spell type. Use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!spell_type_arg.empty()) {
|
||||
if (Bot::GetSpellTypeIDByShortName(spell_type_arg) != UINT16_MAX) {
|
||||
spell_type = Bot::GetSpellTypeIDByShortName(spell_type_arg);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"You must choose a valid spell type. Use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < options.size(); i++) {
|
||||
if (option_arg == options[i]) {
|
||||
if (option_arg == "all") {
|
||||
copy_all = true;
|
||||
valid_option = true;
|
||||
|
||||
break;
|
||||
}
|
||||
else if (option_arg == "misc") {
|
||||
copy_misc = true;
|
||||
valid_option = true;
|
||||
|
||||
break;
|
||||
}
|
||||
else if (option_arg == "spellsettings") {
|
||||
copy_spell_settings = true;
|
||||
valid_option = true;
|
||||
|
||||
break;
|
||||
}
|
||||
else if (option_arg == "spelltypesettings") {
|
||||
copy_spell_type_settings = true;
|
||||
valid_option = true;
|
||||
|
||||
break;
|
||||
}
|
||||
else if (option_arg == "blockedbuffs") {
|
||||
copy_blocked_buffs = true;
|
||||
valid_option = true;
|
||||
|
||||
break;
|
||||
}
|
||||
else if (option_arg == "blockedpetbuffs") {
|
||||
copy_blocked_pet_buffs = true;
|
||||
valid_option = true;
|
||||
|
||||
break;
|
||||
}
|
||||
else {
|
||||
setting_type = Bot::GetBotSpellCategoryIDByShortName(option_arg);
|
||||
|
||||
if (setting_type != UINT16_MAX) {
|
||||
valid_option = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sep->arg[3] == options[i]) {
|
||||
setting_type = Bot::GetBotSpellCategoryIDByShortName(sep->arg[3]);
|
||||
valid_option = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,18 +226,125 @@ void bot_command_copy_settings(Client* c, const Seperator* sep)
|
||||
return;
|
||||
}
|
||||
|
||||
int ab_arg = 4;
|
||||
std::string spell_type_arg = sep->arg[ab_arg];
|
||||
uint16 spell_type = UINT16_MAX;
|
||||
std::string output = "";
|
||||
|
||||
if (sep->IsNumber(ab_arg)) {
|
||||
spell_type = atoi(sep->arg[ab_arg]);
|
||||
if (setting_type != UINT16_MAX) {
|
||||
if (spell_type != UINT16_MAX) {
|
||||
from->CopySettings(to, setting_type, spell_type);
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
from->CopySettings(to, setting_type, i);
|
||||
}
|
||||
}
|
||||
|
||||
if (!EQ::ValueWithin(spell_type, BotSpellTypes::START, BotSpellTypes::END)) {
|
||||
output = Bot::GetBotSpellCategoryName(setting_type);
|
||||
}
|
||||
else {
|
||||
if (!strcasecmp(sep->arg[3], "misc")) {
|
||||
from->CopySettings(to, BotSettingCategories::BaseSetting);
|
||||
output = "Miscellaneous";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[3], "spellsettings")) {
|
||||
from->CopyBotSpellSettings(to);
|
||||
output = "^spellsettings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[3], "spelltypesettings")) {
|
||||
if (spell_type != UINT16_MAX) {
|
||||
from->CopySettings(to, BotSettingCategories::SpellHold, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellDelay, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellMinThreshold, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellMaxThreshold, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeAggroCheck, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeResistLimit, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMinManaPct, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMaxManaPct, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMinHPPct, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMaxHPPct, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeIdlePriority, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeEngagedPriority, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypePursuePriority, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeAEOrGroupTargetCount, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeAnnounceCast, spell_type);
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
from->CopySettings(to, BotSettingCategories::SpellHold, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellDelay, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellMinThreshold, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellMaxThreshold, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeAggroCheck, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeResistLimit, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMinManaPct, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMaxManaPct, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMinHPPct, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMaxHPPct, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeIdlePriority, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeEngagedPriority, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypePursuePriority, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeAEOrGroupTargetCount, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeAnnounceCast, i);
|
||||
}
|
||||
}
|
||||
|
||||
output = "spell type";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[3], "blockedbuffs")) {
|
||||
from->CopyBotBlockedBuffs(to);
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[3], "blockedpetbuffs")) {
|
||||
from->CopyBotBlockedPetBuffs(to);
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[3], "all")) {
|
||||
from->CopySettings(to, BotSettingCategories::BaseSetting);
|
||||
|
||||
if (spell_type != UINT16_MAX) {
|
||||
from->CopySettings(to, BotSettingCategories::SpellHold, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellDelay, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellMinThreshold, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellMaxThreshold, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeAggroCheck, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeResistLimit, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMinManaPct, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMaxManaPct, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMinHPPct, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMaxHPPct, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeIdlePriority, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeEngagedPriority, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypePursuePriority, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeAEOrGroupTargetCount, spell_type);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeAnnounceCast, spell_type);
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
from->CopySettings(to, BotSettingCategories::SpellHold, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellDelay, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellMinThreshold, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellMaxThreshold, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeAggroCheck, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeResistLimit, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMinManaPct, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMaxManaPct, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMinHPPct, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMaxHPPct, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeIdlePriority, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeEngagedPriority, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypePursuePriority, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeAEOrGroupTargetCount, i);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeAnnounceCast, i);
|
||||
}
|
||||
}
|
||||
|
||||
from->CopyBotSpellSettings(to);
|
||||
from->CopyBotBlockedBuffs(to);
|
||||
from->CopyBotBlockedPetBuffs(to);
|
||||
output = "spell type";
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"You must choose a valid spell type. Use {} for information regarding this command.",
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
@@ -256,101 +353,6 @@ void bot_command_copy_settings(Client* c, const Seperator* sep)
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
++ab_arg;
|
||||
}
|
||||
else if (!spell_type_arg.empty()) {
|
||||
if (Bot::GetSpellTypeIDByShortName(spell_type_arg) != UINT16_MAX) {
|
||||
spell_type = Bot::GetSpellTypeIDByShortName(spell_type_arg);
|
||||
++ab_arg;
|
||||
}
|
||||
else {
|
||||
if (
|
||||
!copy_all &&
|
||||
!copy_misc &&
|
||||
!copy_spell_settings &&
|
||||
!copy_blocked_buffs &&
|
||||
!copy_blocked_pet_buffs
|
||||
) {
|
||||
c->Message(Chat::Yellow, "If you are trying to specify a spell type, you must enter a valid spell type. Otherwise you can ignore this message.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string output = "";
|
||||
|
||||
if (copy_all) {
|
||||
for (uint16 i = BotBaseSettings::START; i <= BotBaseSettings::END; ++i) {
|
||||
to->SetBotBaseSetting(i, from->GetBotBaseSetting(i));
|
||||
}
|
||||
|
||||
for (uint16 i = BotSettingCategories::START_NO_BASE; i <= BotSettingCategories::END; ++i) {
|
||||
for (uint16 x = BotSpellTypes::START; x <= BotSpellTypes::END; ++x) {
|
||||
to->SetBotSetting(i, x, from->GetSetting(i, x));
|
||||
}
|
||||
}
|
||||
|
||||
from->CopyBotSpellSettings(to);
|
||||
from->CopyBotBlockedBuffs(to);
|
||||
from->CopyBotBlockedPetBuffs(to);
|
||||
output = "settings were";
|
||||
}
|
||||
else if (copy_misc) {
|
||||
for (uint16 i = BotBaseSettings::START; i <= BotBaseSettings::END; ++i) {
|
||||
to->SetBotBaseSetting(i, from->GetBotBaseSetting(i));
|
||||
output = "miscellaneous settings were";
|
||||
}
|
||||
}
|
||||
else if (copy_spell_settings) {
|
||||
from->ResetBotSpellSettings();
|
||||
output = "^spellsettings were";
|
||||
}
|
||||
else if (copy_spell_type_settings) {
|
||||
if (spell_type != UINT16_MAX) {
|
||||
for (uint16 i = BotSettingCategories::START_NO_BASE; i <= BotSettingCategories::END; ++i) {
|
||||
to->SetBotSetting(i, spell_type, from->GetSetting(i, spell_type));
|
||||
}
|
||||
|
||||
output = fmt::format(
|
||||
"[{}] settings were",
|
||||
Bot::GetSpellTypeNameByID(spell_type)
|
||||
);
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSettingCategories::START_NO_BASE; i <= BotSettingCategories::END; ++i) {
|
||||
for (uint16 x = BotSpellTypes::START; x <= BotSpellTypes::END; ++x) {
|
||||
to->SetBotSetting(i, x, from->GetSetting(i, x));
|
||||
}
|
||||
}
|
||||
|
||||
output = "spell type settings were";
|
||||
}
|
||||
}
|
||||
else if (copy_blocked_buffs) {
|
||||
from->CopyBotBlockedBuffs(to);
|
||||
}
|
||||
else if (copy_blocked_pet_buffs) {
|
||||
from->CopyBotBlockedPetBuffs(to);
|
||||
}
|
||||
else if (setting_type != UINT16_MAX) {
|
||||
if (spell_type != UINT16_MAX) {
|
||||
to->SetBotSetting(setting_type, spell_type, from->GetSetting(setting_type, spell_type));
|
||||
output = fmt::format(
|
||||
"[{}] {} were",
|
||||
Bot::GetSpellTypeNameByID(spell_type),
|
||||
Bot::GetBotSpellCategoryName(Bot::GetBotSpellCategoryIDByShortName(option_arg))
|
||||
);
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
to->SetBotSetting(setting_type, i, from->GetSetting(setting_type, i));
|
||||
}
|
||||
|
||||
output = fmt::format(
|
||||
"{} settings for all spell types",
|
||||
Bot::GetBotSpellCategoryName(Bot::GetBotSpellCategoryIDByShortName(option_arg))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
to->Save();
|
||||
@@ -358,8 +360,15 @@ void bot_command_copy_settings(Client* c, const Seperator* sep)
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{}'s {} copied to {}.",
|
||||
"{}'s{}{} settings were copied to {}.",
|
||||
from->GetCleanName(),
|
||||
(
|
||||
spell_type != UINT16_MAX ?
|
||||
fmt::format(" [{}] ",
|
||||
Bot::GetSpellTypeNameByID(spell_type)
|
||||
)
|
||||
: " "
|
||||
),
|
||||
output,
|
||||
to->GetCleanName()
|
||||
).c_str()
|
||||
|
||||
@@ -11,7 +11,7 @@ void bot_command_default_settings(Client* c, const Seperator* sep)
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
BotCommandHelpParams p;
|
||||
|
||||
p.description = { "Restores a bot's setting(s) to defaults." };
|
||||
p.description = { "Restores a bot's setting(s) to defaults" };
|
||||
p.notes = { "- You can put a spell type ID or shortname after any option except [all], [misc] and [spellsettings] to restore that specifc spell type only"};
|
||||
p.example_format = { fmt::format("{} [option] [optional: spelltype id/short name] [actionable]", sep->arg[0]) };
|
||||
p.examples_one =
|
||||
@@ -38,7 +38,7 @@ void bot_command_default_settings(Client* c, const Seperator* sep)
|
||||
)
|
||||
};
|
||||
p.actionables = { "target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned" };
|
||||
p.options = { "all, misc, spellsettings, spelltypesettings, spellholds, spelldelays, spellminthresholds, spellmaxthresholds, spellresistlimits, spellaggrocheck, spellminmanapct, spellmaxmanapct, spellminhppct, spellmaxhppct, spellidlepriority, spellengagedpriority, spellpursuepriority, spelltargetcounts, spellannouncecasts" };
|
||||
p.options = { "all, misc, spellsettings, spelltypesettings, spellholds, spelldelays, spellminthresholds, spellmaxthresholds, spellminmanapct, spellmaxmanapct, spellminhppct, spellmaxhppct, spellidlepriority, spellengagedpriority, spellpursuepriority, spellaggrocheck, spelltargetcounts, spellresistlimits, spellannouncecasts" };
|
||||
p.options_one =
|
||||
{
|
||||
"[spellsettings] will restore ^spellsettings options",
|
||||
@@ -75,6 +75,12 @@ void bot_command_default_settings(Client* c, const Seperator* sep)
|
||||
return;
|
||||
}
|
||||
|
||||
int spell_type_arg_int = 2;
|
||||
std::string spell_type_arg = sep->arg[spell_type_arg_int];
|
||||
int ab_arg = 2;
|
||||
bool valid_option = false;
|
||||
uint16 spell_type = UINT16_MAX;
|
||||
uint16 setting_type = UINT16_MAX;
|
||||
std::vector<std::string> options =
|
||||
{
|
||||
"all",
|
||||
@@ -85,8 +91,6 @@ void bot_command_default_settings(Client* c, const Seperator* sep)
|
||||
"spelldelays",
|
||||
"spellminthresholds",
|
||||
"spellmaxthresholds",
|
||||
"spellresistlimits",
|
||||
"spellaggrochecks",
|
||||
"spellminmanapct",
|
||||
"spellmaxmanapct",
|
||||
"spellminhppct",
|
||||
@@ -94,76 +98,14 @@ void bot_command_default_settings(Client* c, const Seperator* sep)
|
||||
"spellidlepriority",
|
||||
"spellengagedpriority",
|
||||
"spellpursuepriority",
|
||||
"spellaggrochecks",
|
||||
"spelltargetcounts",
|
||||
"spellresistlimits",
|
||||
"spellannouncecasts"
|
||||
};
|
||||
|
||||
std::string option_arg = Strings::ToLower(sep->arg[1]);
|
||||
bool valid_option = false;
|
||||
bool default_all = false;
|
||||
bool default_misc = false;
|
||||
bool default_spell_settings = false;
|
||||
bool default_spell_type_settings = false;
|
||||
uint16 setting_type = UINT16_MAX;
|
||||
|
||||
for (int i = 0; i < options.size(); i++) {
|
||||
if (option_arg == options[i]) {
|
||||
if (option_arg == "all") {
|
||||
default_all = true;
|
||||
valid_option = true;
|
||||
|
||||
break;
|
||||
}
|
||||
else if (option_arg == "misc") {
|
||||
default_misc = true;
|
||||
valid_option = true;
|
||||
|
||||
break;
|
||||
}
|
||||
else if (option_arg == "spellsettings") {
|
||||
default_spell_settings = true;
|
||||
valid_option = true;
|
||||
|
||||
break;
|
||||
}
|
||||
else if (option_arg == "spelltypesettings") {
|
||||
default_spell_type_settings = true;
|
||||
valid_option = true;
|
||||
|
||||
break;
|
||||
}
|
||||
else {
|
||||
setting_type = Bot::GetBotSpellCategoryIDByShortName(option_arg);
|
||||
|
||||
if (setting_type != UINT16_MAX) {
|
||||
valid_option = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid_option) {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int ab_arg = 2;
|
||||
std::string spell_type_arg = sep->arg[ab_arg];
|
||||
uint16 spell_type = UINT16_MAX;
|
||||
|
||||
if (sep->IsNumber(ab_arg)) {
|
||||
spell_type = atoi(sep->arg[ab_arg]);
|
||||
if (sep->IsNumber(spell_type_arg_int)) {
|
||||
spell_type = atoi(sep->arg[spell_type_arg_int]);
|
||||
|
||||
if (!EQ::ValueWithin(spell_type, BotSpellTypes::START, BotSpellTypes::END)) {
|
||||
c->Message(
|
||||
@@ -184,13 +126,44 @@ void bot_command_default_settings(Client* c, const Seperator* sep)
|
||||
else if (!spell_type_arg.empty()) {
|
||||
if (Bot::GetSpellTypeIDByShortName(spell_type_arg) != UINT16_MAX) {
|
||||
spell_type = Bot::GetSpellTypeIDByShortName(spell_type_arg);
|
||||
++ab_arg;
|
||||
}
|
||||
else {
|
||||
if (!default_all && !default_misc && !default_spell_settings) {
|
||||
c->Message(Chat::Yellow, "If you are trying to specify a spell type, you must enter a valid spell type. Otherwise you can ignore this message.");
|
||||
}
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"You must choose a valid spell type. Use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
++ab_arg;
|
||||
}
|
||||
|
||||
for (int i = 0; i < options.size(); i++) {
|
||||
if (sep->arg[1] == options[i]) {
|
||||
setting_type = Bot::GetBotSpellCategoryIDByShortName(sep->arg[1]);
|
||||
valid_option = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid_option) {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
@@ -220,72 +193,286 @@ void bot_command_default_settings(Client* c, const Seperator* sep)
|
||||
}
|
||||
|
||||
bot_stance = my_bot->GetBotStance();
|
||||
|
||||
if (default_all) {
|
||||
for (uint16 i = BotBaseSettings::START; i <= BotBaseSettings::END; ++i) {
|
||||
my_bot->SetBotBaseSetting(i, my_bot->GetDefaultBotBaseSetting(i, bot_stance));
|
||||
}
|
||||
|
||||
for (uint16 i = BotSettingCategories::START_NO_BASE; i <= BotSettingCategories::END; ++i) {
|
||||
for (uint16 x = BotSpellTypes::START; x <= BotSpellTypes::END; ++x) {
|
||||
my_bot->SetBotSetting(i, x, my_bot->GetDefaultSetting(i, x, bot_stance));
|
||||
}
|
||||
}
|
||||
|
||||
my_bot->ResetBotSpellSettings();
|
||||
my_bot->ClearBotBlockedBuffs();
|
||||
output = "settings were reset";
|
||||
}
|
||||
else if (default_misc) {
|
||||
for (uint16 i = BotBaseSettings::START; i <= BotBaseSettings::END; ++i) {
|
||||
my_bot->SetBotBaseSetting(i, my_bot->GetDefaultBotBaseSetting(i, bot_stance));
|
||||
output = "miscellaneous settings were reset";
|
||||
}
|
||||
}
|
||||
else if (default_spell_settings) {
|
||||
my_bot->ResetBotSpellSettings();
|
||||
output = "^spellsettings were reset";
|
||||
}
|
||||
else if (default_spell_type_settings) {
|
||||
if (spell_type != UINT16_MAX) {
|
||||
for (uint16 i = BotSettingCategories::START_NO_BASE; i <= BotSettingCategories::END; ++i) {
|
||||
my_bot->SetBotSetting(i, spell_type, my_bot->GetDefaultSetting(i, spell_type, bot_stance));
|
||||
}
|
||||
|
||||
output = fmt::format(
|
||||
"[{}] settings were reset",
|
||||
Bot::GetSpellTypeNameByID(spell_type)
|
||||
);
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSettingCategories::START_NO_BASE; i <= BotSettingCategories::END; ++i) {
|
||||
for (uint16 x = BotSpellTypes::START; x <= BotSpellTypes::END; ++x) {
|
||||
my_bot->SetBotSetting(i, x, my_bot->GetDefaultSetting(i, x, bot_stance));
|
||||
}
|
||||
}
|
||||
|
||||
output = "spell type settings were reset";
|
||||
}
|
||||
}
|
||||
else if (setting_type != UINT16_MAX) {
|
||||
if (setting_type != UINT16_MAX) {
|
||||
if (spell_type != UINT16_MAX) {
|
||||
my_bot->SetBotSetting(setting_type, spell_type, my_bot->GetDefaultSetting(setting_type, spell_type, bot_stance));
|
||||
output = fmt::format(
|
||||
"[{}] {} were reset",
|
||||
Bot::GetSpellTypeNameByID(spell_type),
|
||||
Bot::GetBotSpellCategoryName(Bot::GetBotSpellCategoryIDByShortName(option_arg))
|
||||
);
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetBotSetting(setting_type, i, my_bot->GetDefaultSetting(setting_type, i, bot_stance));
|
||||
}
|
||||
|
||||
output = fmt::format(
|
||||
"{} settings were reset for all spell types",
|
||||
Bot::GetBotSpellCategoryName(Bot::GetBotSpellCategoryIDByShortName(option_arg))
|
||||
);
|
||||
}
|
||||
|
||||
output = (spell_type != UINT16_MAX ? Bot::GetSpellTypeNameByID(spell_type) : "");
|
||||
output += sep->arg[3];
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "misc")) {
|
||||
for (uint16 i = BotBaseSettings::START; i <= BotBaseSettings::END; ++i) {
|
||||
my_bot->SetBotBaseSetting(i, my_bot->GetDefaultBotBaseSetting(i, bot_stance));
|
||||
output = "miscellanous settings";
|
||||
}
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "spellsettings")) {
|
||||
my_bot->ResetBotSpellSettings();
|
||||
output = "^spellsettings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "spelltypesettings")) {
|
||||
if (spell_type != UINT16_MAX) {
|
||||
my_bot->SetSpellTypeHold(spell_type, my_bot->GetDefaultSpellTypeHold(spell_type, bot_stance));
|
||||
my_bot->SetSpellTypeDelay(spell_type, my_bot->GetDefaultSpellTypeDelay(spell_type, bot_stance));
|
||||
my_bot->SetSpellTypeMinThreshold(
|
||||
spell_type,
|
||||
my_bot->GetDefaultSpellTypeMinThreshold(spell_type, bot_stance));
|
||||
my_bot->SetSpellTypeMaxThreshold(
|
||||
spell_type,
|
||||
my_bot->GetDefaultSpellTypeMaxThreshold(spell_type, bot_stance));
|
||||
my_bot->SetSpellTypeAggroCheck(spell_type, my_bot->GetDefaultSpellTypeAggroCheck(spell_type, bot_stance));
|
||||
my_bot->SetSpellTypeResistLimit(spell_type, my_bot->GetDefaultSpellTypeResistLimit(spell_type, bot_stance));
|
||||
my_bot->SetSpellTypeMinManaLimit(spell_type, my_bot->GetDefaultSpellTypeMinManaLimit(spell_type, bot_stance));
|
||||
my_bot->SetSpellTypeMaxManaLimit(spell_type, my_bot->GetDefaultSpellTypeMaxManaLimit(spell_type, bot_stance));
|
||||
my_bot->SetSpellTypeMinHPLimit(spell_type, my_bot->GetDefaultSpellTypeMinHPLimit(spell_type, bot_stance));
|
||||
my_bot->SetSpellTypeMaxHPLimit(spell_type, my_bot->GetDefaultSpellTypeMaxHPLimit(spell_type, bot_stance));
|
||||
my_bot->SetSpellTypePriority(spell_type, BotPriorityCategories::Idle, my_bot->GetDefaultSpellTypePriority(spell_type, BotPriorityCategories::Idle, my_bot->GetClass(), bot_stance));
|
||||
my_bot->SetSpellTypePriority(spell_type, BotPriorityCategories::Engaged, my_bot->GetDefaultSpellTypePriority(spell_type, BotPriorityCategories::Engaged, my_bot->GetClass(), bot_stance));
|
||||
my_bot->SetSpellTypePriority(spell_type, BotPriorityCategories::Pursue, my_bot->GetDefaultSpellTypePriority(spell_type, BotPriorityCategories::Pursue, my_bot->GetClass(), bot_stance));
|
||||
my_bot->SetSpellTypeAEOrGroupTargetCount(spell_type, my_bot->GetDefaultSpellTypeAEOrGroupTargetCount(spell_type, bot_stance));
|
||||
my_bot->SetSpellTypeAnnounceCast(spell_type, my_bot->GetDefaultSpellTypeAnnounceCast(spell_type, bot_stance));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellTypeHold(i, my_bot->GetDefaultSpellTypeHold(i, bot_stance));
|
||||
my_bot->SetSpellTypeDelay(i, my_bot->GetDefaultSpellTypeDelay(i, bot_stance));
|
||||
my_bot->SetSpellTypeMinThreshold(i, my_bot->GetDefaultSpellTypeMinThreshold(i, bot_stance));
|
||||
my_bot->SetSpellTypeMaxThreshold(i, my_bot->GetDefaultSpellTypeMaxThreshold(i, bot_stance));
|
||||
my_bot->SetSpellTypeAggroCheck(i, my_bot->GetDefaultSpellTypeAggroCheck(i, bot_stance));
|
||||
my_bot->SetSpellTypeResistLimit(i, my_bot->GetDefaultSpellTypeResistLimit(i, bot_stance));
|
||||
my_bot->SetSpellTypeMinManaLimit(i, my_bot->GetDefaultSpellTypeMinManaLimit(i, bot_stance));
|
||||
my_bot->SetSpellTypeMaxManaLimit(i, my_bot->GetDefaultSpellTypeMaxManaLimit(i, bot_stance));
|
||||
my_bot->SetSpellTypeMinHPLimit(i, my_bot->GetDefaultSpellTypeMinHPLimit(i, bot_stance));
|
||||
my_bot->SetSpellTypeMaxHPLimit(i, my_bot->GetDefaultSpellTypeMaxHPLimit(i, bot_stance));
|
||||
my_bot->SetSpellTypePriority(i, BotPriorityCategories::Idle, my_bot->GetDefaultSpellTypePriority(i, BotPriorityCategories::Idle, my_bot->GetClass(), bot_stance));
|
||||
my_bot->SetSpellTypePriority(i, BotPriorityCategories::Engaged, my_bot->GetDefaultSpellTypePriority(i, BotPriorityCategories::Engaged, my_bot->GetClass(), bot_stance));
|
||||
my_bot->SetSpellTypePriority(i, BotPriorityCategories::Pursue, my_bot->GetDefaultSpellTypePriority(i, BotPriorityCategories::Pursue, my_bot->GetClass(), bot_stance));
|
||||
my_bot->SetSpellTypeAEOrGroupTargetCount(i, my_bot->GetDefaultSpellTypeAEOrGroupTargetCount(i, bot_stance));
|
||||
my_bot->SetSpellTypeAnnounceCast(i, my_bot->GetDefaultSpellTypeAnnounceCast(i, bot_stance));
|
||||
}
|
||||
}
|
||||
|
||||
output = "spell type settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "all")) {
|
||||
for (uint16 i = BotBaseSettings::START; i <= BotBaseSettings::END; ++i) {
|
||||
my_bot->SetBotBaseSetting(i, my_bot->GetDefaultBotBaseSetting(i, bot_stance));
|
||||
}
|
||||
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellTypeHold(i, my_bot->GetDefaultSpellTypeHold(i, bot_stance));
|
||||
my_bot->SetSpellTypeDelay(i, my_bot->GetDefaultSpellTypeDelay(i, bot_stance));
|
||||
my_bot->SetSpellTypeMinThreshold(i, my_bot->GetDefaultSpellTypeMinThreshold(i, bot_stance));
|
||||
my_bot->SetSpellTypeMaxThreshold(i, my_bot->GetDefaultSpellTypeMaxThreshold(i, bot_stance));
|
||||
my_bot->SetSpellTypeAggroCheck(i, my_bot->GetDefaultSpellTypeAggroCheck(i, bot_stance));
|
||||
my_bot->SetSpellTypeResistLimit(i, my_bot->GetDefaultSpellTypeResistLimit(i, bot_stance));
|
||||
my_bot->SetSpellTypeMinManaLimit(i, my_bot->GetDefaultSpellTypeMinManaLimit(i, bot_stance));
|
||||
my_bot->SetSpellTypeMaxManaLimit(i, my_bot->GetDefaultSpellTypeMaxManaLimit(i, bot_stance));
|
||||
my_bot->SetSpellTypeMinHPLimit(i, my_bot->GetDefaultSpellTypeMinHPLimit(i, bot_stance));
|
||||
my_bot->SetSpellTypeMaxHPLimit(i, my_bot->GetDefaultSpellTypeMaxHPLimit(i, bot_stance));
|
||||
my_bot->SetSpellTypePriority(i, BotPriorityCategories::Idle, my_bot->GetDefaultSpellTypePriority(i, BotPriorityCategories::Idle, my_bot->GetClass(), bot_stance));
|
||||
my_bot->SetSpellTypePriority(i, BotPriorityCategories::Engaged, my_bot->GetDefaultSpellTypePriority(i, BotPriorityCategories::Engaged, my_bot->GetClass(), bot_stance));
|
||||
my_bot->SetSpellTypePriority(i, BotPriorityCategories::Pursue, my_bot->GetDefaultSpellTypePriority(i, BotPriorityCategories::Pursue, my_bot->GetClass(), bot_stance));
|
||||
my_bot->SetSpellTypeAEOrGroupTargetCount(i, my_bot->GetDefaultSpellTypeAEOrGroupTargetCount(i, bot_stance));
|
||||
my_bot->SetSpellTypeAnnounceCast(i, my_bot->GetDefaultSpellTypeAnnounceCast(i, bot_stance));
|
||||
};
|
||||
|
||||
my_bot->ResetBotSpellSettings();
|
||||
my_bot->ClearBotBlockedBuffs();
|
||||
|
||||
output = "settings";
|
||||
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "holds")) {
|
||||
if (spell_type != UINT16_MAX) {
|
||||
my_bot->SetSpellTypeHold(spell_type, my_bot->GetDefaultSpellTypeHold(spell_type, bot_stance));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellTypeHold(i, my_bot->GetDefaultSpellTypeHold(i, bot_stance));
|
||||
}
|
||||
}
|
||||
|
||||
output = "hold settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "delays")) {
|
||||
if (spell_type != UINT16_MAX) {
|
||||
my_bot->SetSpellTypeDelay(spell_type, my_bot->GetDefaultSpellTypeDelay(spell_type, bot_stance));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellTypeDelay(i, my_bot->GetDefaultSpellTypeDelay(i, bot_stance));
|
||||
}
|
||||
}
|
||||
|
||||
output = "delay settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "minthresholds")) {
|
||||
if (spell_type != UINT16_MAX) {
|
||||
my_bot->SetSpellTypeMinThreshold(
|
||||
spell_type,
|
||||
my_bot->GetDefaultSpellTypeMinThreshold(spell_type, bot_stance));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellTypeMinThreshold(i, my_bot->GetDefaultSpellTypeMinThreshold(i, bot_stance));
|
||||
}
|
||||
}
|
||||
|
||||
output = "minimum threshold settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "maxthresholds")) {
|
||||
if (spell_type != UINT16_MAX) {
|
||||
my_bot->SetSpellTypeMaxThreshold(
|
||||
spell_type,
|
||||
my_bot->GetDefaultSpellTypeMaxThreshold(spell_type, bot_stance));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellTypeMaxThreshold(i, my_bot->GetDefaultSpellTypeMaxThreshold(i, bot_stance));
|
||||
}
|
||||
}
|
||||
|
||||
output = "maximum threshold settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "aggrochecks")) {
|
||||
if (spell_type != UINT16_MAX) {
|
||||
my_bot->SetSpellTypeAggroCheck(spell_type, my_bot->GetDefaultSpellTypeAggroCheck(spell_type, bot_stance));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellTypeAggroCheck(i, my_bot->GetDefaultSpellTypeAggroCheck(i, bot_stance));
|
||||
}
|
||||
}
|
||||
|
||||
output = "aggro check settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "resist limit")) {
|
||||
if (spell_type != UINT16_MAX) {
|
||||
my_bot->SetSpellTypeAEOrGroupTargetCount(spell_type, my_bot->GetDefaultSpellTypeAEOrGroupTargetCount(spell_type, bot_stance));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellTypeAEOrGroupTargetCount(i, my_bot->GetDefaultSpellTypeAEOrGroupTargetCount(i, bot_stance));
|
||||
}
|
||||
}
|
||||
|
||||
output = "resist limit settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "minmanapct")) {
|
||||
if (spell_type != UINT16_MAX) {
|
||||
my_bot->SetSpellTypeMinManaLimit(spell_type, my_bot->GetDefaultSpellTypeMinManaLimit(spell_type, bot_stance));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellTypeMinManaLimit(i, my_bot->GetDefaultSpellTypeMinManaLimit(i, bot_stance));
|
||||
}
|
||||
}
|
||||
|
||||
output = "min mana settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "maxmanapct")) {
|
||||
if (spell_type != UINT16_MAX) {
|
||||
my_bot->SetSpellTypeMaxManaLimit(spell_type, my_bot->GetDefaultSpellTypeMaxManaLimit(spell_type, bot_stance));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellTypeMaxManaLimit(i, my_bot->GetDefaultSpellTypeMaxManaLimit(i, bot_stance));
|
||||
}
|
||||
}
|
||||
|
||||
output = "max mana settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "minhppct")) {
|
||||
if (spell_type != UINT16_MAX) {
|
||||
my_bot->SetSpellTypeMinHPLimit(spell_type, my_bot->GetDefaultSpellTypeMinHPLimit(spell_type, bot_stance));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellTypeMinHPLimit(i, my_bot->GetDefaultSpellTypeMinHPLimit(i, bot_stance));
|
||||
}
|
||||
}
|
||||
|
||||
output = "min hp settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "maxhppct")) {
|
||||
if (spell_type != UINT16_MAX) {
|
||||
my_bot->SetSpellTypeMaxHPLimit(spell_type, my_bot->GetDefaultSpellTypeMaxHPLimit(spell_type, bot_stance));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellTypeMaxHPLimit(i, my_bot->GetDefaultSpellTypeMaxHPLimit(i, bot_stance));
|
||||
}
|
||||
}
|
||||
|
||||
output = "max hp settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "idlepriority")) {
|
||||
if (spell_type != UINT16_MAX) {
|
||||
my_bot->SetSpellTypePriority(spell_type, BotPriorityCategories::Idle, my_bot->GetDefaultSpellTypePriority(spell_type, BotPriorityCategories::Idle, my_bot->GetClass(), bot_stance));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellTypePriority(i, BotPriorityCategories::Idle, my_bot->GetDefaultSpellTypePriority(i, BotPriorityCategories::Idle, my_bot->GetClass(), bot_stance));
|
||||
}
|
||||
}
|
||||
|
||||
output = "idle priority settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "engagedpriority")) {
|
||||
if (spell_type != UINT16_MAX) {
|
||||
my_bot->SetSpellTypePriority(spell_type, BotPriorityCategories::Engaged, my_bot->GetDefaultSpellTypePriority(spell_type, BotPriorityCategories::Engaged, my_bot->GetClass(), bot_stance));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellTypePriority(i, BotPriorityCategories::Engaged, my_bot->GetDefaultSpellTypePriority(i, BotPriorityCategories::Engaged, my_bot->GetClass(), bot_stance));
|
||||
}
|
||||
}
|
||||
|
||||
output = "engaged priority settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "pursuepriority")) {
|
||||
if (spell_type != UINT16_MAX) {
|
||||
my_bot->SetSpellTypePriority(spell_type, BotPriorityCategories::Pursue, my_bot->GetDefaultSpellTypePriority(spell_type, BotPriorityCategories::Pursue, my_bot->GetClass(), bot_stance));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellTypePriority(i, BotPriorityCategories::Pursue, my_bot->GetDefaultSpellTypePriority(i, BotPriorityCategories::Pursue, my_bot->GetClass(), bot_stance));
|
||||
}
|
||||
}
|
||||
|
||||
output = "pursue priority settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "targetcounts")) {
|
||||
if (spell_type != UINT16_MAX) {
|
||||
my_bot->SetSpellTypeAEOrGroupTargetCount(spell_type, my_bot->GetDefaultSpellTypeAEOrGroupTargetCount(spell_type, bot_stance));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellTypeAEOrGroupTargetCount(i, my_bot->GetDefaultSpellTypeAEOrGroupTargetCount(i, bot_stance));
|
||||
}
|
||||
}
|
||||
|
||||
output = "target count settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "announcecast")) {
|
||||
if (spell_type != UINT16_MAX) {
|
||||
my_bot->SetSpellTypeAEOrGroupTargetCount(spell_type, my_bot->GetDefaultSpellTypeAEOrGroupTargetCount(spell_type, bot_stance));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellTypeAEOrGroupTargetCount(i, my_bot->GetDefaultSpellTypeAEOrGroupTargetCount(i, bot_stance));
|
||||
}
|
||||
}
|
||||
|
||||
output = "announce cast settings";
|
||||
}
|
||||
|
||||
my_bot->Save();
|
||||
@@ -296,8 +483,15 @@ void bot_command_default_settings(Client* c, const Seperator* sep)
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'My {}.'",
|
||||
"{} says, '{}{} were restored.'",
|
||||
first_found->GetCleanName(),
|
||||
(
|
||||
spell_type != UINT16_MAX ?
|
||||
fmt::format("My [{}] ",
|
||||
Bot::GetSpellTypeNameByID(spell_type)
|
||||
)
|
||||
: "My "
|
||||
),
|
||||
output
|
||||
).c_str()
|
||||
);
|
||||
@@ -306,8 +500,15 @@ void bot_command_default_settings(Client* c, const Seperator* sep)
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} of your bots' {}.",
|
||||
"{} of your bot's{}{} were restored.",
|
||||
success_count,
|
||||
(
|
||||
spell_type != UINT16_MAX ?
|
||||
fmt::format(" [{}] ",
|
||||
Bot::GetSpellTypeNameByID(spell_type)
|
||||
)
|
||||
: " "
|
||||
),
|
||||
output
|
||||
).c_str()
|
||||
);
|
||||
|
||||
@@ -220,7 +220,7 @@ void bot_command_depart(Client* c, const Seperator* sep)
|
||||
}
|
||||
|
||||
if (bot_iter->CastSpell(itr->SpellId, tar->GetID(), EQ::spells::CastingSlot::Gem2, -1, -1)) {
|
||||
if (BotSpellTypeUsesTargetSettings(BotSpellTypes::Teleport)) {
|
||||
if (IsBotSpellTypeOtherBeneficial(BotSpellTypes::Teleport)) {
|
||||
bot_iter->SetCastedSpellType(UINT16_MAX);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -209,6 +209,10 @@ void bot_command_discipline(Client* c, const Seperator* sep)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (spell.buff_duration_formula != 0 && spell.target_type == ST_Self && bot_iter->HasDiscBuff()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!tar || (spell.target_type == ST_Self && tar != bot_iter)) {
|
||||
tar = bot_iter;
|
||||
}
|
||||
@@ -227,7 +231,7 @@ void bot_command_discipline(Client* c, const Seperator* sep)
|
||||
}
|
||||
|
||||
if (!is_success) {
|
||||
c->Message(Chat::Yellow, "No bots were capable of doing that. This could be because they don't have the ability or things like Line of Sight, range, endurance, etc.");
|
||||
c->Message(Chat::Yellow, "No bots were selected.");
|
||||
}
|
||||
else {
|
||||
if (aggressive || defensive) {
|
||||
|
||||
@@ -16,7 +16,7 @@ void bot_command_distance_ranged(Client* c, const Seperator* sep)
|
||||
{
|
||||
"- Bots will stay between half the value of the setting and the current value. IE, if set to 60, bots will stay between 30 and 60.",
|
||||
"- Casters will never go closer than their maximum melee range.",
|
||||
"- Archery & Throwing bots will never get closer than the minimum value for ranged to work, or beyond the range of their items."
|
||||
"- Throwing bots will never get closer than the minimum value for ranged to work, or beyond the range of their items."
|
||||
};
|
||||
p.example_format = { fmt::format("{} [value] [actionable]", sep->arg[0]) };
|
||||
p.examples_one = {
|
||||
|
||||
@@ -12,12 +12,6 @@ void bot_command_max_melee_range(Client* c, const Seperator* sep)
|
||||
BotCommandHelpParams p;
|
||||
|
||||
p.description = { "Toggles whether or not bots will stay at max melee range during combat."};
|
||||
p.notes = {
|
||||
fmt::format(
|
||||
"- Bots {} use special abilities when set to max melee range (taunt, kick, bash, etc).",
|
||||
RuleB(Bots, DisableSpecialAbilitiesAtMaxMelee) ? "will not" : "will"
|
||||
)
|
||||
};
|
||||
p.example_format ={ fmt::format("{} [value] [actionable]", sep->arg[0]) };
|
||||
p.examples_one =
|
||||
{
|
||||
|
||||
@@ -106,12 +106,6 @@ void bot_command_pet_set_type(Client *c, const Seperator *sep)
|
||||
BotCommandHelpParams p;
|
||||
|
||||
p.description = { "Allows you to change the type of pet Magician bots will cast." };
|
||||
p.notes = {
|
||||
fmt::format(
|
||||
"- Epic pets are currently {} on this server.",
|
||||
RuleB(Bots, AllowMagicianEpicPet) ? "allowed" : "not allowed"
|
||||
)
|
||||
};
|
||||
p.example_format = { fmt::format("{} [current | water | fire | air | earth | monster | epic] [actionable, default: target]", sep->arg[0]) };
|
||||
p.examples_one =
|
||||
{
|
||||
|
||||
@@ -12,7 +12,6 @@ void bot_command_taunt(Client* c, const Seperator* sep)
|
||||
BotCommandHelpParams p;
|
||||
|
||||
p.description = { "Allows you to turn on/off the taunting state of your bots and/or their pets." };
|
||||
p.notes = { "- If a taunting class is set to Aggressive (5) stance, they will automatically taunt and don't need to have it enabled manually." };
|
||||
p.example_format = { fmt::format("{} [on / off / pet] [optional: pet] [actionable, default: target]", sep->arg[0]) };
|
||||
p.examples_one =
|
||||
{
|
||||
|
||||
@@ -2249,7 +2249,7 @@ bool BotDatabase::LoadBotSettings(Mob* m)
|
||||
else {
|
||||
LogBotSettings("[{}] says, 'Loading {} [{}], {} [{}] - setting to [{}].",
|
||||
m->GetCleanName(),
|
||||
Bot::GetBotSpellCategoryShortName(e.setting_type),
|
||||
Bot::GetBotSpellCategoryName(e.setting_type),
|
||||
e.setting_type,
|
||||
Bot::GetSpellTypeNameByID(e.setting_id),
|
||||
e.setting_id,
|
||||
@@ -2312,7 +2312,7 @@ bool BotDatabase::SaveBotSettings(Mob* m)
|
||||
.setting_id = static_cast<uint16_t>(i),
|
||||
.setting_type = static_cast<uint8_t>(BotSettingCategories::BaseSetting),
|
||||
.value = static_cast<int32_t>(m->CastToBot()->GetBotBaseSetting(i)),
|
||||
.category_name = Bot::GetBotSpellCategoryShortName(BotSettingCategories::BaseSetting),
|
||||
.category_name = Bot::GetBotSpellCategoryName(BotSettingCategories::BaseSetting),
|
||||
.setting_name = Bot::GetBotSettingCategoryName(i)
|
||||
};
|
||||
|
||||
@@ -2332,13 +2332,13 @@ bool BotDatabase::SaveBotSettings(Mob* m)
|
||||
.setting_id = static_cast<uint16_t>(x),
|
||||
.setting_type = static_cast<uint8_t>(i),
|
||||
.value = m->CastToBot()->GetSetting(i, x),
|
||||
.category_name = Bot::GetBotSpellCategoryShortName(i),
|
||||
.category_name = Bot::GetBotSpellCategoryName(i),
|
||||
.setting_name = Bot::GetSpellTypeNameByID(x)
|
||||
};
|
||||
|
||||
v.emplace_back(e);
|
||||
|
||||
LogBotSettings("{} says, 'Saving {} {} [{}] - set to [{}] default [{}].'", m->GetCleanName(), Bot::GetBotSpellCategoryShortName(i), Bot::GetSpellTypeNameByID(x), x, e.value, m->CastToBot()->GetDefaultSetting(i, x, bot_stance));
|
||||
LogBotSettings("{} says, 'Saving {} {} [{}] - set to [{}] default [{}].'", m->GetCleanName(), Bot::GetBotSpellCategoryName(i), Bot::GetSpellTypeNameByID(x), x, e.value, m->CastToBot()->GetDefaultSetting(i, x, bot_stance));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2354,7 +2354,7 @@ bool BotDatabase::SaveBotSettings(Mob* m)
|
||||
.setting_id = static_cast<uint16_t>(BotBaseSettings::IllusionBlock),
|
||||
.setting_type = static_cast<uint8_t>(BotSettingCategories::BaseSetting),
|
||||
.value = m->CastToClient()->GetIllusionBlock(),
|
||||
.category_name = Bot::GetBotSpellCategoryShortName(BotSettingCategories::BaseSetting),
|
||||
.category_name = Bot::GetBotSpellCategoryName(BotSettingCategories::BaseSetting),
|
||||
.setting_name = Bot::GetBotSettingCategoryName(BotBaseSettings::IllusionBlock)
|
||||
};
|
||||
|
||||
@@ -2366,7 +2366,7 @@ bool BotDatabase::SaveBotSettings(Mob* m)
|
||||
|
||||
for (uint16 i = BotSettingCategories::START_CLIENT; i <= BotSettingCategories::END_CLIENT; ++i) {
|
||||
for (uint16 x = BotSpellTypes::START; x <= BotSpellTypes::END; ++x) {
|
||||
LogBotSettings("{} says, 'Checking {} {} [{}] - set to [{}] default [{}].'", m->GetCleanName(), Bot::GetBotSpellCategoryShortName(i), Bot::GetSpellTypeNameByID(x), x, m->CastToClient()->GetBotSetting(i, x), m->CastToClient()->GetDefaultBotSettings(i, x));
|
||||
LogBotSettings("{} says, 'Checking {} {} [{}] - set to [{}] default [{}].'", m->GetCleanName(), Bot::GetBotSpellCategoryName(i), Bot::GetSpellTypeNameByID(x), x, m->CastToClient()->GetBotSetting(i, x), m->CastToClient()->GetDefaultBotSettings(i, x));
|
||||
if (m->CastToClient()->GetBotSetting(i, x) != m->CastToClient()->GetDefaultBotSettings(i, x)) {
|
||||
auto e = BotSettingsRepository::BotSettings{
|
||||
.character_id = character_id,
|
||||
@@ -2375,13 +2375,13 @@ bool BotDatabase::SaveBotSettings(Mob* m)
|
||||
.setting_id = static_cast<uint16_t>(x),
|
||||
.setting_type = static_cast<uint8_t>(i),
|
||||
.value = m->CastToClient()->GetBotSetting(i, x),
|
||||
.category_name = Bot::GetBotSpellCategoryShortName(i),
|
||||
.category_name = Bot::GetBotSpellCategoryName(i),
|
||||
.setting_name = Bot::GetSpellTypeNameByID(x)
|
||||
};
|
||||
|
||||
v.emplace_back(e);
|
||||
|
||||
LogBotSettings("{} says, 'Saving {} {} [{}] - set to [{}] default [{}].'", m->GetCleanName(), Bot::GetBotSpellCategoryShortName(i), Bot::GetSpellTypeNameByID(x), x, e.value, m->CastToClient()->GetDefaultBotSettings(i, x));
|
||||
LogBotSettings("{} says, 'Saving {} {} [{}] - set to [{}] default [{}].'", m->GetCleanName(), Bot::GetBotSpellCategoryName(i), Bot::GetSpellTypeNameByID(x), x, e.value, m->CastToClient()->GetDefaultBotSettings(i, x));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+65
-78
@@ -242,7 +242,7 @@ bool Bot::AICastSpell(Mob* tar, uint8 chance, uint16 spell_type, uint16 sub_targ
|
||||
}
|
||||
|
||||
if (AIDoSpellCast(s.SpellIndex, tar, s.ManaCost)) {
|
||||
if (BotSpellTypeUsesTargetSettings(spell_type)) {
|
||||
if (IsBotSpellTypeOtherBeneficial(spell_type)) {
|
||||
SetCastedSpellType(UINT16_MAX);
|
||||
|
||||
if (!IsCommandedSpell()) {
|
||||
@@ -288,7 +288,7 @@ bool Bot::BotCastMez(Mob* tar, uint8 bot_class, BotSpell& bot_spell, uint16 spel
|
||||
}
|
||||
|
||||
if (AIDoSpellCast(s.SpellIndex, tar, s.ManaCost)) {
|
||||
if (BotSpellTypeUsesTargetSettings(spell_type)) {
|
||||
if (IsBotSpellTypeOtherBeneficial(spell_type)) {
|
||||
SetCastedSpellType(UINT16_MAX);
|
||||
|
||||
if (!IsCommandedSpell()) {
|
||||
@@ -493,10 +493,6 @@ bool Bot::BotCastNuke(Mob* tar, uint8 bot_class, BotSpell& bot_spell, uint16 spe
|
||||
}
|
||||
|
||||
bool Bot::BotCastHeal(Mob* tar, uint8 bot_class, BotSpell& bot_spell, uint16 spell_type) {
|
||||
if (!TargetValidation(tar)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bot_spell = GetSpellByHealType(spell_type, tar);
|
||||
|
||||
if (!IsValidSpell(bot_spell.SpellId)) {
|
||||
@@ -1068,8 +1064,10 @@ std::vector<BotSpell_wPriority> Bot::GetPrioritizedBotSpellsBySpellType(Bot* cas
|
||||
if (
|
||||
caster->IsCommandedSpell() ||
|
||||
!AE ||
|
||||
!BotSpellTypeRequiresAEChecks(spell_type) ||
|
||||
caster->HasValidAETarget(caster, bot_spell_list[i].spellid, spell_type, tar)
|
||||
(
|
||||
BotSpellTypeRequiresAEChecks(spell_type) &&
|
||||
caster->HasValidAETarget(caster, bot_spell_list[i].spellid, spell_type, tar)
|
||||
)
|
||||
) {
|
||||
BotSpell_wPriority bot_spell;
|
||||
bot_spell.SpellId = bot_spell_list[i].spellid;
|
||||
@@ -1289,32 +1287,30 @@ BotSpell Bot::GetBestBotSpellForGroupHeal(Bot* caster, Mob* tar, uint16 spell_ty
|
||||
result.SpellIndex = 0;
|
||||
result.ManaCost = 0;
|
||||
|
||||
if (!caster->TargetValidation(tar)) {
|
||||
return result;
|
||||
}
|
||||
if (caster) {
|
||||
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_CurrentHP);
|
||||
|
||||
int target_count = 0;
|
||||
|
||||
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_CurrentHP);
|
||||
int target_count = 0;
|
||||
int required_count = caster->GetSpellTypeAEOrGroupTargetCount(spell_type);
|
||||
for (std::list<BotSpell>::iterator bot_spell_list_itr = bot_spell_list.begin(); bot_spell_list_itr != bot_spell_list.end(); ++bot_spell_list_itr) {
|
||||
// Assuming all the spells have been loaded into this list by level and in descending order
|
||||
if (IsRegularGroupHealSpell(bot_spell_list_itr->SpellId)) {
|
||||
uint16 spell_id = bot_spell_list_itr->SpellId;
|
||||
|
||||
for (std::list<BotSpell>::iterator bot_spell_list_itr = bot_spell_list.begin(); bot_spell_list_itr != bot_spell_list.end(); ++bot_spell_list_itr) {
|
||||
// Assuming all the spells have been loaded into this list by level and in descending order
|
||||
if (IsRegularGroupHealSpell(bot_spell_list_itr->SpellId)) {
|
||||
uint16 spell_id = bot_spell_list_itr->SpellId;
|
||||
if (!caster->IsCommandedSpell() && caster->IsValidSpellRange(spell_id, tar)) {
|
||||
target_count = caster->GetNumberNeedingHealedInGroup(tar, spell_type, spell_id, caster->GetAOERange(spell_id));
|
||||
|
||||
if (caster->TargetValidation(tar) && !caster->IsCommandedSpell() && caster->IsValidSpellRange(spell_id, tar)) {
|
||||
target_count = caster->GetNumberNeedingHealedInGroup(tar, spell_type, spell_id, caster->GetAOERange(spell_id));
|
||||
|
||||
if (target_count < required_count) {
|
||||
continue;
|
||||
if (target_count < caster->GetSpellTypeAEOrGroupTargetCount(spell_type)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
result.SpellId = bot_spell_list_itr->SpellId;
|
||||
result.SpellIndex = bot_spell_list_itr->SpellIndex;
|
||||
result.ManaCost = bot_spell_list_itr->ManaCost;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
result.SpellId = bot_spell_list_itr->SpellId;
|
||||
result.SpellIndex = bot_spell_list_itr->SpellIndex;
|
||||
result.ManaCost = bot_spell_list_itr->ManaCost;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1328,32 +1324,30 @@ BotSpell Bot::GetBestBotSpellForGroupHealOverTime(Bot* caster, Mob* tar, uint16
|
||||
result.SpellIndex = 0;
|
||||
result.ManaCost = 0;
|
||||
|
||||
if (!caster->TargetValidation(tar)) {
|
||||
return result;
|
||||
}
|
||||
if (caster) {
|
||||
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_HealOverTime);
|
||||
|
||||
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_HealOverTime);
|
||||
int target_count = 0;
|
||||
int required_count = caster->GetSpellTypeAEOrGroupTargetCount(spell_type);
|
||||
int target_count = 0;
|
||||
|
||||
for (std::list<BotSpell>::iterator bot_spell_list_itr = bot_spell_list.begin(); bot_spell_list_itr != bot_spell_list.end(); ++bot_spell_list_itr) {
|
||||
// Assuming all the spells have been loaded into this list by level and in descending order
|
||||
if (IsGroupHealOverTimeSpell(bot_spell_list_itr->SpellId)) {
|
||||
uint16 spell_id = bot_spell_list_itr->SpellId;
|
||||
for (std::list<BotSpell>::iterator bot_spell_list_itr = bot_spell_list.begin(); bot_spell_list_itr != bot_spell_list.end(); ++bot_spell_list_itr) {
|
||||
// Assuming all the spells have been loaded into this list by level and in descending order
|
||||
if (IsGroupHealOverTimeSpell(bot_spell_list_itr->SpellId)) {
|
||||
uint16 spell_id = bot_spell_list_itr->SpellId;
|
||||
|
||||
if (caster->TargetValidation(tar) && !caster->IsCommandedSpell() && caster->IsValidSpellRange(spell_id, tar)) {
|
||||
target_count = caster->GetNumberNeedingHealedInGroup(tar, spell_type, spell_id, caster->GetAOERange(spell_id));
|
||||
if (!caster->IsCommandedSpell() && caster->IsValidSpellRange(spell_id, tar)) {
|
||||
target_count = caster->GetNumberNeedingHealedInGroup(tar, spell_type, spell_id, caster->GetAOERange(spell_id));
|
||||
|
||||
if (target_count < required_count) {
|
||||
continue;
|
||||
if (target_count < caster->GetSpellTypeAEOrGroupTargetCount(spell_type)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
result.SpellId = bot_spell_list_itr->SpellId;
|
||||
result.SpellIndex = bot_spell_list_itr->SpellIndex;
|
||||
result.ManaCost = bot_spell_list_itr->ManaCost;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
result.SpellId = bot_spell_list_itr->SpellId;
|
||||
result.SpellIndex = bot_spell_list_itr->SpellIndex;
|
||||
result.ManaCost = bot_spell_list_itr->ManaCost;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1367,32 +1361,30 @@ BotSpell Bot::GetBestBotSpellForGroupCompleteHeal(Bot* caster, Mob* tar, uint16
|
||||
result.SpellIndex = 0;
|
||||
result.ManaCost = 0;
|
||||
|
||||
if (!caster->TargetValidation(tar)) {
|
||||
return result;
|
||||
}
|
||||
if (caster) {
|
||||
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_CompleteHeal);
|
||||
|
||||
int target_count = 0;
|
||||
|
||||
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_CompleteHeal);
|
||||
int target_count = 0;
|
||||
int required_count = caster->GetSpellTypeAEOrGroupTargetCount(spell_type);
|
||||
for (std::list<BotSpell>::iterator bot_spell_list_itr = bot_spell_list.begin(); bot_spell_list_itr != bot_spell_list.end(); ++bot_spell_list_itr) {
|
||||
// Assuming all the spells have been loaded into this list by level and in descending order
|
||||
if (IsGroupCompleteHealSpell(bot_spell_list_itr->SpellId)) {
|
||||
uint16 spell_id = bot_spell_list_itr->SpellId;
|
||||
|
||||
for (std::list<BotSpell>::iterator bot_spell_list_itr = bot_spell_list.begin(); bot_spell_list_itr != bot_spell_list.end(); ++bot_spell_list_itr) {
|
||||
// Assuming all the spells have been loaded into this list by level and in descending order
|
||||
if (IsGroupCompleteHealSpell(bot_spell_list_itr->SpellId)) {
|
||||
uint16 spell_id = bot_spell_list_itr->SpellId;
|
||||
if (!caster->IsCommandedSpell() && caster->IsValidSpellRange(spell_id, tar)) {
|
||||
target_count = caster->GetNumberNeedingHealedInGroup(tar, spell_type, spell_id, caster->GetAOERange(spell_id));
|
||||
|
||||
if (caster->TargetValidation(tar) && !caster->IsCommandedSpell() && caster->IsValidSpellRange(spell_id, tar)) {
|
||||
target_count = caster->GetNumberNeedingHealedInGroup(tar, spell_type, spell_id, caster->GetAOERange(spell_id));
|
||||
|
||||
if (target_count < required_count) {
|
||||
continue;
|
||||
if (target_count < caster->GetSpellTypeAEOrGroupTargetCount(spell_type)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
result.SpellId = bot_spell_list_itr->SpellId;
|
||||
result.SpellIndex = bot_spell_list_itr->SpellIndex;
|
||||
result.ManaCost = bot_spell_list_itr->ManaCost;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
result.SpellId = bot_spell_list_itr->SpellId;
|
||||
result.SpellIndex = bot_spell_list_itr->SpellIndex;
|
||||
result.ManaCost = bot_spell_list_itr->ManaCost;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1431,8 +1423,7 @@ Mob* Bot::GetFirstIncomingMobToMez(Bot* caster, int16 spell_id, uint16 spell_typ
|
||||
Mob* result = nullptr;
|
||||
|
||||
if (caster && caster->GetOwner()) {
|
||||
int spell_range = caster->GetActSpellRange(spell_id, spells[spell_id].range);
|
||||
int spell_ae_range = caster->GetAOERange(spell_id);
|
||||
int spell_range = (!AE ? caster->GetActSpellRange(spell_id, spells[spell_id].range) : caster->GetActSpellRange(spell_id, spells[spell_id].aoe_range));
|
||||
int buff_count = 0;
|
||||
NPC* npc = nullptr;
|
||||
|
||||
@@ -1463,7 +1454,7 @@ Mob* Bot::GetFirstIncomingMobToMez(Bot* caster, int16 spell_id, uint16 spell_typ
|
||||
}
|
||||
|
||||
if (IsPBAESpell(spell_id)) {
|
||||
if (spell_ae_range < Distance(caster->GetPosition(), m->GetPosition())) {
|
||||
if (spell_range < Distance(caster->GetPosition(), m->GetPosition())) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -2731,11 +2722,7 @@ bool Bot::IsValidSpellRange(uint16 spell_id, Mob* tar) {
|
||||
|
||||
float range = spells[spell_id].range + GetRangeDistTargetSizeMod(tar);
|
||||
|
||||
if (
|
||||
spells[spell_id].target_type != ST_AETargetHateList &&
|
||||
!IsTargetableAESpell(spell_id) &&
|
||||
IsAnyAESpell(spell_id)
|
||||
) {
|
||||
if (IsAnyAESpell(spell_id)) {
|
||||
range = GetAOERange(spell_id);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,277 +0,0 @@
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include "../../common/http/httplib.h"
|
||||
#include "../../common/eqemu_logsys.h"
|
||||
#include "../sidecar_api/sidecar_api.h"
|
||||
#include "../../common/platform.h"
|
||||
#include "../data_bucket.h"
|
||||
#include "../zonedb.h"
|
||||
#include "../../common/repositories/data_buckets_repository.h"
|
||||
|
||||
void RunBenchmarkCycle(uint64_t target_rows)
|
||||
{
|
||||
const size_t OPERATIONS_PER_TEST = 5000;
|
||||
const std::string test_key_prefix = "test_key_";
|
||||
|
||||
std::cout << Strings::Repeat("-", 70) << "\n";
|
||||
std::cout << "📊 Running Benchmark at " << Strings::Commify(target_rows) << " Rows...\n";
|
||||
std::cout << Strings::Repeat("-", 70) << "\n";
|
||||
|
||||
// 🧹 **Purge `test_key_*` Keys Before Each Run**
|
||||
std::cout << "🧹 Purging test keys (`test_key_*`)...\n";
|
||||
auto purge_start = std::chrono::high_resolution_clock::now();
|
||||
DataBucketsRepository::DeleteWhere(database, "`key` LIKE '" + test_key_prefix + "%'");
|
||||
auto purge_end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> purge_time = purge_end - purge_start;
|
||||
std::cout << "✅ Purged test keys in " << purge_time.count() << " seconds.\n";
|
||||
|
||||
// 📊 **Ensure the Table Contains At Least `target_rows`**
|
||||
auto populate_start = std::chrono::high_resolution_clock::now();
|
||||
uint64_t current_count = DataBucketsRepository::Count(database);
|
||||
if (current_count < target_rows) {
|
||||
std::cout << "📌 Populating table to " << Strings::Commify(target_rows) << " rows...\n";
|
||||
std::mt19937 rng(std::random_device{}());
|
||||
std::uniform_int_distribution<int> entity_type(1, 5);
|
||||
std::uniform_int_distribution<int> id_dist(1, 1000000);
|
||||
std::uniform_int_distribution<int> expiry_dist(0, 86400 * 30); // Expiry up to 30 days
|
||||
|
||||
while (current_count < target_rows) {
|
||||
std::vector<DataBucketsRepository::DataBuckets> batch;
|
||||
for (size_t i = 0; i < 100000; ++i) {
|
||||
if (i > target_rows - current_count) {
|
||||
break;
|
||||
}
|
||||
|
||||
int entity_choice = entity_type(rng);
|
||||
int entity_id = id_dist(rng);
|
||||
std::string key = "test_key_" + std::to_string(current_count + i);
|
||||
std::string value = "value_" + std::to_string(current_count + i);
|
||||
int expires = static_cast<int>(std::time(nullptr)) + expiry_dist(rng);
|
||||
|
||||
DataBucketsRepository::DataBuckets e{};
|
||||
e.key_ = key;
|
||||
e.value = value;
|
||||
e.expires = expires;
|
||||
e.account_id = (entity_choice == 1) ? entity_id : 0;
|
||||
e.character_id = (entity_choice == 2) ? entity_id : 0;
|
||||
e.npc_id = (entity_choice == 3) ? entity_id : 0;
|
||||
e.bot_id = (entity_choice == 4) ? entity_id : 0;
|
||||
e.zone_id = (entity_choice == 5) ? entity_id : 0;
|
||||
e.instance_id = (entity_choice == 5) ? entity_id : 0;
|
||||
|
||||
batch.emplace_back(e);
|
||||
}
|
||||
DataBucketsRepository::InsertMany(database, batch);
|
||||
current_count += batch.size();
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::cout << "✅ Table already has " << current_count << " rows, proceeding with benchmark.\n";
|
||||
}
|
||||
|
||||
auto populate_end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> populate_time = populate_end - populate_start;
|
||||
std::cout << "✅ Populated table in " << populate_time.count() << " seconds.\n";
|
||||
|
||||
std::mt19937 rng(std::random_device{}());
|
||||
std::uniform_int_distribution<int> id_dist(1, 1000);
|
||||
|
||||
// 🚀 **Measure Insert Performance**
|
||||
std::vector<DataBucketKey> inserted_keys = {};
|
||||
auto insert_start = std::chrono::high_resolution_clock::now();
|
||||
for (size_t i = 0; i < OPERATIONS_PER_TEST; ++i) {
|
||||
std::string key = test_key_prefix + std::to_string(current_count + i);
|
||||
std::string value = "value_" + std::to_string(current_count + i);
|
||||
int expires = static_cast<int>(std::time(nullptr)) + 3600;
|
||||
|
||||
DataBucketKey e{
|
||||
.key = key,
|
||||
.value = value,
|
||||
.expires = std::to_string(expires),
|
||||
.account_id = 0,
|
||||
.character_id = 0,
|
||||
.npc_id = 0,
|
||||
.bot_id = 0
|
||||
};
|
||||
|
||||
// randomly set account_id, character_id, npc_id, or bot_id
|
||||
switch (i % 4) {
|
||||
case 0:
|
||||
e.account_id = id_dist(rng);
|
||||
break;
|
||||
case 1:
|
||||
e.character_id = id_dist(rng);
|
||||
break;
|
||||
case 2:
|
||||
e.npc_id = id_dist(rng);
|
||||
break;
|
||||
case 3:
|
||||
e.bot_id = id_dist(rng);
|
||||
break;
|
||||
case 4:
|
||||
int entity_choice = id_dist(rng);
|
||||
e.zone_id = entity_choice;
|
||||
e.instance_id = entity_choice;
|
||||
break;
|
||||
}
|
||||
|
||||
DataBucket::SetData(e);
|
||||
|
||||
inserted_keys.emplace_back(e);
|
||||
}
|
||||
auto insert_end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> insert_time = insert_end - insert_start;
|
||||
std::cout << "✅ Completed " << Strings::Commify(OPERATIONS_PER_TEST) << " inserts in " << insert_time.count()
|
||||
<< " seconds. (Individual Insert Performance)\n";
|
||||
|
||||
// ✏️ **Measure Update Performance Using DataBucket**
|
||||
auto update_start = std::chrono::high_resolution_clock::now();
|
||||
for (auto &key: inserted_keys) {
|
||||
// 🔍 Retrieve existing bucket using scoped `GetData`
|
||||
auto e = DataBucket::GetData(key);
|
||||
if (e.id > 0) {
|
||||
// create a new key object with the updated values
|
||||
DataBucketKey bucket_entry_key{
|
||||
.key = e.key_,
|
||||
.value = "some_new_value",
|
||||
.expires = std::to_string(e.expires),
|
||||
.account_id = e.account_id,
|
||||
.character_id = e.character_id,
|
||||
.npc_id = e.npc_id,
|
||||
.bot_id = e.bot_id,
|
||||
.zone_id = e.zone_id,
|
||||
.instance_id = e.instance_id
|
||||
};
|
||||
|
||||
// 🔄 Update using DataBucket class
|
||||
DataBucket::SetData(bucket_entry_key);
|
||||
}
|
||||
}
|
||||
auto update_end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> update_time = update_end - update_start;
|
||||
std::cout << "✅ Completed " << Strings::Commify(OPERATIONS_PER_TEST) << " updates in " << update_time.count()
|
||||
<< " seconds. (Scoped Update Performance)\n";
|
||||
|
||||
|
||||
// 🔍 **Measure Cached Read Performance**
|
||||
auto read_cached_start = std::chrono::high_resolution_clock::now();
|
||||
for (size_t i = 0; i < OPERATIONS_PER_TEST; ++i) {
|
||||
std::string key = test_key_prefix + std::to_string(current_count + i);
|
||||
DataBucketKey k{
|
||||
.key = key,
|
||||
.account_id = 0,
|
||||
.character_id = 0,
|
||||
.npc_id = 0,
|
||||
.bot_id = 0,
|
||||
.zone_id = 0,
|
||||
.instance_id = 0
|
||||
};
|
||||
|
||||
// randomly set account_id, character_id, npc_id, or bot_id
|
||||
switch (i % 4) {
|
||||
case 0:
|
||||
k.account_id = id_dist(rng);
|
||||
break;
|
||||
case 1:
|
||||
k.character_id = id_dist(rng);
|
||||
break;
|
||||
case 2:
|
||||
k.npc_id = id_dist(rng);
|
||||
break;
|
||||
case 3:
|
||||
k.bot_id = id_dist(rng);
|
||||
break;
|
||||
case 4:
|
||||
int entity_choice = id_dist(rng);
|
||||
k.zone_id = entity_choice;
|
||||
k.instance_id = entity_choice;
|
||||
}
|
||||
|
||||
DataBucket::GetData(key);
|
||||
}
|
||||
auto read_cached_end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> read_cached_time = read_cached_end - read_cached_start;
|
||||
std::cout << "✅ Completed " << Strings::Commify(OPERATIONS_PER_TEST) << " cached reads in "
|
||||
<< read_cached_time.count() << " seconds. (DataBucket::GetData)\n";
|
||||
|
||||
// 🔍 **Measure Non-Cached Read Performance (Direct Query)**
|
||||
auto read_uncached_start = std::chrono::high_resolution_clock::now();
|
||||
for (size_t i = 0; i < OPERATIONS_PER_TEST; ++i) {
|
||||
std::string key = test_key_prefix + std::to_string(current_count + i);
|
||||
DataBucketsRepository::GetWhere(database, "`key` = '" + key + "'");
|
||||
}
|
||||
auto read_uncached_end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> read_uncached_time = read_uncached_end - read_uncached_start;
|
||||
std::cout << "✅ Completed " << Strings::Commify(OPERATIONS_PER_TEST) << " non-cached reads in "
|
||||
<< read_uncached_time.count() << " seconds. (DataBucketsRepository::GetWhere)\n";
|
||||
|
||||
// 🗑️ **Measure Delete Performance**
|
||||
auto delete_start = std::chrono::high_resolution_clock::now();
|
||||
for (size_t i = 0; i < OPERATIONS_PER_TEST; ++i) {
|
||||
std::string key = test_key_prefix + std::to_string(current_count + i);
|
||||
|
||||
DataBucketKey k{
|
||||
.key = key,
|
||||
.account_id = 0,
|
||||
.character_id = 0,
|
||||
.npc_id = 0,
|
||||
.bot_id = 0,
|
||||
.zone_id = 0,
|
||||
.instance_id = 0
|
||||
};
|
||||
|
||||
// randomly set account_id, character_id, npc_id, or bot_id
|
||||
switch (i % 4) {
|
||||
case 0:
|
||||
k.account_id = id_dist(rng);
|
||||
break;
|
||||
case 1:
|
||||
k.character_id = id_dist(rng);
|
||||
break;
|
||||
case 2:
|
||||
k.npc_id = id_dist(rng);
|
||||
break;
|
||||
case 3:
|
||||
k.bot_id = id_dist(rng);
|
||||
break;
|
||||
case 4:
|
||||
int entity_choice = id_dist(rng);
|
||||
k.zone_id = entity_choice;
|
||||
k.instance_id = entity_choice;
|
||||
}
|
||||
|
||||
DataBucket::DeleteData(k);
|
||||
}
|
||||
auto delete_end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> delete_time = delete_end - delete_start;
|
||||
std::cout << "✅ Completed " << Strings::Commify(OPERATIONS_PER_TEST) << " deletes in " << delete_time.count()
|
||||
<< " seconds.\n";
|
||||
}
|
||||
|
||||
void ZoneCLI::BenchmarkDatabuckets(int argc, char **argv, argh::parser &cmd, std::string &description)
|
||||
{
|
||||
description = "Benchmark individual reads/writes/deletes in data_buckets at different table sizes.";
|
||||
|
||||
if (cmd[{"-h", "--help"}]) {
|
||||
std::cout << "Usage: BenchmarkDatabuckets\n";
|
||||
return;
|
||||
}
|
||||
|
||||
if (std::getenv("DEBUG")) {
|
||||
LogSys.SetDatabase(&database)->LoadLogDatabaseSettings();
|
||||
}
|
||||
|
||||
auto start_time = std::chrono::high_resolution_clock::now();
|
||||
|
||||
std::vector<uint64_t> benchmark_sizes = {10000, 100000, 1000000};
|
||||
|
||||
for (auto size: benchmark_sizes) {
|
||||
RunBenchmarkCycle(size);
|
||||
}
|
||||
|
||||
// 🚀 **Total Benchmark Time**
|
||||
auto end_time = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> total_elapsed = end_time - start_time;
|
||||
std::cout << "\n🚀 Total Benchmark Time: " << total_elapsed.count() << " seconds\n";
|
||||
}
|
||||
+666
-123
File diff suppressed because it is too large
Load Diff
+33
-29
@@ -21,7 +21,8 @@
|
||||
class Client;
|
||||
class EQApplicationPacket;
|
||||
class DynamicZone;
|
||||
class DzLockout;
|
||||
class Expedition;
|
||||
class ExpeditionLockoutTimer;
|
||||
class ExpeditionRequest;
|
||||
class Group;
|
||||
class NPC;
|
||||
@@ -31,7 +32,6 @@ class Seperator;
|
||||
class ServerPacket;
|
||||
struct DynamicZoneLocation;
|
||||
enum WaterRegionType : int;
|
||||
enum class DynamicZoneMemberStatus;
|
||||
|
||||
namespace EQ
|
||||
{
|
||||
@@ -248,13 +248,6 @@ struct ClientReward
|
||||
uint32 amount;
|
||||
};
|
||||
|
||||
struct ExpeditionInvite
|
||||
{
|
||||
uint32_t dz_id;
|
||||
std::string inviter_name;
|
||||
std::string swap_name;
|
||||
};
|
||||
|
||||
class Client : public Mob
|
||||
{
|
||||
public:
|
||||
@@ -886,9 +879,11 @@ public:
|
||||
void QuestReadBook(const char* text, uint8 type);
|
||||
void SendMoneyUpdate();
|
||||
bool TakeMoneyFromPP(uint64 copper, bool update_client = false);
|
||||
bool TakeMoneyFromPPWithOverFlow(uint64 copper, bool update_client);
|
||||
bool TakePlatinum(uint32 platinum, bool update_client = false);
|
||||
void AddMoneyToPP(uint64 copper, bool update_client = false);
|
||||
void AddMoneyToPP(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, bool update_client = false);
|
||||
void AddMoneyToPPWithOverflow(uint64 copper, bool update_client);
|
||||
void AddPlatinum(uint32 platinu, bool update_client = false);
|
||||
bool HasMoney(uint64 copper);
|
||||
uint64 GetCarriedMoney();
|
||||
@@ -1572,24 +1567,32 @@ public:
|
||||
Client* client, const std::string& client_name, uint16_t chat_type,
|
||||
uint32_t string_id, const std::initializer_list<std::string>& arguments = {});
|
||||
|
||||
void AddDzLockout(const DzLockout& lockout, bool update_db = false);
|
||||
void AddDzLockout(const std::string& expedition, const std::string& event, uint32_t duration, std::string uuid = {});
|
||||
void AddDzLockoutDuration(const DzLockout& lockout, int seconds, const std::string& uuid = {}, bool update_db = false);
|
||||
DynamicZone* CreateExpedition(DynamicZone& dz, bool silent = false);
|
||||
DynamicZone* CreateExpedition(uint32 zone_id, uint32 version, uint32 duration, const std::string& name, uint32 min_players, uint32 max_players, bool silent = false);
|
||||
DynamicZone* CreateExpeditionFromTemplate(uint32_t dz_template_id);
|
||||
DynamicZone* GetExpedition() const;
|
||||
uint32 GetExpeditionID() const;
|
||||
const DzLockout* GetDzLockout(const std::string& expedition, const std::string& event) const;
|
||||
const std::vector<DzLockout>& GetDzLockouts() const { return m_dz_lockouts; };
|
||||
std::vector<DzLockout> GetDzLockouts(const std::string& expedition);
|
||||
uint32 GetPendingDzInviteID() const { return m_dz_invite.dz_id; }
|
||||
void SetPendingDzInvite(const ExpeditionInvite& invite) { m_dz_invite = invite; }
|
||||
void RequestPendingDzInvite() const;
|
||||
bool HasDzLockout(const std::string& expedition, const std::string& event) const;
|
||||
void RemoveDzLockouts(const std::string& expedition, bool update_db = false);
|
||||
void RemoveDzLockout(const std::string& expedition, const std::string& event, bool update_db = false);
|
||||
void SendDzLockoutTimers();
|
||||
void AddExpeditionLockout(const ExpeditionLockoutTimer& lockout, bool update_db = false);
|
||||
void AddExpeditionLockoutDuration(const std::string& expedition_name,
|
||||
const std::string& event_Name, int seconds, const std::string& uuid = {}, bool update_db = false);
|
||||
void AddNewExpeditionLockout(const std::string& expedition_name,
|
||||
const std::string& event_name, uint32_t duration, std::string uuid = {});
|
||||
Expedition* CreateExpedition(DynamicZone& dz, bool disable_messages = false);
|
||||
Expedition* CreateExpedition(const std::string& zone_name,
|
||||
uint32 version, uint32 duration, const std::string& expedition_name,
|
||||
uint32 min_players, uint32 max_players, bool disable_messages = false);
|
||||
Expedition* CreateExpeditionFromTemplate(uint32_t dz_template_id);
|
||||
Expedition* GetExpedition() const;
|
||||
uint32 GetExpeditionID() const { return m_expedition_id; }
|
||||
const ExpeditionLockoutTimer* GetExpeditionLockout(
|
||||
const std::string& expedition_name, const std::string& event_name, bool include_expired = false) const;
|
||||
const std::vector<ExpeditionLockoutTimer>& GetExpeditionLockouts() const { return m_expedition_lockouts; };
|
||||
std::vector<ExpeditionLockoutTimer> GetExpeditionLockouts(const std::string& expedition_name, bool include_expired = false);
|
||||
uint32 GetPendingExpeditionInviteID() const { return m_pending_expedition_invite.expedition_id; }
|
||||
bool HasExpeditionLockout(const std::string& expedition_name, const std::string& event_name, bool include_expired = false);
|
||||
bool IsInExpedition() const { return m_expedition_id != 0; }
|
||||
void RemoveAllExpeditionLockouts(const std::string& expedition_name, bool update_db = false);
|
||||
void RemoveExpeditionLockout(const std::string& expedition_name,
|
||||
const std::string& event_name, bool update_db = false);
|
||||
void RequestPendingExpeditionInvite();
|
||||
void SendExpeditionLockoutTimers();
|
||||
void SetExpeditionID(uint32 expedition_id) { m_expedition_id = expedition_id; };
|
||||
void SetPendingExpeditionInvite(ExpeditionInvite&& invite) { m_pending_expedition_invite = invite; }
|
||||
void DzListTimers();
|
||||
void SetDzRemovalTimer(bool enable_timer);
|
||||
void SendDzCompassUpdate();
|
||||
@@ -2284,8 +2287,9 @@ private:
|
||||
|
||||
uint8 client_max_level;
|
||||
|
||||
ExpeditionInvite m_dz_invite = {};
|
||||
std::vector<DzLockout> m_dz_lockouts;
|
||||
uint32 m_expedition_id = 0;
|
||||
ExpeditionInvite m_pending_expedition_invite { 0 };
|
||||
std::vector<ExpeditionLockoutTimer> m_expedition_lockouts;
|
||||
glm::vec3 m_quest_compass;
|
||||
bool m_has_quest_compass = false;
|
||||
std::vector<uint32_t> m_dynamic_zone_ids;
|
||||
|
||||
+241
-252
@@ -43,8 +43,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "../common/data_verification.h"
|
||||
#include "../common/rdtsc.h"
|
||||
#include "data_bucket.h"
|
||||
#include "dynamic_zone.h"
|
||||
#include "event_codes.h"
|
||||
#include "expedition.h"
|
||||
#include "guild_mgr.h"
|
||||
#include "merc.h"
|
||||
#include "petitions.h"
|
||||
@@ -1781,6 +1781,8 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
m_dynamic_zone_ids.emplace_back(entry.dynamic_zone_id);
|
||||
}
|
||||
|
||||
m_expedition_id = ExpeditionsRepository::GetIDByMemberID(database, CharacterID());
|
||||
|
||||
auto dz = zone->GetDynamicZone();
|
||||
if (dz && dz->GetSafeReturnLocation().zone_id != 0)
|
||||
{
|
||||
@@ -4249,14 +4251,7 @@ void Client::Handle_OP_Camp(const EQApplicationPacket *app)
|
||||
|
||||
if (GetGM())
|
||||
{
|
||||
if (RuleB(Character, EnableHackedFastCampForGM))
|
||||
{
|
||||
camp_timer.Start(100, true);
|
||||
}
|
||||
else {
|
||||
OnDisconnect(true);
|
||||
}
|
||||
|
||||
OnDisconnect(true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -6060,8 +6055,8 @@ void Client::Handle_OP_DzAddPlayer(const EQApplicationPacket *app)
|
||||
}
|
||||
else
|
||||
{
|
||||
// message string 8271 (not in emu clients) is the only /dz command that sends an error if no active expedition
|
||||
Message(Chat::System, "You could not use this command because you are not currently assigned to a dynamic zone.");
|
||||
// the only /dz command that sends an error message if no active expedition
|
||||
Message(Chat::System, DZ_YOU_NOT_ASSIGNED);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6094,14 +6089,14 @@ void Client::Handle_OP_DzChooseZoneReply(const EQApplicationPacket *app)
|
||||
|
||||
void Client::Handle_OP_DzExpeditionInviteResponse(const EQApplicationPacket *app)
|
||||
{
|
||||
auto expedition = DynamicZone::FindDynamicZoneByID(m_dz_invite.dz_id);
|
||||
std::string swap_name = m_dz_invite.swap_name;
|
||||
m_dz_invite = {}; // clear before re-validating
|
||||
auto expedition = Expedition::FindCachedExpeditionByID(m_pending_expedition_invite.expedition_id);
|
||||
std::string swap_remove_name = m_pending_expedition_invite.swap_remove_name;
|
||||
m_pending_expedition_invite = { 0 }; // clear before re-validating
|
||||
|
||||
if (expedition)
|
||||
{
|
||||
auto dzmsg = reinterpret_cast<ExpeditionInviteResponse_Struct*>(app->pBuffer);
|
||||
expedition->DzInviteResponse(this, dzmsg->accepted, swap_name);
|
||||
expedition->DzInviteResponse(this, dzmsg->accepted, swap_remove_name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7590,298 +7585,292 @@ void Client::Handle_OP_GroupUpdate(const EQApplicationPacket *app)
|
||||
|
||||
void Client::Handle_OP_GuildBank(const EQApplicationPacket *app)
|
||||
{
|
||||
if (!GuildBanks) {
|
||||
GuildBankAck();
|
||||
if (!GuildBanks)
|
||||
return;
|
||||
}
|
||||
|
||||
if (zone->GetZoneID() != Zones::GUILDHALL) {
|
||||
if (zone->GetZoneID() != Zones::GUILDHALL)
|
||||
{
|
||||
Message(Chat::Red, "The Guild Bank is not available in this zone.");
|
||||
GuildBankAck();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (app->size < sizeof(uint32)) {
|
||||
LogError("Wrong size: OP_GuildBank, size=[{}], expected [{}]", app->size, sizeof(uint32));
|
||||
DumpPacket(app);
|
||||
GuildBankAck();
|
||||
return;
|
||||
}
|
||||
|
||||
char *Buffer = (char *) app->pBuffer;
|
||||
uint32 Action = VARSTRUCT_DECODE_TYPE(uint32, Buffer);
|
||||
char *Buffer = (char *)app->pBuffer;
|
||||
|
||||
uint32 Action = VARSTRUCT_DECODE_TYPE(uint32, Buffer);
|
||||
uint32 sentAction = Action;
|
||||
|
||||
if (!IsInAGuild()) {
|
||||
if (!IsInAGuild())
|
||||
{
|
||||
Message(Chat::Red, "You must be in a Guild to use the Guild Bank.");
|
||||
if (Action == GuildBankDeposit) {
|
||||
|
||||
if (Action == GuildBankDeposit)
|
||||
GuildBankDepositAck(true, sentAction);
|
||||
}
|
||||
else {
|
||||
else
|
||||
GuildBankAck();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsGuildBanker())
|
||||
{
|
||||
if (Action != GuildBankDeposit && Action != GuildBankViewItem && Action != GuildBankWithdraw)
|
||||
if ((Action != GuildBankDeposit) && (Action != GuildBankViewItem) && (Action != GuildBankWithdraw))
|
||||
{
|
||||
LogError("Suspected hacking attempt on guild bank from [{}]", GetName());
|
||||
|
||||
GuildBankAck();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (Action) {
|
||||
case GuildBankPromote: {
|
||||
if (GuildBanks->IsAreaFull(GuildID(), GuildBankMainArea)) {
|
||||
MessageString(Chat::Red, GUILD_BANK_FULL);
|
||||
GuildBankAck();
|
||||
return;
|
||||
}
|
||||
|
||||
auto gbps = (GuildBankPromote_Struct *) app->pBuffer;
|
||||
int slot_id = GuildBanks->Promote(GuildID(), gbps->Slot, this);
|
||||
|
||||
if (slot_id >= 0) {
|
||||
auto inst = GuildBanks->GetItem(GuildID(), GuildBankMainArea, slot_id, 1);
|
||||
if (inst) {
|
||||
if (player_event_logs.IsEventEnabled(PlayerEvent::GUILD_BANK_MOVE_TO_BANK_AREA)) {
|
||||
PlayerEvent::GuildBankTransaction log{};
|
||||
log.char_id = CharacterID();
|
||||
log.guild_id = GuildID();
|
||||
log.item_id = inst->GetID();
|
||||
log.quantity = inst->GetCharges();
|
||||
if (inst->IsAugmented()) {
|
||||
auto augs = inst->GetAugmentIDs();
|
||||
log.aug_slot_one = augs.at(0);
|
||||
log.aug_slot_two = augs.at(1);
|
||||
log.aug_slot_three = augs.at(2);
|
||||
log.aug_slot_four = augs.at(3);
|
||||
log.aug_slot_five = augs.at(4);
|
||||
log.aug_slot_six = augs.at(5);
|
||||
}
|
||||
|
||||
RecordPlayerEventLog(PlayerEvent::GUILD_BANK_MOVE_TO_BANK_AREA, log);
|
||||
}
|
||||
|
||||
MessageString(Chat::LightGray, GUILD_BANK_TRANSFERRED, inst->GetItem()->Name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Message(Chat::Red, "Unexpected error while moving item into Guild Bank.");
|
||||
}
|
||||
|
||||
GuildBankAck();
|
||||
break;
|
||||
}
|
||||
|
||||
case GuildBankViewItem: {
|
||||
auto gbvis = (GuildBankViewItem_Struct *) app->pBuffer;
|
||||
auto inst = GuildBanks->GetItem(GuildID(), gbvis->Area, gbvis->SlotID, 1);
|
||||
|
||||
if (!inst) {
|
||||
break;
|
||||
}
|
||||
|
||||
SendItemPacket(0, inst.get(), ItemPacketViewLink);
|
||||
break;
|
||||
}
|
||||
|
||||
case GuildBankDeposit: // Deposit Item
|
||||
switch (Action)
|
||||
{
|
||||
case GuildBankPromote:
|
||||
{
|
||||
if (GuildBanks->IsAreaFull(GuildID(), GuildBankMainArea))
|
||||
{
|
||||
const auto cursor_item_inst = GetInv().GetItem(EQ::invslot::slotCursor);
|
||||
bool allowed = true;
|
||||
MessageString(Chat::Red, GUILD_BANK_FULL);
|
||||
|
||||
if (!cursor_item_inst) {
|
||||
Message(Chat::Red, "No Item on the cursor.");
|
||||
GuildBankDepositAck(true, sentAction);
|
||||
return;
|
||||
}
|
||||
GuildBankDepositAck(true, sentAction);
|
||||
|
||||
const auto cursor_item = cursor_item_inst->GetItem();
|
||||
if (GuildBanks->IsAreaFull(GuildID(), GuildBankDepositArea)) {
|
||||
MessageString(Chat::Red, GUILD_BANK_FULL);
|
||||
GuildBankDepositAck(true, sentAction);
|
||||
if (ClientVersion() >= EQ::versions::ClientVersion::RoF) {
|
||||
GetInv().PopItem(EQ::invslot::slotCursor);
|
||||
PushItemOnCursor(*cursor_item_inst, true);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cursor_item->NoDrop ||
|
||||
cursor_item_inst->IsAttuned() ||
|
||||
cursor_item_inst->IsNoneEmptyContainer() ||
|
||||
cursor_item->NoRent == 0 ||
|
||||
(cursor_item->LoreFlag && GuildBanks->HasItem(GuildID(), cursor_item->ID))
|
||||
) {
|
||||
allowed = false;
|
||||
}
|
||||
|
||||
if (!allowed) {
|
||||
MessageString(Chat::Red, GUILD_BANK_CANNOT_DEPOSIT);
|
||||
GuildBankDepositAck(true, sentAction);
|
||||
|
||||
if (ClientVersion() >= EQ::versions::ClientVersion::RoF) {
|
||||
GetInv().PopItem(EQ::invslot::slotCursor);
|
||||
PushItemOnCursor(*cursor_item_inst, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
auto item = GuildBankRepository::NewEntity();
|
||||
item.guild_id = GuildID();
|
||||
item.area = GuildBankDepositArea;
|
||||
item.item_id = cursor_item->ID;
|
||||
item.quantity = cursor_item_inst->GetCharges();
|
||||
item.donator = GetCleanName();
|
||||
item.permissions = GuildBankBankerOnly;
|
||||
if (cursor_item_inst->IsAugmented()) {
|
||||
auto const augs = cursor_item_inst->GetAugmentIDs();
|
||||
item.augment_one_id = augs.at(0);
|
||||
item.augment_two_id = augs.at(1);
|
||||
item.augment_three_id = augs.at(2);
|
||||
item.augment_four_id = augs.at(3);
|
||||
item.augment_five_id = augs.at(4);
|
||||
item.augment_six_id = augs.at(5);
|
||||
}
|
||||
|
||||
if (GuildBanks->AddItem(item, this)) {
|
||||
GuildBankDepositAck(false, sentAction);
|
||||
DeleteItemInInventory(EQ::invslot::slotCursor, 0, false);
|
||||
|
||||
if (player_event_logs.IsEventEnabled(PlayerEvent::GUILD_BANK_DEPOSIT)) {
|
||||
PlayerEvent::GuildBankTransaction log{};
|
||||
log.char_id = CharacterID();
|
||||
log.guild_id = GuildID();
|
||||
log.item_id = item.item_id;
|
||||
log.quantity = item.quantity;
|
||||
log.aug_slot_one = item.augment_one_id;
|
||||
log.aug_slot_two = item.augment_two_id;
|
||||
log.aug_slot_three = item.augment_three_id;
|
||||
log.aug_slot_four = item.augment_four_id;
|
||||
log.aug_slot_five = item.augment_five_id;
|
||||
log.aug_slot_six = item.augment_six_id;
|
||||
|
||||
RecordPlayerEventLog(PlayerEvent::GUILD_BANK_DEPOSIT, log);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
case GuildBankPermissions: {
|
||||
auto gbps = (GuildBankPermissions_Struct *) app->pBuffer;
|
||||
GuildBankPromote_Struct *gbps = (GuildBankPromote_Struct*)app->pBuffer;
|
||||
|
||||
if (gbps->Permissions == 1) {
|
||||
GuildBanks->SetPermissions(GuildID(), gbps->SlotID, gbps->Permissions, gbps->MemberName, this);
|
||||
int Slot = GuildBanks->Promote(GuildID(), gbps->Slot);
|
||||
|
||||
if (Slot >= 0)
|
||||
{
|
||||
EQ::ItemInstance* inst = GuildBanks->GetItem(GuildID(), GuildBankMainArea, Slot, 1);
|
||||
|
||||
if (inst)
|
||||
{
|
||||
MessageString(Chat::LightGray, GUILD_BANK_TRANSFERRED, inst->GetItem()->Name);
|
||||
safe_delete(inst);
|
||||
}
|
||||
else {
|
||||
GuildBanks->SetPermissions(GuildID(), gbps->SlotID, gbps->Permissions, "", this);
|
||||
}
|
||||
else
|
||||
Message(Chat::Red, "Unexpected error while moving item into Guild Bank.");
|
||||
|
||||
GuildBankAck();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case GuildBankViewItem:
|
||||
{
|
||||
GuildBankViewItem_Struct *gbvis = (GuildBankViewItem_Struct*)app->pBuffer;
|
||||
|
||||
EQ::ItemInstance* inst = GuildBanks->GetItem(GuildID(), gbvis->Area, gbvis->SlotID, 1);
|
||||
|
||||
if (!inst)
|
||||
break;
|
||||
|
||||
SendItemPacket(0, inst, ItemPacketViewLink);
|
||||
|
||||
safe_delete(inst);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case GuildBankDeposit: // Deposit Item
|
||||
{
|
||||
EQ::ItemInstance *CursorItemInst = GetInv().GetItem(EQ::invslot::slotCursor);
|
||||
|
||||
bool Allowed = true;
|
||||
|
||||
if (!CursorItemInst)
|
||||
{
|
||||
Message(Chat::Red, "No Item on the cursor.");
|
||||
|
||||
GuildBankDepositAck(true, sentAction);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const EQ::ItemData* CursorItem = CursorItemInst->GetItem();
|
||||
|
||||
if (GuildBanks->IsAreaFull(GuildID(), GuildBankDepositArea))
|
||||
{
|
||||
MessageString(Chat::Red, GUILD_BANK_FULL);
|
||||
GuildBankDepositAck(true, sentAction);
|
||||
if (ClientVersion() >= EQ::versions::ClientVersion::RoF) {
|
||||
GetInv().PopItem(EQ::invslot::slotCursor);
|
||||
PushItemOnCursor(CursorItem, true);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CursorItem->NoDrop || CursorItemInst->IsAttuned())
|
||||
{
|
||||
Allowed = false;
|
||||
}
|
||||
else if (CursorItemInst->IsNoneEmptyContainer())
|
||||
{
|
||||
Allowed = false;
|
||||
}
|
||||
else if (CursorItemInst->IsAugmented())
|
||||
{
|
||||
Allowed = false;
|
||||
}
|
||||
else if (CursorItem->NoRent == 0)
|
||||
{
|
||||
Allowed = false;
|
||||
}
|
||||
else if (CursorItem->LoreFlag && GuildBanks->HasItem(GuildID(), CursorItem->ID))
|
||||
{
|
||||
Allowed = false;
|
||||
}
|
||||
|
||||
if (!Allowed)
|
||||
{
|
||||
MessageString(Chat::Red, GUILD_BANK_CANNOT_DEPOSIT);
|
||||
GuildBankDepositAck(true, sentAction);
|
||||
|
||||
if (ClientVersion() >= EQ::versions::ClientVersion::RoF) {
|
||||
GetInv().PopItem(EQ::invslot::slotCursor);
|
||||
PushItemOnCursor(CursorItem, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (GuildBanks->AddItem(GuildID(), GuildBankDepositArea, CursorItem->ID, CursorItemInst->GetCharges(), GetName(), GuildBankBankerOnly, ""))
|
||||
{
|
||||
GuildBankDepositAck(false, sentAction);
|
||||
|
||||
DeleteItemInInventory(EQ::invslot::slotCursor, 0, false);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case GuildBankPermissions:
|
||||
{
|
||||
GuildBankPermissions_Struct *gbps = (GuildBankPermissions_Struct*)app->pBuffer;
|
||||
|
||||
if (gbps->Permissions == 1)
|
||||
GuildBanks->SetPermissions(GuildID(), gbps->SlotID, gbps->Permissions, gbps->MemberName);
|
||||
else
|
||||
GuildBanks->SetPermissions(GuildID(), gbps->SlotID, gbps->Permissions, "");
|
||||
|
||||
GuildBankAck();
|
||||
break;
|
||||
}
|
||||
|
||||
case GuildBankWithdraw:
|
||||
{
|
||||
if (GetInv()[EQ::invslot::slotCursor])
|
||||
{
|
||||
MessageString(Chat::Red, GUILD_BANK_EMPTY_HANDS);
|
||||
|
||||
GuildBankAck();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case GuildBankWithdraw: {
|
||||
if (GetInv()[EQ::invslot::slotCursor]) {
|
||||
MessageString(Chat::Red, GUILD_BANK_EMPTY_HANDS);
|
||||
GuildBankAck();
|
||||
break;
|
||||
}
|
||||
GuildBankWithdrawItem_Struct *gbwis = (GuildBankWithdrawItem_Struct*)app->pBuffer;
|
||||
|
||||
auto gbwis = (GuildBankWithdrawItem_Struct *) app->pBuffer;
|
||||
auto inst = GuildBanks->GetItem(GuildID(), gbwis->Area, gbwis->SlotID, gbwis->Quantity);
|
||||
EQ::ItemInstance* inst = GuildBanks->GetItem(GuildID(), gbwis->Area, gbwis->SlotID, gbwis->Quantity);
|
||||
|
||||
if (!inst) {
|
||||
GuildBankAck();
|
||||
break;
|
||||
}
|
||||
if (!inst)
|
||||
{
|
||||
GuildBankAck();
|
||||
|
||||
if (!guild_mgr.CheckPermission(GuildID(), GuildRank(), GUILD_ACTION_BANK_WITHDRAW_ITEMS)) {
|
||||
Message(Chat::Red, "You do not have permission to withdraw.");
|
||||
GuildBankAck();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!IsGuildBanker()) {
|
||||
LogError("Suspected attempted hack on the guild bank from [{}]", GetName());
|
||||
GuildBankAck();
|
||||
break;
|
||||
}
|
||||
if (!guild_mgr.CheckPermission(GuildID(), GuildRank(), GUILD_ACTION_BANK_WITHDRAW_ITEMS))
|
||||
{
|
||||
Message(Chat::Red, "You do not have permission to withdraw.");
|
||||
GuildBankAck();
|
||||
safe_delete(inst);
|
||||
break;
|
||||
}
|
||||
|
||||
if (CheckLoreConflict(inst->GetItem())) {
|
||||
MessageString(Chat::Red, DUP_LORE);
|
||||
GuildBankAck();
|
||||
break;
|
||||
}
|
||||
|
||||
if (inst->GetCharges() > 0) {
|
||||
gbwis->Quantity = inst->GetCharges();
|
||||
}
|
||||
|
||||
if (inst->GetCharges() < 0) {
|
||||
gbwis->Quantity = 1;
|
||||
}
|
||||
|
||||
PushItemOnCursor(*inst.get());
|
||||
SendItemPacket(EQ::invslot::slotCursor, inst.get(), ItemPacketLimbo);
|
||||
GuildBanks->DeleteItem(GuildID(), gbwis->Area, gbwis->SlotID, gbwis->Quantity, this);
|
||||
|
||||
if (player_event_logs.IsEventEnabled(PlayerEvent::GUILD_BANK_WITHDRAWAL)) {
|
||||
PlayerEvent::GuildBankTransaction log{};
|
||||
log.char_id = CharacterID();
|
||||
log.guild_id = GuildID();
|
||||
log.item_id = inst->GetID();
|
||||
log.quantity = gbwis->Quantity;
|
||||
if (inst->IsAugmented()) {
|
||||
auto augs = inst->GetAugmentIDs();
|
||||
log.aug_slot_one = augs.at(0);
|
||||
log.aug_slot_two = augs.at(1);
|
||||
log.aug_slot_three = augs.at(2);
|
||||
log.aug_slot_four = augs.at(3);
|
||||
log.aug_slot_five = augs.at(4);
|
||||
log.aug_slot_six = augs.at(5);
|
||||
}
|
||||
|
||||
RecordPlayerEventLog(PlayerEvent::GUILD_BANK_WITHDRAWAL, log);
|
||||
}
|
||||
|
||||
else {
|
||||
Message(Chat::Red, "Unable to withdraw 0 quantity of %s", inst->GetItem()->Name);
|
||||
}
|
||||
if (!IsGuildBanker() && !GuildBanks->AllowedToWithdraw(GuildID(), gbwis->Area, gbwis->SlotID, GetName()))
|
||||
{
|
||||
LogError("Suspected attempted hack on the guild bank from [{}]", GetName());
|
||||
|
||||
GuildBankAck();
|
||||
break;
|
||||
}
|
||||
case GuildBankSplitStacks: {
|
||||
if (GuildBanks->IsAreaFull(GuildID(), GuildBankMainArea)) {
|
||||
MessageString(Chat::Red, GUILD_BANK_FULL);
|
||||
}
|
||||
else {
|
||||
auto gbwis = (GuildBankWithdrawItem_Struct *) app->pBuffer;
|
||||
GuildBanks->SplitStack(GuildID(), gbwis->SlotID, gbwis->Quantity, this);
|
||||
}
|
||||
|
||||
GuildBankAck();
|
||||
break;
|
||||
}
|
||||
case GuildBankMergeStacks: {
|
||||
auto gbwis = (GuildBankWithdrawItem_Struct *) app->pBuffer;
|
||||
GuildBanks->MergeStacks(GuildID(), gbwis->SlotID, this);
|
||||
GuildBankAck();
|
||||
safe_delete(inst);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
Message(Chat::Red, "Unexpected GuildBank action.");
|
||||
LogError("Received unexpected guild bank action code [{}] from [{}]", Action, GetName());
|
||||
if (CheckLoreConflict(inst->GetItem()))
|
||||
{
|
||||
MessageString(Chat::Red, DUP_LORE);
|
||||
|
||||
GuildBankAck();
|
||||
|
||||
safe_delete(inst);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (gbwis->Quantity > 0)
|
||||
{
|
||||
PushItemOnCursor(*inst);
|
||||
|
||||
SendItemPacket(EQ::invslot::slotCursor, inst, ItemPacketLimbo);
|
||||
|
||||
GuildBanks->DeleteItem(GuildID(), gbwis->Area, gbwis->SlotID, gbwis->Quantity);
|
||||
}
|
||||
else
|
||||
{
|
||||
Message(Chat::Red, "Unable to withdraw 0 quantity of %s", inst->GetItem()->Name);
|
||||
}
|
||||
|
||||
safe_delete(inst);
|
||||
|
||||
GuildBankAck();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case GuildBankSplitStacks:
|
||||
{
|
||||
if (GuildBanks->IsAreaFull(GuildID(), GuildBankMainArea))
|
||||
MessageString(Chat::Red, GUILD_BANK_FULL);
|
||||
else
|
||||
{
|
||||
GuildBankWithdrawItem_Struct *gbwis = (GuildBankWithdrawItem_Struct*)app->pBuffer;
|
||||
|
||||
GuildBanks->SplitStack(GuildID(), gbwis->SlotID, gbwis->Quantity);
|
||||
}
|
||||
|
||||
GuildBankAck();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case GuildBankMergeStacks:
|
||||
{
|
||||
GuildBankWithdrawItem_Struct *gbwis = (GuildBankWithdrawItem_Struct*)app->pBuffer;
|
||||
|
||||
GuildBanks->MergeStacks(GuildID(), gbwis->SlotID);
|
||||
|
||||
GuildBankAck();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
Message(Chat::Red, "Unexpected GuildBank action.");
|
||||
|
||||
LogError("Received unexpected guild bank action code [{}] from [{}]", Action, GetName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+19
-3
@@ -39,8 +39,8 @@
|
||||
#include "../common/skills.h"
|
||||
#include "../common/spdat.h"
|
||||
#include "../common/strings.h"
|
||||
#include "dynamic_zone.h"
|
||||
#include "event_codes.h"
|
||||
#include "expedition.h"
|
||||
#include "guild_mgr.h"
|
||||
#include "map.h"
|
||||
#include "petitions.h"
|
||||
@@ -776,8 +776,24 @@ void Client::BulkSendInventoryItems()
|
||||
EQ::OutBuffer ob;
|
||||
EQ::OutBuffer::pos_type last_pos = ob.tellp();
|
||||
|
||||
// Possessions items
|
||||
for (int16 slot_id = EQ::invslot::POSSESSIONS_BEGIN; slot_id <= EQ::invslot::POSSESSIONS_END; slot_id++) {
|
||||
// Equipment items
|
||||
for (int16 slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; slot_id++) {
|
||||
const EQ::ItemInstance* inst = m_inv[slot_id];
|
||||
if (!inst) {
|
||||
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();
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "data_bucket.h"
|
||||
#include "command.h"
|
||||
#include "dynamic_zone.h"
|
||||
#include "expedition.h"
|
||||
#include "queryserv.h"
|
||||
#include "quest_parser_collection.h"
|
||||
#include "titles.h"
|
||||
|
||||
@@ -862,6 +862,13 @@ struct DamageHitInfo {
|
||||
EQ::skills::SkillType skill;
|
||||
};
|
||||
|
||||
struct ExpeditionInvite
|
||||
{
|
||||
uint32_t expedition_id;
|
||||
std::string inviter_name;
|
||||
std::string swap_remove_name;
|
||||
};
|
||||
|
||||
struct DataBucketCache
|
||||
{
|
||||
uint64_t bucket_id;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user