Compare commits
13 commits
feature/bo
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8175ae6187 | ||
|
|
e8f4ffd628 | ||
|
|
0447618f7e | ||
|
|
e71ce001ff | ||
|
|
1575a2af40 | ||
|
|
4b69df646c | ||
|
|
044b9c1420 | ||
|
|
0bbb5b90e7 | ||
|
|
6506ad5b51 | ||
|
|
dcaa0ecdaa | ||
|
|
9b143132be | ||
|
|
231bf8b4ec | ||
|
|
dee58f9a91 |
25 changed files with 2283 additions and 2535 deletions
81
CHANGELOG.md
81
CHANGELOG.md
|
|
@ -1,3 +1,84 @@
|
|||
## [23.10.3] 9/16/2025
|
||||
|
||||
### Hotfix
|
||||
|
||||
* Hotfix crashes occurring in #4987. @Akkadius 2025-09-17
|
||||
|
||||
## [23.10.2] 9/16/2025
|
||||
|
||||
### Hotfix
|
||||
|
||||
* Revert #4996 as it was causing critical issues with spells that needs to be further investigated. @Akkadius 2025-09-17
|
||||
|
||||
## [23.10.1] 9/16/2025
|
||||
|
||||
### Hotfix
|
||||
* Fixed Mail Key Bug ([#5015](https://github.com/EQEmu/Server/pull/5015)) @Kinglykrab 2025-09-16
|
||||
|
||||
## [23.10.0] 9/15/2025
|
||||
|
||||
### Build
|
||||
|
||||
* Fix Linking with GCC ([#4969](https://github.com/EQEmu/Server/pull/4969)) @solar984 2025-08-03
|
||||
|
||||
### Code
|
||||
|
||||
* Add #npcedit npc_tint_id Help Message ([#4982](https://github.com/EQEmu/Server/pull/4982)) @Kinglykrab 2025-08-17
|
||||
* Cleanup #show ip_lookup Message ([#5005](https://github.com/EQEmu/Server/pull/5005)) @Kinglykrab 2025-08-30
|
||||
* Fix #set race 0 Message ([#5004](https://github.com/EQEmu/Server/pull/5004)) @Kinglykrab 2025-08-30
|
||||
* Fix Issues with Strings::Commify and Mob::SendStatsWindow ([#4984](https://github.com/EQEmu/Server/pull/4984)) @Kinglykrab 2025-08-17
|
||||
* Remove Attributions ([#4988](https://github.com/EQEmu/Server/pull/4988)) @KimLS 2025-08-16
|
||||
* Remove Unused errorname Variable ([#5001](https://github.com/EQEmu/Server/pull/5001)) @Kinglykrab 2025-08-29
|
||||
|
||||
### Commands
|
||||
|
||||
* Add #find account Subcommand ([#4981](https://github.com/EQEmu/Server/pull/4981)) @Kinglykrab 2025-08-17
|
||||
* Add #show keyring Subcommand ([#4973](https://github.com/EQEmu/Server/pull/4973)) @Kinglykrab 2025-08-03
|
||||
* Add #task complete Saylink to #task show ([#4985](https://github.com/EQEmu/Server/pull/4985)) @Kinglykrab 2025-08-17
|
||||
|
||||
### Constants
|
||||
|
||||
* Change Race Changes to Race Namespace ([#5000](https://github.com/EQEmu/Server/pull/5000)) @Kinglykrab 2025-08-30
|
||||
* Convert SE Defines to SpellEffect Namespace ([#4999](https://github.com/EQEmu/Server/pull/4999)) @Kinglykrab 2025-08-30
|
||||
|
||||
### Database
|
||||
|
||||
* Add `heal_amount` to `character_stats_record` ([#4986](https://github.com/EQEmu/Server/pull/4986)) @Kinglykrab 2025-08-17
|
||||
|
||||
### Fixes
|
||||
|
||||
* Fix #show recipe uint16 Cap ([#4978](https://github.com/EQEmu/Server/pull/4978)) @Kinglykrab 2025-08-11
|
||||
* Fix Race 474 for Titanium ([#4979](https://github.com/EQEmu/Server/pull/4979)) @regneq 2025-08-11
|
||||
* Fix Recipe Inspect Bug ([#4994](https://github.com/EQEmu/Server/pull/4994)) @Kinglykrab 2025-08-30
|
||||
* Fix Several Evolving Item Bugs ([#4992](https://github.com/EQEmu/Server/pull/4992)) @neckkola 2025-09-08
|
||||
* Fix Task Reloading ([#5002](https://github.com/EQEmu/Server/pull/5002)) @Kinglykrab 2025-08-29
|
||||
|
||||
### Loginserver
|
||||
|
||||
* Fix Legacy World When Using Local DB ([#4970](https://github.com/EQEmu/Server/pull/4970)) @solar984 2025-08-03
|
||||
|
||||
### Pets
|
||||
|
||||
* Add Pet Constants and Methods ([#4987](https://github.com/EQEmu/Server/pull/4987)) @Kinglykrab 2025-08-17
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add EVENT_CHARM_START and EVENT_CHARM_END ([#5013](https://github.com/EQEmu/Server/pull/5013)) @Kinglykrab 2025-09-15
|
||||
* Add GetKeyRing() to Perl/Lua ([#4980](https://github.com/EQEmu/Server/pull/4980)) @Kinglykrab 2025-08-17
|
||||
* Add GetNPCTintIndex() to Perl/Lua ([#4983](https://github.com/EQEmu/Server/pull/4983)) @Kinglykrab 2025-08-17
|
||||
* Add GetTimers() and GetPausedTimers() to Perl/Lua ([#4965](https://github.com/EQEmu/Server/pull/4965)) @Kinglykrab 2025-08-03
|
||||
* Add Identifiers to Get/Modify NPC Stat Methods ([#5012](https://github.com/EQEmu/Server/pull/5012)) @Kinglykrab 2025-09-15
|
||||
|
||||
### Repositories
|
||||
|
||||
* Convert Character Inspect Messages to Repositories ([#4997](https://github.com/EQEmu/Server/pull/4997)) @Kinglykrab 2025-08-30
|
||||
* Convert Damage Shield Types to Repositories ([#4995](https://github.com/EQEmu/Server/pull/4995)) @Kinglykrab 2025-08-30
|
||||
* Convert Item Loading to Repositories ([#4998](https://github.com/EQEmu/Server/pull/4998)) @Kinglykrab 2025-08-30
|
||||
* Convert Mail Key to Repositories ([#5007](https://github.com/EQEmu/Server/pull/5007)) @Kinglykrab 2025-09-15
|
||||
* Convert Shared Bank Platinum to Repositories ([#5006](https://github.com/EQEmu/Server/pull/5006)) @Kinglykrab 2025-09-02
|
||||
* Convert Spell Loading to Repositories ([#4996](https://github.com/EQEmu/Server/pull/4996)) @Kinglykrab 2025-08-30
|
||||
* Convert Total Time Played to Repositories ([#5008](https://github.com/EQEmu/Server/pull/5008)) @Kinglykrab 2025-09-15
|
||||
|
||||
## [23.9.1] 8/2/2025
|
||||
|
||||
### Hotfix
|
||||
|
|
|
|||
|
|
@ -7173,24 +7173,19 @@ ADD COLUMN `heal_amount` int(11) NULL DEFAULT 0 AFTER `spell_damage`;
|
|||
},
|
||||
ManifestEntry{
|
||||
.version = 9328,
|
||||
.description = "2025_08_27_spells_new_column_names.sql",
|
||||
.check = "SHOW COLUMNS FROM `spells_new` LIKE 'feedbackable'",
|
||||
.description = "2025_08_22_character_parcel_updates.sql",
|
||||
.check = "SHOW COLUMNS FROM `character_parcels` LIKE 'evolve_amount'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `spells_new`
|
||||
CHANGE COLUMN `field160` `feedbackable` int(11) NOT NULL DEFAULT 0 AFTER `npc_no_los`,
|
||||
CHANGE COLUMN `field198` `no_detrimental_spell_aggro` int(11) NOT NULL DEFAULT 0 AFTER `not_extendable`,
|
||||
CHANGE COLUMN `field209` `no_resist` int(11) NULL DEFAULT 0 AFTER `rank`,
|
||||
CHANGE COLUMN `field217` `override_crit_chance` int(11) NULL DEFAULT 0 AFTER `field216`,
|
||||
CHANGE COLUMN `field220` `no_heal_damage_item_mod` int(11) NULL DEFAULT 0 AFTER `maxtargets`,
|
||||
CHANGE COLUMN `field221` `caster_requirement_id` int(11) NULL DEFAULT 0 AFTER `no_heal_damage_item_mod`,
|
||||
CHANGE COLUMN `field222` `spell_class` int(11) NULL DEFAULT 0 AFTER `caster_requirement_id`,
|
||||
CHANGE COLUMN `field223` `spell_subclass` int(11) NULL DEFAULT 0 AFTER `spell_class`,
|
||||
CHANGE COLUMN `field232` `no_remove` int(11) NOT NULL DEFAULT 0 AFTER `min_range`;
|
||||
)"
|
||||
}
|
||||
ALTER TABLE `character_parcels`
|
||||
ADD COLUMN `evolve_amount` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `quantity`;
|
||||
|
||||
ALTER TABLE `character_parcels_containers`
|
||||
ADD COLUMN `evolve_amount` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `quantity`;
|
||||
)",
|
||||
.content_schema_update = false
|
||||
},
|
||||
// -- template; copy/paste this when you need to create a new entry
|
||||
// ManifestEntry{
|
||||
// .version = 9228,
|
||||
|
|
|
|||
|
|
@ -74,6 +74,10 @@ void EvolvingItemsManager::DoLootChecks(const uint32 char_id, const uint16 slot_
|
|||
e.item_id = inst.GetID();
|
||||
e.equipped = inst.GetEvolveEquipped();
|
||||
e.final_item_id = EvolvingItemsManager::Instance()->GetFinalItemID(inst);
|
||||
if (inst.GetEvolveCurrentAmount() > 0) {
|
||||
e.current_amount = inst.GetEvolveCurrentAmount();
|
||||
inst.CalculateEvolveProgression();
|
||||
}
|
||||
|
||||
auto r = CharacterEvolvingItemsRepository::InsertOne(*m_db, e);
|
||||
e.id = r.id;
|
||||
|
|
|
|||
|
|
@ -6481,7 +6481,7 @@ namespace RoF2
|
|||
hdr.scaled_value = (inst->IsScaling() ? (inst->GetExp() / 100) : 0);
|
||||
hdr.instance_id = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : inst->GetSerialNumber());
|
||||
hdr.parcel_item_id = packet_type == ItemPacketParcel ? inst->GetID() : 0;
|
||||
if (item->EvolvingItem) {
|
||||
if (item->EvolvingItem && packet_type != ItemPacketParcel && packet_type != ItemPacketMerchant) {
|
||||
hdr.instance_id = inst->GetEvolveUniqueID() & 0xFFFFFFFF; //lower dword
|
||||
hdr.parcel_item_id = inst->GetEvolveUniqueID() >> 32; //upper dword
|
||||
}
|
||||
|
|
@ -6500,6 +6500,7 @@ namespace RoF2
|
|||
|
||||
if (item->EvolvingItem > 0) {
|
||||
RoF2::structs::EvolvingItem_Struct evotop;
|
||||
inst->CalculateEvolveProgression();
|
||||
|
||||
evotop.final_item_id = inst->GetEvolveFinalItemID();
|
||||
evotop.evolve_level = item->EvolvingLevel;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ public:
|
|||
uint32_t aug_slot_5;
|
||||
uint32_t aug_slot_6;
|
||||
uint32_t quantity;
|
||||
uint32_t evolve_amount;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
|
|
@ -51,6 +52,7 @@ public:
|
|||
"aug_slot_5",
|
||||
"aug_slot_6",
|
||||
"quantity",
|
||||
"evolve_amount",
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -68,6 +70,7 @@ public:
|
|||
"aug_slot_5",
|
||||
"aug_slot_6",
|
||||
"quantity",
|
||||
"evolve_amount",
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -108,17 +111,18 @@ public:
|
|||
{
|
||||
CharacterParcelsContainers e{};
|
||||
|
||||
e.id = 0;
|
||||
e.parcels_id = 0;
|
||||
e.slot_id = 0;
|
||||
e.item_id = 0;
|
||||
e.aug_slot_1 = 0;
|
||||
e.aug_slot_2 = 0;
|
||||
e.aug_slot_3 = 0;
|
||||
e.aug_slot_4 = 0;
|
||||
e.aug_slot_5 = 0;
|
||||
e.aug_slot_6 = 0;
|
||||
e.quantity = 0;
|
||||
e.id = 0;
|
||||
e.parcels_id = 0;
|
||||
e.slot_id = 0;
|
||||
e.item_id = 0;
|
||||
e.aug_slot_1 = 0;
|
||||
e.aug_slot_2 = 0;
|
||||
e.aug_slot_3 = 0;
|
||||
e.aug_slot_4 = 0;
|
||||
e.aug_slot_5 = 0;
|
||||
e.aug_slot_6 = 0;
|
||||
e.quantity = 0;
|
||||
e.evolve_amount = 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
|
@ -155,17 +159,18 @@ public:
|
|||
if (results.RowCount() == 1) {
|
||||
CharacterParcelsContainers e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.parcels_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.slot_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.item_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.aug_slot_1 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.aug_slot_2 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.aug_slot_3 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.aug_slot_4 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.aug_slot_5 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.aug_slot_6 = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.parcels_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.slot_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.item_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.aug_slot_1 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.aug_slot_2 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.aug_slot_3 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.aug_slot_4 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.aug_slot_5 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.aug_slot_6 = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
|
||||
e.evolve_amount = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
|
@ -209,6 +214,7 @@ public:
|
|||
v.push_back(columns[8] + " = " + std::to_string(e.aug_slot_5));
|
||||
v.push_back(columns[9] + " = " + std::to_string(e.aug_slot_6));
|
||||
v.push_back(columns[10] + " = " + std::to_string(e.quantity));
|
||||
v.push_back(columns[11] + " = " + std::to_string(e.evolve_amount));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
|
|
@ -241,6 +247,7 @@ public:
|
|||
v.push_back(std::to_string(e.aug_slot_5));
|
||||
v.push_back(std::to_string(e.aug_slot_6));
|
||||
v.push_back(std::to_string(e.quantity));
|
||||
v.push_back(std::to_string(e.evolve_amount));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
|
|
@ -281,6 +288,7 @@ public:
|
|||
v.push_back(std::to_string(e.aug_slot_5));
|
||||
v.push_back(std::to_string(e.aug_slot_6));
|
||||
v.push_back(std::to_string(e.quantity));
|
||||
v.push_back(std::to_string(e.evolve_amount));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
|
@ -314,17 +322,18 @@ public:
|
|||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
CharacterParcelsContainers e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.parcels_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.slot_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.item_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.aug_slot_1 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.aug_slot_2 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.aug_slot_3 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.aug_slot_4 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.aug_slot_5 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.aug_slot_6 = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.parcels_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.slot_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.item_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.aug_slot_1 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.aug_slot_2 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.aug_slot_3 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.aug_slot_4 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.aug_slot_5 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.aug_slot_6 = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
|
||||
e.evolve_amount = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
|
@ -349,17 +358,18 @@ public:
|
|||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
CharacterParcelsContainers e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.parcels_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.slot_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.item_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.aug_slot_1 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.aug_slot_2 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.aug_slot_3 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.aug_slot_4 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.aug_slot_5 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.aug_slot_6 = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.parcels_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.slot_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.item_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.aug_slot_1 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.aug_slot_2 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.aug_slot_3 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.aug_slot_4 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.aug_slot_5 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.aug_slot_6 = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
|
||||
e.evolve_amount = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
|
@ -445,6 +455,7 @@ public:
|
|||
v.push_back(std::to_string(e.aug_slot_5));
|
||||
v.push_back(std::to_string(e.aug_slot_6));
|
||||
v.push_back(std::to_string(e.quantity));
|
||||
v.push_back(std::to_string(e.evolve_amount));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
|
|
@ -478,6 +489,7 @@ public:
|
|||
v.push_back(std::to_string(e.aug_slot_5));
|
||||
v.push_back(std::to_string(e.aug_slot_6));
|
||||
v.push_back(std::to_string(e.quantity));
|
||||
v.push_back(std::to_string(e.evolve_amount));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ public:
|
|||
uint32_t aug_slot_6;
|
||||
uint32_t slot_id;
|
||||
uint32_t quantity;
|
||||
uint32_t evolve_amount;
|
||||
std::string from_name;
|
||||
std::string note;
|
||||
time_t sent_date;
|
||||
|
|
@ -54,6 +55,7 @@ public:
|
|||
"aug_slot_6",
|
||||
"slot_id",
|
||||
"quantity",
|
||||
"evolve_amount",
|
||||
"from_name",
|
||||
"note",
|
||||
"sent_date",
|
||||
|
|
@ -74,6 +76,7 @@ public:
|
|||
"aug_slot_6",
|
||||
"slot_id",
|
||||
"quantity",
|
||||
"evolve_amount",
|
||||
"from_name",
|
||||
"note",
|
||||
"UNIX_TIMESTAMP(sent_date)",
|
||||
|
|
@ -117,20 +120,21 @@ public:
|
|||
{
|
||||
CharacterParcels e{};
|
||||
|
||||
e.id = 0;
|
||||
e.char_id = 0;
|
||||
e.item_id = 0;
|
||||
e.aug_slot_1 = 0;
|
||||
e.aug_slot_2 = 0;
|
||||
e.aug_slot_3 = 0;
|
||||
e.aug_slot_4 = 0;
|
||||
e.aug_slot_5 = 0;
|
||||
e.aug_slot_6 = 0;
|
||||
e.slot_id = 0;
|
||||
e.quantity = 0;
|
||||
e.from_name = "";
|
||||
e.note = "";
|
||||
e.sent_date = 0;
|
||||
e.id = 0;
|
||||
e.char_id = 0;
|
||||
e.item_id = 0;
|
||||
e.aug_slot_1 = 0;
|
||||
e.aug_slot_2 = 0;
|
||||
e.aug_slot_3 = 0;
|
||||
e.aug_slot_4 = 0;
|
||||
e.aug_slot_5 = 0;
|
||||
e.aug_slot_6 = 0;
|
||||
e.slot_id = 0;
|
||||
e.quantity = 0;
|
||||
e.evolve_amount = 0;
|
||||
e.from_name = "";
|
||||
e.note = "";
|
||||
e.sent_date = 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
|
@ -167,20 +171,21 @@ public:
|
|||
if (results.RowCount() == 1) {
|
||||
CharacterParcels e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.slot_id = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
|
||||
e.from_name = row[11] ? row[11] : "";
|
||||
e.note = row[12] ? row[12] : "";
|
||||
e.sent_date = strtoll(row[13] ? row[13] : "-1", nullptr, 10);
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.slot_id = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
|
||||
e.evolve_amount = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
|
||||
e.from_name = row[12] ? row[12] : "";
|
||||
e.note = row[13] ? row[13] : "";
|
||||
e.sent_date = strtoll(row[14] ? row[14] : "-1", nullptr, 10);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
|
@ -224,9 +229,10 @@ public:
|
|||
v.push_back(columns[8] + " = " + std::to_string(e.aug_slot_6));
|
||||
v.push_back(columns[9] + " = " + std::to_string(e.slot_id));
|
||||
v.push_back(columns[10] + " = " + std::to_string(e.quantity));
|
||||
v.push_back(columns[11] + " = '" + Strings::Escape(e.from_name) + "'");
|
||||
v.push_back(columns[12] + " = '" + Strings::Escape(e.note) + "'");
|
||||
v.push_back(columns[13] + " = FROM_UNIXTIME(" + (e.sent_date > 0 ? std::to_string(e.sent_date) : "null") + ")");
|
||||
v.push_back(columns[11] + " = " + std::to_string(e.evolve_amount));
|
||||
v.push_back(columns[12] + " = '" + Strings::Escape(e.from_name) + "'");
|
||||
v.push_back(columns[13] + " = '" + Strings::Escape(e.note) + "'");
|
||||
v.push_back(columns[14] + " = FROM_UNIXTIME(" + (e.sent_date > 0 ? std::to_string(e.sent_date) : "null") + ")");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
|
|
@ -259,6 +265,7 @@ public:
|
|||
v.push_back(std::to_string(e.aug_slot_6));
|
||||
v.push_back(std::to_string(e.slot_id));
|
||||
v.push_back(std::to_string(e.quantity));
|
||||
v.push_back(std::to_string(e.evolve_amount));
|
||||
v.push_back("'" + Strings::Escape(e.from_name) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.note) + "'");
|
||||
v.push_back("FROM_UNIXTIME(" + (e.sent_date > 0 ? std::to_string(e.sent_date) : "null") + ")");
|
||||
|
|
@ -302,6 +309,7 @@ public:
|
|||
v.push_back(std::to_string(e.aug_slot_6));
|
||||
v.push_back(std::to_string(e.slot_id));
|
||||
v.push_back(std::to_string(e.quantity));
|
||||
v.push_back(std::to_string(e.evolve_amount));
|
||||
v.push_back("'" + Strings::Escape(e.from_name) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.note) + "'");
|
||||
v.push_back("FROM_UNIXTIME(" + (e.sent_date > 0 ? std::to_string(e.sent_date) : "null") + ")");
|
||||
|
|
@ -338,20 +346,21 @@ public:
|
|||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
CharacterParcels e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.slot_id = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
|
||||
e.from_name = row[11] ? row[11] : "";
|
||||
e.note = row[12] ? row[12] : "";
|
||||
e.sent_date = strtoll(row[13] ? row[13] : "-1", nullptr, 10);
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.slot_id = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
|
||||
e.evolve_amount = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
|
||||
e.from_name = row[12] ? row[12] : "";
|
||||
e.note = row[13] ? row[13] : "";
|
||||
e.sent_date = strtoll(row[14] ? row[14] : "-1", nullptr, 10);
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
|
@ -376,20 +385,21 @@ public:
|
|||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
CharacterParcels e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.slot_id = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
|
||||
e.from_name = row[11] ? row[11] : "";
|
||||
e.note = row[12] ? row[12] : "";
|
||||
e.sent_date = strtoll(row[13] ? row[13] : "-1", nullptr, 10);
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.slot_id = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
|
||||
e.evolve_amount = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
|
||||
e.from_name = row[12] ? row[12] : "";
|
||||
e.note = row[13] ? row[13] : "";
|
||||
e.sent_date = strtoll(row[14] ? row[14] : "-1", nullptr, 10);
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
|
@ -475,6 +485,7 @@ public:
|
|||
v.push_back(std::to_string(e.aug_slot_6));
|
||||
v.push_back(std::to_string(e.slot_id));
|
||||
v.push_back(std::to_string(e.quantity));
|
||||
v.push_back(std::to_string(e.evolve_amount));
|
||||
v.push_back("'" + Strings::Escape(e.from_name) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.note) + "'");
|
||||
v.push_back("FROM_UNIXTIME(" + (e.sent_date > 0 ? std::to_string(e.sent_date) : "null") + ")");
|
||||
|
|
@ -511,6 +522,7 @@ public:
|
|||
v.push_back(std::to_string(e.aug_slot_6));
|
||||
v.push_back(std::to_string(e.slot_id));
|
||||
v.push_back(std::to_string(e.quantity));
|
||||
v.push_back(std::to_string(e.evolve_amount));
|
||||
v.push_back("'" + Strings::Escape(e.from_name) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.note) + "'");
|
||||
v.push_back("FROM_UNIXTIME(" + (e.sent_date > 0 ? std::to_string(e.sent_date) : "null") + ")");
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -191,6 +191,22 @@ public:
|
|||
|
||||
return character_ids;
|
||||
}
|
||||
|
||||
static uint32_t GetTotalTimePlayed(Database& db, uint32_t account_id)
|
||||
{
|
||||
auto query = fmt::format(
|
||||
"SELECT SUM(time_played) FROM `character_data` WHERE `account_id` = {}",
|
||||
account_id
|
||||
);
|
||||
|
||||
auto results = db.QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto row = results.begin();
|
||||
return Strings::ToUnsignedInt(row[0]);
|
||||
}
|
||||
};
|
||||
|
||||
#endif //EQEMU_CHARACTER_DATA_REPOSITORY_H
|
||||
|
|
|
|||
|
|
@ -122,66 +122,41 @@ bool SharedDatabase::SetGMFlymode(uint32 account_id, uint8 flymode)
|
|||
return a.id > 0;
|
||||
}
|
||||
|
||||
uint32 SharedDatabase::GetTotalTimeEntitledOnAccount(uint32 AccountID) {
|
||||
uint32 EntitledTime = 0;
|
||||
const std::string query = StringFormat("SELECT `time_played` FROM `character_data` WHERE `account_id` = %u", AccountID);
|
||||
auto results = QueryDatabase(query);
|
||||
for (auto& row = results.begin(); row != results.end(); ++row) {
|
||||
EntitledTime += Strings::ToUnsignedInt(row[0]);
|
||||
}
|
||||
return EntitledTime;
|
||||
}
|
||||
|
||||
void SharedDatabase::SetMailKey(int CharID, int IPAddress, int MailKey)
|
||||
void SharedDatabase::SetMailKey(uint32 character_id, uint32 ip_address, uint32 mail_key)
|
||||
{
|
||||
char mail_key[17];
|
||||
std::string full_mail_key;
|
||||
|
||||
if (RuleB(Chat, EnableMailKeyIPVerification) == true) {
|
||||
sprintf(mail_key, "%08X%08X", IPAddress, MailKey);
|
||||
}
|
||||
else {
|
||||
sprintf(mail_key, "%08X", MailKey);
|
||||
if (RuleB(Chat, EnableMailKeyIPVerification)) {
|
||||
full_mail_key = fmt::format("{:08X}{:08X}", ip_address, mail_key);
|
||||
} else {
|
||||
full_mail_key = fmt::format("{:08X}", mail_key);
|
||||
}
|
||||
|
||||
const std::string query = StringFormat(
|
||||
"UPDATE character_data SET mailkey = '%s' WHERE id = '%i'",
|
||||
mail_key, CharID
|
||||
);
|
||||
auto e = CharacterDataRepository::FindOne(*this, character_id);
|
||||
if (!e.id) {
|
||||
LogError("Failed to find character_id [{}] when setting mailkey", character_id);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
LogError("SharedDatabase::SetMailKey({}, {}) : {}", CharID, mail_key, results.ErrorMessage().c_str());
|
||||
e.mailkey = full_mail_key;
|
||||
|
||||
if (!CharacterDataRepository::UpdateOne(*this, e)) {
|
||||
LogError("Failed to set mailkey to [{}] for character_id [{}]", full_mail_key, character_id);
|
||||
}
|
||||
}
|
||||
|
||||
SharedDatabase::MailKeys SharedDatabase::GetMailKey(int character_id)
|
||||
SharedDatabase::MailKeys SharedDatabase::GetMailKey(uint32 character_id)
|
||||
{
|
||||
const std::string query = StringFormat("SELECT `mailkey` FROM `character_data` WHERE `id`='%i' LIMIT 1", character_id);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return MailKeys{};
|
||||
auto e = CharacterDataRepository::FindOne(*this, character_id);
|
||||
|
||||
if (!e.id) {
|
||||
return MailKeys{ };
|
||||
}
|
||||
|
||||
if (!results.RowCount()) {
|
||||
Log(Logs::General,
|
||||
Logs::ClientLogin,
|
||||
"Error: Mailkey for character id [%i] does not exist or could not be found",
|
||||
character_id
|
||||
);
|
||||
return MailKeys{};
|
||||
}
|
||||
|
||||
auto &row = results.begin();
|
||||
if (row != results.end()) {
|
||||
std::string mail_key = row[0];
|
||||
|
||||
return MailKeys{
|
||||
.mail_key = mail_key.substr(8),
|
||||
.mail_key_full = mail_key
|
||||
};
|
||||
}
|
||||
|
||||
return MailKeys{};
|
||||
return MailKeys{
|
||||
.mail_key = e.mailkey.substr(8),
|
||||
.mail_key_full = e.mailkey
|
||||
};
|
||||
}
|
||||
|
||||
bool SharedDatabase::SaveCursor(
|
||||
|
|
@ -448,27 +423,20 @@ bool SharedDatabase::DeleteSharedBankSlot(uint32 char_id, int16 slot_id)
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
int32 SharedDatabase::GetSharedPlatinum(uint32 account_id)
|
||||
{
|
||||
const auto query = fmt::format("SELECT sharedplat FROM account WHERE id = {}", account_id);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success() || !results.RowCount()) {
|
||||
return 0;
|
||||
}
|
||||
const auto& e = AccountRepository::FindOne(*this, account_id);
|
||||
|
||||
auto row = results.begin();
|
||||
return Strings::ToInt(row[0]);
|
||||
return e.sharedplat;
|
||||
}
|
||||
|
||||
bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) {
|
||||
const std::string query = StringFormat("UPDATE account SET sharedplat = sharedplat + %i WHERE id = %i", amount_to_add, account_id);
|
||||
const auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return false;
|
||||
}
|
||||
bool SharedDatabase::AddSharedPlatinum(uint32 account_id, int amount)
|
||||
{
|
||||
auto e = AccountRepository::FindOne(*this, account_id);
|
||||
|
||||
return true;
|
||||
e.sharedplat += amount;
|
||||
|
||||
return AccountRepository::UpdateOne(*this, e);
|
||||
}
|
||||
|
||||
bool SharedDatabase::SetStartingItems(
|
||||
|
|
@ -1662,9 +1630,16 @@ const EvolveInfo* SharedDatabase::GetEvolveInfo(uint32 loregroup) {
|
|||
return nullptr; // nothing here for now... database and/or sharemem pulls later
|
||||
}
|
||||
|
||||
int SharedDatabase::GetMaxSpellID()
|
||||
{
|
||||
return SpellsNewRepository::GetMaxId(*this);
|
||||
int SharedDatabase::GetMaxSpellID() {
|
||||
const std::string query = "SELECT MAX(id) FROM spells_new";
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto& row = results.begin();
|
||||
|
||||
return Strings::ToInt(row[0]);
|
||||
}
|
||||
|
||||
bool SharedDatabase::LoadSpells(const std::string &prefix, int32 *records, const SPDat_Spell_Struct **sp) {
|
||||
|
|
@ -1696,247 +1671,173 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) {
|
|||
*static_cast<uint32*>(data) = max_spells;
|
||||
SPDat_Spell_Struct *sp = reinterpret_cast<SPDat_Spell_Struct*>(static_cast<char*>(data) + sizeof(uint32));
|
||||
|
||||
const auto& l = SpellsNewRepository::All(*this);
|
||||
const std::string query = "SELECT * FROM spells_new ORDER BY id ASC";
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (l.empty()) {
|
||||
if(results.ColumnCount() <= SPELL_LOAD_FIELD_COUNT) {
|
||||
LogSpells("Fatal error loading spells: Spell field count < SPELL_LOAD_FIELD_COUNT([{}])", SPELL_LOAD_FIELD_COUNT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& e : l) {
|
||||
if (e.id >= max_spells) {
|
||||
int counter = 0;
|
||||
|
||||
for (auto& row = results.begin(); row != results.end(); ++row) {
|
||||
const int tempid = Strings::ToInt(row[0]);
|
||||
if(tempid >= max_spells) {
|
||||
LogSpells("Non fatal error: spell.id >= max_spells, ignoring");
|
||||
continue;
|
||||
}
|
||||
|
||||
sp[e.id].id = e.id;
|
||||
++counter;
|
||||
sp[tempid].id = tempid;
|
||||
strn0cpy(sp[tempid].name, row[1], sizeof(sp[tempid].name));
|
||||
strn0cpy(sp[tempid].player_1, row[2], sizeof(sp[tempid].player_1));
|
||||
strn0cpy(sp[tempid].teleport_zone, row[3], sizeof(sp[tempid].teleport_zone));
|
||||
strn0cpy(sp[tempid].you_cast, row[4], sizeof(sp[tempid].you_cast));
|
||||
strn0cpy(sp[tempid].other_casts, row[5], sizeof(sp[tempid].other_casts));
|
||||
strn0cpy(sp[tempid].cast_on_you, row[6], sizeof(sp[tempid].cast_on_you));
|
||||
strn0cpy(sp[tempid].cast_on_other, row[7], sizeof(sp[tempid].cast_on_other));
|
||||
strn0cpy(sp[tempid].spell_fades, row[8], sizeof(sp[tempid].spell_fades));
|
||||
|
||||
strn0cpy(sp[e.id].name, e.name.c_str(), sizeof(sp[e.id].name));
|
||||
strn0cpy(sp[e.id].player_1, e.player_1.c_str(), sizeof(sp[e.id].player_1));
|
||||
strn0cpy(sp[e.id].teleport_zone, e.teleport_zone.c_str(), sizeof(sp[e.id].teleport_zone));
|
||||
strn0cpy(sp[e.id].you_cast, e.you_cast.c_str(), sizeof(sp[e.id].you_cast));
|
||||
strn0cpy(sp[e.id].other_casts, e.other_casts.c_str(), sizeof(sp[e.id].other_casts));
|
||||
strn0cpy(sp[e.id].cast_on_you, e.cast_on_you.c_str(), sizeof(sp[e.id].cast_on_you));
|
||||
strn0cpy(sp[e.id].cast_on_other, e.cast_on_other.c_str(), sizeof(sp[e.id].cast_on_other));
|
||||
strn0cpy(sp[e.id].spell_fades, e.spell_fades.c_str(), sizeof(sp[e.id].spell_fades));
|
||||
sp[tempid].range = Strings::ToFloat(row[9]);
|
||||
sp[tempid].aoe_range = Strings::ToFloat(row[10]);
|
||||
sp[tempid].push_back = Strings::ToFloat(row[11]);
|
||||
sp[tempid].push_up = Strings::ToFloat(row[12]);
|
||||
sp[tempid].cast_time=Strings::ToUnsignedInt(row[13]);
|
||||
sp[tempid].recovery_time=Strings::ToUnsignedInt(row[14]);
|
||||
sp[tempid].recast_time=Strings::ToUnsignedInt(row[15]);
|
||||
sp[tempid].buff_duration_formula=Strings::ToUnsignedInt(row[16]);
|
||||
sp[tempid].buff_duration=Strings::ToUnsignedInt(row[17]);
|
||||
sp[tempid].aoe_duration=Strings::ToUnsignedInt(row[18]);
|
||||
sp[tempid].mana=Strings::ToInt(row[19]);
|
||||
|
||||
sp[e.id].range = e.range_;
|
||||
sp[e.id].aoe_range = e.aoerange;
|
||||
sp[e.id].push_back = e.pushback;
|
||||
sp[e.id].push_up = e.pushup;
|
||||
sp[e.id].cast_time = e.cast_time;
|
||||
sp[e.id].recovery_time = e.recovery_time;
|
||||
sp[e.id].recast_time = e.recast_time;
|
||||
sp[e.id].buff_duration_formula = e.buffdurationformula;
|
||||
sp[e.id].buff_duration = e.buffduration;
|
||||
sp[e.id].aoe_duration = e.AEDuration;
|
||||
sp[e.id].mana = e.mana;
|
||||
int y=0;
|
||||
for(y=0; y< EFFECT_COUNT;y++)
|
||||
sp[tempid].base_value[y]=Strings::ToInt(row[20+y]); // effect_base_value
|
||||
|
||||
sp[e.id].base_value[0] = e.effect_base_value1;
|
||||
sp[e.id].base_value[1] = e.effect_base_value2;
|
||||
sp[e.id].base_value[2] = e.effect_base_value3;
|
||||
sp[e.id].base_value[3] = e.effect_base_value4;
|
||||
sp[e.id].base_value[4] = e.effect_base_value5;
|
||||
sp[e.id].base_value[5] = e.effect_base_value6;
|
||||
sp[e.id].base_value[6] = e.effect_base_value7;
|
||||
sp[e.id].base_value[7] = e.effect_base_value8;
|
||||
sp[e.id].base_value[8] = e.effect_base_value9;
|
||||
sp[e.id].base_value[9] = e.effect_base_value10;
|
||||
sp[e.id].base_value[10] = e.effect_base_value11;
|
||||
sp[e.id].base_value[11] = e.effect_base_value12;
|
||||
for(y=0; y < EFFECT_COUNT; y++)
|
||||
sp[tempid].limit_value[y]=Strings::ToInt(row[32+y]); // effect_limit_value
|
||||
|
||||
sp[e.id].limit_value[0] = e.effect_limit_value1;
|
||||
sp[e.id].limit_value[1] = e.effect_limit_value2;
|
||||
sp[e.id].limit_value[2] = e.effect_limit_value3;
|
||||
sp[e.id].limit_value[3] = e.effect_limit_value4;
|
||||
sp[e.id].limit_value[4] = e.effect_limit_value5;
|
||||
sp[e.id].limit_value[5] = e.effect_limit_value6;
|
||||
sp[e.id].limit_value[6] = e.effect_limit_value7;
|
||||
sp[e.id].limit_value[7] = e.effect_limit_value8;
|
||||
sp[e.id].limit_value[8] = e.effect_limit_value9;
|
||||
sp[e.id].limit_value[9] = e.effect_limit_value10;
|
||||
sp[e.id].limit_value[10] = e.effect_limit_value11;
|
||||
sp[e.id].limit_value[11] = e.effect_limit_value12;
|
||||
for(y=0; y< EFFECT_COUNT;y++)
|
||||
sp[tempid].max_value[y]=Strings::ToInt(row[44+y]);
|
||||
|
||||
sp[e.id].max_value[0] = e.max1;
|
||||
sp[e.id].max_value[1] = e.max2;
|
||||
sp[e.id].max_value[2] = e.max3;
|
||||
sp[e.id].max_value[3] = e.max4;
|
||||
sp[e.id].max_value[4] = e.max5;
|
||||
sp[e.id].max_value[5] = e.max6;
|
||||
sp[e.id].max_value[6] = e.max7;
|
||||
sp[e.id].max_value[7] = e.max8;
|
||||
sp[e.id].max_value[8] = e.max9;
|
||||
sp[e.id].max_value[9] = e.max10;
|
||||
sp[e.id].max_value[10] = e.max11;
|
||||
sp[e.id].max_value[11] = e.max12;
|
||||
for(y=0; y< 4;y++)
|
||||
sp[tempid].component[y]=Strings::ToInt(row[58+y]);
|
||||
|
||||
sp[e.id].component[0] = e.components1;
|
||||
sp[e.id].component[1] = e.components2;
|
||||
sp[e.id].component[2] = e.components3;
|
||||
sp[e.id].component[3] = e.components4;
|
||||
for(y=0; y< 4;y++)
|
||||
sp[tempid].component_count[y]=Strings::ToInt(row[62+y]);
|
||||
|
||||
sp[e.id].component_count[0] = e.component_counts1;
|
||||
sp[e.id].component_count[1] = e.component_counts2;
|
||||
sp[e.id].component_count[2] = e.component_counts3;
|
||||
sp[e.id].component_count[3] = e.component_counts4;
|
||||
for(y=0; y< 4;y++)
|
||||
sp[tempid].no_expend_reagent[y]=Strings::ToInt(row[66+y]);
|
||||
|
||||
sp[e.id].no_expend_reagent[0] = e.NoexpendReagent1;
|
||||
sp[e.id].no_expend_reagent[1] = e.NoexpendReagent2;
|
||||
sp[e.id].no_expend_reagent[2] = e.NoexpendReagent3;
|
||||
sp[e.id].no_expend_reagent[3] = e.NoexpendReagent4;
|
||||
for(y=0; y< EFFECT_COUNT;y++)
|
||||
sp[tempid].formula[y]=Strings::ToUnsignedInt(row[70+y]);
|
||||
|
||||
sp[e.id].formula[0] = e.formula1;
|
||||
sp[e.id].formula[1] = e.formula2;
|
||||
sp[e.id].formula[2] = e.formula3;
|
||||
sp[e.id].formula[3] = e.formula4;
|
||||
sp[e.id].formula[4] = e.formula5;
|
||||
sp[e.id].formula[5] = e.formula6;
|
||||
sp[e.id].formula[6] = e.formula7;
|
||||
sp[e.id].formula[7] = e.formula8;
|
||||
sp[e.id].formula[8] = e.formula9;
|
||||
sp[e.id].formula[9] = e.formula10;
|
||||
sp[e.id].formula[10] = e.formula11;
|
||||
sp[e.id].formula[11] = e.formula12;
|
||||
sp[tempid].good_effect=Strings::ToInt(row[83]);
|
||||
sp[tempid].activated=Strings::ToInt(row[84]);
|
||||
sp[tempid].resist_type=Strings::ToInt(row[85]);
|
||||
|
||||
sp[e.id].good_effect = e.goodEffect;
|
||||
sp[e.id].activated = e.Activated;
|
||||
sp[e.id].resist_type = e.resisttype;
|
||||
for(y=0; y< EFFECT_COUNT;y++)
|
||||
sp[tempid].effect_id[y]=Strings::ToInt(row[86+y]);
|
||||
|
||||
sp[e.id].effect_id[0] = e.effectid1;
|
||||
sp[e.id].effect_id[1] = e.effectid2;
|
||||
sp[e.id].effect_id[2] = e.effectid3;
|
||||
sp[e.id].effect_id[3] = e.effectid4;
|
||||
sp[e.id].effect_id[4] = e.effectid5;
|
||||
sp[e.id].effect_id[5] = e.effectid6;
|
||||
sp[e.id].effect_id[6] = e.effectid7;
|
||||
sp[e.id].effect_id[7] = e.effectid8;
|
||||
sp[e.id].effect_id[8] = e.effectid9;
|
||||
sp[e.id].effect_id[9] = e.effectid10;
|
||||
sp[e.id].effect_id[10] = e.effectid11;
|
||||
sp[e.id].effect_id[11] = e.effectid12;
|
||||
sp[tempid].target_type = static_cast<SpellTargetType>(Strings::ToInt(row[98]));
|
||||
sp[tempid].base_difficulty=Strings::ToInt(row[99]);
|
||||
|
||||
sp[e.id].target_type = static_cast<SpellTargetType>(e.targettype);
|
||||
int tmp_skill = Strings::ToInt(row[100]);
|
||||
|
||||
sp[e.id].base_difficulty = e.basediff;
|
||||
if (tmp_skill < 0 || tmp_skill > EQ::skills::HIGHEST_SKILL)
|
||||
sp[tempid].skill = EQ::skills::SkillBegging; /* not much better we can do. */ // can probably be changed to client-based 'SkillNone' once activated
|
||||
else
|
||||
sp[tempid].skill = static_cast<EQ::skills::SkillType>(tmp_skill);
|
||||
|
||||
sp[e.id].skill = (
|
||||
EQ::ValueWithin(e.skill, 0, EQ::skills::HIGHEST_SKILL) ?
|
||||
static_cast<EQ::skills::SkillType>(e.skill) :
|
||||
EQ::skills::SkillBegging
|
||||
);
|
||||
sp[tempid].zone_type=Strings::ToInt(row[101]);
|
||||
sp[tempid].environment_type=Strings::ToInt(row[102]);
|
||||
sp[tempid].time_of_day=Strings::ToInt(row[103]);
|
||||
|
||||
sp[e.id].zone_type = e.zonetype;
|
||||
sp[e.id].environment_type = e.EnvironmentType;
|
||||
sp[e.id].time_of_day = e.TimeOfDay;
|
||||
for(y=0; y < Class::PLAYER_CLASS_COUNT;y++)
|
||||
sp[tempid].classes[y]=Strings::ToInt(row[104+y]);
|
||||
|
||||
sp[e.id].classes[0] = e.classes1;
|
||||
sp[e.id].classes[1] = e.classes2;
|
||||
sp[e.id].classes[2] = e.classes3;
|
||||
sp[e.id].classes[3] = e.classes4;
|
||||
sp[e.id].classes[4] = e.classes5;
|
||||
sp[e.id].classes[5] = e.classes6;
|
||||
sp[e.id].classes[6] = e.classes7;
|
||||
sp[e.id].classes[7] = e.classes8;
|
||||
sp[e.id].classes[8] = e.classes9;
|
||||
sp[e.id].classes[9] = e.classes10;
|
||||
sp[e.id].classes[10] = e.classes11;
|
||||
sp[e.id].classes[11] = e.classes12;
|
||||
sp[e.id].classes[12] = e.classes13;
|
||||
sp[e.id].classes[13] = e.classes14;
|
||||
sp[e.id].classes[14] = e.classes15;
|
||||
sp[e.id].classes[15] = e.classes16;
|
||||
sp[tempid].casting_animation=Strings::ToInt(row[120]);
|
||||
sp[tempid].spell_affect_index=Strings::ToInt(row[123]);
|
||||
sp[tempid].disallow_sit=Strings::ToInt(row[124]);
|
||||
sp[tempid].deity_agnostic=Strings::ToInt(row[125]);
|
||||
|
||||
sp[e.id].casting_animation = e.CastingAnim;
|
||||
sp[e.id].spell_affect_index = e.SpellAffectIndex;
|
||||
sp[e.id].disallow_sit = e.disallow_sit;
|
||||
for (y = 0; y < 16; y++)
|
||||
sp[tempid].deities[y]=Strings::ToInt(row[126+y]);
|
||||
|
||||
sp[e.id].deity_agnostic = e.deities0; // Agnostic
|
||||
sp[e.id].deities[0] = e.deities1; // Bertoxxulous
|
||||
sp[e.id].deities[1] = e.deities2; // Brell Serilis
|
||||
sp[e.id].deities[2] = e.deities3; // Cazic Thule
|
||||
sp[e.id].deities[3] = e.deities4; // Erollsi Marr
|
||||
sp[e.id].deities[4] = e.deities5; // Bristlebane
|
||||
sp[e.id].deities[5] = e.deities6; // Innoruuk
|
||||
sp[e.id].deities[6] = e.deities7; // Karana
|
||||
sp[e.id].deities[7] = e.deities8; // Mithaniel Marr
|
||||
sp[e.id].deities[8] = e.deities9; // Prexius
|
||||
sp[e.id].deities[9] = e.deities10; // Quellious
|
||||
sp[e.id].deities[10] = e.deities11; // Rallos Zek
|
||||
sp[e.id].deities[11] = e.deities12; // Rodcet Nife
|
||||
sp[e.id].deities[12] = e.deities13; // Solusek Ro
|
||||
sp[e.id].deities[13] = e.deities14; // The Tribunal
|
||||
sp[e.id].deities[14] = e.deities15; // Tunare
|
||||
sp[e.id].deities[15] = e.deities16; // Veeshan
|
||||
sp[tempid].new_icon=Strings::ToInt(row[144]);
|
||||
sp[tempid].uninterruptable=Strings::ToBool(row[146]);
|
||||
sp[tempid].resist_difficulty=Strings::ToInt(row[147]);
|
||||
sp[tempid].unstackable_dot = Strings::ToBool(row[148]);
|
||||
sp[tempid].recourse_link = Strings::ToUnsignedInt(row[150]);
|
||||
sp[tempid].no_partial_resist = Strings::ToBool(row[151]);
|
||||
|
||||
sp[e.id].new_icon = e.new_icon;
|
||||
sp[e.id].uninterruptable = e.uninterruptable;
|
||||
sp[e.id].resist_difficulty = e.ResistDiff;
|
||||
sp[e.id].unstackable_dot = e.dot_stacking_exempt;
|
||||
sp[e.id].recourse_link = e.RecourseLink;
|
||||
sp[e.id].no_partial_resist = e.no_partial_resist;
|
||||
sp[e.id].short_buff_box = e.short_buff_box;
|
||||
sp[e.id].description_id = e.descnum;
|
||||
sp[e.id].type_description_id = e.typedescnum;
|
||||
sp[e.id].effect_description_id = e.effectdescnum;
|
||||
sp[e.id].npc_no_los = e.npc_no_los;
|
||||
sp[e.id].feedbackable = e.feedbackable;
|
||||
sp[e.id].reflectable = e.reflectable;
|
||||
sp[e.id].bonus_hate = e.bonushate;
|
||||
sp[e.id].ldon_trap = e.ldon_trap;
|
||||
sp[e.id].endurance_cost = e.EndurCost;
|
||||
sp[e.id].timer_id = e.EndurTimerIndex;
|
||||
sp[e.id].is_discipline = e.IsDiscipline;
|
||||
sp[e.id].hate_added = e.HateAdded;
|
||||
sp[e.id].endurance_upkeep = e.EndurUpkeep;
|
||||
sp[e.id].hit_number_type = e.numhits;
|
||||
sp[e.id].hit_number = e.numhitstype;
|
||||
sp[e.id].pvp_resist_base = e.pvpresistbase;
|
||||
sp[e.id].pvp_resist_per_level = e.pvpresistcalc;
|
||||
sp[e.id].pvp_resist_cap = e.pvpresistcap;
|
||||
sp[e.id].spell_category = e.spell_category;
|
||||
sp[e.id].pvp_duration = e.pvp_duration;
|
||||
sp[e.id].pvp_duration_cap = e.pvp_duration_cap;
|
||||
sp[e.id].pcnpc_only_flag = e.pcnpc_only_flag;
|
||||
sp[e.id].cast_not_standing = e.cast_not_standing;
|
||||
sp[e.id].can_mgb = e.can_mgb;
|
||||
sp[e.id].dispel_flag = e.nodispell;
|
||||
sp[e.id].min_resist = e.MinResist;
|
||||
sp[e.id].max_resist = e.MaxResist;
|
||||
sp[e.id].viral_targets = e.viral_targets;
|
||||
sp[e.id].viral_timer = e.viral_timer;
|
||||
sp[e.id].nimbus_effect = e.nimbuseffect;
|
||||
sp[e.id].directional_start = e.ConeStartAngle;
|
||||
sp[e.id].directional_end = e.ConeStopAngle;
|
||||
sp[e.id].sneak = e.sneaking;
|
||||
sp[e.id].not_focusable = e.not_extendable;
|
||||
sp[tempid].short_buff_box = Strings::ToInt(row[154]);
|
||||
sp[tempid].description_id = Strings::ToInt(row[155]);
|
||||
sp[tempid].type_description_id = Strings::ToInt(row[156]);
|
||||
sp[tempid].effect_description_id = Strings::ToInt(row[157]);
|
||||
|
||||
sp[e.id].no_detrimental_spell_aggro = e.no_detrimental_spell_aggro;
|
||||
sp[tempid].npc_no_los = Strings::ToBool(row[159]);
|
||||
sp[tempid].feedbackable = Strings::ToBool(row[160]);
|
||||
sp[tempid].reflectable = Strings::ToBool(row[161]);
|
||||
sp[tempid].bonus_hate=Strings::ToInt(row[162]);
|
||||
|
||||
sp[e.id].suspendable = e.suspendable;
|
||||
sp[e.id].viral_range = e.viral_range;
|
||||
sp[e.id].song_cap = e.songcap;
|
||||
sp[e.id].no_block = e.no_block;
|
||||
sp[e.id].spell_group = e.spellgroup;
|
||||
sp[e.id].rank = e.rank_;
|
||||
sp[e.id].no_resist = e.no_resist;
|
||||
sp[e.id].cast_restriction = e.CastRestriction;
|
||||
sp[e.id].allow_rest = e.allowrest;
|
||||
sp[e.id].can_cast_in_combat = e.InCombat;
|
||||
sp[e.id].can_cast_out_of_combat = e.OutofCombat;
|
||||
sp[e.id].override_crit_chance = e.override_crit_chance;
|
||||
sp[e.id].aoe_max_targets = e.aemaxtargets;
|
||||
sp[e.id].no_heal_damage_item_mod = e.no_heal_damage_item_mod;
|
||||
sp[e.id].caster_requirement_id = e.caster_requirement_id;
|
||||
sp[e.id].spell_class = e.spell_class;
|
||||
sp[e.id].spell_subclass = e.spell_subclass;
|
||||
sp[e.id].persist_death = e.persistdeath;
|
||||
sp[e.id].min_distance = e.min_dist;
|
||||
sp[e.id].min_distance_mod = e.min_dist_mod;
|
||||
sp[e.id].max_distance = e.max_dist;
|
||||
sp[e.id].max_distance_mod = e.max_dist_mod;
|
||||
sp[e.id].min_range = e.min_range;
|
||||
sp[e.id].no_remove = e.no_remove;
|
||||
sp[e.id].damage_shield_type = 0;
|
||||
sp[tempid].ldon_trap = Strings::ToBool(row[165]);
|
||||
sp[tempid].endurance_cost= Strings::ToInt(row[166]);
|
||||
sp[tempid].timer_id= Strings::ToInt(row[167]);
|
||||
sp[tempid].is_discipline = Strings::ToBool(row[168]);
|
||||
sp[tempid].hate_added= Strings::ToInt(row[173]);
|
||||
sp[tempid].endurance_upkeep=Strings::ToInt(row[174]);
|
||||
sp[tempid].hit_number_type = Strings::ToInt(row[175]);
|
||||
sp[tempid].hit_number = Strings::ToInt(row[176]);
|
||||
sp[tempid].pvp_resist_base= Strings::ToInt(row[177]);
|
||||
sp[tempid].pvp_resist_per_level= Strings::ToInt(row[178]);
|
||||
sp[tempid].pvp_resist_cap= Strings::ToInt(row[179]);
|
||||
sp[tempid].spell_category= Strings::ToInt(row[180]);
|
||||
sp[tempid].pvp_duration = Strings::ToInt(row[181]);
|
||||
sp[tempid].pvp_duration_cap = Strings::ToInt(row[182]);
|
||||
sp[tempid].pcnpc_only_flag= Strings::ToInt(row[183]);
|
||||
sp[tempid].cast_not_standing = Strings::ToInt(row[184]) != 0;
|
||||
sp[tempid].can_mgb= Strings::ToBool(row[185]);
|
||||
sp[tempid].dispel_flag = Strings::ToInt(row[186]);
|
||||
sp[tempid].min_resist = Strings::ToInt(row[189]);
|
||||
sp[tempid].max_resist = Strings::ToInt(row[190]);
|
||||
sp[tempid].viral_targets = Strings::ToInt(row[191]);
|
||||
sp[tempid].viral_timer = Strings::ToInt(row[192]);
|
||||
sp[tempid].nimbus_effect = Strings::ToInt(row[193]);
|
||||
sp[tempid].directional_start = Strings::ToFloat(row[194]);
|
||||
sp[tempid].directional_end = Strings::ToFloat(row[195]);
|
||||
sp[tempid].sneak = Strings::ToBool(row[196]);
|
||||
sp[tempid].not_focusable = Strings::ToBool(row[197]);
|
||||
sp[tempid].no_detrimental_spell_aggro = Strings::ToBool(row[198]);
|
||||
sp[tempid].suspendable = Strings::ToBool(row[200]);
|
||||
sp[tempid].viral_range = Strings::ToInt(row[201]);
|
||||
sp[tempid].song_cap = Strings::ToInt(row[202]);
|
||||
sp[tempid].no_block = Strings::ToInt(row[205]);
|
||||
sp[tempid].spell_group=Strings::ToInt(row[207]);
|
||||
sp[tempid].rank = Strings::ToInt(row[208]);
|
||||
sp[tempid].no_resist=Strings::ToInt(row[209]);
|
||||
sp[tempid].cast_restriction = Strings::ToInt(row[211]);
|
||||
sp[tempid].allow_rest = Strings::ToBool(row[212]);
|
||||
sp[tempid].can_cast_in_combat = Strings::ToBool(row[213]);
|
||||
sp[tempid].can_cast_out_of_combat = Strings::ToBool(row[214]);
|
||||
sp[tempid].override_crit_chance = Strings::ToInt(row[217]);
|
||||
sp[tempid].aoe_max_targets = Strings::ToInt(row[218]);
|
||||
sp[tempid].no_heal_damage_item_mod = Strings::ToInt(row[219]);
|
||||
sp[tempid].caster_requirement_id = Strings::ToInt(row[220]);
|
||||
sp[tempid].spell_class = Strings::ToInt(row[221]);
|
||||
sp[tempid].spell_subclass = Strings::ToInt(row[222]);
|
||||
sp[tempid].persist_death = Strings::ToBool(row[224]);
|
||||
sp[tempid].min_distance = Strings::ToFloat(row[227]);
|
||||
sp[tempid].min_distance_mod = Strings::ToFloat(row[228]);
|
||||
sp[tempid].max_distance = Strings::ToFloat(row[229]);
|
||||
sp[tempid].max_distance_mod = Strings::ToFloat(row[230]);
|
||||
sp[tempid].min_range = Strings::ToFloat(row[231]);
|
||||
sp[tempid].no_remove = Strings::ToBool(row[232]);
|
||||
sp[tempid].damage_shield_type = 0;
|
||||
}
|
||||
|
||||
LoadDamageShieldTypes(sp);
|
||||
|
|
@ -1969,7 +1870,18 @@ void SharedDatabase::SaveCharacterInspectMessage(uint32 character_id, const Insp
|
|||
|
||||
uint32 SharedDatabase::GetSpellsCount()
|
||||
{
|
||||
return SpellsNewRepository::Count(*this);
|
||||
auto results = QueryDatabase("SELECT count(*) FROM spells_new");
|
||||
if (!results.Success() || !results.RowCount()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto& row = results.begin();
|
||||
|
||||
if (row[0]) {
|
||||
return Strings::ToUnsignedInt(row[0]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 SharedDatabase::GetItemsCount()
|
||||
|
|
|
|||
|
|
@ -82,15 +82,14 @@ public:
|
|||
bool UpdateInjectedCommandSettings(const std::vector<std::pair<std::string, uint8>> &injected);
|
||||
bool UpdateOrphanedCommandSettings(const std::vector<std::string> &orphaned);
|
||||
bool GetCommandSubSettings(std::vector<CommandSubsettingsRepository::CommandSubsettings> &command_subsettings);
|
||||
uint32 GetTotalTimeEntitledOnAccount(uint32 AccountID);
|
||||
bool SetGMInvul(uint32 account_id, bool gminvul);
|
||||
bool SetGMFlymode(uint32 account_id, uint8 flymode);
|
||||
void SetMailKey(int CharID, int IPAddress, int MailKey);
|
||||
void SetMailKey(uint32 character_id, uint32 ip_address, uint32 mail_key);
|
||||
struct MailKeys {
|
||||
std::string mail_key;
|
||||
std::string mail_key_full;
|
||||
};
|
||||
MailKeys GetMailKey(int character_id);
|
||||
MailKeys GetMailKey(uint32 character_id);
|
||||
bool SaveCursor(
|
||||
uint32 char_id,
|
||||
std::list<EQ::ItemInstance *>::const_iterator &start,
|
||||
|
|
@ -104,7 +103,7 @@ public:
|
|||
bool VerifyInventory(uint32 account_id, int16 slot_id, const EQ::ItemInstance *inst);
|
||||
bool GetSharedBank(uint32 id, EQ::InventoryProfile *inv, bool is_charid);
|
||||
int32 GetSharedPlatinum(uint32 account_id);
|
||||
bool SetSharedPlatinum(uint32 account_id, int32 amount_to_add);
|
||||
bool AddSharedPlatinum(uint32 account_id, int amount);
|
||||
bool GetInventory(Client* c);
|
||||
bool GetInventory(uint32 account_id, char *name, EQ::InventoryProfile *inv); // deprecated
|
||||
std::map<uint32, uint32> GetItemRecastTimestamps(uint32 char_id);
|
||||
|
|
|
|||
|
|
@ -1600,6 +1600,7 @@ namespace SpellEffect {
|
|||
// number. note that the id field is counted as 0, this way the numbers
|
||||
// here match the numbers given to sep in the loading function net.cpp
|
||||
//
|
||||
#define SPELL_LOAD_FIELD_COUNT 236
|
||||
|
||||
struct SPDat_Spell_Struct
|
||||
{
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
// Build variables
|
||||
// these get injected during the build pipeline
|
||||
#define CURRENT_VERSION "23.9.1-dev" // always append -dev to the current version for custom-builds
|
||||
#define CURRENT_VERSION "23.10.3-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__
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "eqemu-server",
|
||||
"version": "23.9.1",
|
||||
"version": "23.10.3",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/EQEmu/Server.git"
|
||||
|
|
|
|||
|
|
@ -985,7 +985,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
|||
safe_delete(outapp);
|
||||
|
||||
// set mailkey - used for duration of character session
|
||||
int mail_key = EQ::Random::Instance()->Int(1, INT_MAX);
|
||||
uint32 mail_key = EQ::Random::Instance()->Int(1, INT_MAX);
|
||||
|
||||
database.SetMailKey(charid, GetIP(), mail_key);
|
||||
if (UCSServerAvailable_) {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1571,7 +1571,7 @@ void Client::OPMoveCoin(const EQApplicationPacket* app)
|
|||
if (from_bucket == &m_pp.platinum_shared)
|
||||
amount_to_add = 0 - amount_to_take;
|
||||
|
||||
database.SetSharedPlatinum(AccountID(),amount_to_add);
|
||||
database.AddSharedPlatinum(AccountID(),amount_to_add);
|
||||
}
|
||||
}
|
||||
else{
|
||||
|
|
|
|||
|
|
@ -854,6 +854,66 @@ struct DataBucketCache
|
|||
uint32_t bucket_expires;
|
||||
};
|
||||
|
||||
// Defines based on the RoF2 Client
|
||||
#define PET_HEALTHREPORT 0 // 0x00 - /pet health or Pet Window
|
||||
#define PET_LEADER 1 // 0x01 - /pet leader or Pet Window
|
||||
#define PET_ATTACK 2 // 0x02 - /pet attack or Pet Window
|
||||
#define PET_QATTACK 3 // 0x03 - /pet qattack or Pet Window
|
||||
#define PET_FOLLOWME 4 // 0x04 - /pet follow or Pet Window
|
||||
#define PET_GUARDHERE 5 // 0x05 - /pet guard or Pet Window
|
||||
#define PET_SIT 6 // 0x06 - /pet sit or Pet Window
|
||||
#define PET_SITDOWN 7 // 0x07 - /pet sit on
|
||||
#define PET_STANDUP 8 // 0x08 - /pet sit off
|
||||
#define PET_STOP 9 // 0x09 - /pet stop or Pet Window - Not implemented
|
||||
#define PET_STOP_ON 10 // 0x0a - /pet stop on - Not implemented
|
||||
#define PET_STOP_OFF 11 // 0x0b - /pet stop off - Not implemented
|
||||
#define PET_TAUNT 12 // 0x0c - /pet taunt or Pet Window
|
||||
#define PET_TAUNT_ON 13 // 0x0d - /pet taunt on
|
||||
#define PET_TAUNT_OFF 14 // 0x0e - /pet taunt off
|
||||
#define PET_HOLD 15 // 0x0f - /pet hold or Pet Window, won't add to hate list unless attacking
|
||||
#define PET_HOLD_ON 16 // 0x10 - /pet hold on
|
||||
#define PET_HOLD_OFF 17 // 0x11 - /pet hold off
|
||||
#define PET_GHOLD 18 // 0x12 - /pet ghold, will never add to hate list unless told to
|
||||
#define PET_GHOLD_ON 19 // 0x13 - /pet ghold on
|
||||
#define PET_GHOLD_OFF 20 // 0x14 - /pet ghold off
|
||||
#define PET_SPELLHOLD 21 // 0x15 - /pet no cast or /pet spellhold or Pet Window
|
||||
#define PET_SPELLHOLD_ON 22 // 0x16 - /pet spellhold on
|
||||
#define PET_SPELLHOLD_OFF 23 // 0x17 - /pet spellhold off
|
||||
#define PET_FOCUS 24 // 0x18 - /pet focus or Pet Window
|
||||
#define PET_FOCUS_ON 25 // 0x19 - /pet focus on
|
||||
#define PET_FOCUS_OFF 26 // 0x1a - /pet focus off
|
||||
#define PET_FEIGN 27 // 0x1b - /pet feign
|
||||
#define PET_BACKOFF 28 // 0x1c - /pet back off
|
||||
#define PET_GETLOST 29 // 0x1d - /pet get lost
|
||||
#define PET_GUARDME 30 // 0x1e - Same as /pet follow, but different message in older clients - define not from client /pet target in modern clients but doesn't send packet
|
||||
#define PET_REGROUP 31 // 0x1f - /pet regroup, acts like classic hold. Stops attack and moves back to guard/you but doesn't clear hate list
|
||||
#define PET_REGROUP_ON 32 // 0x20 - /pet regroup on, turns on regroup
|
||||
#define PET_REGROUP_OFF 33 // 0x21 - /pet regroup off, turns off regroup
|
||||
#define PET_MAXCOMMANDS PET_REGROUP_OFF + 1
|
||||
|
||||
// can change the state of these buttons with a packet
|
||||
#define PET_BUTTON_SIT 0
|
||||
#define PET_BUTTON_STOP 1
|
||||
#define PET_BUTTON_REGROUP 2
|
||||
#define PET_BUTTON_FOLLOW 3
|
||||
#define PET_BUTTON_GUARD 4
|
||||
#define PET_BUTTON_TAUNT 5
|
||||
#define PET_BUTTON_HOLD 6
|
||||
#define PET_BUTTON_GHOLD 7
|
||||
#define PET_BUTTON_FOCUS 8
|
||||
#define PET_BUTTON_SPELLHOLD 9
|
||||
|
||||
enum eStandingPetOrder { SPO_Follow, SPO_Sit, SPO_Guard, SPO_FeignDeath };
|
||||
|
||||
typedef enum {
|
||||
petFamiliar, //only listens to /pet get lost
|
||||
petAnimation, //does not listen to any commands
|
||||
petOther,
|
||||
petCharmed,
|
||||
petNPCFollow,
|
||||
petTargetLock, //remain active as long something is on the hatelist. Don't listen to any commands
|
||||
petNone = 0xFF // not a pet
|
||||
} PetTypeOld;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -208,6 +208,8 @@ const char* QuestEventSubroutines[_LargestEventID] = {
|
|||
"EVENT_SPELL_BLOCKED",
|
||||
"EVENT_READ_ITEM",
|
||||
"EVENT_PET_COMMAND",
|
||||
"EVENT_CHARM_START",
|
||||
"EVENT_CHARM_END",
|
||||
|
||||
// Add new events before these or Lua crashes
|
||||
"EVENT_SPELL_EFFECT_BOT",
|
||||
|
|
|
|||
|
|
@ -146,6 +146,8 @@ typedef enum {
|
|||
EVENT_SPELL_BLOCKED,
|
||||
EVENT_READ_ITEM,
|
||||
EVENT_PET_COMMAND,
|
||||
EVENT_CHARM_START,
|
||||
EVENT_CHARM_END,
|
||||
|
||||
// Add new events before these or Lua crashes
|
||||
EVENT_SPELL_EFFECT_BOT,
|
||||
|
|
|
|||
|
|
@ -6992,7 +6992,9 @@ luabind::scope lua_register_events() {
|
|||
luabind::value("entity_variable_update", static_cast<int>(EVENT_ENTITY_VARIABLE_UPDATE)),
|
||||
luabind::value("aa_loss", static_cast<int>(EVENT_AA_LOSS)),
|
||||
luabind::value("read", static_cast<int>(EVENT_READ_ITEM)),
|
||||
luabind::value("pet_command", static_cast<int>(EVENT_PET_COMMAND))
|
||||
luabind::value("pet_command", static_cast<int>(EVENT_PET_COMMAND)),
|
||||
luabind::value("charm_start", static_cast<int>(EVENT_CHARM_START)),
|
||||
luabind::value("charm_end", static_cast<int>(EVENT_CHARM_END))
|
||||
)];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -189,7 +189,9 @@ const char *LuaEvents[_LargestEventID] = {
|
|||
"event_aa_loss",
|
||||
"event_spell_blocked",
|
||||
"event_read_item",
|
||||
"event_pet_command"
|
||||
"event_pet_command",
|
||||
"event_charm_start",
|
||||
"event_charm_end"
|
||||
};
|
||||
|
||||
extern Zone *zone;
|
||||
|
|
@ -266,6 +268,8 @@ LuaParser::LuaParser() {
|
|||
NPCArgumentDispatch[EVENT_ENTITY_VARIABLE_UPDATE] = handle_npc_entity_variable;
|
||||
NPCArgumentDispatch[EVENT_SPELL_BLOCKED] = handle_npc_spell_blocked;
|
||||
NPCArgumentDispatch[EVENT_PET_COMMAND] = handle_npc_pet_command;
|
||||
NPCArgumentDispatch[EVENT_CHARM_START] = handle_npc_single_mob;
|
||||
NPCArgumentDispatch[EVENT_CHARM_END] = handle_npc_single_mob;
|
||||
|
||||
PlayerArgumentDispatch[EVENT_SAY] = handle_player_say;
|
||||
PlayerArgumentDispatch[EVENT_ENVIRONMENTAL_DAMAGE] = handle_player_environmental_damage;
|
||||
|
|
|
|||
477
zone/npc.cpp
477
zone/npc.cpp
|
|
@ -2274,9 +2274,9 @@ void NPC::SetLevel(uint8 in_level, bool command)
|
|||
|
||||
void NPC::ModifyNPCStat(const std::string& stat, const std::string& value)
|
||||
{
|
||||
auto stat_lower = Strings::ToLower(stat);
|
||||
const std::string& stat_lower = Strings::ToLower(stat);
|
||||
|
||||
auto variable_key = fmt::format(
|
||||
const std::string& variable_key = fmt::format(
|
||||
"modify_stat_{}",
|
||||
stat_lower
|
||||
);
|
||||
|
|
@ -2288,40 +2288,24 @@ void NPC::ModifyNPCStat(const std::string& stat, const std::string& value)
|
|||
if (stat_lower == "ac") {
|
||||
AC = Strings::ToInt(value);
|
||||
CalcAC();
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "str") {
|
||||
} else if (stat_lower == "str") {
|
||||
STR = Strings::ToInt(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "sta") {
|
||||
} else if (stat_lower == "sta") {
|
||||
STA = Strings::ToInt(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "agi") {
|
||||
} else if (stat_lower == "agi") {
|
||||
AGI = Strings::ToInt(value);
|
||||
CalcAC();
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "dex") {
|
||||
} else if (stat_lower == "dex") {
|
||||
DEX = Strings::ToInt(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "wis") {
|
||||
} else if (stat_lower == "wis") {
|
||||
WIS = Strings::ToInt(value);
|
||||
CalcMaxMana();
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "int" || stat_lower == "_int") {
|
||||
} else if (stat_lower == "int" || stat_lower == "_int") {
|
||||
INT = Strings::ToInt(value);
|
||||
CalcMaxMana();
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "cha") {
|
||||
} else if (stat_lower == "cha") {
|
||||
CHA = Strings::ToInt(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "max_hp") {
|
||||
} else if (stat_lower == "max_hp") {
|
||||
base_hp = Strings::ToBigInt(value);
|
||||
|
||||
CalcMaxHP();
|
||||
|
|
@ -2329,45 +2313,27 @@ void NPC::ModifyNPCStat(const std::string& stat, const std::string& value)
|
|||
current_hp = max_hp;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "max_mana") {
|
||||
} else if (stat_lower == "max_mana") {
|
||||
npc_mana = Strings::ToUnsignedBigInt(value);
|
||||
CalcMaxMana();
|
||||
if (current_mana > max_mana) {
|
||||
current_mana = max_mana;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "mr") {
|
||||
} else if (stat_lower == "mr") {
|
||||
MR = Strings::ToInt(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "fr") {
|
||||
} else if (stat_lower == "fr") {
|
||||
FR = Strings::ToInt(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "cr") {
|
||||
} else if (stat_lower == "cr") {
|
||||
CR = Strings::ToInt(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "cor") {
|
||||
} else if (stat_lower == "cor") {
|
||||
Corrup = Strings::ToInt(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "pr") {
|
||||
} else if (stat_lower == "pr") {
|
||||
PR = Strings::ToInt(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "dr") {
|
||||
} else if (stat_lower == "dr") {
|
||||
DR = Strings::ToInt(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "phr") {
|
||||
} else if (stat_lower == "phr") {
|
||||
PhR = Strings::ToInt(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "runspeed") {
|
||||
} else if (stat_lower == "runspeed") {
|
||||
runspeed = Strings::ToFloat(value);
|
||||
base_runspeed = (int) (runspeed * 40.0f);
|
||||
base_walkspeed = base_runspeed * 100 / 265;
|
||||
|
|
@ -2375,297 +2341,229 @@ void NPC::ModifyNPCStat(const std::string& stat, const std::string& value)
|
|||
base_fearspeed = base_runspeed * 100 / 127;
|
||||
fearspeed = ((float) base_fearspeed) * 0.025f;
|
||||
CalcBonuses();
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "special_attacks") {
|
||||
} else if (stat_lower == "special_attacks") {
|
||||
NPCSpecialAttacks(value.c_str(), 0, true);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "special_abilities") {
|
||||
} else if (stat_lower == "special_abilities") {
|
||||
ProcessSpecialAbilities(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "attack_speed") {
|
||||
} else if (stat_lower == "attack_speed") {
|
||||
attack_speed = Strings::ToFloat(value);
|
||||
CalcBonuses();
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "attack_delay") {
|
||||
} else if (stat_lower == "attack_delay") {
|
||||
/* TODO: fix DB */
|
||||
attack_delay = Strings::ToInt(value) * 100;
|
||||
CalcBonuses();
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "atk") {
|
||||
} else if (stat_lower == "atk") {
|
||||
ATK = Strings::ToInt(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "accuracy") {
|
||||
} else if (stat_lower == "accuracy") {
|
||||
accuracy_rating = Strings::ToInt(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "avoidance") {
|
||||
} else if (stat_lower == "avoidance") {
|
||||
avoidance_rating = Strings::ToInt(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "trackable") {
|
||||
} else if (stat_lower == "trackable") {
|
||||
trackable = Strings::ToInt(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "min_hit") {
|
||||
min_dmg = Strings::ToInt(value);
|
||||
} else if (stat_lower == "min_hit") {
|
||||
min_dmg = Strings::ToInt(value);
|
||||
// Clamp max_dmg to be >= min_dmg
|
||||
max_dmg = std::max(min_dmg, max_dmg);
|
||||
max_dmg = std::max(min_dmg, max_dmg);
|
||||
base_damage = round((max_dmg - min_dmg) / 1.9);
|
||||
min_damage = min_dmg - round(base_damage / 10.0);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "max_hit") {
|
||||
max_dmg = Strings::ToInt(value);
|
||||
} else if (stat_lower == "max_hit") {
|
||||
max_dmg = Strings::ToInt(value);
|
||||
// Clamp min_dmg to be <= max_dmg
|
||||
min_dmg = std::min(min_dmg, max_dmg);
|
||||
min_dmg = std::min(min_dmg, max_dmg);
|
||||
base_damage = round((max_dmg - min_dmg) / 1.9);
|
||||
min_damage = min_dmg - round(base_damage / 10.0);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "attack_count") {
|
||||
} else if (stat_lower == "attack_count") {
|
||||
attack_count = Strings::ToInt(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "see_invis") {
|
||||
} else if (stat_lower == "see_invis") {
|
||||
see_invis = Strings::ToInt(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "see_invis_undead") {
|
||||
} else if (stat_lower == "see_invis_undead") {
|
||||
see_invis_undead = Strings::ToInt(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "see_hide") {
|
||||
} else if (stat_lower == "see_hide") {
|
||||
see_hide = Strings::ToInt(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "see_improved_hide") {
|
||||
} else if (stat_lower == "see_improved_hide") {
|
||||
see_improved_hide = Strings::ToInt(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "hp_regen") {
|
||||
} else if (stat_lower == "hp_regen") {
|
||||
hp_regen = Strings::ToBigInt(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "hp_regen_per_second") {
|
||||
} else if (stat_lower == "hp_regen_per_second") {
|
||||
hp_regen_per_second = Strings::ToBigInt(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "mana_regen") {
|
||||
} else if (stat_lower == "mana_regen") {
|
||||
mana_regen = Strings::ToBigInt(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "level") {
|
||||
} else if (stat_lower == "level") {
|
||||
SetLevel(Strings::ToInt(value));
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "aggro") {
|
||||
} else if (stat_lower == "aggro") {
|
||||
pAggroRange = Strings::ToFloat(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "assist") {
|
||||
} else if (stat_lower == "assist") {
|
||||
pAssistRange = Strings::ToFloat(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "slow_mitigation") {
|
||||
} else if (stat_lower == "slow_mitigation") {
|
||||
slow_mitigation = Strings::ToInt(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "loottable_id") {
|
||||
} else if (stat_lower == "loottable_id") {
|
||||
m_loottable_id = Strings::ToFloat(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "healscale") {
|
||||
} else if (stat_lower == "healscale") {
|
||||
healscale = Strings::ToFloat(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "spellscale") {
|
||||
} else if (stat_lower == "spellscale") {
|
||||
spellscale = Strings::ToFloat(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "npc_spells_id") {
|
||||
} else if (stat_lower == "npc_spells_id") {
|
||||
AI_AddNPCSpells(Strings::ToInt(value));
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "npc_spells_effects_id") {
|
||||
} else if (stat_lower == "npc_spells_effects_id") {
|
||||
AI_AddNPCSpellsEffects(Strings::ToInt(value));
|
||||
CalcBonuses();
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "heroic_strikethrough") {
|
||||
} else if (stat_lower == "heroic_strikethrough") {
|
||||
heroic_strikethrough = Strings::ToInt(value);
|
||||
return;
|
||||
}
|
||||
else if (stat_lower == "keeps_sold_items") {
|
||||
} else if (stat_lower == "keeps_sold_items") {
|
||||
SetKeepsSoldItems(Strings::ToBool(value));
|
||||
return;
|
||||
} else if (stat_lower == "charm_ac") {
|
||||
charm_ac = Strings::ToInt(value);
|
||||
} else if (stat_lower == "charm_min_dmg") {
|
||||
charm_min_dmg = Strings::ToInt(value);
|
||||
} else if (stat_lower == "charm_max_dmg") {
|
||||
charm_max_dmg = Strings::ToInt(value);
|
||||
} else if (stat_lower == "charm_attack_delay") {
|
||||
charm_attack_delay = Strings::ToInt(value);
|
||||
} else if (stat_lower == "charm_accuracy_rating") {
|
||||
charm_accuracy_rating = Strings::ToInt(value);
|
||||
} else if (stat_lower == "charm_avoidance_rating") {
|
||||
charm_avoidance_rating = Strings::ToInt(value);
|
||||
} else if (stat_lower == "charm_atk") {
|
||||
charm_atk = Strings::ToInt(value);
|
||||
} else if (stat_lower == "default_ac") {
|
||||
default_ac = Strings::ToInt(value);
|
||||
} else if (stat_lower == "default_min_dmg") {
|
||||
default_min_dmg = Strings::ToInt(value);
|
||||
} else if (stat_lower == "default_max_dmg") {
|
||||
default_max_dmg = Strings::ToInt(value);
|
||||
} else if (stat_lower == "default_attack_delay") {
|
||||
default_attack_delay = Strings::ToInt(value);
|
||||
} else if (stat_lower == "default_accuracy_rating") {
|
||||
default_accuracy_rating = Strings::ToInt(value);
|
||||
} else if (stat_lower == "default_avoidance_rating") {
|
||||
default_avoidance_rating = Strings::ToInt(value);
|
||||
} else if (stat_lower == "default_atk") {
|
||||
default_atk = Strings::ToInt(value);
|
||||
}
|
||||
}
|
||||
|
||||
float NPC::GetNPCStat(const std::string& stat)
|
||||
{
|
||||
const std::string& stat_lower = Strings::ToLower(stat);
|
||||
|
||||
if (auto stat_lower = Strings::ToLower(stat); stat_lower == "ac") {
|
||||
if (stat_lower == "ac") {
|
||||
return AC;
|
||||
}
|
||||
else if (stat_lower == "str") {
|
||||
} else if (stat_lower == "str") {
|
||||
return STR;
|
||||
}
|
||||
else if (stat_lower == "sta") {
|
||||
} else if (stat_lower == "sta") {
|
||||
return STA;
|
||||
}
|
||||
else if (stat_lower == "agi") {
|
||||
} else if (stat_lower == "agi") {
|
||||
return AGI;
|
||||
}
|
||||
else if (stat_lower == "dex") {
|
||||
} else if (stat_lower == "dex") {
|
||||
return DEX;
|
||||
}
|
||||
else if (stat_lower == "wis") {
|
||||
} else if (stat_lower == "wis") {
|
||||
return WIS;
|
||||
}
|
||||
else if (stat_lower == "int" || stat_lower == "_int") {
|
||||
} else if (stat_lower == "int" || stat_lower == "_int") {
|
||||
return INT;
|
||||
}
|
||||
else if (stat_lower == "cha") {
|
||||
} else if (stat_lower == "cha") {
|
||||
return CHA;
|
||||
}
|
||||
else if (stat_lower == "max_hp") {
|
||||
} else if (stat_lower == "max_hp") {
|
||||
return base_hp;
|
||||
}
|
||||
else if (stat_lower == "max_mana") {
|
||||
} else if (stat_lower == "max_mana") {
|
||||
return npc_mana;
|
||||
}
|
||||
else if (stat_lower == "mr") {
|
||||
} else if (stat_lower == "mr") {
|
||||
return MR;
|
||||
}
|
||||
else if (stat_lower == "fr") {
|
||||
} else if (stat_lower == "fr") {
|
||||
return FR;
|
||||
}
|
||||
else if (stat_lower == "cr") {
|
||||
} else if (stat_lower == "cr") {
|
||||
return CR;
|
||||
}
|
||||
else if (stat_lower == "cor") {
|
||||
} else if (stat_lower == "cor") {
|
||||
return Corrup;
|
||||
}
|
||||
else if (stat_lower == "phr") {
|
||||
} else if (stat_lower == "phr") {
|
||||
return PhR;
|
||||
}
|
||||
else if (stat_lower == "pr") {
|
||||
} else if (stat_lower == "pr") {
|
||||
return PR;
|
||||
}
|
||||
else if (stat_lower == "dr") {
|
||||
} else if (stat_lower == "dr") {
|
||||
return DR;
|
||||
}
|
||||
else if (stat_lower == "runspeed") {
|
||||
} else if (stat_lower == "runspeed") {
|
||||
return runspeed;
|
||||
}
|
||||
else if (stat_lower == "attack_speed") {
|
||||
} else if (stat_lower == "attack_speed") {
|
||||
return attack_speed;
|
||||
}
|
||||
else if (stat_lower == "attack_delay") {
|
||||
} else if (stat_lower == "attack_delay") {
|
||||
return attack_delay;
|
||||
}
|
||||
else if (stat_lower == "atk") {
|
||||
} else if (stat_lower == "atk") {
|
||||
return ATK;
|
||||
}
|
||||
else if (stat_lower == "accuracy") {
|
||||
} else if (stat_lower == "accuracy") {
|
||||
return accuracy_rating;
|
||||
}
|
||||
else if (stat_lower == "avoidance") {
|
||||
} else if (stat_lower == "avoidance") {
|
||||
return avoidance_rating;
|
||||
}
|
||||
else if (stat_lower == "trackable") {
|
||||
} else if (stat_lower == "trackable") {
|
||||
return trackable;
|
||||
}
|
||||
else if (stat_lower == "min_hit") {
|
||||
} else if (stat_lower == "min_hit") {
|
||||
return min_dmg;
|
||||
}
|
||||
else if (stat_lower == "max_hit") {
|
||||
} else if (stat_lower == "max_hit") {
|
||||
return max_dmg;
|
||||
}
|
||||
else if (stat_lower == "attack_count") {
|
||||
} else if (stat_lower == "attack_count") {
|
||||
return attack_count;
|
||||
}
|
||||
else if (stat_lower == "see_invis") {
|
||||
} else if (stat_lower == "see_invis") {
|
||||
return see_invis;
|
||||
}
|
||||
else if (stat_lower == "see_invis_undead") {
|
||||
} else if (stat_lower == "see_invis_undead") {
|
||||
return see_invis_undead;
|
||||
}
|
||||
else if (stat_lower == "see_hide") {
|
||||
} else if (stat_lower == "see_hide") {
|
||||
return see_hide;
|
||||
}
|
||||
else if (stat_lower == "see_improved_hide") {
|
||||
} else if (stat_lower == "see_improved_hide") {
|
||||
return see_improved_hide;
|
||||
}
|
||||
else if (stat_lower == "hp_regen") {
|
||||
} else if (stat_lower == "hp_regen") {
|
||||
return hp_regen;
|
||||
}
|
||||
else if (stat_lower == "hp_regen_per_second") {
|
||||
} else if (stat_lower == "hp_regen_per_second") {
|
||||
return hp_regen_per_second;
|
||||
}
|
||||
else if (stat_lower == "mana_regen") {
|
||||
} else if (stat_lower == "mana_regen") {
|
||||
return mana_regen;
|
||||
}
|
||||
else if (stat_lower == "level") {
|
||||
} else if (stat_lower == "level") {
|
||||
return GetOrigLevel();
|
||||
}
|
||||
else if (stat_lower == "aggro") {
|
||||
} else if (stat_lower == "aggro") {
|
||||
return pAggroRange;
|
||||
}
|
||||
else if (stat_lower == "assist") {
|
||||
} else if (stat_lower == "assist") {
|
||||
return pAssistRange;
|
||||
}
|
||||
else if (stat_lower == "slow_mitigation") {
|
||||
} else if (stat_lower == "slow_mitigation") {
|
||||
return slow_mitigation;
|
||||
}
|
||||
else if (stat_lower == "loottable_id") {
|
||||
} else if (stat_lower == "loottable_id") {
|
||||
return m_loottable_id;
|
||||
}
|
||||
else if (stat_lower == "healscale") {
|
||||
} else if (stat_lower == "healscale") {
|
||||
return healscale;
|
||||
}
|
||||
else if (stat_lower == "spellscale") {
|
||||
} else if (stat_lower == "spellscale") {
|
||||
return spellscale;
|
||||
}
|
||||
else if (stat_lower == "npc_spells_id") {
|
||||
} else if (stat_lower == "npc_spells_id") {
|
||||
return npc_spells_id;
|
||||
}
|
||||
else if (stat_lower == "npc_spells_effects_id") {
|
||||
} else if (stat_lower == "npc_spells_effects_id") {
|
||||
return npc_spells_effects_id;
|
||||
}
|
||||
else if (stat_lower == "heroic_strikethrough") {
|
||||
} else if (stat_lower == "heroic_strikethrough") {
|
||||
return heroic_strikethrough;
|
||||
}
|
||||
else if (stat_lower == "keeps_sold_items") {
|
||||
} else if (stat_lower == "keeps_sold_items") {
|
||||
return keeps_sold_items;
|
||||
}
|
||||
//default values
|
||||
else if (stat_lower == "default_ac") {
|
||||
} else if (stat_lower == "default_ac") {
|
||||
return default_ac;
|
||||
}
|
||||
else if (stat_lower == "default_min_hit") {
|
||||
} else if (stat_lower == "default_min_hit") {
|
||||
return default_min_dmg;
|
||||
}
|
||||
else if (stat_lower == "default_max_hit") {
|
||||
} else if (stat_lower == "default_max_hit") {
|
||||
return default_max_dmg;
|
||||
}
|
||||
else if (stat_lower == "default_attack_delay") {
|
||||
} else if (stat_lower == "default_attack_delay") {
|
||||
return default_attack_delay;
|
||||
}
|
||||
else if (stat_lower == "default_accuracy") {
|
||||
} else if (stat_lower == "default_accuracy") {
|
||||
return default_accuracy_rating;
|
||||
}
|
||||
else if (stat_lower == "default_avoidance") {
|
||||
} else if (stat_lower == "default_avoidance") {
|
||||
return default_avoidance_rating;
|
||||
}
|
||||
else if (stat_lower == "default_atk") {
|
||||
} else if (stat_lower == "default_atk") {
|
||||
return default_atk;
|
||||
} else if (stat_lower == "charm_ac") {
|
||||
return charm_ac;
|
||||
} else if (stat_lower == "charm_min_hit") {
|
||||
return charm_min_dmg;
|
||||
} else if (stat_lower == "charm_max_hit") {
|
||||
return charm_max_dmg;
|
||||
} else if (stat_lower == "charm_attack_delay") {
|
||||
return charm_attack_delay;
|
||||
} else if (stat_lower == "charm_accuracy") {
|
||||
return charm_accuracy_rating;
|
||||
} else if (stat_lower == "charm_avoidance") {
|
||||
return charm_avoidance_rating;
|
||||
} else if (stat_lower == "charm_atk") {
|
||||
return charm_atk;
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
|
|
@ -3387,62 +3285,55 @@ void NPC::DepopSwarmPets()
|
|||
}
|
||||
}
|
||||
|
||||
void NPC::ModifyStatsOnCharm(bool is_charm_removed)
|
||||
void NPC::ModifyStatsOnCharm(bool remove_charm, Mob* charmer)
|
||||
{
|
||||
if (is_charm_removed) {
|
||||
if (charm_ac) {
|
||||
AC = default_ac;
|
||||
}
|
||||
if (charm_attack_delay) {
|
||||
attack_delay = default_attack_delay;
|
||||
}
|
||||
if (charm_accuracy_rating) {
|
||||
accuracy_rating = default_accuracy_rating;
|
||||
}
|
||||
if (charm_avoidance_rating) {
|
||||
avoidance_rating = default_avoidance_rating;
|
||||
}
|
||||
if (charm_atk) {
|
||||
ATK = default_atk;
|
||||
}
|
||||
if (charm_min_dmg || charm_max_dmg) {
|
||||
base_damage = round((default_max_dmg - default_min_dmg) / 1.9);
|
||||
min_damage = default_min_dmg - round(base_damage / 10.0);
|
||||
}
|
||||
if (RuleB(Spells, CharmDisablesSpecialAbilities)) {
|
||||
ProcessSpecialAbilities(default_special_abilities);
|
||||
}
|
||||
|
||||
SetAttackTimer();
|
||||
CalcAC();
|
||||
|
||||
return;
|
||||
if (!remove_charm && parse->HasQuestSub(GetNPCTypeID(), EVENT_CHARM_START)) {
|
||||
parse->EventNPC(EVENT_CHARM_START, this, charmer, "", 0);
|
||||
} else if (remove_charm && parse->HasQuestSub(GetNPCTypeID(), EVENT_CHARM_END)) {
|
||||
parse->EventNPC(EVENT_CHARM_END, this, charmer, "", 0);
|
||||
}
|
||||
|
||||
if (charm_ac) {
|
||||
AC = charm_ac;
|
||||
const int new_ac = remove_charm ? default_ac : charm_ac;
|
||||
const int new_attack_delay = remove_charm ? default_attack_delay : charm_attack_delay;
|
||||
const int new_accuracy_rating = remove_charm ? default_accuracy_rating : charm_accuracy_rating;
|
||||
const int new_avoidance_rating = remove_charm ? default_avoidance_rating : charm_avoidance_rating;
|
||||
const int new_atk = remove_charm ? default_atk : charm_atk;
|
||||
const int new_min_dmg = remove_charm ? default_min_dmg : charm_min_dmg;
|
||||
const int new_max_dmg = remove_charm ? default_max_dmg : charm_max_dmg;
|
||||
|
||||
if (new_ac) {
|
||||
AC = new_ac;
|
||||
}
|
||||
if (charm_attack_delay) {
|
||||
attack_delay = charm_attack_delay;
|
||||
|
||||
if (new_attack_delay) {
|
||||
attack_delay = new_attack_delay;
|
||||
}
|
||||
if (charm_accuracy_rating) {
|
||||
accuracy_rating = charm_accuracy_rating;
|
||||
|
||||
if (new_accuracy_rating) {
|
||||
accuracy_rating = new_accuracy_rating;
|
||||
}
|
||||
if (charm_avoidance_rating) {
|
||||
avoidance_rating = charm_avoidance_rating;
|
||||
|
||||
if (new_avoidance_rating) {
|
||||
avoidance_rating = new_avoidance_rating;
|
||||
}
|
||||
if (charm_atk) {
|
||||
ATK = charm_atk;
|
||||
|
||||
if (new_atk) {
|
||||
ATK = new_atk;
|
||||
}
|
||||
if (charm_min_dmg || charm_max_dmg) {
|
||||
base_damage = round((charm_max_dmg - charm_min_dmg) / 1.9);
|
||||
min_damage = charm_min_dmg - round(base_damage / 10.0);
|
||||
|
||||
if (new_min_dmg || new_max_dmg) {
|
||||
base_damage = std::round((new_max_dmg - new_min_dmg) / 1.9);
|
||||
min_damage = new_min_dmg - std::round(base_damage / 10.0);
|
||||
}
|
||||
|
||||
if (RuleB(Spells, CharmDisablesSpecialAbilities)) {
|
||||
ClearSpecialAbilities();
|
||||
if (remove_charm) {
|
||||
ProcessSpecialAbilities(default_special_abilities);
|
||||
} else {
|
||||
ClearSpecialAbilities();
|
||||
}
|
||||
}
|
||||
|
||||
// the rest of the stats aren't cached, so lets just do these two instead of full CalcBonuses()
|
||||
SetAttackTimer();
|
||||
CalcAC();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -346,7 +346,7 @@ public:
|
|||
int64 GetNPCHPRegen() const { return hp_regen + itembonuses.HPRegen + spellbonuses.HPRegen; }
|
||||
inline const char* GetAmmoIDfile() const { return ammo_idfile; }
|
||||
|
||||
void ModifyStatsOnCharm(bool is_charm_removed);
|
||||
void ModifyStatsOnCharm(bool remove_charm, Mob* charmer);
|
||||
|
||||
//waypoint crap
|
||||
int GetMaxWp() const { return max_wp; }
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ void Client::SendBulkParcels()
|
|||
inst->SetCharges(p.second.quantity);
|
||||
inst->SetMerchantCount(1);
|
||||
inst->SetMerchantSlot(p.second.slot_id);
|
||||
inst->SetEvolveCurrentAmount(p.second.evolve_amount);
|
||||
if (inst->IsStackable()) {
|
||||
inst->SetCharges(p.second.quantity);
|
||||
}
|
||||
|
|
@ -164,6 +165,7 @@ void Client::SendParcel(Parcel_Struct &parcel_in)
|
|||
inst->SetCharges(p.quantity);
|
||||
inst->SetMerchantCount(1);
|
||||
inst->SetMerchantSlot(p.slot_id);
|
||||
inst->SetEvolveCurrentAmount(p.evolve_amount);
|
||||
if (inst->IsStackable()) {
|
||||
inst->SetCharges(p.quantity);
|
||||
}
|
||||
|
|
@ -381,23 +383,23 @@ void Client::DoParcelSend(const Parcel_Struct *parcel_in)
|
|||
return;
|
||||
}
|
||||
|
||||
uint32 quantity{};
|
||||
uint32 quantity = 1;
|
||||
if (inst->IsStackable()) {
|
||||
quantity = parcel_in->quantity;
|
||||
}
|
||||
else {
|
||||
quantity = inst->GetCharges() >= 0 ? inst->GetCharges() : parcel_in->quantity;
|
||||
} else if (inst->GetItem()->MaxCharges > 0) {
|
||||
quantity = inst->GetCharges();
|
||||
}
|
||||
|
||||
CharacterParcelsRepository::CharacterParcels parcel_out{};
|
||||
parcel_out.from_name = GetName();
|
||||
parcel_out.note = parcel_in->note;
|
||||
parcel_out.sent_date = time(nullptr);
|
||||
parcel_out.quantity = quantity;
|
||||
parcel_out.item_id = inst->GetID();
|
||||
parcel_out.char_id = send_to_client.at(0).char_id;
|
||||
parcel_out.slot_id = next_slot;
|
||||
parcel_out.id = 0;
|
||||
parcel_out.from_name = GetName();
|
||||
parcel_out.note = parcel_in->note;
|
||||
parcel_out.sent_date = time(nullptr);
|
||||
parcel_out.quantity = quantity;
|
||||
parcel_out.item_id = inst->GetID();
|
||||
parcel_out.char_id = send_to_client.at(0).char_id;
|
||||
parcel_out.slot_id = next_slot;
|
||||
parcel_out.evolve_amount = inst->GetEvolveCurrentAmount();
|
||||
parcel_out.id = 0;
|
||||
|
||||
if (inst->IsAugmented()) {
|
||||
auto augs = inst->GetAugmentIDs();
|
||||
|
|
@ -445,7 +447,9 @@ void Client::DoParcelSend(const Parcel_Struct *parcel_in)
|
|||
cpc.aug_slot_5 = augs.at(4);
|
||||
cpc.aug_slot_6 = augs.at(5);
|
||||
}
|
||||
cpc.quantity = kv.second->GetCharges() >= 0 ? kv.second->GetCharges() : 1;
|
||||
|
||||
cpc.quantity = kv.second->GetCharges() >= 0 ? kv.second->GetCharges() : 1;
|
||||
cpc.evolve_amount = kv.second->GetEvolveCurrentAmount();
|
||||
all_entries.push_back(cpc);
|
||||
}
|
||||
CharacterParcelsContainersRepository::InsertMany(database, all_entries);
|
||||
|
|
@ -679,6 +683,8 @@ void Client::DoParcelRetrieve(const ParcelRetrieve_Struct &parcel_in)
|
|||
return;
|
||||
}
|
||||
|
||||
inst->SetEvolveCurrentAmount(p->second.evolve_amount);
|
||||
|
||||
if (inst->IsStackable()) {
|
||||
inst->SetCharges(item_quantity > 0 ? item_quantity : 1);
|
||||
}
|
||||
|
|
@ -715,6 +721,8 @@ void Client::DoParcelRetrieve(const ParcelRetrieve_Struct &parcel_in)
|
|||
return;
|
||||
}
|
||||
|
||||
item->SetEvolveCurrentAmount(i.evolve_amount);
|
||||
|
||||
if (CheckLoreConflict(item->GetItem())) {
|
||||
if (RuleB(Parcel, DeleteOnDuplicate)) {
|
||||
MessageString(Chat::Yellow, PARCEL_DUPLICATE_DELETE, inst->GetItem()->Name);
|
||||
|
|
|
|||
|
|
@ -835,12 +835,11 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
|||
SendAppearancePacket(AppearanceType::Pet, caster->GetID(), true, true);
|
||||
}
|
||||
|
||||
if (IsClient())
|
||||
{
|
||||
if (IsClient()) {
|
||||
CastToClient()->AI_Start();
|
||||
} else if(IsNPC()) {
|
||||
CastToNPC()->SetPetSpellID(0); //not a pet spell.
|
||||
CastToNPC()->ModifyStatsOnCharm(false);
|
||||
} else if (IsNPC()) {
|
||||
CastToNPC()->SetPetSpellID(0); //not a pet spell.
|
||||
CastToNPC()->ModifyStatsOnCharm(false, caster);
|
||||
}
|
||||
|
||||
bool bBreak = false;
|
||||
|
|
@ -4418,10 +4417,9 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
|
|||
|
||||
case SpellEffect::Charm:
|
||||
{
|
||||
if(IsNPC())
|
||||
{
|
||||
if (IsNPC()) {
|
||||
CastToNPC()->RestoreGuardSpotCharm();
|
||||
CastToNPC()->ModifyStatsOnCharm(true);
|
||||
CastToNPC()->ModifyStatsOnCharm(true, GetOwner());
|
||||
}
|
||||
|
||||
SendAppearancePacket(AppearanceType::Pet, 0, true, true);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue