Compare commits

..

12 Commits

Author SHA1 Message Date
Chris Miles e8f4ffd628 [Release] 23.10.2 2025-09-17 00:52:31 -05:00
Chris Miles 0447618f7e hotfix: merge fix 2025-09-17 00:50:03 -05:00
Chris Miles e71ce001ff Hotfix: revert #4996 2025-09-17 00:47:42 -05:00
Alex King 1575a2af40 [Hotfix] Fixed Mail Key Bug (#5015)
* [Hotfix] Fixed Mail Key Bug

* Release
2025-09-16 22:52:57 -04:00
JJ 4b69df646c [Release] 23.10.0 (#5014)
* Update CHANGELOG.md

* Update version.h

* Update package.json
2025-09-16 11:35:03 -04:00
Alex King 044b9c1420 [Repositories] Convert Mail Key to Repositories (#5007)
* [Repositories] Convert Mail Key to Repositories

* Update shareddb.cpp

---------

Co-authored-by: JJ <3617814+joligario@users.noreply.github.com>
2025-09-15 14:23:48 -04:00
Alex King 0bbb5b90e7 [Repositories] Convert Total Time Played to Repositories (#5008) 2025-09-15 09:14:59 -04:00
Alex King 6506ad5b51 [Quest API] Add EVENT_CHARM_START and EVENT_CHARM_END (#5013) 2025-09-15 09:14:46 -04:00
Alex King dcaa0ecdaa [Quest API] Add Identifiers to Get/Modify NPC Stat Methods (#5012) 2025-09-15 09:14:29 -04:00
Mitch Freeman 9b143132be [Bug Fix] Fix Several Evolving Item Bugs (#4992)
* Add sending evolving items via parcels
Send, retrieve and inspect tested ok

* Sell evolving items to a merchant and purchase tested ok.

* Fix a problem with potions and quantity
2025-09-07 22:51:39 -04:00
Mitch Freeman 231bf8b4ec Update database_update_manifest.cpp (#5011) 2025-09-07 19:13:00 -04:00
Alex King dee58f9a91 [Repositories] Convert Shared Bank Platinum to Repositories (#5006) 2025-09-01 21:39:24 -04:00
49 changed files with 1759 additions and 3092 deletions
+75
View File
@@ -1,3 +1,78 @@
## [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
+9 -29
View File
@@ -7173,39 +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`;
)"
},
ManifestEntry{
.version = 9329,
.description = "2025_08_20_character_stat_caps.sql",
.check = "SHOW TABLES LIKE 'character_stat_caps'",
.condition = "empty",
.match = "",
.sql = R"(
CREATE TABLE `character_stat_caps` (
`character_id` int(11) UNSIGNED NOT NULL,
`stat_id` tinyint(3) UNSIGNED NULL,
`stat_cap` int(11) NOT NULL DEFAULT -1,
PRIMARY KEY (`character_id`, `stat_id`)
)
)"
}
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,
@@ -204,11 +204,11 @@ INNER JOIN bot_stances bs ON bd.bot_id = bs.bot_id
WHERE bd.follow_distance != 184
GROUP BY bd.bot_id;
INSERT INTO bot_settings
INSERT INTO bot_settings
SELECT 0, bd.bot_id, bs.stance_id, 3, 0, bd.stop_melee_level, 'BaseSetting', 'StopMeleeLevel'
FROM bot_data bd
INNER JOIN bot_stances bs ON bd.bot_id = bs.bot_id
WHERE (CASE
WHERE (CASE
WHEN bd.class IN (2, 6, 10, 11, 12, 13, 14) THEN 13
ELSE 255
END) != bd.stop_melee_level
@@ -532,7 +532,7 @@ UPDATE bot_spells_entries SET `type` = 17 WHERE `spell_id` = 3229;
.condition = "empty",
.match = "",
.sql = R"(
INSERT INTO `bot_spells_entries` (`npc_spells_id`, `spell_id`, `type`, `minlevel`, `maxlevel`)
INSERT INTO `bot_spells_entries` (`npc_spells_id`, `spell_id`, `type`, `minlevel`, `maxlevel`)
VALUES
(3006, 9957, 100, 20, 254),
(3006, 9956, 100, 20, 254),
@@ -1106,7 +1106,7 @@ FROM bot_spells_entries
WHERE `npc_spells_id` = 3005
AND `type` = 10;
INSERT INTO `bot_spells_entries` (`npc_spells_id`, `spell_id`, `type`, `minlevel`, `maxlevel`, `priority`)
INSERT INTO `bot_spells_entries` (`npc_spells_id`, `spell_id`, `type`, `minlevel`, `maxlevel`, `priority`)
VALUES
(3003, 10173, 24, 72, 76, 3),
(3003, 10174, 24, 72, 76, 2),
@@ -2122,22 +2122,7 @@ WHERE NOT EXISTS
FROM spells_new
WHERE bot_spells_entries.spell_id = spells_new.id);
)",
},
ManifestEntry{
.version = 9055,
.description = "08_20_2025_bot_stat_caps.sql",
.check = "SHOW TABLES LIKE 'bot_stat_caps'",
.condition = "empty",
.match = "",
.sql = R"(
CREATE TABLE `bot_stat_caps` (
`bot_id` int(11) UNSIGNED NOT NULL,
`stat_id` tinyint(3) UNSIGNED NULL,
`stat_cap` int(11) NOT NULL DEFAULT -1,
PRIMARY KEY (`bot_id`, `stat_id`)
)
)"
},
}
// -- template; copy/paste this when you need to create a new entry
// ManifestEntry{
// .version = 9228,
-3
View File
@@ -69,7 +69,6 @@ namespace DatabaseSchema {
{"character_potionbelt", "id"},
{"character_skills", "id"},
{"character_spells", "id"},
{"character_stat_caps", "character_id"},
{"character_stats_record", "character_id"},
{"character_task_timers", "character_id"},
{"character_tasks", "charid"},
@@ -145,7 +144,6 @@ namespace DatabaseSchema {
"character_potionbelt",
"character_skills",
"character_spells",
"character_stat_caps",
"character_stats_record",
"character_task_timers",
"character_tasks",
@@ -414,7 +412,6 @@ namespace DatabaseSchema {
"bot_spell_settings",
"bot_spells_entries",
"bot_stances",
"bot_stat_caps",
"bot_timers"
};
}
-10
View File
@@ -471,13 +471,3 @@ bool PetType::IsValid(uint8 pet_type)
{
return pet_types.find(pet_type) != pet_types.end();
}
std::string StatCap::GetName(uint8 stat_id)
{
return IsValid(stat_id) ? stat_caps[stat_id] : "UNKNOWN STAT CAP";
}
bool StatCap::IsValid(uint8 stat_id)
{
return stat_caps.find(stat_id) != stat_caps.end();
}
-53
View File
@@ -919,57 +919,4 @@ namespace PetType {
bool IsValid(uint8 pet_type);
}
namespace StatCap {
constexpr uint8 Accuracy = 0;
constexpr uint8 Attack = 1;
constexpr uint8 Avoidance = 2;
constexpr uint8 Clairvoyance = 3;
constexpr uint8 CombatEffects = 4;
constexpr uint8 DamageShield = 5;
constexpr uint8 DOTShielding = 6;
constexpr uint8 DSMitigation = 7;
constexpr uint8 EnduranceRegen = 8;
constexpr uint8 ExtraDamage = 9;
constexpr uint8 Haste = 10;
constexpr uint8 HasteV3 = 11;
constexpr uint8 HealAmount = 12;
constexpr uint8 HealthRegen = 13;
constexpr uint8 ManaRegen = 14;
constexpr uint8 QuiverHaste = 15;
constexpr uint8 Shielding = 16;
constexpr uint8 SpellDamage = 17;
constexpr uint8 SpellShielding = 18;
constexpr uint8 Stat = 19;
constexpr uint8 Strikethrough = 20;
constexpr uint8 StunResist = 21;
static std::map<uint8, std::string> stat_caps = {
{ Accuracy, "Accuracy" },
{ Attack, "Attack" },
{ Avoidance, "Avoidance" },
{ Clairvoyance, "Clairvoyance" },
{ CombatEffects, "Combat Effects" },
{ DamageShield, "Damage Shield" },
{ DOTShielding, "Damage Over Time Shielding" },
{ DSMitigation, "Damage Shield Mitigation" },
{ EnduranceRegen, "Endurance Regen" },
{ ExtraDamage, "Extra Damage" },
{ Haste, "Haste" },
{ HasteV3, "Haste V3" },
{ HealAmount, "Heal Amount" },
{ HealthRegen, "Health Regen" },
{ ManaRegen, "Mana Regen" },
{ QuiverHaste, "Quiver Haste" },
{ Shielding, "Shielding" },
{ SpellDamage, "Spell Damage" },
{ SpellShielding, "Spell Shielding" },
{ Stat, "Stat" },
{ Strikethrough, "Strikethrough" },
{ StunResist, "Stun Resist" }
};
std::string GetName(uint8 stat_id);
bool IsValid(uint8 stat_id);
}
#endif /*COMMON_EMU_CONSTANTS_H*/
+4
View File
@@ -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;
+2 -1
View File
@@ -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;
@@ -1,404 +0,0 @@
/**
* DO NOT MODIFY THIS FILE
*
* This repository was automatically generated and is NOT to be modified directly.
* Any repository modifications are meant to be made to the repository extending the base.
* Any modifications to base repositories are to be made by the generator only
*
* @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://docs.eqemu.io/developer/repositories
*/
#ifndef EQEMU_BASE_BOT_STAT_CAPS_REPOSITORY_H
#define EQEMU_BASE_BOT_STAT_CAPS_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseBotStatCapsRepository {
public:
struct BotStatCaps {
uint32_t bot_id;
uint8_t stat_id;
int32_t stat_cap;
};
static std::string PrimaryKey()
{
return std::string("bot_id");
}
static std::vector<std::string> Columns()
{
return {
"bot_id",
"stat_id",
"stat_cap",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"bot_id",
"stat_id",
"stat_cap",
};
}
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("bot_stat_caps");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static BotStatCaps NewEntity()
{
BotStatCaps e{};
e.bot_id = 0;
e.stat_id = 0;
e.stat_cap = -1;
return e;
}
static BotStatCaps GetBotStatCaps(
const std::vector<BotStatCaps> &bot_stat_capss,
int bot_stat_caps_id
)
{
for (auto &bot_stat_caps : bot_stat_capss) {
if (bot_stat_caps.bot_id == bot_stat_caps_id) {
return bot_stat_caps;
}
}
return NewEntity();
}
static BotStatCaps FindOne(
Database& db,
int bot_stat_caps_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
bot_stat_caps_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
BotStatCaps e{};
e.bot_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.stat_id = row[1] ? static_cast<uint8_t>(strtoul(row[1], nullptr, 10)) : 0;
e.stat_cap = row[2] ? static_cast<int32_t>(atoi(row[2])) : -1;
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int bot_stat_caps_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
bot_stat_caps_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const BotStatCaps &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[0] + " = " + std::to_string(e.bot_id));
v.push_back(columns[1] + " = " + std::to_string(e.stat_id));
v.push_back(columns[2] + " = " + std::to_string(e.stat_cap));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.bot_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static BotStatCaps InsertOne(
Database& db,
BotStatCaps e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.stat_id));
v.push_back(std::to_string(e.stat_cap));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.bot_id = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<BotStatCaps> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.stat_id));
v.push_back(std::to_string(e.stat_cap));
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<BotStatCaps> All(Database& db)
{
std::vector<BotStatCaps> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
BotStatCaps e{};
e.bot_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.stat_id = row[1] ? static_cast<uint8_t>(strtoul(row[1], nullptr, 10)) : 0;
e.stat_cap = row[2] ? static_cast<int32_t>(atoi(row[2])) : -1;
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<BotStatCaps> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<BotStatCaps> 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) {
BotStatCaps e{};
e.bot_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.stat_id = row[1] ? static_cast<uint8_t>(strtoul(row[1], nullptr, 10)) : 0;
e.stat_cap = row[2] ? static_cast<int32_t>(atoi(row[2])) : -1;
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 BotStatCaps &e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.stat_id));
v.push_back(std::to_string(e.stat_cap));
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<BotStatCaps> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.stat_id));
v.push_back(std::to_string(e.stat_cap));
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_BOT_STAT_CAPS_REPOSITORY_H
@@ -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") + ")");
@@ -1,404 +0,0 @@
/**
* DO NOT MODIFY THIS FILE
*
* This repository was automatically generated and is NOT to be modified directly.
* Any repository modifications are meant to be made to the repository extending the base.
* Any modifications to base repositories are to be made by the generator only
*
* @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://docs.eqemu.io/developer/repositories
*/
#ifndef EQEMU_BASE_CHARACTER_STAT_CAPS_REPOSITORY_H
#define EQEMU_BASE_CHARACTER_STAT_CAPS_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseCharacterStatCapsRepository {
public:
struct CharacterStatCaps {
uint32_t character_id;
uint8_t stat_id;
int32_t stat_cap;
};
static std::string PrimaryKey()
{
return std::string("character_id");
}
static std::vector<std::string> Columns()
{
return {
"character_id",
"stat_id",
"stat_cap",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"character_id",
"stat_id",
"stat_cap",
};
}
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("character_stat_caps");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static CharacterStatCaps NewEntity()
{
CharacterStatCaps e{};
e.character_id = 0;
e.stat_id = 0;
e.stat_cap = -1;
return e;
}
static CharacterStatCaps GetCharacterStatCaps(
const std::vector<CharacterStatCaps> &character_stat_capss,
int character_stat_caps_id
)
{
for (auto &character_stat_caps : character_stat_capss) {
if (character_stat_caps.character_id == character_stat_caps_id) {
return character_stat_caps;
}
}
return NewEntity();
}
static CharacterStatCaps FindOne(
Database& db,
int character_stat_caps_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
character_stat_caps_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
CharacterStatCaps e{};
e.character_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.stat_id = row[1] ? static_cast<uint8_t>(strtoul(row[1], nullptr, 10)) : 0;
e.stat_cap = row[2] ? static_cast<int32_t>(atoi(row[2])) : -1;
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int character_stat_caps_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
character_stat_caps_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const CharacterStatCaps &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[0] + " = " + std::to_string(e.character_id));
v.push_back(columns[1] + " = " + std::to_string(e.stat_id));
v.push_back(columns[2] + " = " + std::to_string(e.stat_cap));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.character_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static CharacterStatCaps InsertOne(
Database& db,
CharacterStatCaps e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.stat_id));
v.push_back(std::to_string(e.stat_cap));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.character_id = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<CharacterStatCaps> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.stat_id));
v.push_back(std::to_string(e.stat_cap));
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<CharacterStatCaps> All(Database& db)
{
std::vector<CharacterStatCaps> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
CharacterStatCaps e{};
e.character_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.stat_id = row[1] ? static_cast<uint8_t>(strtoul(row[1], nullptr, 10)) : 0;
e.stat_cap = row[2] ? static_cast<int32_t>(atoi(row[2])) : -1;
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<CharacterStatCaps> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<CharacterStatCaps> 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) {
CharacterStatCaps e{};
e.character_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.stat_id = row[1] ? static_cast<uint8_t>(strtoul(row[1], nullptr, 10)) : 0;
e.stat_cap = row[2] ? static_cast<int32_t>(atoi(row[2])) : -1;
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 CharacterStatCaps &e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.stat_id));
v.push_back(std::to_string(e.stat_cap));
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<CharacterStatCaps> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.stat_id));
v.push_back(std::to_string(e.stat_cap));
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_CHARACTER_STAT_CAPS_REPOSITORY_H
File diff suppressed because it is too large Load Diff
@@ -1,50 +0,0 @@
#ifndef EQEMU_BOT_STAT_CAPS_REPOSITORY_H
#define EQEMU_BOT_STAT_CAPS_REPOSITORY_H
#include "../database.h"
#include "../strings.h"
#include "base/base_bot_stat_caps_repository.h"
class BotStatCapsRepository: public BaseBotStatCapsRepository {
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
*
* BotStatCapsRepository::GetByZoneAndVersion(int zone_id, int zone_version)
* BotStatCapsRepository::GetWhereNeverExpires()
* BotStatCapsRepository::GetWhereXAndY()
* BotStatCapsRepository::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_BOT_STAT_CAPS_REPOSITORY_H
@@ -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
@@ -1,50 +0,0 @@
#ifndef EQEMU_CHARACTER_STAT_CAPS_REPOSITORY_H
#define EQEMU_CHARACTER_STAT_CAPS_REPOSITORY_H
#include "../database.h"
#include "../strings.h"
#include "base/base_character_stat_caps_repository.h"
class CharacterStatCapsRepository: public BaseCharacterStatCapsRepository {
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
*
* CharacterStatCapsRepository::GetByZoneAndVersion(int zone_id, int zone_version)
* CharacterStatCapsRepository::GetWhereNeverExpires()
* CharacterStatCapsRepository::GetWhereXAndY()
* CharacterStatCapsRepository::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_CHARACTER_STAT_CAPS_REPOSITORY_H
+193 -281
View File
@@ -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()
+3 -4
View File
@@ -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);
+1
View File
@@ -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
{
+3 -3
View File
@@ -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.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,8 +42,8 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9329
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9055
#define CURRENT_BINARY_DATABASE_VERSION 9328
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9054
#define CUSTOM_BINARY_DATABASE_VERSION 0
#endif
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "eqemu-server",
"version": "23.9.1",
"version": "23.10.2",
"repository": {
"type": "git",
"url": "https://github.com/EQEmu/Server.git"
+1 -1
View File
@@ -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_) {
+1 -1
View File
@@ -6701,7 +6701,7 @@ void Client::SetAttackTimer()
if (ItemToUse && ItemToUse->ItemType == EQ::item::ItemTypeBow) {
// Live actually had a bug here where they would return the non-modified attack speed
// rather than the cap ...
speed = std::max(speed - GetQuiverHaste(speed), GetStatCap(StatCap::QuiverHaste));
speed = std::max(speed - GetQuiverHaste(speed), RuleI(Combat, QuiverHasteCap));
}
else {
if (RuleB(Spells, Jun182014HundredHandsRevamp))
+21 -46
View File
@@ -246,24 +246,16 @@ void Mob::ProcessItemCaps()
itembonuses.ATK = std::min(itembonuses.ATK, CalcItemATKCap());
if (IsOfClientBotMerc() && itembonuses.SpellDmg > GetStatCap(StatCap::SpellDamage)) {
itembonuses.SpellDmg = GetStatCap(StatCap::SpellDamage);
if (IsOfClientBotMerc() && itembonuses.SpellDmg > RuleI(Character, ItemSpellDmgCap)) {
itembonuses.SpellDmg = RuleI(Character, ItemSpellDmgCap);
}
if (IsOfClientBotMerc() && itembonuses.HealAmt > GetStatCap(StatCap::HealAmount)) {
itembonuses.HealAmt = GetStatCap(StatCap::HealAmount);
if (IsOfClientBotMerc() && itembonuses.HealAmt > RuleI(Character, ItemHealAmtCap)) {
itembonuses.HealAmt = RuleI(Character, ItemHealAmtCap);
}
}
void Mob::AddItemBonuses(
const EQ::ItemInstance* inst,
StatBonuses* b,
bool is_augment,
bool is_tribute,
int recommended_level_override,
bool is_ammo_item
)
{
void Mob::AddItemBonuses(const EQ::ItemInstance* inst, StatBonuses* b, bool is_augment, bool is_tribute, int recommended_level_override, bool is_ammo_item) {
if (!inst || !inst->IsClassCommon()) {
return;
}
@@ -360,29 +352,20 @@ void Mob::AddItemBonuses(
b->EnduranceRegen += CalcItemBonus(item->EnduranceRegen);
// These have rule-configured caps.
b->ATK = CalcCappedItemBonus(
b->ATK,
item->Attack,
(
GetStatCap(StatCap::Attack) +
itembonuses.ItemATKCap +
spellbonuses.ItemATKCap +
aabonuses.ItemATKCap
)
);
b->AvoidMeleeChance = CalcCappedItemBonus(b->AvoidMeleeChance, item->Avoidance, GetStatCap(StatCap::Avoidance));
b->Clairvoyance = CalcCappedItemBonus(b->Clairvoyance, item->Clairvoyance, GetStatCap(StatCap::Clairvoyance));
b->DamageShield = CalcCappedItemBonus(b->DamageShield, item->DamageShield, GetStatCap(StatCap::DamageShield));
b->DoTShielding = CalcCappedItemBonus(b->DoTShielding, item->DotShielding, GetStatCap(StatCap::DOTShielding));
b->DSMitigation = CalcCappedItemBonus(b->DSMitigation, item->DSMitigation, GetStatCap(StatCap::DSMitigation));
b->HealAmt = CalcCappedItemBonus(b->HealAmt, item->HealAmt, GetStatCap(StatCap::HealAmount));
b->HitChance = CalcCappedItemBonus(b->HitChance, item->Accuracy, GetStatCap(StatCap::Accuracy));
b->MeleeMitigation = CalcCappedItemBonus(b->MeleeMitigation, item->Shielding, GetStatCap(StatCap::Shielding));
b->ProcChance = CalcCappedItemBonus(b->ProcChance, item->CombatEffects, GetStatCap(StatCap::CombatEffects));
b->SpellDmg = CalcCappedItemBonus(b->SpellDmg, item->SpellDmg, GetStatCap(StatCap::SpellDamage));
b->SpellShield = CalcCappedItemBonus(b->SpellShield, item->SpellShield, GetStatCap(StatCap::SpellShielding));
b->StrikeThrough = CalcCappedItemBonus(b->StrikeThrough, item->StrikeThrough, GetStatCap(StatCap::Strikethrough));
b->StunResist = CalcCappedItemBonus(b->StunResist, item->StunResist, GetStatCap(StatCap::StunResist));
b->ATK = CalcCappedItemBonus(b->ATK, item->Attack, RuleI(Character, ItemATKCap) + itembonuses.ItemATKCap + spellbonuses.ItemATKCap + aabonuses.ItemATKCap);
b->DamageShield = CalcCappedItemBonus(b->DamageShield, item->DamageShield, RuleI(Character, ItemDamageShieldCap));
b->SpellShield = CalcCappedItemBonus(b->SpellShield, item->SpellShield, RuleI(Character, ItemSpellShieldingCap));
b->MeleeMitigation = CalcCappedItemBonus(b->MeleeMitigation, item->Shielding, RuleI(Character, ItemShieldingCap));
b->StunResist = CalcCappedItemBonus(b->StunResist, item->StunResist, RuleI(Character, ItemStunResistCap));
b->StrikeThrough = CalcCappedItemBonus(b->StrikeThrough, item->StrikeThrough, RuleI(Character, ItemStrikethroughCap));
b->AvoidMeleeChance = CalcCappedItemBonus(b->AvoidMeleeChance, item->Avoidance, RuleI(Character, ItemAvoidanceCap));
b->HitChance = CalcCappedItemBonus(b->HitChance, item->Accuracy, RuleI(Character, ItemAccuracyCap));
b->ProcChance = CalcCappedItemBonus(b->ProcChance, item->CombatEffects, RuleI(Character, ItemCombatEffectsCap));
b->DoTShielding = CalcCappedItemBonus(b->DoTShielding, item->DotShielding, RuleI(Character, ItemDoTShieldingCap));
b->HealAmt = CalcCappedItemBonus(b->HealAmt, item->HealAmt, RuleI(Character, ItemHealAmtCap));
b->SpellDmg = CalcCappedItemBonus(b->SpellDmg, item->SpellDmg, RuleI(Character, ItemSpellDmgCap));
b->Clairvoyance = CalcCappedItemBonus(b->Clairvoyance, item->Clairvoyance, RuleI(Character, ItemClairvoyanceCap));
b->DSMitigation = CalcCappedItemBonus(b->DSMitigation, item->DSMitigation, RuleI(Character, ItemDSMitigationCap));
if (b->haste < item->Haste) {
b->haste = item->Haste;
@@ -391,18 +374,10 @@ void Mob::AddItemBonuses(
if (item->ExtraDmgAmt != 0 && item->ExtraDmgSkill <= EQ::skills::HIGHEST_SKILL) {
if (item->ExtraDmgSkill == ALL_SKILLS) {
for (const auto &skill_id: EQ::skills::GetExtraDamageSkills()) {
b->SkillDamageAmount[skill_id] = CalcCappedItemBonus(
b->SkillDamageAmount[skill_id],
item->ExtraDmgAmt,
GetStatCap(StatCap::ExtraDamage)
);
b->SkillDamageAmount[skill_id] = CalcCappedItemBonus(b->SkillDamageAmount[skill_id], item->ExtraDmgAmt, RuleI(Character, ItemExtraDmgCap));
}
} else {
b->SkillDamageAmount[item->ExtraDmgSkill] = CalcCappedItemBonus(
b->SkillDamageAmount[item->ExtraDmgSkill],
item->ExtraDmgAmt,
GetStatCap(StatCap::ExtraDamage)
);
b->SkillDamageAmount[item->ExtraDmgSkill] = CalcCappedItemBonus(b->SkillDamageAmount[item->ExtraDmgSkill], item->ExtraDmgAmt, RuleI(Character, ItemExtraDmgCap));
}
}
-3
View File
@@ -268,8 +268,6 @@ Bot::Bot(
LoadDefaultBotSettings();
database.botdb.LoadBotSettings(this);
database.LoadStatCaps(this);
if (RuleB(Bots, AllowBotBlockedBuffs)) {
bot_blocked_buffs.clear();
database.botdb.LoadBotBlockedBuffs(this);
@@ -1422,7 +1420,6 @@ bool Bot::Save()
database.botdb.SaveTimers(this);
database.botdb.SaveStance(this);
database.botdb.SaveBotSettings(this);
database.SaveStatCaps(this);
if (RuleB(Bots, AllowBotBlockedBuffs)) {
database.botdb.SaveBotBlockedBuffs(this);
+7 -6
View File
@@ -101,7 +101,7 @@ namespace BotSettingCategories {
constexpr uint8 SpellTypeMinManaPct = 7;
constexpr uint8 SpellTypeMaxManaPct = 8;
constexpr uint8 SpellTypeMinHPPct = 9;
constexpr uint8 SpellTypeMaxHPPct = 10;
constexpr uint8 SpellTypeMaxHPPct = 10;
constexpr uint8 SpellTypeIdlePriority = 11;
constexpr uint8 SpellTypeEngagedPriority = 12;
constexpr uint8 SpellTypePursuePriority = 13;
@@ -166,7 +166,7 @@ namespace BotBaseSettings {
constexpr uint16 ExpansionBitmask = 0;
constexpr uint16 ShowHelm = 1;
constexpr uint16 FollowDistance = 2;
constexpr uint16 StopMeleeLevel = 3;
constexpr uint16 StopMeleeLevel = 3;
constexpr uint16 EnforceSpellSettings = 4;
constexpr uint16 RangedSetting = 5;
constexpr uint16 PetSetTypeSetting = 6;
@@ -487,7 +487,7 @@ public:
void SetCommandedSpell(bool value) { _commandedSpell = value; }
bool IsPullingSpell() const { return _pullingSpell; }
void SetPullingSpell(bool value) { _pullingSpell = value; }
void SetGuardMode();
void SetHoldMode();
@@ -550,7 +550,7 @@ public:
bool IsValidMezTarget(Mob* owner, Mob* npc, uint16 spell_id);
// Cast checks
bool PrecastChecks(Mob* tar, uint16 spell_type);
bool PrecastChecks(Mob* tar, uint16 spell_type);
bool CastChecks(uint16 spell_id, Mob* tar, uint16 spell_type, bool prechecks = false, bool ae_check = false);
bool IsImmuneToBotSpell(uint16 spell_id, Mob* caster);
bool CanCastSpellType(uint16 spell_type, uint16 spell_id, Mob* tar);
@@ -601,7 +601,7 @@ public:
void ResetBotSpellSettings();
void CopyBotBlockedBuffs(Bot* to);
void CopyBotBlockedPetBuffs(Bot* to);
void CopyBotBlockedPetBuffs(Bot* to);
void CleanBotBlockedBuffs();
void ClearBotBlockedBuffs() { bot_blocked_buffs.clear(); }
bool IsBlockedBuff(int32 spell_id) override;
@@ -658,7 +658,7 @@ public:
bool GetBehindMob() const { return _behindMobStatus; }
void SetBehindMob(bool value) { _behindMobStatus = value; }
bool GetMaxMeleeRange() const { return _maxMeleeRangeStatus; }
void SetMaxMeleeRange(bool value) { _maxMeleeRangeStatus = value; }
void SetMaxMeleeRange(bool value) { _maxMeleeRangeStatus = value; }
uint8 GetStopMeleeLevel() const { return _stopMeleeLevel; }
void SetStopMeleeLevel(uint8 level) { _stopMeleeLevel = level; }
uint32 GetBotDistanceRanged() const { return _distanceRanged; }
@@ -1210,6 +1210,7 @@ private:
bool _hasLoS;
bool _commandedSpell;
bool _pullingSpell;
bool _illusionBlock;
std::vector<BotSpellSettings> m_bot_spell_settings;
std::vector<Mob*> _spell_target_list;
-2
View File
@@ -1103,8 +1103,6 @@ bool Client::Save(uint8 iCommitNow) {
database.SaveCharacterEXPModifier(this);
database.SaveStatCaps(this);
if (RuleB(Bots, Enabled)) {
database.botdb.SaveBotSettings(this);
}
+16 -17
View File
@@ -32,24 +32,23 @@
int32 Client::GetMaxStat() const
{
int character_cap = GetStatCap(StatCap::Stat);
if (character_cap > 0) {
return character_cap;
if ((RuleI(Character, StatCap)) > 0) {
return (RuleI(Character, StatCap));
}
uint8 level = GetLevel();
int base = 0;
int level = GetLevel();
int32 base = 0;
if (level < 61) {
base = 255;
} else if (ClientVersion() >= EQ::versions::ClientVersion::SoF) {
}
else if (ClientVersion() >= EQ::versions::ClientVersion::SoF) {
base = 255 + 5 * (level - 60);
} else if (level < 71) {
}
else if (level < 71) {
base = 255 + 5 * (level - 60);
} else {
}
else {
base = 330;
}
return base;
}
@@ -301,7 +300,7 @@ int64 Client::CalcHPRegen(bool bCombat)
int64 Client::CalcHPRegenCap()
{
int64 cap = GetStatCap(StatCap::HealthRegen);
int64 cap = RuleI(Character, ItemHealthRegenCap);
if (GetLevel() > 60) {
cap = std::max(cap, static_cast<int64>(GetLevel() - 30)); // if the rule is set greater than normal I guess
}
@@ -718,7 +717,7 @@ int64 Client::CalcManaRegen(bool bCombat)
int64 Client::CalcManaRegenCap()
{
int64 cap = GetStatCap(StatCap::ManaRegen) + aabonuses.ItemManaRegenCap + itembonuses.ItemManaRegenCap + spellbonuses.ItemManaRegenCap;
int64 cap = RuleI(Character, ItemManaRegenCap) + aabonuses.ItemManaRegenCap + itembonuses.ItemManaRegenCap + spellbonuses.ItemManaRegenCap;
return (cap * RuleI(Character, ManaRegenMultiplier) / 100);
}
@@ -977,7 +976,7 @@ int Client::CalcHaste()
}
// 60+ 100, 51-59 85, 1-50 level+25
if (level > 59 || RuleB(Character, IgnoreLevelBasedHasteCaps)) { // 60+
cap = GetStatCap(StatCap::Haste);
cap = RuleI(Character, HasteCap);
}
else if (level > 50) { // 51-59
cap = 85;
@@ -990,7 +989,7 @@ int Client::CalcHaste()
}
// 51+ 25 (despite there being higher spells...), 1-50 10
if (level > 50 || RuleB(Character, IgnoreLevelBasedHasteCaps)) { // 51+
cap = GetStatCap(StatCap::HasteV3);
cap = RuleI(Character, Hastev3Cap);
if (spellbonuses.hastetype3 > cap) {
h += cap;
} else {
@@ -1746,13 +1745,13 @@ int64 Client::CalcEnduranceRegen(bool bCombat)
int64 Client::CalcEnduranceRegenCap()
{
int64 cap = GetStatCap(StatCap::EnduranceRegen) + aabonuses.ItemEnduranceRegenCap + itembonuses.ItemEnduranceRegenCap + spellbonuses.ItemEnduranceRegenCap;
int64 cap = RuleI(Character, ItemEnduranceRegenCap) + aabonuses.ItemEnduranceRegenCap + itembonuses.ItemEnduranceRegenCap + spellbonuses.ItemEnduranceRegenCap;
return (cap * RuleI(Character, EnduranceRegenMultiplier) / 100);
}
int32 Client::CalcItemATKCap()
{
int cap = GetStatCap(StatCap::Attack) + itembonuses.ItemATKCap + spellbonuses.ItemATKCap + aabonuses.ItemATKCap;
int cap = RuleI(Character, ItemATKCap) + itembonuses.ItemATKCap + spellbonuses.ItemATKCap + aabonuses.ItemATKCap;
return cap;
}
+2 -3
View File
@@ -1386,7 +1386,6 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
database.LoadCharacterTribute(this); /* Load CharacterTribute */
database.LoadCharacterEXPModifier(this); /* Load Character EXP Modifier */
database.LoadCharacterTitleSets(this); /* Load Character Title Sets */
database.LoadStatCaps(this); /* Load Character Stat Caps */
// this pattern is strange
// this is remnants of the old way of doing things
@@ -1714,7 +1713,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
if (zone->IsPVPZone())
m_pp.pvp = 1;
/* Time entitled on Account: Move to account */
m_pp.timeentitledonaccount = database.GetTotalTimeEntitledOnAccount(AccountID()) / 1440;
m_pp.timeentitledonaccount = CharacterDataRepository::GetTotalTimePlayed(database, AccountID()) / 1440;
/* Reset rest timer if the durations have been lowered in the database */
if ((m_pp.RestTimer > RuleI(Character, RestRegenTimeToActivate)) && (m_pp.RestTimer > RuleI(Character, RestRegenRaidTimeToActivate)))
m_pp.RestTimer = 0;
@@ -7989,7 +7988,7 @@ void Client::Handle_OP_GuildCreate(const EQApplicationPacket *app)
if ((Admin() < RuleI(Guild, PlayerCreationRequiredStatus)) ||
(GetLevel() < RuleI(Guild, PlayerCreationRequiredLevel)) ||
(database.GetTotalTimeEntitledOnAccount(AccountID()) < (unsigned int)RuleI(Guild, PlayerCreationRequiredTime)))
(CharacterDataRepository::GetTotalTimePlayed(database, AccountID()) < (unsigned int)RuleI(Guild, PlayerCreationRequiredTime)))
{
Message(Chat::Red, "Your status, level or time playing on this account are insufficient to use this feature.");
return;
+1 -1
View File
@@ -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{
+2
View File
@@ -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",
-6
View File
@@ -6049,11 +6049,6 @@ std::string Perl__get_pet_type_name(uint8 pet_type)
return PetType::GetName(pet_type);
}
std::string Perl__get_stat_cap_name(uint8 stat_id)
{
return StatCap::GetName(stat_id);
}
void perl_register_quest()
{
perl::interpreter perl(PERL_GET_THX);
@@ -6765,7 +6760,6 @@ void perl_register_quest()
package.add("getspellstat", (int(*)(uint32, std::string))&Perl__getspellstat);
package.add("getspellstat", (int(*)(uint32, std::string, uint8))&Perl__getspellstat);
package.add("getskillname", &Perl__getskillname);
package.add("get_stat_cap_name", &Perl__get_stat_cap_name);
package.add("get_timers", &Perl__get_timers);
package.add("getlevel", &Perl__getlevel);
package.add("getplayerburiedcorpsecount", &Perl__getplayerburiedcorpsecount);
+2
View File
@@ -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,
-14
View File
@@ -664,18 +664,6 @@ void Lua_Bot::RaidGroupSay(const char* message) {
self->RaidGroupSay(message);
}
int Lua_Bot::GetStatCap(uint8 stat_id)
{
Lua_Safe_Call_Int();
return self->GetStatCap(stat_id);
}
void Lua_Bot::SetStatCap(uint8 stat_id, int stat_cap)
{
Lua_Safe_Call_Void();
self->SetStatCap(stat_id, stat_cap, true);
}
luabind::scope lua_register_bot() {
return luabind::class_<Lua_Bot, Lua_Mob>("Bot")
.def(luabind::constructor<>())
@@ -759,7 +747,6 @@ luabind::scope lua_register_bot() {
.def("GetSpellDamage", (int(Lua_Bot::*)(void))&Lua_Bot::GetSpellDamage)
.def("GetSpellRecastTimer", (uint32(Lua_Bot::*)())&Lua_Bot::GetSpellRecastTimer)
.def("GetSpellRecastTimer", (uint32(Lua_Bot::*)(uint16))&Lua_Bot::GetSpellRecastTimer)
.def("GetStatCap", (int(Lua_Bot::*)(uint8))&Lua_Bot::GetStatCap)
.def("HasAugmentEquippedByID", (bool(Lua_Bot::*)(uint32))&Lua_Bot::HasAugmentEquippedByID)
.def("HasBotItem", (int16(Lua_Bot::*)(uint32))&Lua_Bot::HasBotItem)
.def("HasBotSpellEntry", (bool(Lua_Bot::*)(uint16))&Lua_Bot::HasBotSpellEntry)
@@ -796,7 +783,6 @@ luabind::scope lua_register_bot() {
.def("SetSpellDurationRaid", (void(Lua_Bot::*)(int,int,int,bool,bool))&Lua_Bot::SetSpellDurationRaid)
.def("SetSpellRecastTimer", (void(Lua_Bot::*)(uint16))&Lua_Bot::SetSpellRecastTimer)
.def("SetSpellRecastTimer", (void(Lua_Bot::*)(uint16, uint32))&Lua_Bot::SetSpellRecastTimer)
.def("SetStatCap", (void(Lua_Bot::*)(uint8,int))&Lua_Bot::SetStatCap)
.def("SendPayload", (void(Lua_Bot::*)(int))&Lua_Bot::SendPayload)
.def("SendPayload", (void(Lua_Bot::*)(int,std::string))&Lua_Bot::SendPayload)
.def("Signal", (void(Lua_Bot::*)(int))&Lua_Bot::Signal)
-2
View File
@@ -126,8 +126,6 @@ public:
void SetItemReuseTimer(uint32 item_id, uint32 reuse_timer);
void SetSpellRecastTimer(uint16 spell_id);
void SetSpellRecastTimer(uint16 spell_id, uint32 reuse_timer);
int GetStatCap(uint8 stat_id);
void SetStatCap(uint8 stat_id, int stat_cap);
uint32 CountAugmentEquippedByID(uint32 item_id);
uint32 CountItemEquippedByID(uint32 item_id);
-14
View File
@@ -3624,18 +3624,6 @@ luabind::object Lua_Client::GetKeyRing(lua_State* L)
return lua_table;
}
int Lua_Client::GetStatCap(uint8 stat_id)
{
Lua_Safe_Call_Int();
return self->GetStatCap(stat_id);
}
void Lua_Client::SetStatCap(uint8 stat_id, int stat_cap)
{
Lua_Safe_Call_Void();
self->SetStatCap(stat_id, stat_cap, true);
}
luabind::scope lua_register_client() {
return luabind::class_<Lua_Client, Lua_Mob>("Client")
.def(luabind::constructor<>())
@@ -3910,7 +3898,6 @@ luabind::scope lua_register_client() {
.def("GetSpellDamage", (int(Lua_Client::*)(void))&Lua_Client::GetSpellDamage)
.def("GetSpellIDByBookSlot", (uint32(Lua_Client::*)(int))&Lua_Client::GetSpellIDByBookSlot)
.def("GetSpentAA", (int(Lua_Client::*)(void))&Lua_Client::GetSpentAA)
.def("GetStatCap", (int(Lua_Client::*)(uint8))&Lua_Client::GetStatCap)
.def("GetStartZone", (int(Lua_Client::*)(void))&Lua_Client::GetStartZone)
.def("GetTargetRingX", (float(Lua_Client::*)(void))&Lua_Client::GetTargetRingX)
.def("GetTargetRingY", (float(Lua_Client::*)(void))&Lua_Client::GetTargetRingY)
@@ -4176,7 +4163,6 @@ luabind::scope lua_register_client() {
.def("SetStartZone", (void(Lua_Client::*)(int,float))&Lua_Client::SetStartZone)
.def("SetStartZone", (void(Lua_Client::*)(int,float,float))&Lua_Client::SetStartZone)
.def("SetStartZone", (void(Lua_Client::*)(int,float,float,float))&Lua_Client::SetStartZone)
.def("SetStatCap", (void(Lua_Client::*)(uint8,int))&Lua_Client::SetStatCap)
.def("SetStats", (void(Lua_Client::*)(int,int))&Lua_Client::SetStats)
.def("SetThirst", (void(Lua_Client::*)(int))&Lua_Client::SetThirst)
.def("SetTint", (void(Lua_Client::*)(int,uint32))&Lua_Client::SetTint)
-2
View File
@@ -607,8 +607,6 @@ public:
bool RemoveAAPoints(uint32 points);
bool RemoveAlternateCurrencyValue(uint32 currency_id, uint32 amount);
bool AreTasksCompleted(luabind::object task_ids);
int GetStatCap(uint8 stat_id);
void SetStatCap(uint8 stat_id, int stat_cap);
void DialogueWindow(std::string markdown);
+3 -7
View File
@@ -5711,11 +5711,6 @@ std::string lua_get_pet_type_name(uint8 pet_type)
return PetType::GetName(pet_type);
}
std::string lua_get_stat_cap_name(uint8 stat_id)
{
return StatCap::GetName(stat_id);
}
#define LuaCreateNPCParse(name, c_type, default_value) do { \
cur = table[#name]; \
if(luabind::type(cur) != LUA_TNIL) { \
@@ -6531,7 +6526,6 @@ luabind::scope lua_register_general() {
luabind::def("get_timers", &lua_get_timers),
luabind::def("get_pet_command_name", &lua_get_pet_command_name),
luabind::def("get_pet_type_name", &lua_get_pet_type_name),
luabind::def("get_stat_cap_name", &lua_get_stat_cap_name),
/*
Cross Zone
*/
@@ -6998,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))
)];
}
+5 -1
View File
@@ -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;
+20 -91
View File
@@ -22,9 +22,7 @@
#include "../common/misc_functions.h"
#include "../common/repositories/bot_data_repository.h"
#include "../common/repositories/bot_stat_caps_repository.h"
#include "../common/repositories/character_data_repository.h"
#include "../common/repositories/character_stat_caps_repository.h"
#include "../common/data_bucket.h"
#include "quest_parser_collection.h"
@@ -2063,8 +2061,8 @@ void Mob::SendStatsWindow(Client* c, bool use_window)
case 0: {
mod2a_name = "Avoidance";
mod2b_name = "Combat Effects";
mod2a_cap = Strings::Commify(GetStatCap(StatCap::Avoidance));
mod2b_cap = Strings::Commify(GetStatCap(StatCap::CombatEffects));
mod2a_cap = Strings::Commify(RuleI(Character, ItemAvoidanceCap));
mod2b_cap = Strings::Commify(RuleI(Character, ItemCombatEffectsCap));
if (IsBot()) {
mod2a = Strings::Commify(CastToBot()->GetAvoidance());
@@ -2083,8 +2081,8 @@ void Mob::SendStatsWindow(Client* c, bool use_window)
case 1: {
mod2a_name = "Accuracy";
mod2b_name = "Strikethrough";
mod2a_cap = Strings::Commify(GetStatCap(StatCap::Accuracy));
mod2b_cap = Strings::Commify(GetStatCap(StatCap::Strikethrough));
mod2a_cap = Strings::Commify(RuleI(Character, ItemAccuracyCap));
mod2b_cap = Strings::Commify(RuleI(Character, ItemStrikethroughCap));
if (IsBot()) {
mod2a = Strings::Commify(CastToBot()->GetAccuracy());
@@ -2103,8 +2101,8 @@ void Mob::SendStatsWindow(Client* c, bool use_window)
case 2: {
mod2a_name = "Shielding";
mod2b_name = "Spell Shielding";
mod2a_cap = Strings::Commify(GetStatCap(StatCap::Shielding));
mod2b_cap = Strings::Commify(GetStatCap(StatCap::SpellShielding));
mod2a_cap = Strings::Commify(RuleI(Character, ItemShieldingCap));
mod2b_cap = Strings::Commify(RuleI(Character, ItemSpellShieldingCap));
if (IsBot()) {
mod2a = Strings::Commify(CastToBot()->GetShielding());
@@ -2124,8 +2122,8 @@ void Mob::SendStatsWindow(Client* c, bool use_window)
case 3: {
mod2a_name = "Stun Resist";
mod2b_name = "DOT Shielding";
mod2a_cap = Strings::Commify(GetStatCap(StatCap::DOTShielding));
mod2b_cap = Strings::Commify(GetStatCap(StatCap::StunResist));
mod2a_cap = Strings::Commify(RuleI(Character, ItemStunResistCap));
mod2b_cap = Strings::Commify(RuleI(Character, ItemDoTShieldingCap));
if (IsBot()) {
mod2a = Strings::Commify(CastToBot()->GetStunResist());
@@ -2370,7 +2368,7 @@ void Mob::SendStatsWindow(Client* c, bool use_window)
fmt::format(
" | Item: {} / {} | Used: {}",
Strings::Commify(itembonuses.ATK),
Strings::Commify(GetStatCap(StatCap::Attack)),
Strings::Commify(RuleI(Character, ItemATKCap)),
Strings::Commify(static_cast<int>(itembonuses.ATK * 1.342))
) :
""
@@ -2435,7 +2433,7 @@ void Mob::SendStatsWindow(Client* c, bool use_window)
fmt::format(
"{} ({})",
IsClient() ? Strings::Commify(CastToClient()->GetHaste()) : Strings::Commify(GetHaste()),
Strings::Commify(GetStatCap(StatCap::Haste))
Strings::Commify(RuleI(Character, HasteCap))
)
)
)
@@ -2473,17 +2471,17 @@ void Mob::SendStatsWindow(Client* c, bool use_window)
final_string += fmt::format(
"Heal Amount: {} / {}{}",
Strings::Commify(GetHealAmt()),
Strings::Commify(GetStatCap(StatCap::HealAmount)),
Strings::Commify(RuleI(Character, ItemHealAmtCap)),
DialogueWindow::Break(1)
);
}
// Spell Damage
// Heal Amount
if (GetSpellDmg()) {
final_string += fmt::format(
"Spell Damage: {} / {}{}",
Strings::Commify(GetSpellDmg()),
Strings::Commify(GetStatCap(StatCap::SpellDamage)),
Strings::Commify(RuleI(Character, ItemSpellDmgCap)),
DialogueWindow::Break(1)
);
}
@@ -2503,7 +2501,7 @@ void Mob::SendStatsWindow(Client* c, bool use_window)
fmt::format(
" | Item: {} / {}",
Strings::Commify(itembonuses.DamageShield),
Strings::Commify(GetStatCap(StatCap::DamageShield))
Strings::Commify(RuleI(Character, ItemDamageShieldCap))
) :
""
),
@@ -2512,12 +2510,12 @@ void Mob::SendStatsWindow(Client* c, bool use_window)
}
// Clairvoyance
const auto clairvoyance = IsBot() ? CastToBot()->GetClair() : CastToClient()->GetClair();
const auto clairvoyance = IsBot() ? CastToBot()->GetClair() : CastToClient()->GetClair();
if (clairvoyance) {
final_string += fmt::format(
"Clairvoyance: {} / {}{}",
Strings::Commify(clairvoyance),
Strings::Commify(GetStatCap(StatCap::Clairvoyance)),
Strings::Commify(RuleI(Character, ItemClairvoyanceCap)),
DialogueWindow::Break(1)
);
}
@@ -2528,7 +2526,7 @@ void Mob::SendStatsWindow(Client* c, bool use_window)
final_string += fmt::format(
"DS Mitigation: {} / {}{}",
Strings::Commify(ds_mitigation),
Strings::Commify(GetStatCap(StatCap::DSMitigation)),
Strings::Commify(RuleI(Character, ItemDSMitigationCap)),
DialogueWindow::Break(1)
);
}
@@ -2598,7 +2596,7 @@ void Mob::SendStatsWindow(Client* c, bool use_window)
GetRaceIDName(GetRace()),
GetRace(),
IsBot() ? Strings::Commify(CastToBot()->GetDS()) : Strings::Commify(CastToClient()->GetDS()),
Strings::Commify(GetStatCap(StatCap::DamageShield)),
Strings::Commify(RuleI(Character, ItemDamageShieldCap)),
GetSize(),
GetRunspeed(),
IsBot() ? static_cast<float>(CastToBot()->CalcCurrentWeight()) / 10.0f : static_cast<float>(CastToClient()->CalcCurrentWeight()) / 10.0f,
@@ -2696,7 +2694,7 @@ void Mob::SendStatsWindow(Client* c, bool use_window)
"Attack: {} Item and Spell Attack: {}/{} Server Side Attack: {}",
IsBot() ? Strings::Commify(CastToBot()->GetTotalATK()) : Strings::Commify(CastToClient()->GetTotalATK()),
Strings::Commify(GetATKBonus()),
Strings::Commify(GetStatCap(StatCap::Attack)),
Strings::Commify(RuleI(Character, ItemATKCap)),
Strings::Commify(GetATK())
).c_str()
);
@@ -2707,7 +2705,7 @@ void Mob::SendStatsWindow(Client* c, bool use_window)
fmt::format(
"Haste: {}/{} (Item: {} + Spell: {} + Over: {})",
IsClient() ? Strings::Commify(CastToClient()->GetHaste()) : Strings::Commify(GetHaste()),
Strings::Commify(GetStatCap(StatCap::Haste)),
Strings::Commify(RuleI(Character, HasteCap)),
Strings::Commify(itembonuses.haste),
Strings::Commify(spellbonuses.haste + spellbonuses.hastetype2),
Strings::Commify(spellbonuses.hastetype3 + extra_haste)
@@ -8795,72 +8793,3 @@ bool Mob::LoadDataBucketsCache()
return true;
}
int Mob::GetStatCap(uint8 stat_id) const
{
if (HasStatCap(stat_id)) {
return m_stat_caps.at(stat_id);
}
static const std::map<uint8, int> default_caps = {
{ StatCap::Accuracy, RuleI(Character, ItemAccuracyCap) },
{ StatCap::Attack, RuleI(Character, ItemATKCap) },
{ StatCap::Avoidance, RuleI(Character, ItemAvoidanceCap) },
{ StatCap::Clairvoyance, RuleI(Character, ItemClairvoyanceCap) },
{ StatCap::CombatEffects, RuleI(Character, ItemCombatEffectsCap) },
{ StatCap::DamageShield, RuleI(Character, ItemDamageShieldCap) },
{ StatCap::DOTShielding, RuleI(Character, ItemDoTShieldingCap) },
{ StatCap::DSMitigation, RuleI(Character, ItemDSMitigationCap) },
{ StatCap::EnduranceRegen, RuleI(Character, ItemEnduranceRegenCap) },
{ StatCap::ExtraDamage, RuleI(Character, ItemExtraDmgCap) },
{ StatCap::Haste, RuleI(Character, HasteCap) },
{ StatCap::HasteV3, RuleI(Character, Hastev3Cap) },
{ StatCap::HealAmount, RuleI(Character, ItemHealAmtCap) },
{ StatCap::HealthRegen, RuleI(Character, ItemHealthRegenCap) },
{ StatCap::ManaRegen, RuleI(Character, ItemManaRegenCap) },
{ StatCap::QuiverHaste, RuleI(Combat, QuiverHasteCap) },
{ StatCap::Shielding, RuleI(Character, ItemShieldingCap) },
{ StatCap::SpellDamage, RuleI(Character, ItemSpellDmgCap) },
{ StatCap::SpellShielding, RuleI(Character, ItemSpellShieldingCap) },
{ StatCap::Stat, RuleI(Character, StatCap) },
{ StatCap::Strikethrough, RuleI(Character, ItemStrikethroughCap) },
{ StatCap::StunResist, RuleI(Character, ItemStunResistCap) },
};
auto it = default_caps.find(stat_id);
if (it != default_caps.end()) {
return it->second;
}
return -1;
}
void Mob::SetStatCap(uint8 stat_id, int stat_cap, bool save)
{
m_stat_caps[stat_id] = stat_cap;
if (!save) {
return;
}
if (IsBot()) {
BotStatCapsRepository::ReplaceOne(
database,
BotStatCapsRepository::BotStatCaps{
.bot_id = CastToBot()->GetBotID(),
.stat_id = stat_id,
.stat_cap = stat_cap
}
);
}
else if (IsClient()) {
CharacterStatCapsRepository::ReplaceOne(
database,
CharacterStatCapsRepository::CharacterStatCaps{
.character_id = CastToClient()->CharacterID(),
.stat_id = stat_id,
.stat_cap = stat_cap
}
);
}
}
-7
View File
@@ -1519,11 +1519,6 @@ public:
bool IsGuildmaster() const;
bool IsDestroying() const { return m_destroying; }
int GetStatCap(uint8 stat_id) const;
std::map<uint8, int> GetStatCaps() { return m_stat_caps; }
bool HasStatCap(uint8 stat_id) const { return m_stat_caps.count(stat_id); }
void SetStatCap(uint8 stat_id, int stat_cap, bool save = false);
protected:
void CommonDamage(Mob* other, int64 &damage, const uint16 spell_id, const EQ::skills::SkillType attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic, eSpecialAttacks specal = eSpecialAttacks::None);
static uint16 GetProcID(uint16 spell_id, uint8 effect_index);
@@ -1807,8 +1802,6 @@ protected:
CombatRecord m_combat_record{};
std::map<uint8, int> m_stat_caps;
public:
const CombatRecord &GetCombatRecord() const;
+184 -293
View File
@@ -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();
}
+1 -1
View File
@@ -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; }
+21 -13
View File
@@ -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);
+7 -19
View File
@@ -620,16 +620,6 @@ void Perl_Bot_RaidGroupSay(Bot* self, const char* message) // @categories Script
self->RaidGroupSay(message);
}
int Perl_Bot_GetStatCap(Bot* self, uint8 stat_id)
{
return self->GetStatCap(stat_id);
}
void Perl_Bot_SetStatCap(Bot* self, uint8 stat_id, int stat_cap)
{
self->SetStatCap(stat_id, stat_cap, true);
}
void perl_register_bot()
{
perl::interpreter state(PERL_GET_THX);
@@ -693,28 +683,27 @@ void perl_register_bot()
package.add("GetBotItem", &Perl_Bot_GetBotItem);
package.add("GetBotItemIDBySlot", &Perl_Bot_GetBotItemIDBySlot);
package.add("GetClassAbbreviation", &Perl_Bot_GetClassAbbreviation);
package.add("GetDisciplineReuseTimer", (uint32(*)(Bot*))&Perl_Bot_GetDisciplineReuseTimer);
package.add("GetDisciplineReuseTimer", (uint32(*)(Bot*, uint16))&Perl_Bot_GetDisciplineReuseTimer);
package.add("GetExpansionBitmask", &Perl_Bot_GetExpansionBitmask);
package.add("GetGroup", &Perl_Bot_GetGroup);
package.add("GetHealAmount", &Perl_Bot_GetHealAmount);
package.add("GetInstrumentMod", &Perl_Bot_GetInstrumentMod);
package.add("GetItemAt", &Perl_Bot_GetItemAt);
package.add("GetItemEquippedByID", &Perl_Bot_HasItemEquippedByID);
package.add("GetItemIDAt", &Perl_Bot_GetItemIDAt);
package.add("GetItemReuseTimer", (uint32(*)(Bot*))&Perl_Bot_GetItemReuseTimer);
package.add("GetItemReuseTimer", (uint32(*)(Bot*, uint32))&Perl_Bot_GetItemReuseTimer);
package.add("GetOwner", &Perl_Bot_GetOwner);
package.add("GetRaceAbbreviation", &Perl_Bot_GetRaceAbbreviation);
package.add("GetRawItemAC", &Perl_Bot_GetRawItemAC);
package.add("GetSpellDamage", &Perl_Bot_GetSpellDamage);
package.add("GetSpellRecastTimer", (uint32(*)(Bot*))&Perl_Bot_GetSpellRecastTimer);
package.add("GetSpellRecastTimer", (uint32(*)(Bot*, uint16))&Perl_Bot_GetSpellRecastTimer);
package.add("GetStatCap", &Perl_Bot_GetStatCap);
package.add("HasAugmentEquippedByID", &Perl_Bot_HasAugmentEquippedByID);
package.add("HasBotItem", &Perl_Bot_HasBotItem);
package.add("HasBotSpellEntry", &Perl_Bot_HasBotSpellEntry);
package.add("HasItemEquippedByID", &Perl_Bot_HasItemEquippedByID);
package.add("GetDisciplineReuseTimer", (uint32(*)(Bot*))&Perl_Bot_GetDisciplineReuseTimer);
package.add("GetDisciplineReuseTimer", (uint32(*)(Bot*, uint16))&Perl_Bot_GetDisciplineReuseTimer);
package.add("GetItemEquippedByID", &Perl_Bot_HasItemEquippedByID);
package.add("GetItemReuseTimer", (uint32(*)(Bot*))&Perl_Bot_GetItemReuseTimer);
package.add("GetItemReuseTimer", (uint32(*)(Bot*, uint32))&Perl_Bot_GetItemReuseTimer);
package.add("GetSpellRecastTimer", (uint32(*)(Bot*))&Perl_Bot_GetSpellRecastTimer);
package.add("GetSpellRecastTimer", (uint32(*)(Bot*, uint16))&Perl_Bot_GetSpellRecastTimer);
package.add("IsGrouped", &Perl_Bot_IsGrouped);
package.add("IsSitting", &Perl_Bot_IsSitting);
package.add("IsStanding", &Perl_Bot_IsStanding);
@@ -747,7 +736,6 @@ void perl_register_bot()
package.add("SetSpellDurationRaid", (void(*)(Bot*, int, int, int, bool, bool))&Perl_Bot_SetSpellDurationRaid);
package.add("SetSpellRecastTimer", (void(*)(Bot*, uint16))&Perl_Bot_SetSpellRecastTimer);
package.add("SetSpellRecastTimer", (void(*)(Bot*, uint16, uint32))&Perl_Bot_SetSpellRecastTimer);
package.add("SetStatCap", &Perl_Bot_SetStatCap);
package.add("Signal", &Perl_Bot_Signal);
package.add("Sit", &Perl_Bot_Sit);
package.add("Stand", &Perl_Bot_Stand);
-12
View File
@@ -3363,16 +3363,6 @@ perl::array Perl_Client_GetKeyRing(Client* self)
return result;
}
int Perl_Client_GetStatCap(Client* self, uint8 stat_id)
{
return self->GetStatCap(stat_id);
}
void Perl_Client_SetStatCap(Client* self, uint8 stat_id, int stat_cap)
{
self->SetStatCap(stat_id, stat_cap, true);
}
void perl_register_client()
{
perl::interpreter perl(PERL_GET_THX);
@@ -3645,7 +3635,6 @@ void perl_register_client()
package.add("GetSpellBookSlotBySpellID", &Perl_Client_GetSpellBookSlotBySpellID);
package.add("GetSpellIDByBookSlot", &Perl_Client_GetSpellIDByBookSlot);
package.add("GetSpentAA", &Perl_Client_GetSpentAA);
package.add("GetStatCap", &Perl_Client_GetStatCap);
package.add("GetStartZone", &Perl_Client_GetStartZone);
package.add("GetTargetRingX", &Perl_Client_GetTargetRingX);
package.add("GetTargetRingY", &Perl_Client_GetTargetRingY);
@@ -3910,7 +3899,6 @@ void perl_register_client()
package.add("SetStartZone", (void(*)(Client*, uint32))&Perl_Client_SetStartZone);
package.add("SetStartZone", (void(*)(Client*, uint32, float, float, float))&Perl_Client_SetStartZone);
package.add("SetStartZone", (void(*)(Client*, uint32, float, float, float, float))&Perl_Client_SetStartZone);
package.add("SetStatCap", &Perl_Client_SetStatCap);
package.add("SetStats", &Perl_Client_SetStats);
package.add("SetThirst", &Perl_Client_SetThirst);
package.add("SetTint", &Perl_Client_SetTint);
+6 -8
View File
@@ -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);
-82
View File
@@ -50,8 +50,6 @@
#include "../common/repositories/character_corpses_repository.h"
#include "../common/repositories/character_corpse_items_repository.h"
#include "../common/repositories/zone_repository.h"
#include "../common/repositories/bot_stat_caps_repository.h"
#include "../common/repositories/character_stat_caps_repository.h"
#include "../common/repositories/trader_repository.h"
#include "../common/repositories/character_evolving_items_repository.h"
@@ -4299,83 +4297,3 @@ void ZoneDatabase::LoadCharacterTitleSets(Client* c)
c->EnableTitle(e.title_set, false);
}
}
void ZoneDatabase::LoadStatCaps(Mob* m)
{
if (!zone || !m) {
return;
}
if (m->IsBot()) {
const auto& l = BotStatCapsRepository::GetWhere(
*this,
fmt::format(
"`bot_id` = {}",
m->CastToBot()->GetBotID()
)
);
if (l.empty()) {
return;
}
for (const auto& e : l) {
m->SetStatCap(e.stat_id, e.stat_cap);
}
} else if (m->IsClient()) {
const auto& l = CharacterStatCapsRepository::GetWhere(
*this,
fmt::format(
"`character_id` = {}",
m->CastToClient()->CharacterID()
)
);
if (l.empty()) {
return;
}
for (const auto& e : l) {
m->SetStatCap(e.stat_id, e.stat_cap);
}
}
}
void ZoneDatabase::SaveStatCaps(Mob* m)
{
if (m->IsBot()) {
std::vector<BotStatCapsRepository::BotStatCaps> v;
BotStatCapsRepository::BotStatCaps stat_cap;
stat_cap.bot_id = m->CastToBot()->GetBotID();
for (const auto& e: m->GetStatCaps()) {
stat_cap.stat_id = e.first;
stat_cap.stat_cap = e.second;
v.emplace_back(stat_cap);
}
if (!v.empty()) {
BotStatCapsRepository::ReplaceMany(*this, v);
}
} else if (m->IsClient()) {
std::vector<CharacterStatCapsRepository::CharacterStatCaps> v;
CharacterStatCapsRepository::CharacterStatCaps stat_cap;
stat_cap.character_id = m->CastToClient()->CharacterID();
for (const auto& e: m->GetStatCaps()) {
stat_cap.stat_id = e.first;
stat_cap.stat_cap = e.second;
v.emplace_back(stat_cap);
}
if (!v.empty()) {
CharacterStatCapsRepository::ReplaceMany(*this, v);
}
}
}
-4
View File
@@ -465,10 +465,6 @@ public:
void LoadCharacterEXPModifier(Client* c);
void SaveCharacterEXPModifier(Client *c);
/* Stat Caps */
void LoadStatCaps(Mob* m);
void SaveStatCaps(Mob* m);
/* Player Title Sets */
void LoadCharacterTitleSets(Client* c);