Merge branch 'master' into repositories/mail_key

This commit is contained in:
JJ 2025-09-15 13:18:36 -04:00 committed by GitHub
commit fd8b00928b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 404 additions and 445 deletions

View File

@ -7188,9 +7188,24 @@ CHANGE COLUMN `field221` `caster_requirement_id` int(11) NULL DEFAULT 0 AFTER `n
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`;
)"
}
)",
.content_schema_update = true
},
ManifestEntry{
.version = 9329,
.description = "2025_08_22_character_parcel_updates.sql",
.check = "SHOW COLUMNS FROM `character_parcels` LIKE 'evolve_amount'",
.condition = "empty",
.match = "",
.sql = R"(
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,

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;

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;

View File

@ -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) + ")");
}

View File

@ -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") + ")");

View File

@ -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

View File

@ -429,27 +429,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;
}
auto row = results.begin();
return Strings::ToInt(row[0]);
const auto& e = AccountRepository::FindOne(*this, account_id);
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(

View File

@ -82,7 +82,6 @@ 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(uint32 character_id, int ip_address, int mail_key);
@ -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);

View File

@ -42,7 +42,7 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9328
#define CURRENT_BINARY_DATABASE_VERSION 9329
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9054
#define CUSTOM_BINARY_DATABASE_VERSION 0

View File

@ -1713,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;
@ -7988,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;

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{

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",

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,

View File

@ -6992,7 +6992,9 @@ luabind::scope lua_register_events() {
luabind::value("entity_variable_update", static_cast<int>(EVENT_ENTITY_VARIABLE_UPDATE)),
luabind::value("aa_loss", static_cast<int>(EVENT_AA_LOSS)),
luabind::value("read", static_cast<int>(EVENT_READ_ITEM)),
luabind::value("pet_command", static_cast<int>(EVENT_PET_COMMAND))
luabind::value("pet_command", static_cast<int>(EVENT_PET_COMMAND)),
luabind::value("charm_start", static_cast<int>(EVENT_CHARM_START)),
luabind::value("charm_end", static_cast<int>(EVENT_CHARM_END))
)];
}

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;

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();
}

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; }

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);

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);