Add Heal function for monsters. Make player stat functions const return. Add Missing Health bonus stat from buffs. Refactor names of stat functions to be more explicit. Add more stat buff and pct buff checks. Fix up discrepancies with how stat up buffs work for the player. 53/53 passing tests.
//This gear is supposed to be provide an additional 100% defense, 100% Attack, 100% Move Spd, 100% CDR, 100% Crit Rate, 100% Crit Dmg, 100% Health %, 100% HP/6 Recovery
Assert::AreEqual(100.f+player->GetBaseStat("Defense %"),player->GetStat("Defense %"),L"Defense % stat was not increased by 100%.");
Assert::AreEqual(100.f+player->GetBaseStat("Attack %"),player->GetStat("Attack %"),L"Attack % stat was not increased by 100%.");
Assert::AreEqual(100.f+player->GetBaseStat("Move Spd %"),player->GetStat("Move Spd %"),L"Move Spd % stat was not increased by 100%.");
Assert::AreEqual(100.f+player->GetBaseStat("CDR"),player->GetStat("CDR"),L"CDR stat was not increased by 100%.");
Assert::AreEqual(100.f+player->GetBaseStat("Crit Rate"),player->GetStat("Crit Rate"),L"Crit Rate % stat was not increased by 100%.");
Assert::AreEqual(100.f+player->GetBaseStat("Crit Dmg"),player->GetStat("Crit Dmg"),L"Critical Damage stat was not increased by 100%.");
Assert::AreEqual(100.f+player->GetBaseStat("Health %"),player->GetStat("Health %"),L"Health Points was not increased by 100%.");
Assert::AreEqual(100.f+player->GetBaseStat("HP6 Recovery %"),player->GetStat("HP6 Recovery %"),L"HP/6s Recovery stat was not increased by 100%.");
Assert::AreEqual(100.f+player->GetBaseStat("Defense %"),player->GetEquipStat("Defense %"),L"Defense % stat was not increased by 100%.");
Assert::AreEqual(100.f+player->GetBaseStat("Attack %"),player->GetEquipStat("Attack %"),L"Attack % stat was not increased by 100%.");
Assert::AreEqual(100.f+player->GetBaseStat("Move Spd %"),player->GetEquipStat("Move Spd %"),L"Move Spd % stat was not increased by 100%.");
Assert::AreEqual(100.f+player->GetBaseStat("CDR"),player->GetEquipStat("CDR"),L"CDR stat was not increased by 100%.");
Assert::AreEqual(100.f+player->GetBaseStat("Crit Rate"),player->GetEquipStat("Crit Rate"),L"Crit Rate % stat was not increased by 100%.");
Assert::AreEqual(100.f+player->GetBaseStat("Crit Dmg"),player->GetEquipStat("Crit Dmg"),L"Critical Damage stat was not increased by 100%.");
Assert::AreEqual(100.f+player->GetBaseStat("Health %"),player->GetEquipStat("Health %"),L"Health Points was not increased by 100%.");
Assert::AreEqual(100.f+player->GetBaseStat("HP6 Recovery %"),player->GetEquipStat("HP6 Recovery %"),L"HP/6s Recovery stat was not increased by 100%.");
//This gear is supposed to be provide an additional 100% HP/4 Recovery, 100% Damage Reduction
Assert::AreEqual(100.f+player->GetBaseStat("HP4 Recovery %"),player->GetStat("HP4 Recovery %"),L"HP/4s Recovery stat was not increased by 100%.");
Assert::AreEqual(100.f+player->GetBaseStat("Damage Reduction"),player->GetStat("Damage Reduction"),L"Damage Reduction stat was not increased by 100%.");
Assert::AreEqual(100.f+player->GetBaseStat("HP4 Recovery %"),player->GetEquipStat("HP4 Recovery %"),L"HP/4s Recovery stat was not increased by 100%.");
Assert::AreEqual(100.f+player->GetBaseStat("Damage Reduction"),player->GetEquipStat("Damage Reduction"),L"Damage Reduction stat was not increased by 100%.");
Assert::AreEqual(5+player->GetBaseStat("Crit Rate"),player->GetStat("Crit Rate"),L"Crit Rate does not increase by 5% with 2 Bone Equips (Set Bonus)");
Assert::AreEqual(player->GetBaseStat("Crit Dmg"),player->GetStat("Crit Dmg"),L"Crit Dmg does not remain the same with 2 Bone Equips (Set Bonus)");
Assert::AreEqual(5+player->GetBaseStat("Crit Rate"),player->GetEquipStat("Crit Rate"),L"Crit Rate does not increase by 5% with 2 Bone Equips (Set Bonus)");
Assert::AreEqual(player->GetBaseStat("Crit Dmg"),player->GetEquipStat("Crit Dmg"),L"Crit Dmg does not remain the same with 2 Bone Equips (Set Bonus)");
Inventory::UnequipItem(EquipSlot::ARMOR);
Assert::AreEqual(player->GetBaseStat("Crit Rate"),player->GetStat("Crit Rate"),L"Removing an armor piece does not remove the crit rate set effect");
Assert::AreEqual(player->GetBaseStat("Crit Dmg"),player->GetStat("Crit Dmg"),L"Removing an armor piece affects crit dmg incorrectly");
Assert::AreEqual(player->GetBaseStat("Crit Rate"),player->GetEquipStat("Crit Rate"),L"Removing an armor piece does not remove the crit rate set effect");
Assert::AreEqual(player->GetBaseStat("Crit Dmg"),player->GetEquipStat("Crit Dmg"),L"Removing an armor piece affects crit dmg incorrectly");
Assert::AreEqual(5+player->GetBaseStat("Crit Rate"),player->GetStat("Crit Rate"),L"Crit Rate does not increase by 5% with 4 Bone Equips (Set Bonus)");
Assert::AreEqual(7+player->GetBaseStat("Crit Dmg"),player->GetStat("Crit Dmg"),L"Crit Dmg does not increase by 5% with 4 Bone Equips (Set Bonus)");
Assert::AreEqual(5+player->GetBaseStat("Crit Rate"),player->GetEquipStat("Crit Rate"),L"Crit Rate does not increase by 5% with 4 Bone Equips (Set Bonus)");
Assert::AreEqual(7+player->GetBaseStat("Crit Dmg"),player->GetEquipStat("Crit Dmg"),L"Crit Dmg does not increase by 5% with 4 Bone Equips (Set Bonus)");
testRing2.lock()->RandomStats().A_Read("Mana")<=ITEM_DATA.at("Bird's Treasure"s).GetMaxStats().A_Read("Mana"),std::format(L"Generated Mana {} is out of bounds: Min:{} Max:{}",testRing2.lock()->RandomStats().A_Read("Mana"),ITEM_DATA.at("Bird's Treasure"s).GetMinStats().A_Read("Mana"),ITEM_DATA.at("Bird's Treasure"s).GetMaxStats().A_Read("Mana")).c_str());
//Ensure stats are default.
Assert::AreEqual(player->GetBaseStat("Move Spd %"),player->GetStat("Move Spd %"),L"Base Move Spd %does not match initial Move Spd %");
Assert::AreEqual(player->GetBaseStat("Crit Rate"),player->GetStat("Crit Rate"),L"Base Crit Rate does not match initial Crit Rate");
Assert::AreEqual(player->GetBaseStat("Mana"),player->GetStat("Mana"),L"Base Mana does not match initial Mana");
Assert::AreEqual(player->GetBaseStat("Move Spd %"),player->GetEquipStat("Move Spd %"),L"Base Move Spd %does not match initial Move Spd %");
Assert::AreEqual(player->GetBaseStat("Crit Rate"),player->GetEquipStat("Crit Rate"),L"Base Crit Rate does not match initial Crit Rate");
Assert::AreEqual(player->GetBaseStat("Mana"),player->GetEquipStat("Mana"),L"Base Mana does not match initial Mana");
Inventory::EquipItem(testRing,EquipSlot::RING1);
Assert::AreEqual(3+player->GetBaseStat("Move Spd %"),player->GetStat("Move Spd %"),L"Move Spd % increased incorrectly when ring 1 equipped!");
Assert::AreEqual(2+player->GetBaseStat("Crit Rate"),player->GetStat("Crit Rate"),L"Crit Rate increased incorrectly when ring 1 equipped!");
Assert::AreEqual(5+player->GetBaseStat("Mana"),player->GetStat("Mana"),L"Mana increased incorrectly when ring 1 equipped!");
Assert::AreEqual(3+player->GetBaseStat("Move Spd %"),player->GetEquipStat("Move Spd %"),L"Move Spd % increased incorrectly when ring 1 equipped!");
Assert::AreEqual(2+player->GetBaseStat("Crit Rate"),player->GetEquipStat("Crit Rate"),L"Crit Rate increased incorrectly when ring 1 equipped!");
Assert::AreEqual(5+player->GetBaseStat("Mana"),player->GetEquipStat("Mana"),L"Mana increased incorrectly when ring 1 equipped!");
//Equipping to same slot should undo the previous stats and apply the new ring's stats.
Inventory::EquipItem(testRing2,EquipSlot::RING1);
Assert::AreEqual(2+player->GetBaseStat("Move Spd %"),player->GetStat("Move Spd %"),L"Move Spd % increased incorrectly when ring 1 equipped!");
Assert::AreEqual(2+player->GetBaseStat("Crit Rate"),player->GetStat("Crit Rate"),L"Crit Rate increased incorrectly when ring 1 equipped!");
Assert::AreEqual(2+player->GetBaseStat("Mana"),player->GetStat("Mana"),L"Mana increased incorrectly when ring 1 equipped!");
Assert::AreEqual(2+player->GetBaseStat("Move Spd %"),player->GetEquipStat("Move Spd %"),L"Move Spd % increased incorrectly when ring 1 equipped!");
Assert::AreEqual(2+player->GetBaseStat("Crit Rate"),player->GetEquipStat("Crit Rate"),L"Crit Rate increased incorrectly when ring 1 equipped!");
Assert::AreEqual(2+player->GetBaseStat("Mana"),player->GetEquipStat("Mana"),L"Mana increased incorrectly when ring 1 equipped!");
Inventory::UnequipItem(EquipSlot::RING1);
//Ensure stats are default again.
Assert::AreEqual(player->GetBaseStat("Move Spd %"),player->GetStat("Move Spd %"),L"Base Move Spd %does not match initial Move Spd % after unequipping the ring.");
Assert::AreEqual(player->GetBaseStat("Crit Rate"),player->GetStat("Crit Rate"),L"Base Crit Rate does not match initial Crit Rate after unequipping the ring.");
Assert::AreEqual(player->GetBaseStat("Mana"),player->GetStat("Mana"),L"Base Mana does not match initial Mana after unequipping the ring.");
Assert::AreEqual(player->GetBaseStat("Move Spd %"),player->GetEquipStat("Move Spd %"),L"Base Move Spd %does not match initial Move Spd % after unequipping the ring.");
Assert::AreEqual(player->GetBaseStat("Crit Rate"),player->GetEquipStat("Crit Rate"),L"Base Crit Rate does not match initial Crit Rate after unequipping the ring.");
Assert::AreEqual(player->GetBaseStat("Mana"),player->GetEquipStat("Mana"),L"Base Mana does not match initial Mana after unequipping the ring.");
Inventory::EquipItem(testRing,EquipSlot::RING1);
Inventory::EquipItem(testRing2,EquipSlot::RING2);
Assert::AreEqual(5+player->GetBaseStat("Move Spd %"),player->GetStat("Move Spd %"),L"Move Spd % increased incorrectly when both rings equipped!");
Assert::AreEqual(4+player->GetBaseStat("Crit Rate"),player->GetStat("Crit Rate"),L"Crit Rate increased incorrectly when both rings equipped!");
Assert::AreEqual(7+player->GetBaseStat("Mana"),player->GetStat("Mana"),L"Mana increased incorrectly when both rings equipped!");
Assert::AreEqual(5+player->GetBaseStat("Move Spd %"),player->GetEquipStat("Move Spd %"),L"Move Spd % increased incorrectly when both rings equipped!");
Assert::AreEqual(4+player->GetBaseStat("Crit Rate"),player->GetEquipStat("Crit Rate"),L"Crit Rate increased incorrectly when both rings equipped!");
Assert::AreEqual(7+player->GetBaseStat("Mana"),player->GetEquipStat("Mana"),L"Mana increased incorrectly when both rings equipped!");
Assert::AreEqual(enhancedDamageDealt,damageDealt*5,L"Original damage dealt should be half of the new attack. Factor in 100% crit rate and a bonus 100% crit dmg (making it 250%) 200%*2.5=500% damage.");
//NOTE: Marking a monster for deletion does not trigger any death events. It just simply removes the monster from the field!!
// The way this works is that monsters marked for deletion will cause the monster update loop to detect there's at least one or more monsters that must be deleted and will call erase_if on the list at the end of the iteration loop.
if(ItemAttribute::Get(stat).DisplayAsPercent())ERR(std::format("WARNING! Stat {} was provided. A percentage-based stat should not be supplied here! GetModdedStatBonuses() is supposed to calculate using a BASE stat and includes the percentage modifier already! Please fix this!",stat))