Migrated PlayerTests. Release Build 13532.
All checks were successful
Emscripten Build / Build_and_Deploy_Web_Build (push) Successful in 11m59s
Emscripten Build / UnitTesting (push) Successful in 9m7s

This commit is contained in:
AMay 2026-05-04 15:39:18 -05:00
parent 30c65071f9
commit b31bae86ba
6 changed files with 876 additions and 12 deletions

View File

@ -1113,7 +1113,12 @@
<ClCompile Include="tests\ItemTests.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Desktop|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="tests\MonsterTests.cpp" />
<ClCompile Include="tests\MonsterTests.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Desktop|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="tests\PlayerTests.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Desktop|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="ThunderOrb.cpp" />
<ClCompile Include="TileGroup.cpp" />
<ClCompile Include="Menu.cpp" />

View File

@ -1418,6 +1418,9 @@
<ClCompile Include="tests\MonsterTests.cpp">
<Filter>Source Files\Unit Tests</Filter>
</ClCompile>
<ClCompile Include="tests\PlayerTests.cpp">
<Filter>Source Files\Unit Tests</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="cpp.hint" />

View File

@ -167,10 +167,6 @@ public:
const std::vector<std::pair<int,Stats>>&GetSetBonusBreakpoints()const;
};
namespace PlayerTests{
class PlayerTest;
};
using IncreaseAmount=int;
using RefineResult=std::pair<ItemAttribute,IncreaseAmount>;
@ -181,7 +177,6 @@ class Item{
friend class SaveFile;
friend void Merchant::PurchaseItem(IT item,uint32_t amt);
friend void Merchant::SellItem(std::weak_ptr<Item>,uint32_t amt);
friend class PlayerTests::PlayerTest;
public:
static const std::string BLANK_ITEM_NAME;
Item();

View File

@ -151,10 +151,6 @@ public:
static uint64_t ingameControlsHandle;
};
namespace PlayerTests{
class PlayerTest;
}
class InputGroup{
friend class AiL;
friend class Menu;
@ -162,7 +158,6 @@ class InputGroup{
friend class InputListener;
friend class SaveFile;
friend class State_MainMenu;
friend class PlayerTests::PlayerTest;
std::set<Input>keys;
std::vector<Input>keyOrder; //A list of keys inserted in order, for primary key mapping.
static safemap<std::string,InputGroup*>menuNamesToInputGroups;

View File

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 1
#define VERSION_MINOR 3
#define VERSION_PATCH 0
#define VERSION_BUILD 13526
#define VERSION_BUILD 13532
#define stringify(a) stringify_(a)
#define stringify_(a) #a

View File

@ -0,0 +1,866 @@
#pragma region License
/*
License (OLC-3)
~~~~~~~~~~~~~~~
Copyright 2026 Amy Sigona <sigonasr2@gmail.com>
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions or derivations of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions or derivative works in binary form must reproduce the above
copyright notice. This list of conditions and the following disclaimer must be
reproduced in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may
be used to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
Portions of this software are copyright © 2024 The FreeType
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
All rights reserved.
*/
#pragma endregion
#include "AdventuresInLestoria.h"
#include "Tutorial.h"
#include <random>
#include <format>
#include "ItemDrop.h"
#include "DamageNumber.h"
#include <ranges>
#include "GameHelper.h"
#include"SoundEffect.h"
using namespace olc::utils;
INCLUDE_GFX
INCLUDE_ITEM_DATA
INCLUDE_DAMAGENUMBER_LIST
INCLUDE_INITIALIZEGAMECONFIGURATIONS
extern std::mt19937 rng;
class PlayerTests{
public:
std::unique_ptr<AiL>testGame;
InputGroup testKeyboardInput;
Player*player;
HWButton*testKey;
PlayerTests(){
InitializeGameConfigurations();
rng=std::mt19937{57189U};//Establish a fixed random seed on setup so the exact same results are generated every test run.
testGame.reset(new AiL(true));
ItemAttribute::Initialize();
ItemInfo::InitializeItems();
testGame->InitializeGraphics();
testGame->InitializeClasses();
sig::Animation::InitializeAnimations();
testGame->InitializeDefaultKeybinds();
testGame->InitializePlayer();
sig::Animation::SetupPlayerAnimations();
Menu::InitializeMenus();
Tutorial::Initialize();
Stats::InitializeDamageReductionTable();
SoundEffect::Initialize();
GameState::Initialize();
GameState::STATE=GameState::states.at(States::State::GAME_RUN);
#pragma region Setup a fake test map and test monster
game->MAP_DATA.Unlock();
game->MAP_DATA["CAMPAIGN_1_1"];
ItemDrop::ClearDrops();
MonsterData testMonsterData{"TestName","Test Monster",1000,10,5,{MonsterDropData{"Health Potion",100.f,1,1}},200.f};
MONSTER_DATA["TestName"]=testMonsterData;
#pragma endregion
testGame->ResetLevelStates();
player=testGame->GetPlayer();
//Setup key "0" as a test input
testKeyboardInput.AddKeybind(Input{InputType::KEY,0});
testKey=testGame->GetKeyboardState(0);
testGame->olc_UpdateKeyFocus(true); //Force the game to be "focused" for tests. Required if we want keyboard inputs to work.
Menu::themes.SetInitialized();
GFX.SetInitialized();
DAMAGENUMBER_LIST.clear();
game->MAP_DATA.SetInitialized();
}
~PlayerTests(){
testGame->EndGame();
testGame->OnUserUpdate(0.f);
testGame.reset();
}
};
TEST(PlayerTests,"PlayerAlive"){
REQUIRE(player->IsAlive());
}
TEST(PlayerTests,"PlayerTakesDamageAndNoDamageFlagWorks"){
player->Hurt(30,player->OnUpperLevel(),player->GetZ());
REQUIRE(70==player->GetHealth());
REQUIRE(size_t(1)==DAMAGENUMBER_LIST.size());
Game::Update(0.1f); //Prevent stacking up damage all on one damage number.
player->Hurt(0,player->OnUpperLevel(),player->GetZ());
REQUIRE(size_t(2)==DAMAGENUMBER_LIST.size());
Game::Update(0.1f); //Prevent stacking up damage all on one damage number.
player->Hurt(0,player->OnUpperLevel(),player->GetZ(),HurtFlag::NO_DAMAGE_NUMBER);
REQUIRE(size_t(2)==DAMAGENUMBER_LIST.size());
}
TEST(PlayerTests,"PlayerTakesDamageSoundEffectsWork"){
player->Hurt(30,player->OnUpperLevel(),player->GetZ());
REQUIRE(1==SoundEffect::soundsPlayedLog["Player Hit"]);
Game::Update(0.1f); //Prevent stacking up damage all on one damage number.
player->Hurt(20,player->OnUpperLevel(),player->GetZ(),HurtFlag::NO_DAMAGE_NUMBER);
REQUIRE(1==SoundEffect::soundsPlayedLog["Player Hit"]);
Game::Update(0.1f); //Prevent stacking up damage all on one damage number.
player->Hurt(5,player->OnUpperLevel(),player->GetZ(),HurtFlag::DOT);
REQUIRE(1==SoundEffect::soundsPlayedLog["Player Hit"]);
}
TEST(PlayerTests,"PlayerBlockingTakesNoDamage"){
player->SetState(State::BLOCK);
player->Hurt(30,player->OnUpperLevel(),player->GetZ());
REQUIRE(100==player->GetHealth());
}
TEST(PlayerTests,"PlayerIframesPreventsDamage"){
player->ApplyIframes(0.5f);
player->Hurt(30,player->OnUpperLevel(),player->GetZ());
REQUIRE(100==player->GetHealth());
}
TEST(PlayerTests,"PlayerConsumesManaOnRightClickAbilityUse"){
int abilityManaCost{player->GetRightClickAbility().manaCost};
testKey->bHeld=true; //Force the key to be held down for testing purposes.
player->CheckAndPerformAbility(player->GetRightClickAbility(),testKeyboardInput);
REQUIRE(player->GetMaxMana()-abilityManaCost==player->GetMana());
}
TEST(PlayerTests,"PlayerConsumesManaOnAbility1Use"){
int abilityManaCost{player->GetAbility1().manaCost};
testKey->bHeld=true; //Force the key to be held down for testing purposes.
player->CheckAndPerformAbility(player->GetAbility1(),testKeyboardInput);
REQUIRE(player->GetMaxMana()-abilityManaCost==player->GetMana());
}
TEST(PlayerTests,"PlayerConsumesManaOnAbility2Use"){
int abilityManaCost{player->GetAbility2().manaCost};
testKey->bHeld=true; //Force the key to be held down for testing purposes.
player->CheckAndPerformAbility(player->GetAbility2(),testKeyboardInput);
REQUIRE(player->GetMaxMana()-abilityManaCost==player->GetMana());
}
TEST(PlayerTests,"PlayerConsumesManaOnAbility3Use"){
int abilityManaCost{player->GetAbility3().manaCost};
testKey->bHeld=true; //Force the key to be held down for testing purposes.
player->CheckAndPerformAbility(player->GetAbility3(),testKeyboardInput);
REQUIRE(player->GetMaxMana()-abilityManaCost==player->GetMana());
}
TEST(PlayerTests,"PlayerConsumesManaOnAbility4Use"){
int abilityManaCost{player->GetAbility4().manaCost};
testKey->bHeld=true; //Force the key to be held down for testing purposes.
player->CheckAndPerformAbility(player->GetAbility4(),testKeyboardInput);
REQUIRE(player->GetMaxMana()-abilityManaCost==player->GetMana());
}
TEST(PlayerTests,"WarriorBlockActivatesBlock"){
player->GetRightClickAbility().action(player,player->GetPos());
REQUIRE(int(State::BLOCK)==int(player->GetState()));
}
TEST(PlayerTests,"WizardCastDoesNotConsumeManaImmediately"){
testGame->ResetPlayerAndChangeClass(WIZARD);
player=testGame->GetPlayer(); //The player pointer has been reassigned...
//Ability 3 is Meteor, which is a cast. Mana should not be consumed for a spell that begins as a cast.
testKey->bHeld=true; //Force the key to be held down for testing purposes.
player->CheckAndPerformAbility(player->GetAbility3(),testKeyboardInput);
REQUIRE(player->GetMaxMana()==player->GetMana());
}
TEST(PlayerTests,"RangerCastDoesNotConsumeManaImmediately"){
testGame->ResetPlayerAndChangeClass(RANGER);
player=testGame->GetPlayer(); //The player pointer has been reassigned...
//Ability 2 is Charged Shot, which is a cast. Mana should not be consumed for a spell that begins as a cast.
testKey->bHeld=true; //Force the key to be held down for testing purposes.
player->CheckAndPerformAbility(player->GetAbility2(),testKeyboardInput);
REQUIRE(player->GetMaxMana()==player->GetMana());
}
TEST(PlayerTests,"PlayerTakesDamageWithDamageReductionApplied"){
std::weak_ptr<Item>testArmor{Inventory::AddItem("Bone Armor"s)};
testArmor.lock()->enhancementLevel="Item.Item Max Enhancement Level"_I; //Force enhance the item to the max enhancement level.
Inventory::EquipItem(testArmor,EquipSlot::ARMOR);
//If any of these values change, the armor piece may return a different value and these need to be updated for
//BONE ARMOR +10!
REQUIRE(72.f==testArmor.lock()->GetStats().A_Read("Defense"));
REQUIRE(14.f==testArmor.lock()->GetStats().A_Read("Health"));
REQUIRE(7.f==testArmor.lock()->GetStats().A_Read("Attack"));
player->Hurt(30,player->OnUpperLevel(),player->GetZ());
REQUIRE(74==player->GetHealth()); //Even though we are supposed to take 30 damage, damage reduction reduces it to 26 instead. (Random variance is controlled during testing. If this number changes at some point, either the damage formula or the item's stats have changed!)
}
TEST(PlayerTests,"PlayerSetEffectsAcknowledged"){
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor"s)};
setArmor.lock()->enhancementLevel="Item.Item Max Enhancement Level"_I; //Force enhance the item to the max enhancement level.
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
//This gear is supposed to be provide an additional 100 defense, 1000 health, and 100 attack.
REQUIRE(100.f+player->GetBaseStat("Defense")==player->GetEquipStat("Defense"));
REQUIRE(100.f+player->GetBaseStat("Attack")==player->GetEquipStat("Attack"));
REQUIRE(1000.f+player->GetBaseStat("Health")==player->GetEquipStat("Health"));
}
TEST(PlayerTests,"PlayerSetEffectsAcknowledged2"){
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor2"s)};
setArmor.lock()->enhancementLevel="Item.Item Max Enhancement Level"_I; //Force enhance the item to the max enhancement level.
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
//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
REQUIRE(100.f+player->GetBaseStat("Defense %")==player->GetEquipStat("Defense %"));
REQUIRE(100.f+player->GetBaseStat("Attack %")==player->GetEquipStat("Attack %"));
REQUIRE(100.f+player->GetBaseStat("Move Spd %")==player->GetEquipStat("Move Spd %"));
REQUIRE(100.f+player->GetBaseStat("CDR")==player->GetEquipStat("CDR"));
REQUIRE(100.f+player->GetBaseStat("Crit Rate")==player->GetEquipStat("Crit Rate"));
REQUIRE(100.f+player->GetBaseStat("Crit Dmg")==player->GetEquipStat("Crit Dmg"));
REQUIRE(100.f+player->GetBaseStat("Health %")==player->GetEquipStat("Health %"));
REQUIRE(100.f+player->GetBaseStat("HP6 Recovery %")==player->GetEquipStat("HP6 Recovery %"));
}
TEST(PlayerTests,"PlayerSetEffectsAcknowledged3"){
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor3"s)};
setArmor.lock()->enhancementLevel="Item.Item Max Enhancement Level"_I; //Force enhance the item to the max enhancement level.
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
//This gear is supposed to be provide an additional 100% HP/4 Recovery, 100% Damage Reduction
REQUIRE(100.f+player->GetBaseStat("HP4 Recovery %")==player->GetEquipStat("HP4 Recovery %"));
REQUIRE(100.f+player->GetBaseStat("Damage Reduction")==player->GetEquipStat("Damage Reduction"));
}
TEST(PlayerTests,"PlayerSetEffectsAcknowledged4"){
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor4"s)};
setArmor.lock()->enhancementLevel="Item.Item Max Enhancement Level"_I; //Force enhance the item to the max enhancement level.
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
//This gear is supposed to be provide an additional 100% HP/s Recovery, 50% Attack Spd, and 100 More Base Mana.
REQUIRE(100.f+player->GetBaseStat("HP Recovery %")==player->GetEquipStat("HP Recovery %"));
REQUIRE(50.f+player->GetBaseStat("Attack Spd")==player->GetEquipStat("Attack Spd"));
REQUIRE(100.f+player->GetBaseStat("Mana")==player->GetEquipStat("Mana"));
}
TEST(PlayerTests,"MultiPieceSetEffectsWork"){
std::weak_ptr<Item>testArmor{Inventory::AddItem("Bone Armor"s)};
std::weak_ptr<Item>testHeadpiece{Inventory::AddItem("Bone Helmet"s)};
std::weak_ptr<Item>testLeggings{Inventory::AddItem("Bone Pants"s)};
std::weak_ptr<Item>testGloves{Inventory::AddItem("Bone Gloves"s)};
REQUIRE(player->GetBaseStat("Crit Rate")==player->GetEquipStat("Crit Rate"));
REQUIRE(player->GetBaseStat("Crit Dmg")==player->GetEquipStat("Crit Dmg"));
Inventory::EquipItem(testArmor,EquipSlot::ARMOR);
Inventory::EquipItem(testHeadpiece,EquipSlot::HELMET);
REQUIRE(5+player->GetBaseStat("Crit Rate")==player->GetEquipStat("Crit Rate"));
REQUIRE(player->GetBaseStat("Crit Dmg")==player->GetEquipStat("Crit Dmg"));
Inventory::UnequipItem(EquipSlot::ARMOR);
REQUIRE(player->GetBaseStat("Crit Rate")==player->GetEquipStat("Crit Rate"));
REQUIRE(player->GetBaseStat("Crit Dmg")==player->GetEquipStat("Crit Dmg"));
Inventory::EquipItem(testArmor,EquipSlot::ARMOR);
Inventory::EquipItem(testLeggings,EquipSlot::PANTS);
Inventory::EquipItem(testGloves,EquipSlot::GLOVES);
REQUIRE(5+player->GetBaseStat("Crit Rate")==player->GetEquipStat("Crit Rate"));
REQUIRE(7+player->GetBaseStat("Crit Dmg")==player->GetEquipStat("Crit Dmg"));
}
TEST(PlayerTests,"AccessoriesWork"){
std::weak_ptr<Item>testRing{Inventory::AddItem("Bird's Treasure"s)};
std::weak_ptr<Item>testRing2{Inventory::AddItem("Bird's Treasure"s)};
REQUIRE(3.f==testRing.lock()->RandomStats().A_Read("Move Spd %"));
REQUIRE(2.f==testRing.lock()->RandomStats().A_Read("Crit Rate"));
REQUIRE(5.f==testRing.lock()->RandomStats().A_Read("Mana"));
REQUIRE(2.f==testRing2.lock()->RandomStats().A_Read("Move Spd %"));
REQUIRE(2.f==testRing2.lock()->RandomStats().A_Read("Crit Rate"));
REQUIRE(2.f==testRing2.lock()->RandomStats().A_Read("Mana"));
REQUIRE((testRing.lock()->RandomStats().A_Read("Move Spd %")>=ITEM_DATA.at("Bird's Treasure"s).GetMinStats().A_Read("Move Spd %")&&
testRing.lock()->RandomStats().A_Read("Move Spd %")<=ITEM_DATA.at("Bird's Treasure"s).GetMaxStats().A_Read("Move Spd %")));
REQUIRE((testRing.lock()->RandomStats().A_Read("Crit Rate")>=ITEM_DATA.at("Bird's Treasure"s).GetMinStats().A_Read("Crit Rate")&&
testRing.lock()->RandomStats().A_Read("Crit Rate")<=ITEM_DATA.at("Bird's Treasure"s).GetMaxStats().A_Read("Crit Rate")));
REQUIRE((testRing.lock()->RandomStats().A_Read("Mana")>=ITEM_DATA.at("Bird's Treasure"s).GetMinStats().A_Read("Mana")&&
testRing.lock()->RandomStats().A_Read("Mana")<=ITEM_DATA.at("Bird's Treasure"s).GetMaxStats().A_Read("Mana")));
REQUIRE((testRing2.lock()->RandomStats().A_Read("Move Spd %")>=ITEM_DATA.at("Bird's Treasure"s).GetMinStats().A_Read("Move Spd %")&&
testRing2.lock()->RandomStats().A_Read("Move Spd %")<=ITEM_DATA.at("Bird's Treasure"s).GetMaxStats().A_Read("Move Spd %")));
REQUIRE((testRing2.lock()->RandomStats().A_Read("Crit Rate")>=ITEM_DATA.at("Bird's Treasure"s).GetMinStats().A_Read("Crit Rate")&&
testRing2.lock()->RandomStats().A_Read("Crit Rate")<=ITEM_DATA.at("Bird's Treasure"s).GetMaxStats().A_Read("Crit Rate")));
REQUIRE((testRing2.lock()->RandomStats().A_Read("Mana")>=ITEM_DATA.at("Bird's Treasure"s).GetMinStats().A_Read("Mana")&&
testRing2.lock()->RandomStats().A_Read("Mana")<=ITEM_DATA.at("Bird's Treasure"s).GetMaxStats().A_Read("Mana")));
//Ensure stats are default.
REQUIRE(player->GetBaseStat("Move Spd %")==player->GetEquipStat("Move Spd %"));
REQUIRE(player->GetBaseStat("Crit Rate")==player->GetEquipStat("Crit Rate"));
REQUIRE(player->GetBaseStat("Mana")==player->GetEquipStat("Mana"));
Inventory::EquipItem(testRing,EquipSlot::RING1);
REQUIRE(3+player->GetBaseStat("Move Spd %")==player->GetEquipStat("Move Spd %"));
REQUIRE(2+player->GetBaseStat("Crit Rate")==player->GetEquipStat("Crit Rate"));
REQUIRE(5+player->GetBaseStat("Mana")==player->GetEquipStat("Mana"));
//Equipping to same slot should undo the previous stats and apply the new ring's stats.
Inventory::EquipItem(testRing2,EquipSlot::RING1);
REQUIRE(2+player->GetBaseStat("Move Spd %")==player->GetEquipStat("Move Spd %"));
REQUIRE(2+player->GetBaseStat("Crit Rate")==player->GetEquipStat("Crit Rate"));
REQUIRE(2+player->GetBaseStat("Mana")==player->GetEquipStat("Mana"));
Inventory::UnequipItem(EquipSlot::RING1);
//Ensure stats are default again.
REQUIRE(player->GetBaseStat("Move Spd %")==player->GetEquipStat("Move Spd %"));
REQUIRE(player->GetBaseStat("Crit Rate")==player->GetEquipStat("Crit Rate"));
REQUIRE(player->GetBaseStat("Mana")==player->GetEquipStat("Mana"));
Inventory::EquipItem(testRing,EquipSlot::RING1);
Inventory::EquipItem(testRing2,EquipSlot::RING2);
REQUIRE(5+player->GetBaseStat("Move Spd %")==player->GetEquipStat("Move Spd %"));
REQUIRE(4+player->GetBaseStat("Crit Rate")==player->GetEquipStat("Crit Rate"));
REQUIRE(7+player->GetBaseStat("Mana")==player->GetEquipStat("Mana"));
}
TEST(PlayerTests,"FlatDefenseStatEquipCheck"){
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor"s)};
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
player->Hurt(100,player->OnUpperLevel(),player->GetZ());
REQUIRE(17==player->GetHealth());
}
TEST(PlayerTests,"HealthStatEquipCheck"){
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor"s)};
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
REQUIRE(1000+player->GetBaseStat("Health")==float(player->GetMaxHealth()));
}
TEST(PlayerTests,"HealthStatUpBuffCheck"){
Game::AddBuffToPlayer(BuffType::STAT_UP,5.f,1000.f,{"Health"});
REQUIRE(1000+player->GetBaseStat("Health")==float(player->GetMaxHealth()));
}
TEST(PlayerTests,"HealthPctStatUpBuffCheck"){
Game::AddBuffToPlayer(BuffType::STAT_UP,5.f,1000.0_Pct,{"Health %"});
REQUIRE(1000+player->GetBaseStat("Health")==float(player->GetMaxHealth()));
}
TEST(PlayerTests,"IllegalCritRateStatUpBuffCheck"){
try{
player->AddBuff(BuffType::STAT_UP,5.f,1000.0_Pct,{"Crit Rate"});
FAIL("Adding a Crit Rate buff succeeded! This should NOT be allowed!");
}catch(std::exception&e){}
}
TEST(PlayerTests,"IllegalCritDmgStatUpBuffCheck"){
try{
player->AddBuff(BuffType::STAT_UP,5.f,1000.0_Pct,{"Crit Damage"});
FAIL("Adding a Crit Damage buff succeeded! This should NOT be allowed!");
}catch(std::exception&e){}
}
TEST(PlayerTests,"IllegalHPRecoveryPctStatUpBuffCheck"){
try{
player->AddBuff(BuffType::STAT_UP,5.f,1000.0_Pct,{"HP Recovery %"});
FAIL("Adding a HP Recovery % buff succeeded! This should NOT be allowed!");
}catch(std::exception&e){}
}
TEST(PlayerTests,"IllegalHP6RecoveryPctStatUpBuffCheck"){
try{
player->AddBuff(BuffType::STAT_UP,5.f,1000.0_Pct,{"HP6 Recovery %"});
FAIL("Adding a HP6 Recovery % buff succeeded! This should NOT be allowed!");
}catch(std::exception&e){}
}
TEST(PlayerTests,"IllegalHP4RecoveryPctStatUpBuffCheck"){
try{
player->AddBuff(BuffType::STAT_UP,5.f,1000.0_Pct,{"HP4 Recovery %"});
FAIL("Adding a HP4 Recovery % buff succeeded! This should NOT be allowed!");
}catch(std::exception&e){}
}
TEST(PlayerTests,"IllegalDamageReductionStatUpBuffCheck"){
try{
player->AddBuff(BuffType::STAT_UP,5.f,1000.0_Pct,{"Damage Reduction"});
FAIL("Adding a Damage Reduction buff succeeded! This should NOT be allowed!");
}catch(std::exception&e){}
}
TEST(PlayerTests,"IllegalAttackSpdStatUpBuffCheck"){
try{
player->AddBuff(BuffType::STAT_UP,5.f,1000.0_Pct,{"Attack Spd"});
FAIL("Adding a Attack Spd buff succeeded! This should NOT be allowed!");
}catch(std::exception&e){};
}
TEST(PlayerTests,"IllegalManaStatUpBuffCheck"){
try{
player->AddBuff(BuffType::STAT_UP,5.f,1000.0_Pct,{"Mana"});
FAIL("Adding a Mana buff succeeded! This should NOT be allowed!");
}catch(std::exception&e){}
}
TEST(PlayerTests,"AttackStatEquipCheck"){
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor"s)};
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
REQUIRE(100+player->GetBaseStat("Attack")==float(player->GetAttack()));
}
TEST(PlayerTests,"DefensePctStatEquipCheck"){
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor2"s)};
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
REQUIRE(player->GetBaseStat("Defense")==float(player->GetDefense()));
std::weak_ptr<Item>bonePants{Inventory::AddItem("Bone Pants"s)};
bonePants.lock()->enhancementLevel="Item.Item Max Enhancement Level"_I; //Force enhance the item to the max enhancement level.
Inventory::EquipItem(bonePants,EquipSlot::PANTS);
REQUIRE(122.f+player->GetBaseStat("Defense")==float(player->GetDefense()));
Inventory::UnequipItem(EquipSlot::ARMOR);
player->Hurt(100,player->OnUpperLevel(),player->GetZ());
REQUIRE(13==player->GetHealth());
player->Heal(87); //Back to 100 Health.
LOG(std::format("Player Health is now {}",player->GetHealth()));
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
player->Hurt(100,player->OnUpperLevel(),player->GetZ());
REQUIRE(36==player->GetHealth());
}
TEST(PlayerTests,"AttackPctStatEquipCheck"){
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor2"s)};
Monster testMonster{{},MONSTER_DATA["TestName"]};
testMonster.Hurt(player->GetAttack(),player->OnUpperLevel(),player->GetZ());
const int damageDealt{testMonster.GetMaxHealth()-testMonster.GetHealth()};
testMonster.Heal(testMonster.GetMaxHealth());
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
REQUIRE(player->GetBaseStat("Attack")*2==float(player->GetAttack()));
testMonster.Hurt(player->GetAttack(),player->OnUpperLevel(),player->GetZ());
const int enhancedDamageDealt{testMonster.GetMaxHealth()-testMonster.GetHealth()};
REQUIRE(enhancedDamageDealt==damageDealt*5);
}
TEST(PlayerTests,"MoveSpdPctStatEquipCheck"){
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor2"s)};
REQUIRE(1.f==player->GetMoveSpdMult());
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
REQUIRE(2.f==player->GetMoveSpdMult());
}
TEST(PlayerTests,"CDRStatEquipCheck"){
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor2"s)};
REQUIRE(0.f==player->GetCooldownReductionPct());
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
REQUIRE(1.f==player->GetCooldownReductionPct());
testKey->bHeld=true; //Force the key to be held down for testing purposes.
player->CheckAndPerformAbility(player->GetRightClickAbility(),testKeyboardInput);
player->CheckAndPerformAbility(player->GetAbility1(),testKeyboardInput);
player->CheckAndPerformAbility(player->GetAbility2(),testKeyboardInput);
player->CheckAndPerformAbility(player->GetAbility3(),testKeyboardInput);
player->CheckAndPerformAbility(player->GetAbility4(),testKeyboardInput);
Inventory::AddItem("Health Potion"s);
Inventory::AddItem("Berries"s);
Inventory::AddItem("Mana Potion"s);
game->SetLoadoutItem(0,"Health Potion");
game->SetLoadoutItem(1,"Berries");
game->SetLoadoutItem(2,"Mana Potion");
player->CheckAndPerformAbility(player->GetItem1(),testKeyboardInput);
player->CheckAndPerformAbility(player->GetItem2(),testKeyboardInput);
player->CheckAndPerformAbility(player->GetItem3(),testKeyboardInput);
game->SetElapsedTime(0.01f); //Force elapsed time value.
game->OnUserUpdate(0.01f); //Let 0.01 seconds go by. All abilities should be off cooldown.
REQUIRE(0.f==player->GetRightClickAbility().cooldown);
REQUIRE(0.f==player->GetAbility1().cooldown);
REQUIRE(0.f==player->GetAbility2().cooldown);
REQUIRE(0.f==player->GetAbility3().cooldown);
REQUIRE(0.f==player->GetAbility4().cooldown);
REQUIRE(0.f!=player->GetItem1().cooldown);
REQUIRE(0.f!=player->GetItem2().cooldown);
REQUIRE(0.f!=player->GetItem3().cooldown);
}
TEST(PlayerTests,"CritRateStatEquipCheck"){
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor2"s)};
REQUIRE(0.f==player->GetCritRatePct());
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
REQUIRE(1.f==player->GetCritRatePct());
}
TEST(PlayerTests,"CritDmgStatEquipCheck"){
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor2"s)};
REQUIRE(0.5f==player->GetCritDmgPct());
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
REQUIRE(1.5f==player->GetCritDmgPct());
}
TEST(PlayerTests,"HealthPctStatEquipCheck"){
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor2"s)};
REQUIRE(100==player->GetHealth());
REQUIRE(100==player->GetMaxHealth());
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
REQUIRE(100==player->GetHealth());
REQUIRE(200==player->GetMaxHealth());
}
TEST(PlayerTests,"HP6RecoveryStatEquipCheck"){
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor2"s)};
REQUIRE(0.0_Pct==player->GetHP6RecoveryPct());
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
REQUIRE(100.0_Pct==player->GetHP6RecoveryPct());
}
TEST(PlayerTests,"HP4RecoveryStatEquipCheck"){
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor3"s)};
REQUIRE(0.0_Pct==player->GetHP4RecoveryPct());
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
REQUIRE(100.0_Pct==player->GetHP4RecoveryPct());
}
TEST(PlayerTests,"DamageReductionStatEquipCheck"){
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor3"s)};
REQUIRE(0.0_Pct==player->GetDamageReductionFromBuffs());
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
REQUIRE(75.0_Pct==player->GetDamageReductionFromBuffs());
}
TEST(PlayerTests,"HPRecoveryStatEquipCheck"){
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor4"s)};
REQUIRE(0.0_Pct==player->GetHPRecoveryPct());
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
REQUIRE(100.0_Pct==player->GetHPRecoveryPct());
}
TEST(PlayerTests,"AttackSpeedStatEquipCheck"){
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor4"s)};
REQUIRE(0.f==player->GetAttackRecoveryRateReduction());
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
REQUIRE(50.f==player->GetAttackRecoveryRateReduction());
}
TEST(PlayerTests,"ManaStatEquipCheck"){
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor4"s)};
REQUIRE(100==player->GetMana());
REQUIRE(100==player->GetMaxMana());
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
REQUIRE(100==player->GetMana());
REQUIRE(200==player->GetMaxMana());
}
TEST(PlayerTests,"HP6RecoveryTest"){
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor2"s)};
game->SetElapsedTime(0.1f);
game->OnUserUpdate(0.1f); //Advance the game by 0.1s so that all healing ticks occur at least once.
//Hurt the player for most of their health.
player->Hurt(player->GetMaxHealth()-1,player->OnUpperLevel(),player->GetZ());
REQUIRE(1==player->GetHealth());
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
REQUIRE(100.0_Pct==player->GetHP6RecoveryPct());
game->SetElapsedTime(3.f);
game->OnUserUpdate(3.f); //Wait 3 seconds. The player shouldn't be healed yet.
REQUIRE(1==player->GetHealth());
game->SetElapsedTime(3.f);
game->OnUserUpdate(3.f); //Wait 3 more seconds. The player should be healed now.
REQUIRE(player->GetMaxHealth()==player->GetHealth());
}
TEST(PlayerTests,"HP4RecoveryTest"){
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor3"s)};
game->SetElapsedTime(0.1f);
game->OnUserUpdate(0.1f); //Advance the game by 0.1s so that all healing ticks occur at least once.
//Hurt the player for most of their health.
player->Hurt(player->GetMaxHealth()-1,player->OnUpperLevel(),player->GetZ());
REQUIRE(1==player->GetHealth());
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
REQUIRE(100.0_Pct==player->GetHP4RecoveryPct());
game->SetElapsedTime(2.f);
game->OnUserUpdate(2.f); //Wait 2 seconds. The player shouldn't be healed yet.
REQUIRE(1==player->GetHealth());
game->SetElapsedTime(2.f);
game->OnUserUpdate(2.f); //Wait 2 more seconds. The player should be healed now.
REQUIRE(player->GetMaxHealth()==player->GetHealth());
}
TEST(PlayerTests,"HPRecoveryTest"){
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor4"s)};
game->SetElapsedTime(0.1f);
game->OnUserUpdate(0.1f); //Advance the game by 0.1s so that all healing ticks occur at least once.
//Hurt the player for most of their health.
player->Hurt(player->GetMaxHealth()-1,player->OnUpperLevel(),player->GetZ());
REQUIRE(1==player->GetHealth());
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
REQUIRE(100.0_Pct==player->GetHPRecoveryPct());
game->SetElapsedTime(0.5f);
game->OnUserUpdate(0.5f); //Wait 0.5 seconds. The player shouldn't be healed yet.
REQUIRE(1==player->GetHealth());
game->SetElapsedTime(0.5f);
game->OnUserUpdate(0.5f); //Wait 0.5 more seconds. The player should be healed now.
REQUIRE(player->GetMaxHealth()==player->GetHealth());
}
TEST(PlayerTests,"AdrenalineRushSkillBuffTest"){
testGame->ResetPlayerAndChangeClass(THIEF);
player=testGame->GetPlayer(); //The player pointer has been reassigned...
REQUIRE(1.f==player->GetMoveSpdMult());
REQUIRE(0.f==player->GetAttackRecoveryRateReduction());
testKey->bHeld=true; //Force the key to be held down for testing purposes.
player->CheckAndPerformAbility(player->GetAbility3(),testKeyboardInput);
Game::Update(0.f);
REQUIRE(player->GetBuffs(BuffType::ADRENALINE_RUSH).size()>0);
REQUIRE(1.1f==player->GetMoveSpdMult());
REQUIRE(0.105f==player->GetAttackRecoveryRateReduction());
}
TEST(PlayerTests,"TrueDamageCheck"){
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor3"s)};
Inventory::EquipItem(setArmor,EquipSlot::ARMOR); //Equip an item with 100% damage reduction.
player->Hurt(20,player->OnUpperLevel(),player->GetZ(),TrueDamageFlag::IGNORE_DAMAGE_RULES);
REQUIRE(80==player->GetHealth());
player->ApplyIframes(0.5f);
player->Hurt(20,player->OnUpperLevel(),player->GetZ(),TrueDamageFlag::IGNORE_DAMAGE_RULES);
REQUIRE(60==player->GetHealth());
}
TEST(PlayerTests,"DOTDamageCheck"){
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor3"s)};
Inventory::EquipItem(setArmor,EquipSlot::ARMOR); //Equip an item with 100% damage reduction.
player->Hurt(20,player->OnUpperLevel(),player->GetZ(),HurtFlag::DOT);
REQUIRE(80==player->GetHealth());
REQUIRE(1==std::accumulate(DAMAGENUMBER_LIST.begin(),DAMAGENUMBER_LIST.end(),0,[](int count,const std::shared_ptr<DamageNumber>&damageNumber){
if(damageNumber->GetType()==DamageNumberType::DOT)return count+1;
else return count;
})
);
player->Update(1.0f);//Let some time pass so two DOT numbers don't stack up.
player->ApplyIframes(0.5f);
player->Hurt(20,player->OnUpperLevel(),player->GetZ(),HurtFlag::DOT);
REQUIRE(80==player->GetHealth());
REQUIRE(2==std::accumulate(DAMAGENUMBER_LIST.begin(),DAMAGENUMBER_LIST.end(),0,[](int count,const std::shared_ptr<DamageNumber>&damageNumber){
if(damageNumber->GetType()==DamageNumberType::DOT)return count+1;
else return count;
})
);
}
TEST(PlayerTests,"HasEnchantCheck"){
std::weak_ptr<Item>slimeKingRing{Inventory::AddItem("Ring of the Slime King"s)};
Inventory::EquipItem(slimeKingRing,EquipSlot::RING1);
slimeKingRing.lock()->_EnchantItem("Emergency Recovery"sv);
REQUIRE(player->HasEnchant("Emergency Recovery"));
Inventory::EquipItem(slimeKingRing,EquipSlot::RING2);
REQUIRE(player->HasEnchant("Emergency Recovery"));
Inventory::EquipItem(slimeKingRing,EquipSlot::RING1);
slimeKingRing.lock()->_EnchantItem("Reaper of Souls"sv);
REQUIRE(player->HasEnchant("Reaper of Souls"));
Inventory::EquipItem(slimeKingRing,EquipSlot::RING2);
REQUIRE(player->HasEnchant("Reaper of Souls"));
Inventory::EquipItem(slimeKingRing,EquipSlot::RING1);
slimeKingRing.lock()->_EnchantItem("Attack Boost"sv);
REQUIRE(player->HasEnchant("Attack Boost"));
Inventory::EquipItem(slimeKingRing,EquipSlot::RING2);
REQUIRE(player->HasEnchant("Attack Boost"));
std::weak_ptr<Item>leatherHelmet{Inventory::AddItem("Leather Helmet"s)};
std::weak_ptr<Item>leatherArmor{Inventory::AddItem("Leather Armor"s)};
std::weak_ptr<Item>leatherPants{Inventory::AddItem("Leather Pants"s)};
std::weak_ptr<Item>leatherGloves{Inventory::AddItem("Leather Gloves"s)};
std::weak_ptr<Item>leatherShoes{Inventory::AddItem("Leather Shoes"s)};
std::weak_ptr<Item>woodenSword{Inventory::AddItem("Wooden Sword"s)};
Inventory::EquipItem(leatherHelmet,EquipSlot::HELMET);
Inventory::EquipItem(leatherArmor,EquipSlot::ARMOR);
Inventory::EquipItem(leatherPants,EquipSlot::PANTS);
Inventory::EquipItem(leatherGloves,EquipSlot::GLOVES);
Inventory::EquipItem(leatherShoes,EquipSlot::SHOES);
Inventory::EquipItem(woodenSword,EquipSlot::WEAPON);
leatherHelmet.lock()->_EnchantItem("Wizard's Soul"sv);
REQUIRE(player->HasEnchant("Wizard's Soul"));
leatherArmor.lock()->_EnchantItem("Ability Haste"sv);
REQUIRE(player->HasEnchant("Ability Haste"));
leatherPants.lock()->_EnchantItem("Improved Ground Slam"sv);
REQUIRE(player->HasEnchant("Improved Ground Slam"));
leatherGloves.lock()->_EnchantItem("Battle Shout"sv);
REQUIRE(player->HasEnchant("Battle Shout"));
leatherShoes.lock()->_EnchantItem("Attack Boost"sv);
Inventory::UnequipItem(EquipSlot::RING2);
REQUIRE(player->HasEnchant("Attack Boost"));
woodenSword.lock()->_EnchantItem("Mana Pool"sv);
REQUIRE(player->HasEnchant("Mana Pool"));
Inventory::UnequipItem(EquipSlot::HELMET);
Inventory::UnequipItem(EquipSlot::ARMOR);
Inventory::UnequipItem(EquipSlot::PANTS);
Inventory::UnequipItem(EquipSlot::GLOVES);
Inventory::UnequipItem(EquipSlot::SHOES);
Inventory::UnequipItem(EquipSlot::WEAPON);
Inventory::UnequipItem(EquipSlot::RING1);
Inventory::UnequipItem(EquipSlot::RING2);
REQUIRE(!player->HasEnchant("Emergency Recovery"));
REQUIRE(!player->HasEnchant("Reaper of Souls"));
REQUIRE(!player->HasEnchant("Attack Boost"));
REQUIRE(!player->HasEnchant("Wizard's Soul"));
REQUIRE(!player->HasEnchant("Ability Haste"));
REQUIRE(!player->HasEnchant("Improved Ground Slam"));
REQUIRE(!player->HasEnchant("Battle Shout"));
REQUIRE(!player->HasEnchant("Attack Boost"));
REQUIRE(!player->HasEnchant("Mana Pool"));
}
TEST(PlayerTests,"AutoAttackReductionFunctionCheck"){
REQUIRE(0.f==player->GetAutoAttackTimer());
player->AutoAttack();
REQUIRE("Warrior.Auto Attack.Cooldown"_F==player->GetAutoAttackTimer());
player->ReduceAutoAttackTimer(0.2f);
REQUIRE("Warrior.Auto Attack.Cooldown"_F-0.2f==player->GetAutoAttackTimer());
}
TEST(PlayerTests,"CooldownChargesCheck"){
player->GetAbility4()=Ranger::ability1;
for(const std::reference_wrapper<Ability>&a:player->GetAbilities()){
if(a.get().name=="???")continue;
REQUIRE(uint8_t(1)==a.get().charges);
REQUIRE(0.f==a.get().cooldown);
testKey->bHeld=true; //Force the key to be held down for testing purposes.
player->CheckAndPerformAbility(a.get(),testKeyboardInput);
REQUIRE(uint8_t(0)==a.get().charges);
REQUIRE(a.get().COOLDOWN_TIME==a.get().cooldown);
player->RestoreMana(100);
player->SetState(State::NORMAL);
player->CheckAndPerformAbility(a.get(),testKeyboardInput);
a.get().MAX_CHARGES=5;
for(int i:std::ranges::iota_view(0,5)){
testGame->SetElapsedTime(a.get().COOLDOWN_TIME);
testGame->OnUserUpdate(a.get().COOLDOWN_TIME);
REQUIRE(uint8_t(i+1)==a.get().charges);
if(i!=4)REQUIRE(a.get().COOLDOWN_TIME==a.get().cooldown);
else REQUIRE(0.f==a.get().cooldown);
}
player->RestoreMana(100);
player->SetState(State::NORMAL);
}
}
TEST(PlayerTests,"ChargesEquipBehaviorCheck"){
testGame->ResetPlayerAndChangeClass(RANGER);
player=testGame->GetPlayer();
player->GetAbility3().charges=3;
testKey->bHeld=true; //Force the key to be held down for testing purposes.
testGame->SetElapsedTime(0.25f);
testGame->OnUserUpdate(0.25f);
REQUIRE(uint8_t(1)==player->GetAbility3().charges);
player->CheckAndPerformAbility(player->GetAbility3(),testKeyboardInput);
REQUIRE(uint8_t(0)==player->GetAbility3().charges);
}
TEST(PlayerTests,"CooldownEquipBehaviorCheck"){
testGame->ResetPlayerAndChangeClass(RANGER);
player=testGame->GetPlayer();
float oldCooldownTime{player->GetAbility3().GetCooldownTime()};
player->GetAbility3().cooldown=player->GetAbility3().GetCooldownTime();
std::weak_ptr<Item>nullRing{Inventory::AddItem("Null Ring"s)};
Inventory::EquipItem(nullRing,EquipSlot::RING1);
nullRing.lock()->_EnchantItem("Multi-Multishot"sv);
testKey->bHeld=true; //Force the key to be held down for testing purposes.
REQUIRE(player->GetAbility3().GetCooldownTime()==oldCooldownTime-oldCooldownTime*"Multi-Multishot"_ENC["COOLDOWN REDUCTION PCT"]/100.f);
testGame->SetElapsedTime(0.f);
testGame->OnUserUpdate(0.f);
REQUIRE(player->GetAbility3().GetCooldownTime()==player->GetAbility3().cooldown);
}
TEST(PlayerTests,"PlayerGetShieldCheck"){
player=testGame->GetPlayer();
REQUIRE(0U==player->GetShield());
}
TEST(PlayerTests,"PlayerAddShieldCheck"){
player=testGame->GetPlayer();
player->AddShield(60U,5.f,PlayerTimerType::ADVANCE_SHIELD_TIMER);
REQUIRE(60U==player->GetShield());
testGame->SetElapsedTime(5.f);
testGame->OnUserUpdate(5.f);
REQUIRE(0U==player->GetShield());
}
TEST(PlayerTests,"PlayerMultiShieldCheck"){
player=testGame->GetPlayer();
player->AddShield(60U,5.f,PlayerTimerType::ADVANCE_SHIELD_TIMER);
player->AddShield(100U,2.f,PlayerTimerType::PLAYER_OUTLINE_TIMER);
REQUIRE(160U==player->GetShield());
testGame->SetElapsedTime(2.f);
testGame->OnUserUpdate(2.f);
REQUIRE(60U==player->GetShield());
testGame->SetElapsedTime(3.f);
testGame->OnUserUpdate(3.f);
REQUIRE(0U==player->GetShield());
}
TEST(PlayerTests,"PlayerSubtractShieldCheck"){
player=testGame->GetPlayer();
player->AddShield(60U,5.f,PlayerTimerType::ADVANCE_SHIELD_TIMER);
REQUIRE(60U==player->GetShield());
player->SubtractShield(40U);
REQUIRE(20U==player->GetShield());
player->SubtractShield(200U);
REQUIRE(0U==player->GetShield());
}
TEST(PlayerTests,"PlayerDamageShieldCheck"){
player=testGame->GetPlayer();
player->AddShield(60U,5.f,PlayerTimerType::ADVANCE_SHIELD_TIMER);
REQUIRE(60U==player->GetShield());
player->Hurt(20U,player->OnUpperLevel(),player->GetZ());
REQUIRE(40U==player->GetShield());
REQUIRE(player->GetMaxHealth()==player->GetHealth());
player->Hurt(200U,player->OnUpperLevel(),player->GetZ());
REQUIRE(0U==player->GetShield());
REQUIRE(player->GetMaxHealth()==player->GetHealth());
player->Hurt(10U,player->OnUpperLevel(),player->GetZ());
REQUIRE(player->GetMaxHealth()-10==player->GetHealth());
}
TEST(PlayerTests,"PlayerHasteMoveCheck"){
Game::LoadLevelWithTMX("TEST_MAP",testGame.get());
player=testGame->GetPlayer();
player->ForceSetPos({12,12});
testKeyboardInput.AddKeybind(Input{InputType::KEY,D});
testKey=testGame->GetKeyboardState(D);
testKey->bHeld=true;
{
const vf2d originalPlayerPos{player->GetPos()};
Game::Update(0.5f);
REQUIRE(originalPlayerPos!=player->GetPos());
const float movedDist{(originalPlayerPos-player->GetPos()).mag()};
REQUIRE(50.f==movedDist);
}
Game::AddBuffToPlayer(BuffType::HASTEN,INFINITE,0.3f);
const vf2d originalHastenedPlayerPos{player->GetPos()};
Game::Update(0.5f);
const float hastenMovedDist{(originalHastenedPlayerPos-player->GetPos()).mag()};
REQUIRE(65.f==hastenMovedDist);
player->RemoveAllBuffs();
{
const vf2d originalPlayerPos{player->GetPos()};
Game::Update(0.5f);
const float movedDist{(originalPlayerPos-player->GetPos()).mag()};
REQUIRE(50.f==movedDist);
}
}
TEST(PlayerTests,"PlayerHasteCooldownCheck"){
Game::LoadLevelWithTMX("TEST_MAP",testGame.get());
player=testGame->GetPlayer();
player->ForceSetPos({12,12});
testKeyboardInput.AddKeybind(Input{InputType::KEY,D});
testKey=testGame->GetKeyboardState(D);
testKey->bHeld=true;
Game::CastAbilityAtLocation(player->GetAbility3(),{});
Game::Update(5.f);
REQUIRE(player->GetAbility3().GetCooldownTime()-5.f==player->GetAbility3().cooldown);
Game::ResetPlayerAndChangeClass(Class::WARRIOR,player,&*testGame);
Game::CastAbilityAtLocation(player->GetAbility3(),{});
Game::AddBuffToPlayer(BuffType::HASTEN,INFINITE,0.3f);
Game::Update(5.f);
REQUIRE(player->GetAbility3().GetCooldownTime()-6.5f==player->GetAbility3().cooldown);
player->RemoveAllBuffs();
player->GetAbility3().cooldown=0;
Game::CastAbilityAtLocation(player->GetAbility3(),{});
Game::Update(5.f);
REQUIRE(player->GetAbility3().GetCooldownTime()-5.f==player->GetAbility3().cooldown);
}