From 51fb7d8b77066dcc1f9c1f075403b6cef99528b9 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Mon, 20 Jan 2020 15:38:07 -0500 Subject: [PATCH 1/7] _GetRunSpeed did not correctly report aa mods for Clients. I actually believe this was some old cut-n-paste error. aa_mod was being set to a total of all (3) caps - like the previous line. --- zone/mob.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index 71e876938..ea0cf761b 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -684,7 +684,7 @@ int Mob::_GetRunSpeed() const { int runspeedcap = RuleI(Character,BaseRunSpeedCap); runspeedcap += itembonuses.IncreaseRunSpeedCap + spellbonuses.IncreaseRunSpeedCap + aabonuses.IncreaseRunSpeedCap; - aa_mod = itembonuses.IncreaseRunSpeedCap + spellbonuses.IncreaseRunSpeedCap + aabonuses.IncreaseRunSpeedCap; + aa_mod += aabonuses.BaseMovementSpeed + aabonuses.movementspeed; int spell_mod = spellbonuses.movementspeed + itembonuses.movementspeed; int movemod = 0; From 8bcef6c2e72d8e7b25c2f8302e88029907a6515b Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 6 Feb 2020 01:08:53 -0500 Subject: [PATCH 2/7] Fix BodyType bug in GlobalLoot --- zone/loottables.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 3b5ae520f..500af9d70 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -518,7 +518,7 @@ void ZoneDatabase::LoadGlobalLoot() auto bodytypes = SplitString(row[9], '|'); for (auto &b : bodytypes) - e.AddRule(GlobalLoot::RuleTypes::Class, std::stoi(b)); + e.AddRule(GlobalLoot::RuleTypes::BodyType, std::stoi(b)); } zone->AddGlobalLootEntry(e); From 501204a4d2e843433d35956868c6b0cfb918879d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 6 Feb 2020 01:52:35 -0500 Subject: [PATCH 3/7] Add hot_zone filtering for global loot We do this in GlobalLootEntry::PassesRules since we want to check if the hot zone status changes during run time Value can be null, if null it's not checked. If the value is 0 the zone must not be a hot zone (I guess one might want that) and if it's not 0, the zone must be a hot zone --- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + utils/sql/git/required/2020_02_06_globalloot.sql | 2 ++ zone/global_loot_manager.cpp | 9 +++++++++ zone/global_loot_manager.h | 1 + zone/loottables.cpp | 7 ++++++- 6 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 utils/sql/git/required/2020_02_06_globalloot.sql diff --git a/common/version.h b/common/version.h index ca37150ec..13579c3d2 100644 --- a/common/version.h +++ b/common/version.h @@ -34,7 +34,7 @@ * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9148 +#define CURRENT_BINARY_DATABASE_VERSION 9149 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9026 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 8e3172b87..fdaa4a946 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -402,6 +402,7 @@ 9146|2020_01_10_character_soft_deletes.sql|SHOW COLUMNS FROM `character_data` LIKE 'deleted_at'|empty| 9147|2020_01_24_grid_centerpoint_wp.sql|SHOW COLUMNS FROM `grid_entries` LIKE 'centerpoint'|empty| 9148|2020_01_28_corpse_guild_consent_id.sql|SHOW COLUMNS FROM `character_corpses` LIKE 'guild_consent_id'|empty| +9149|2020_02_06_globalloot.sql|SHOW COLUMNS FROM `global_loot` LIKE 'hot_zone'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2020_02_06_globalloot.sql b/utils/sql/git/required/2020_02_06_globalloot.sql new file mode 100644 index 000000000..83144bbb8 --- /dev/null +++ b/utils/sql/git/required/2020_02_06_globalloot.sql @@ -0,0 +1,2 @@ +ALTER TABLE `global_loot` ADD `hot_zone` TINYINT NULL; + diff --git a/zone/global_loot_manager.cpp b/zone/global_loot_manager.cpp index ccdf88840..706769f77 100644 --- a/zone/global_loot_manager.cpp +++ b/zone/global_loot_manager.cpp @@ -1,6 +1,9 @@ #include "global_loot_manager.h" #include "npc.h" #include "client.h" +#include "zone.h" + +extern Zone *zone; std::vector GlobalLootManager::GetGlobalLootTables(NPC *mob) const { @@ -78,6 +81,12 @@ bool GlobalLootEntry::PassesRules(NPC *mob) const if (mob->GetBodyType() == r.value) bPassesBodyType = true; break; + case GlobalLoot::RuleTypes::HotZone: // value == 0 must not be hot_zone, value != must be hot_zone + if (zone->IsHotzone() && !r.value) + return false; + if (!zone->IsHotzone() && r.value) + return false; + break; default: break; } diff --git a/zone/global_loot_manager.h b/zone/global_loot_manager.h index fec5a7215..1de6e7831 100644 --- a/zone/global_loot_manager.h +++ b/zone/global_loot_manager.h @@ -17,6 +17,7 @@ enum class RuleTypes { BodyType = 4, Rare = 5, Raid = 6, + HotZone = 7, Max }; diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 500af9d70..794883c1f 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -464,7 +464,7 @@ void NPC::CheckGlobalLootTables() void ZoneDatabase::LoadGlobalLoot() { auto query = StringFormat("SELECT id, loottable_id, description, min_level, max_level, rare, raid, race, " - "class, bodytype, zone FROM global_loot WHERE enabled = 1"); + "class, bodytype, zone, hot_zone FROM global_loot WHERE enabled = 1"); auto results = QueryDatabase(query); if (!results.Success() || results.RowCount() == 0) @@ -482,6 +482,7 @@ void ZoneDatabase::LoadGlobalLoot() continue; } + GlobalLootEntry e(atoi(row[0]), atoi(row[1]), row[2] ? row[2] : ""); auto min_level = atoi(row[3]); @@ -521,6 +522,10 @@ void ZoneDatabase::LoadGlobalLoot() e.AddRule(GlobalLoot::RuleTypes::BodyType, std::stoi(b)); } + // null is not used + if (row[11]) + e.AddRule(GlobalLoot::RuleTypes::HotZone, atoi(row[11])); + zone->AddGlobalLootEntry(e); } } From 16ac6f624bcec91f8e3aeb2e75c2f7a60305f5b3 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 6 Feb 2020 01:59:18 -0500 Subject: [PATCH 4/7] Remove extra whitespace --- zone/loottables.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 794883c1f..0e5ba8d60 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -482,7 +482,6 @@ void ZoneDatabase::LoadGlobalLoot() continue; } - GlobalLootEntry e(atoi(row[0]), atoi(row[1]), row[2] ? row[2] : ""); auto min_level = atoi(row[3]); From 2f5909d4cbf5ee4f4f87cd781e9d1803dab8cf80 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 6 Feb 2020 14:20:18 -0500 Subject: [PATCH 5/7] Implement AA timers reset on death This is a field in the packet, live only uses this for Lay on Hands Currently I didn't add this to the packet since it has 0 effect on the client. We could move this field to aa_ranks which would give more flexibility for custom servers, but no one said they wanted it there. --- common/patches/rof2_structs.h | 2 +- common/patches/rof_structs.h | 2 +- common/patches/sod_structs.h | 2 +- common/patches/sof_structs.h | 2 +- common/patches/uf_structs.h | 2 +- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../required/2020_02_06_aa_reset_on_death.sql | 2 ++ zone/aa.cpp | 23 +++++++++++++++++-- zone/aa_ability.h | 1 + zone/attack.cpp | 5 ++++ zone/client.h | 1 + 12 files changed, 37 insertions(+), 8 deletions(-) create mode 100644 utils/sql/git/required/2020_02_06_aa_reset_on_death.sql diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index cecafb767..10ce35654 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -4401,7 +4401,7 @@ struct SendAA_Struct { /*0104*/ uint32 special_category; /*0108*/ uint8 shroud; /*0109*/ uint8 unknown109; -/*0110*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter? +/*0110*/ uint8 reset_on_death; // timer is reset on death /*0111*/ uint8 unknown111; /*0112*/ uint32 total_abilities; /*0116*/ AA_Ability abilities[0]; diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 7f466f09b..03f1a951a 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -4341,7 +4341,7 @@ struct SendAA_Struct { /*0104*/ uint32 special_category; /*0108*/ uint8 shroud; /*0109*/ uint8 unknown109; -/*0110*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter? +/*0110*/ uint8 reset_on_death; // timer is reset on death /*0111*/ uint8 unknown111; /*0112*/ uint32 total_abilities; /*0116*/ AA_Ability abilities[0]; diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 0803432db..76a534e6a 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -3780,7 +3780,7 @@ struct SendAA_Struct { /*0092*/ uint32 special_category; /*0096*/ uint8 shroud; /*0097*/ uint8 unknown97; -/*0098*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter? +/*0098*/ uint8 reset_on_death; // timer is reset on death /*0099*/ uint8 unknown99; /*0100*/ uint32 total_abilities; /*0104*/ AA_Ability abilities[0]; diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 0b175b643..1507630bd 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -3704,7 +3704,7 @@ struct SendAA_Struct { /*0088*/ uint32 aa_expansion; /*0092*/ uint32 special_category; /*0096*/ uint8 shroud; -/*0097*/ uint8 unknown97; +/*0097*/ uint8 reset_on_death; // timer is reset on death -- guess /*0098*/ uint32 total_abilities; /*0102*/ AA_Ability abilities[0]; }; diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index e165da794..b6eb414e1 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -3835,7 +3835,7 @@ struct SendAA_Struct { /*0092*/ uint32 special_category; /*0096*/ uint8 shroud; /*0097*/ uint8 unknown97; -/*0098*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter? +/*0098*/ uint8 reset_on_death; // timer is reset on death /*0099*/ uint8 unknown99; /*0100*/ uint32 total_abilities; /*0104*/ AA_Ability abilities[0]; diff --git a/common/version.h b/common/version.h index 13579c3d2..a950edbe0 100644 --- a/common/version.h +++ b/common/version.h @@ -34,7 +34,7 @@ * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9149 +#define CURRENT_BINARY_DATABASE_VERSION 9150 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9026 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index fdaa4a946..9d0aa9231 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -403,6 +403,7 @@ 9147|2020_01_24_grid_centerpoint_wp.sql|SHOW COLUMNS FROM `grid_entries` LIKE 'centerpoint'|empty| 9148|2020_01_28_corpse_guild_consent_id.sql|SHOW COLUMNS FROM `character_corpses` LIKE 'guild_consent_id'|empty| 9149|2020_02_06_globalloot.sql|SHOW COLUMNS FROM `global_loot` LIKE 'hot_zone'|empty| +9150|2020_02_06_aa_reset_on_death.sql|SHOW COLUMNS FROM `aa_ability` LIKE 'reset_on_death'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2020_02_06_aa_reset_on_death.sql b/utils/sql/git/required/2020_02_06_aa_reset_on_death.sql new file mode 100644 index 000000000..91edb5d4a --- /dev/null +++ b/utils/sql/git/required/2020_02_06_aa_reset_on_death.sql @@ -0,0 +1,2 @@ +ALTER TABLE `aa_ability` ADD `reset_on_death` TINYINT(4) NOT NULL DEFAULT '0'; +UPDATE `aa_ability` SET `reset_on_death` = '1' WHERE `id` = 6001; diff --git a/zone/aa.cpp b/zone/aa.cpp index 1383ad2f9..1ccc6f656 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1023,6 +1023,24 @@ void Client::ResetAlternateAdvancementTimers() { safe_delete(outapp); } +void Client::ResetOnDeathAlternateAdvancement() { + for (const auto &aa : aa_ranks) { + auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(aa.first, aa.second.first); + auto ability = ability_rank.first; + auto rank = ability_rank.second; + + if (!ability) + continue; + + if (!rank) + continue; + + // since they're dying, we just need to clear the DB + if (ability->reset_on_death) + p_timers.Clear(&database, rank->spell_type + pTimerAAStart); + } +} + void Client::PurchaseAlternateAdvancementRank(int rank_id) { AA::Rank *rank = zone->GetAlternateAdvancementRank(rank_id); if(!rank) { @@ -1646,7 +1664,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_maptype = atoi(row[8]); ability->charges = atoi(row[9]); ability->grant_only = atoi(row[10]) != 0 ? true : false; - ability->first_rank_id = atoi(row[11]); + ability->reset_on_death = atoi(row[11]) != 0 ? true : false; + ability->first_rank_id = atoi(row[12]); ability->first = nullptr; abilities[ability->id] = std::unique_ptr(ability); diff --git a/zone/aa_ability.h b/zone/aa_ability.h index 0d6a240c4..5ec08d986 100644 --- a/zone/aa_ability.h +++ b/zone/aa_ability.h @@ -50,6 +50,7 @@ public: int drakkin_heritage; int status; bool grant_only; + bool reset_on_death; int type; int charges; int first_rank_id; diff --git a/zone/attack.cpp b/zone/attack.cpp index 083176e39..bd169908c 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1852,6 +1852,11 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQEmu::skills::Sk BuffFadeDetrimental(); } + /* + Reset AA reuse timers that need to be, live-like this is only Lay on Hands + */ + ResetOnDeathAlternateAdvancement(); + /* Finally, send em home diff --git a/zone/client.h b/zone/client.h index a0655584b..030484229 100644 --- a/zone/client.h +++ b/zone/client.h @@ -838,6 +838,7 @@ public: void SendAlternateAdvancementTimers(); void ResetAlternateAdvancementTimer(int ability); void ResetAlternateAdvancementTimers(); + void ResetOnDeathAlternateAdvancement(); void SetAAPoints(uint32 points) { m_pp.aapoints = points; SendAlternateAdvancementStats(); } void AddAAPoints(uint32 points) { m_pp.aapoints += points; SendAlternateAdvancementStats(); } From 29fccd923924638613be36fb269e1672970dfe37 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 6 Feb 2020 16:44:46 -0500 Subject: [PATCH 6/7] LoH skill needs to be reset on death --- zone/attack.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/zone/attack.cpp b/zone/attack.cpp index bd169908c..4da160608 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1857,6 +1857,12 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQEmu::skills::Sk */ ResetOnDeathAlternateAdvancement(); + /* + Reset reuse timer for classic skill based Lay on Hands (For tit I guess) + */ + if (GetClass() == PALADIN) // we could check if it's not expired I guess, but should be fine not to + p_timers.Clear(&database, pTimerLayHands); + /* Finally, send em home From 5f8d193d6a68eb5e7e0fb45451d2ec0125264a24 Mon Sep 17 00:00:00 2001 From: Xackery Xtal Date: Sat, 8 Feb 2020 18:01:46 -0800 Subject: [PATCH 7/7] Added EnableFoodRequirement --- common/ruletypes.h | 1 + zone/client.h | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index 8e5793bc3..4284e0d0b 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -121,6 +121,7 @@ RULE_BOOL(Character, EnableAggroMeter, true, "Enable Aggro Meter, for users with RULE_BOOL(Character, KeepLevelOverMax, false, "Don't delevel a character that has somehow gone over the level cap") RULE_INT(Character, FoodLossPerUpdate, 32, "How much food/water you lose per stamina update") RULE_BOOL(Character, EnableHungerPenalties, false, "being hungry/thirsty has negative effects -- it does appear normal live servers do not have penalties") +RULE_BOOL(Character, EnableFoodRequirement, true, "if disabled, food is no longer required") RULE_INT(Character, BaseInstrumentSoftCap, 36, "Softcap for instrument mods, 36 commonly referred to as \"3.6\" as well") RULE_BOOL(Character, UseSpellFileSongCap, true, "When they removed the AA that increased the cap they removed the above and just use the spell field") RULE_INT(Character, BaseRunSpeedCap, 158, "Base Run Speed Cap, on live it's 158% which will give you a runspeed of 1.580 hard capped to 225") diff --git a/zone/client.h b/zone/client.h index 030484229..52af842be 100644 --- a/zone/client.h +++ b/zone/client.h @@ -901,14 +901,14 @@ public: void BreakFeignDeathWhenCastOn(bool IsResisted); void LeaveGroup(); - bool Hungry() const {if (GetGM()) return false; return m_pp.hunger_level <= 3000;} - bool Thirsty() const {if (GetGM()) return false; return m_pp.thirst_level <= 3000;} + bool Hungry() const {if (GetGM() || !RuleB(Character, EnableFoodRequirement)) return false; return m_pp.hunger_level <= 3000;} + bool Thirsty() const {if (GetGM() || !RuleB(Character, EnableFoodRequirement)) return false; return m_pp.thirst_level <= 3000;} int32 GetHunger() const { return m_pp.hunger_level; } int32 GetThirst() const { return m_pp.thirst_level; } void SetHunger(int32 in_hunger); void SetThirst(int32 in_thirst); void SetConsumption(int32 in_hunger, int32 in_thirst); - bool IsStarved() const { if (GetGM() || !RuleB(Character, EnableHungerPenalties)) return false; return m_pp.hunger_level == 0 || m_pp.thirst_level == 0; } + bool IsStarved() const { if (GetGM() || !RuleB(Character, EnableFoodRequirement) || !RuleB(Character, EnableHungerPenalties)) return false; return m_pp.hunger_level == 0 || m_pp.thirst_level == 0; } bool CheckTradeLoreConflict(Client* other); bool CheckTradeNonDroppable();