# pragma region License
/*
License ( OLC - 3 )
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
Copyright 2024 Joshua 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 <EFBFBD> 2024 The FreeType
Project ( www . freetype . org ) . Please see LICENSE_FT . txt for more information .
All rights reserved .
*/
# pragma endregion
# include "CppUnitTest.h"
# include "AdventuresInLestoria.h"
# include "Tutorial.h"
# include <random>
# include <format>
# include "ItemDrop.h"
# include "DamageNumber.h"
# include <ranges>
# include "BulletTypes.h"
# include "GameHelper.h"
using namespace Microsoft : : VisualStudio : : CppUnitTestFramework ;
using namespace olc : : utils ;
INCLUDE_GFX
INCLUDE_ITEM_DATA
INCLUDE_DAMAGENUMBER_LIST
INCLUDE_INITIALIZEGAMECONFIGURATIONS
INCLUDE_MONSTER_LIST
extern std : : mt19937 rng ;
namespace Test
{
template < class T >
inline static void InRange ( T initialVal , std : : pair < T , T > range , std : : wstring_view assertMessage ) {
Assert : : IsTrue ( initialVal > = range . first & & initialVal < = range . second , std : : format ( L " Expected: {}~{} Actual: {} - {} " , range . first , range . second , initialVal , assertMessage ) . c_str ( ) ) ;
}
}
namespace EnchantTests
{
TEST_CLASS ( EnchantTest )
{
public :
std : : unique_ptr < AiL > testGame ;
InputGroup testKeyboardInput ;
Player * player ;
HWButton * testKey ;
TEST_METHOD_INITIALIZE ( PlayerInitialize ) {
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 ( ) ;
GameState : : Initialize ( ) ;
GameState : : STATE = GameState : : states . at ( States : : State : : GAME_RUN ) ;
ItemDrop : : Initialize ( ) ;
testGame - > ResetLevelStates ( ) ;
# pragma region Setup a fake test map and test monster
game - > MAP_DATA [ " CAMPAIGN_1_1 " ] ;
game - > MAP_DATA [ " CAMPAIGN_1_1 " ] . _SetMapData ( MapTag { 24 * 24 , 24 * 24 , 24 , 24 } ) ;
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 - > InitializeCamera ( ) ;
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.
testKey - > bHeld = true ; //Assume key is held for every test unless otherwise needs to be changed.
Menu : : themes . SetInitialized ( ) ;
GFX . SetInitialized ( ) ;
DAMAGENUMBER_LIST . clear ( ) ;
}
TEST_METHOD ( HealthBoostCheck ) {
Assert : : AreEqual ( 100 , player - > GetMaxHealth ( ) , L " Player starts with 100 health. " ) ;
std : : weak_ptr < Item > nullRing { Game : : GiveAndEquipEnchantedRing ( " Aura of the Beast " ) } ;
std : : unordered_map < int , uint32_t > statDistribution ;
for ( int i : std : : ranges : : iota_view ( 0 , 1000 ) ) {
nullRing . lock ( ) - > EnchantItem ( " Health Boost " ) ;
statDistribution [ player - > GetMaxHealth ( ) ] + + ;
}
Assert : : AreEqual ( size_t ( 3 ) , statDistribution . size ( ) , L " There should be three entries generated. If not, then the RNG picking is likely not working! " ) ;
std : : weak_ptr < Item > nullRing2 { Game : : GiveAndEquipEnchantedRing ( " Aura of the Beast " , EquipSlot : : RING2 ) } ;
for ( int i : std : : ranges : : iota_view ( 0 , 1000 ) ) {
nullRing2 . lock ( ) - > EnchantItem ( " Health Boost " ) ;
Test : : InRange ( player - > GetMaxHealth ( ) , { 106 , 110 } , L " Max Health not in expected range with two rings equipped. " ) ;
}
}
TEST_METHOD ( AttackBoostCheck ) {
player - > SetBaseStat ( " Attack " , 100.f ) ;
Assert : : AreEqual ( 100 , player - > GetAttack ( ) , L " Player starts with 100 attack. " ) ;
std : : weak_ptr < Item > nullRing { Game : : GiveAndEquipEnchantedRing ( " Attack Boost " ) } ;
for ( int i : std : : ranges : : iota_view ( 0 , 1000 ) ) {
nullRing . lock ( ) - > EnchantItem ( " Attack Boost " ) ;
Test : : InRange ( player - > GetAttack ( ) , { 103 , 105 } , L " Attack not in expected range. " ) ;
}
std : : weak_ptr < Item > nullRing2 { Game : : GiveAndEquipEnchantedRing ( " Attack Boost " , EquipSlot : : RING2 ) } ;
for ( int i : std : : ranges : : iota_view ( 0 , 1000 ) ) {
nullRing2 . lock ( ) - > EnchantItem ( " Attack Boost " ) ;
Test : : InRange ( player - > GetAttack ( ) , { 106 , 110 } , L " Attack not in expected range with two rings equipped. " ) ;
}
}
TEST_METHOD ( MovementBoostCheck ) {
Assert : : AreEqual ( 100.0 _Pct , player - > GetMoveSpdMult ( ) , L " Player starts with 100% Movespd. " ) ;
std : : weak_ptr < Item > nullRing { Game : : GiveAndEquipEnchantedRing ( " Movement Boost " ) } ;
for ( int i : std : : ranges : : iota_view ( 0 , 1000 ) ) {
nullRing . lock ( ) - > EnchantItem ( " Movement Boost " ) ;
Test : : InRange ( player - > GetMoveSpdMult ( ) , { 103.0 _Pct , 105.0 _Pct } , L " Move Speed not in expected range. " ) ;
}
std : : weak_ptr < Item > nullRing2 { Game : : GiveAndEquipEnchantedRing ( " Movement Boost " , EquipSlot : : RING2 ) } ;
for ( int i : std : : ranges : : iota_view ( 0 , 1000 ) ) {
nullRing2 . lock ( ) - > EnchantItem ( " Movement Boost " ) ;
Test : : InRange ( player - > GetMoveSpdMult ( ) , { 106.0 _Pct , 110.0 _Pct } , L " Move Speed not in expected range with two rings equipped. " ) ;
}
}
TEST_METHOD ( AbilityHasteCheck ) {
Assert : : AreEqual ( 0.0 _Pct , player - > GetCooldownReductionPct ( ) , L " Player starts with 0% CDR. " ) ;
std : : weak_ptr < Item > nullRing { Game : : GiveAndEquipEnchantedRing ( " Ability Haste " ) } ;
for ( int i : std : : ranges : : iota_view ( 0 , 1000 ) ) {
nullRing . lock ( ) - > EnchantItem ( " Ability Haste " ) ;
Test : : InRange ( player - > GetCooldownReductionPct ( ) , { 3.0 _Pct , 5.0 _Pct } , L " CDR not in expected range. " ) ;
}
std : : weak_ptr < Item > nullRing2 { Game : : GiveAndEquipEnchantedRing ( " Ability Haste " , EquipSlot : : RING2 ) } ;
for ( int i : std : : ranges : : iota_view ( 0 , 1000 ) ) {
nullRing2 . lock ( ) - > EnchantItem ( " Ability Haste " ) ;
Test : : InRange ( player - > GetCooldownReductionPct ( ) , { 6.0 _Pct , 10.0 _Pct } , L " CDR not in expected range with two rings. " ) ;
}
}
TEST_METHOD ( CritRateCheck ) {
Assert : : AreEqual ( 0.0 _Pct , player - > GetCritRatePct ( ) , L " Player starts with 0% Crit Rate. " ) ;
std : : weak_ptr < Item > nullRing { Game : : GiveAndEquipEnchantedRing ( " Crit Rate " ) } ;
for ( int i : std : : ranges : : iota_view ( 0 , 1000 ) ) {
nullRing . lock ( ) - > EnchantItem ( " Crit Rate " ) ;
Test : : InRange ( player - > GetCritRatePct ( ) , { 3.0 _Pct , 5.0 _Pct } , L " Crit Rate not in expected range. " ) ;
}
std : : weak_ptr < Item > nullRing2 { Game : : GiveAndEquipEnchantedRing ( " Crit Rate " , EquipSlot : : RING2 ) } ;
for ( int i : std : : ranges : : iota_view ( 0 , 1000 ) ) {
nullRing2 . lock ( ) - > EnchantItem ( " Crit Rate " ) ;
Test : : InRange ( player - > GetCritRatePct ( ) , { 6.0 _Pct , 10.0 _Pct } , L " Crit Rate not in expected range with two rings. " ) ;
}
}
TEST_METHOD ( CritDamageCheck ) {
Assert : : AreEqual ( 50.0 _Pct , player - > GetCritDmgPct ( ) , L " Player starts with 50% Crit Damage. " ) ;
std : : weak_ptr < Item > nullRing { Game : : GiveAndEquipEnchantedRing ( " Crit Damage " ) } ;
for ( int i : std : : ranges : : iota_view ( 0 , 1000 ) ) {
nullRing . lock ( ) - > EnchantItem ( " Crit Damage " ) ;
Test : : InRange ( player - > GetCritDmgPct ( ) , { 57.0 _Pct , 60.0 _Pct } , L " Crit Damage not in expected range. " ) ;
}
std : : weak_ptr < Item > nullRing2 { Game : : GiveAndEquipEnchantedRing ( " Crit Damage " , EquipSlot : : RING2 ) } ;
for ( int i : std : : ranges : : iota_view ( 0 , 1000 ) ) {
nullRing2 . lock ( ) - > EnchantItem ( " Crit Damage " ) ;
Test : : InRange ( player - > GetCritDmgPct ( ) , { 64.0 _Pct , 70.0 _Pct } , L " Crit Damage not in expected range with two rings. " ) ;
}
}
TEST_METHOD ( StoneskinCheck ) {
Assert : : AreEqual ( 0.0 _Pct , player - > GetDamageReductionFromBuffs ( ) , L " Player starts with 0% Damage Reduction. " ) ;
std : : weak_ptr < Item > nullRing { Game : : GiveAndEquipEnchantedRing ( " Stoneskin " ) } ;
for ( int i : std : : ranges : : iota_view ( 0 , 1000 ) ) {
nullRing . lock ( ) - > EnchantItem ( " Stoneskin " ) ;
Test : : InRange ( player - > GetDamageReductionFromBuffs ( ) , { 3.0 _Pct , 5.0 _Pct } , L " Damage Reduction not in expected range. " ) ;
}
std : : weak_ptr < Item > nullRing2 { Game : : GiveAndEquipEnchantedRing ( " Stoneskin " , EquipSlot : : RING2 ) } ;
for ( int i : std : : ranges : : iota_view ( 0 , 1000 ) ) {
nullRing2 . lock ( ) - > EnchantItem ( " Stoneskin " ) ;
Test : : InRange ( player - > GetDamageReductionFromBuffs ( ) , { 6.0 _Pct , 10.0 _Pct } , L " Damage Reduction not in expected range with two rings. " ) ;
}
}
TEST_METHOD ( ManaPoolCheck ) {
Assert : : AreEqual ( 100 , player - > GetMaxMana ( ) , L " Player starts with 100 mana. " ) ;
std : : weak_ptr < Item > nullRing { Game : : GiveAndEquipEnchantedRing ( " Mana Pool " ) } ;
for ( int i : std : : ranges : : iota_view ( 0 , 1000 ) ) {
nullRing . lock ( ) - > EnchantItem ( " Mana Pool " ) ;
Test : : InRange ( player - > GetMaxMana ( ) , { 107 , 112 } , L " Mana Pool not in expected range. " ) ;
}
std : : weak_ptr < Item > nullRing2 { Game : : GiveAndEquipEnchantedRing ( " Mana Pool " , EquipSlot : : RING2 ) } ;
for ( int i : std : : ranges : : iota_view ( 0 , 1000 ) ) {
nullRing2 . lock ( ) - > EnchantItem ( " Mana Pool " ) ;
Test : : InRange ( player - > GetMaxMana ( ) , { 114 , 124 } , L " Mana Pool not in expected range with two rings. " ) ;
}
}
TEST_METHOD ( MagicalProtectionCheck ) {
Assert : : AreEqual ( 100 , player - > GetMaxHealth ( ) , L " Player starts with 100 health. " ) ;
Assert : : AreEqual ( 0.0 _Pct , player - > GetDamageReductionFromBuffs ( ) , L " Player starts with 0% damage reduction. " ) ;
Assert : : AreEqual ( 100.0 _Pct , player - > GetMoveSpdMult ( ) , L " Player starts with 100% move speed. " ) ;
Assert : : AreEqual ( 0.0 _Pct , player - > GetHP6RecoveryPct ( ) , L " Player starts with 0% HP/6 recovery. " ) ;
std : : weak_ptr < Item > nullRing { Game : : GiveAndEquipEnchantedRing ( " Magical Protection " ) } ;
for ( int i : std : : ranges : : iota_view ( 0 , 1000 ) ) {
nullRing . lock ( ) - > EnchantItem ( " Magical Protection " ) ;
Test : : InRange ( player - > GetMaxHealth ( ) , { 102 , 103 } , L " Max Health not in expected range. " ) ;
Test : : InRange ( player - > GetDamageReductionFromBuffs ( ) , { 2.0 _Pct , 3.0 _Pct } , L " Damage Reduction not in expected range. " ) ;
Test : : InRange ( player - > GetMoveSpdMult ( ) , { 102.0 _Pct , 103.0 _Pct } , L " Move Speed % not in expected range. " ) ;
Test : : InRange ( player - > GetHP6RecoveryPct ( ) , { 1.0 _Pct , 1.0 _Pct } , L " HP/6 Recovery not in expected range. " ) ;
}
std : : weak_ptr < Item > nullRing2 { Game : : GiveAndEquipEnchantedRing ( " Magical Protection " , EquipSlot : : RING2 ) } ;
for ( int i : std : : ranges : : iota_view ( 0 , 1000 ) ) {
nullRing2 . lock ( ) - > EnchantItem ( " Magical Protection " ) ;
Test : : InRange ( player - > GetMaxHealth ( ) , { 102 , 103 } , L " Max Health not in expected range with two rings. " ) ;
Test : : InRange ( player - > GetDamageReductionFromBuffs ( ) , { 2.0 _Pct , 3.0 _Pct } , L " Damage Reduction not in expected range with two rings. " ) ;
Test : : InRange ( player - > GetMoveSpdMult ( ) , { 102.0 _Pct , 103.0 _Pct } , L " Move Speed % not in expected range with two rings. " ) ;
Test : : InRange ( player - > GetHP6RecoveryPct ( ) , { 1.0 _Pct , 1.0 _Pct } , L " HP/6 Recovery not in expected range with two rings. " ) ;
}
}
TEST_METHOD ( AuraOfTheBeastCheck ) {
player - > SetBaseStat ( " Attack " , 100.f ) ;
Assert : : AreEqual ( 100 , player - > GetAttack ( ) , L " Player starts with 100 attack. " ) ;
Assert : : AreEqual ( 0.0 _Pct , player - > GetCritRatePct ( ) , L " Player starts with 0% crit rate. " ) ;
Assert : : AreEqual ( 0.0 _Pct , player - > GetCooldownReductionPct ( ) , L " Player starts with 0% cooldown reduction. " ) ;
Assert : : AreEqual ( 50.0 _Pct , player - > GetCritDmgPct ( ) , L " Player starts with 50% crit rate. " ) ;
std : : weak_ptr < Item > nullRing { Game : : GiveAndEquipEnchantedRing ( " Aura of the Beast " ) } ;
for ( int i : std : : ranges : : iota_view ( 0 , 1000 ) ) {
nullRing . lock ( ) - > EnchantItem ( " Aura of the Beast " ) ;
Test : : InRange ( player - > GetAttack ( ) , { 102 , 103 } , L " Attack not in expected range. " ) ;
Test : : InRange ( player - > GetCritRatePct ( ) , { 2.0 _Pct , 3.0 _Pct } , L " Crit Rate not in expected range. " ) ;
Test : : InRange ( player - > GetCooldownReductionPct ( ) , { 2.0 _Pct , 3.0 _Pct } , L " Cooldown Reduction % not in expected range. " ) ;
Test : : InRange ( player - > GetCritDmgPct ( ) , { 53.0 _Pct , 57.0 _Pct } , L " Crit Damage not in expected range. " ) ;
}
std : : weak_ptr < Item > nullRing2 { Game : : GiveAndEquipEnchantedRing ( " Aura of the Beast " , EquipSlot : : RING2 ) } ;
for ( int i : std : : ranges : : iota_view ( 0 , 1000 ) ) {
nullRing2 . lock ( ) - > EnchantItem ( " Aura of the Beast " ) ;
Test : : InRange ( player - > GetAttack ( ) , { 102 , 103 } , L " Attack not in expected range with two rings. " ) ;
Test : : InRange ( player - > GetCritRatePct ( ) , { 2.0 _Pct , 3.0 _Pct } , L " Crit Rate not in expected range with two rings. " ) ;
Test : : InRange ( player - > GetCooldownReductionPct ( ) , { 2.0 _Pct , 3.0 _Pct } , L " Cooldown Reduction % not in expected range with two rings. " ) ;
Test : : InRange ( player - > GetCritDmgPct ( ) , { 53.0 _Pct , 57.0 _Pct } , L " Crit Damage not in expected range with two rings. " ) ;
}
}
TEST_METHOD ( LethalTempoCheck ) {
MonsterData testMonsterData { " TestName " , " Test Monster " , 30 , 10 , 5 , { MonsterDropData { " Health Potion " , 100.f , 1 , 1 } } , 200.f } ;
MONSTER_DATA [ " TestName " ] = testMonsterData ;
Monster testMonster { { } , MONSTER_DATA [ " TestName " ] } ;
testMonster . Hurt ( 0 , testMonster . OnUpperLevel ( ) , testMonster . GetZ ( ) ) ;
Assert : : AreEqual ( size_t ( 0 ) , player - > GetBuffs ( BuffType : : LETHAL_TEMPO ) . size ( ) , L " Lethal Tempo does not stack up without the enchant. " ) ;
testMonster . Hurt ( 0 , testMonster . OnUpperLevel ( ) , testMonster . GetZ ( ) , HurtFlag : : PLAYER_ABILITY ) ;
Assert : : AreEqual ( size_t ( 0 ) , player - > GetBuffs ( BuffType : : LETHAL_TEMPO ) . size ( ) , L " Lethal Tempo does not stack up without the enchant. " ) ;
Game : : GiveAndEquipEnchantedRing ( " Lethal Tempo " ) ;
testMonster . Hurt ( 0 , testMonster . OnUpperLevel ( ) , testMonster . GetZ ( ) , HurtFlag : : PLAYER_ABILITY ) ;
Assert : : AreEqual ( size_t ( 1 ) , player - > GetBuffs ( BuffType : : LETHAL_TEMPO ) . size ( ) , L " Lethal Tempo buff is active after attacking with the enchant.. " ) ;
Assert : : AreEqual ( 0.0175f , player - > GetAttackRecoveryRateReduction ( ) , L " Lethal Tempo buff reduced attack Recovery Rate by 0.0175 (5% of 0.35). " ) ;
for ( int i : std : : ranges : : iota_view ( 0 , 10 ) ) {
testMonster . Hurt ( 0 , testMonster . OnUpperLevel ( ) , testMonster . GetZ ( ) , HurtFlag : : PLAYER_ABILITY ) ;
}
Assert : : AreEqual ( 0.0875f , player - > GetAttackRecoveryRateReduction ( ) , L " Lethal Tempo buff should cap at 5 stacks. " ) ;
Assert : : AreEqual ( size_t ( 1 ) , player - > GetBuffs ( BuffType : : LETHAL_TEMPO ) . size ( ) , L " Lethal Tempo buff is active. " ) ;
}
TEST_METHOD ( SecondWindCheck ) {
Assert : : AreEqual ( 0.0 _Pct , player - > GetHPRecoveryPct ( ) , L " HP Recovery Pct is 0% at the start. " ) ;
player - > Hurt ( 90 , player - > OnUpperLevel ( ) , player - > GetZ ( ) ) ;
Assert : : AreEqual ( 0.0 _Pct , player - > GetHPRecoveryPct ( ) , L " HP Recovery Pct is still 0% without Second Wind. " ) ;
Game : : GiveAndEquipEnchantedRing ( " Second Wind " ) ;
Assert : : AreEqual ( 1.0 _Pct , player - > GetHPRecoveryPct ( ) , L " HP Recovery Pct is now 1% with low health with Second Wind. " ) ;
player - > Heal ( 11 ) ;
Assert : : AreEqual ( 0.0 _Pct , player - > GetHPRecoveryPct ( ) , L " HP Recovery Pct is now 0% since Second Wind should no longer activate above 20% health. " ) ;
}
TEST_METHOD ( EmergencyRecoveryCheck ) {
Assert : : AreEqual ( 0.0 _Pct , player - > GetHP6RecoveryPct ( ) , 0.1 _Pct , L " HP Recovery/6 Pct is 0% at the start. " ) ;
Assert : : AreEqual ( 0.0 _Pct , player - > GetHP4RecoveryPct ( ) , 0.1 _Pct , L " HP Recovery/4 Pct is 0% at the start. " ) ;
Game : : GiveAndEquipEnchantedRing ( " Emergency Recovery " ) ;
Assert : : AreEqual ( 1.0 _Pct , player - > GetHP6RecoveryPct ( ) , 0.1 _Pct , L " HP Recovery/6 Pct is base 1% even with full HP. " ) ;
Assert : : AreEqual ( 0.0 _Pct , player - > GetHP4RecoveryPct ( ) , 0.1 _Pct , L " HP Recovery/4 Pct is still 0% since the player is not lower than 30% health. " ) ;
for ( int i : std : : ranges : : iota_view ( 1 , 7 ) ) {
player - > Hurt ( 10 , player - > OnUpperLevel ( ) , player - > GetZ ( ) ) ;
Assert : : AreEqual ( 1.0 _Pct + 0.5 _Pct * i , player - > GetHP6RecoveryPct ( ) , 0.1 _Pct , L " HP Recovery/6 Pct is increasing by 0.5% per 10% missing health. " ) ;
}
player - > Hurt ( 10 , player - > OnUpperLevel ( ) , player - > GetZ ( ) ) ;
Assert : : AreEqual ( 0.0 _Pct , player - > GetHP6RecoveryPct ( ) , 0.1 _Pct , L " HP Recovery/6 Pct is now 0% as the HP Recovery/4 sec version should have activated. " ) ;
Assert : : AreEqual ( 4.5 _Pct , player - > GetHP4RecoveryPct ( ) , 0.1 _Pct , L " HP Recovery/4 Pct is now 4.5% " ) ;
for ( int i : std : : ranges : : iota_view ( 1 , 3 ) ) {
player - > Hurt ( 10 , player - > OnUpperLevel ( ) , player - > GetZ ( ) ) ;
Assert : : AreEqual ( 4.5 _Pct + 0.5 _Pct * i , player - > GetHP4RecoveryPct ( ) , 0.1 _Pct , L " HP Recovery/4 Pct is increasing by 0.5% per 10% missing health. " ) ;
}
}
TEST_METHOD ( DeathDefianceCheck ) {
for ( int i : std : : ranges : : iota_view ( 0 , 10 ) ) {
player - > Heal ( 100 ) ;
player - > Hurt ( 1000 , player - > OnUpperLevel ( ) , player - > GetZ ( ) ) ;
if ( player - > IsAlive ( ) ) { Assert : : Fail ( L " Player survived while not having the Death Defiance Enchant! THIS SHOULD NOT BE HAPPENING! " ) ; }
player - > _SetIframes ( 0.f ) ;
}
Game : : GiveAndEquipEnchantedRing ( " Death Defiance " ) ;
player - > Heal ( 100 ) ;
for ( int i : std : : ranges : : iota_view ( 0 , 10 ) ) {
const int prevPlayerHP { player - > GetHealth ( ) } ;
player - > Hurt ( 1 , player - > OnUpperLevel ( ) , player - > GetZ ( ) ) ;
Assert : : AreNotEqual ( prevPlayerHP , player - > GetHealth ( ) , L " Death Defiance triggered even though the player did not take lethal damage! " ) ;
player - > _SetIframes ( 0.f ) ;
}
bool survivedAtLeastOnce { false } ;
for ( int i : std : : ranges : : iota_view ( 0 , 10 ) ) {
player - > Heal ( 100 ) ;
player - > Hurt ( 1000 , player - > OnUpperLevel ( ) , player - > GetZ ( ) ) ;
if ( player - > IsAlive ( ) ) {
survivedAtLeastOnce = true ;
break ;
}
player - > _SetIframes ( 0.f ) ;
}
Assert : : AreEqual ( true , survivedAtLeastOnce , L " Player should have survived at least one time with Death Defiance. " ) ;
}
TEST_METHOD ( ReaperOfSoulsCheck ) {
MonsterData testMonsterData { " TestName " , " Test Monster " , 30 , 10 , 5 , { } , 200.f } ;
MONSTER_DATA [ " TestName " ] = testMonsterData ;
Monster testMonster { { } , MONSTER_DATA [ " TestName " ] } ;
Monster testMonster2 { { } , MONSTER_DATA [ " TestName " ] } ;
testMonster . Hurt ( 1000 , testMonster . OnUpperLevel ( ) , testMonster . GetZ ( ) ) ;
Game : : Update ( 0.5f ) ;
for ( Effect * eff : game - > GetAllEffects ( ) | std : : views : : filter ( [ ] ( Effect * eff ) { return eff - > GetType ( ) = = EffectType : : MONSTER_SOUL ; } ) ) {
Assert : : Fail ( L " A Monster Soul should not be generated " ) ;
}
Game : : GiveAndEquipEnchantedRing ( " Reaper of Souls " ) ;
testMonster2 . Hurt ( 1000 , testMonster2 . OnUpperLevel ( ) , testMonster2 . GetZ ( ) ) ;
Game : : Update ( 0.5f ) ;
bool foundSoul { false } ;
for ( const Effect * eff : game - > GetAllEffects ( ) | std : : views : : filter ( [ ] ( const Effect * eff ) { return eff - > GetType ( ) = = EffectType : : MONSTER_SOUL ; } ) ) {
foundSoul = true ;
break ;
}
if ( ! foundSoul ) Assert : : Fail ( L " A soul was not generated from a kill with the Reaper of Souls enchant. " ) ;
Game : : Update ( 3.5f ) ;
player - > Hurt ( 5 , player - > OnUpperLevel ( ) , player - > GetZ ( ) ) ;
player - > ConsumeMana ( 10 ) ;
player - > GetRightClickAbility ( ) . cooldown = player - > GetAbility1 ( ) . cooldown = player - > GetAbility2 ( ) . cooldown = player - > GetAbility3 ( ) . cooldown = player - > GetAbility4 ( ) . cooldown = 1.5f ;
for ( int i : std : : ranges : : iota_view ( 0 , 2 ) ) {
Game : : Update ( 0.5f ) ;
}
Assert : : AreEqual ( 98 , player - > GetHealth ( ) , L " Player should have healed for 3 health from contacting the soul. " ) ;
Assert : : AreEqual ( 97 , player - > GetMana ( ) , L " Player should have gained 2 mana from contacting the soul. " ) ;
Assert : : AreEqual ( 0.f , player - > GetRightClickAbility ( ) . cooldown , L " Player's ability cooldowns should reduce from contacting the soul. " ) ;
Assert : : AreEqual ( 0.f , player - > GetAbility1 ( ) . cooldown , L " Player's ability cooldowns should reduce from contacting the soul. " ) ;
Assert : : AreEqual ( 0.f , player - > GetAbility2 ( ) . cooldown , L " Player's ability cooldowns should reduce from contacting the soul. " ) ;
Assert : : AreEqual ( 0.f , player - > GetAbility3 ( ) . cooldown , L " Player's ability cooldowns should reduce from contacting the soul. " ) ;
Assert : : AreEqual ( 0.f , player - > GetAbility4 ( ) . cooldown , L " Player's ability cooldowns should reduce from contacting the soul. " ) ;
//This should be the moment the wisp is fading out.
Game : : Update ( 0.5f ) ;
for ( Effect * eff : game - > GetAllEffects ( ) | std : : views : : filter ( [ ] ( Effect * eff ) { return eff - > GetType ( ) = = EffectType : : MONSTER_SOUL ; } ) ) {
Assert : : Fail ( L " A Monster Soul has not disappeared after colliding with a player. " ) ;
}
}
TEST_METHOD ( WizardsSoulCheck ) {
player - > CheckAndPerformAbility ( player - > GetRightClickAbility ( ) , testKeyboardInput ) ;
player - > SetState ( State : : NORMAL ) ;
player - > RestoreMana ( 100 ) ;
player - > CheckAndPerformAbility ( player - > GetAbility1 ( ) , testKeyboardInput ) ;
player - > SetState ( State : : NORMAL ) ;
player - > RestoreMana ( 100 ) ;
player - > CheckAndPerformAbility ( player - > GetAbility2 ( ) , testKeyboardInput ) ;
player - > SetState ( State : : NORMAL ) ;
player - > RestoreMana ( 100 ) ;
player - > CheckAndPerformAbility ( player - > GetAbility3 ( ) , testKeyboardInput ) ;
player - > SetState ( State : : NORMAL ) ;
player - > RestoreMana ( 100 ) ;
player - > CheckAndPerformAbility ( player - > GetAbility4 ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( player - > GetRightClickAbility ( ) . GetCooldownTime ( ) , player - > GetRightClickAbility ( ) . cooldown , L " By default the player cooldowns are unaffected without the Wizard's Soul enchant. " ) ;
Assert : : AreEqual ( player - > GetAbility1 ( ) . GetCooldownTime ( ) , player - > GetAbility1 ( ) . cooldown , L " By default the player cooldowns are unaffected without the Wizard's Soul enchant. " ) ;
Assert : : AreEqual ( player - > GetAbility2 ( ) . GetCooldownTime ( ) , player - > GetAbility2 ( ) . cooldown , L " By default the player cooldowns are unaffected without the Wizard's Soul enchant. " ) ;
Assert : : AreEqual ( player - > GetAbility3 ( ) . GetCooldownTime ( ) , player - > GetAbility3 ( ) . cooldown , L " By default the player cooldowns are unaffected without the Wizard's Soul enchant. " ) ;
Assert : : AreEqual ( player - > GetAbility4 ( ) . GetCooldownTime ( ) , player - > GetAbility4 ( ) . cooldown , L " By default the player cooldowns are unaffected without the Wizard's Soul enchant. " ) ;
Game : : GiveAndEquipEnchantedRing ( " Wizard's Soul " ) ;
player - > SetState ( State : : NORMAL ) ;
player - > RestoreMana ( 100 ) ;
player - > GetRightClickAbility ( ) . charges = 1 ; //Reset the cooldown so it can be used.
player - > GetRightClickAbility ( ) . cooldown = 0.f ; //Reset the cooldown so it can be used.
player - > CheckAndPerformAbility ( player - > GetRightClickAbility ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( player - > GetRightClickAbility ( ) . GetCooldownTime ( ) , player - > GetRightClickAbility ( ) . cooldown , L " Right-click ability goes on cooldown like normal. " ) ;
Assert : : AreEqual ( player - > GetAbility1 ( ) . GetCooldownTime ( ) , player - > GetAbility1 ( ) . cooldown , L " All other abilities are unaffected by Right-click ability being used. " ) ;
Assert : : AreEqual ( player - > GetAbility2 ( ) . GetCooldownTime ( ) , player - > GetAbility2 ( ) . cooldown , L " All other abilities are unaffected by Right-click ability being used. " ) ;
Assert : : AreEqual ( player - > GetAbility3 ( ) . GetCooldownTime ( ) , player - > GetAbility3 ( ) . cooldown , L " All other abilities are unaffected by Right-click ability being used. " ) ;
Assert : : AreEqual ( player - > GetAbility4 ( ) . GetCooldownTime ( ) , player - > GetAbility4 ( ) . cooldown , L " All other abilities are unaffected by Right-click ability being used. " ) ;
player - > SetState ( State : : NORMAL ) ;
player - > RestoreMana ( 100 ) ;
player - > GetAbility1 ( ) . charges = 1 ; //Reset the cooldown so it can be used.
player - > GetAbility1 ( ) . cooldown = 0.f ; //Reset the cooldown so it can be used.
player - > CheckAndPerformAbility ( player - > GetAbility1 ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( player - > GetRightClickAbility ( ) . GetCooldownTime ( ) , player - > GetRightClickAbility ( ) . cooldown , L " Right-click ability remains unaffected by other abilities. " ) ;
Assert : : AreEqual ( player - > GetAbility1 ( ) . GetCooldownTime ( ) , player - > GetAbility1 ( ) . cooldown , L " Same ability used should not be affected. " ) ;
Assert : : AreEqual ( player - > GetAbility2 ( ) . GetCooldownTime ( ) - 1.5f , player - > GetAbility2 ( ) . cooldown , L " All other abilities have cooldowns reduced by 1.5 seconds. " ) ;
Assert : : AreEqual ( player - > GetAbility3 ( ) . GetCooldownTime ( ) - 1.5f , player - > GetAbility3 ( ) . cooldown , L " All other abilities have cooldowns reduced by 1.5 seconds. " ) ;
Assert : : AreEqual ( player - > GetAbility4 ( ) . GetCooldownTime ( ) - 1.5f , player - > GetAbility4 ( ) . cooldown , L " All other abilities have cooldowns reduced by 1.5 seconds. " ) ;
player - > SetState ( State : : NORMAL ) ;
player - > RestoreMana ( 100 ) ;
player - > GetAbility2 ( ) . charges = 1 ; //Reset the cooldown so it can be used.
player - > GetAbility2 ( ) . cooldown = 0.f ; //Reset the cooldown so it can be used.
player - > CheckAndPerformAbility ( player - > GetAbility2 ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( player - > GetRightClickAbility ( ) . GetCooldownTime ( ) , player - > GetRightClickAbility ( ) . cooldown , L " Right-click ability remains unaffected by other abilities. " ) ;
Assert : : AreEqual ( player - > GetAbility1 ( ) . GetCooldownTime ( ) - 1.5f , player - > GetAbility1 ( ) . cooldown , L " All other abilities have cooldowns reduced by 1.5 seconds. " ) ;
Assert : : AreEqual ( player - > GetAbility2 ( ) . GetCooldownTime ( ) , player - > GetAbility2 ( ) . cooldown , L " Same ability used should not be affected. " ) ;
Assert : : AreEqual ( player - > GetAbility3 ( ) . GetCooldownTime ( ) - 3.f , player - > GetAbility3 ( ) . cooldown , L " All other abilities have cooldowns reduced by 1.5 seconds. " ) ;
Assert : : AreEqual ( player - > GetAbility4 ( ) . GetCooldownTime ( ) - 3.f , player - > GetAbility4 ( ) . cooldown , L " All other abilities have cooldowns reduced by 1.5 seconds. " ) ;
player - > SetState ( State : : NORMAL ) ;
player - > RestoreMana ( 100 ) ;
player - > GetAbility3 ( ) . charges = 1 ; //Reset the cooldown so it can be used.
player - > GetAbility3 ( ) . cooldown = 0.f ; //Reset the cooldown so it can be used.
player - > CheckAndPerformAbility ( player - > GetAbility3 ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( player - > GetRightClickAbility ( ) . GetCooldownTime ( ) , player - > GetRightClickAbility ( ) . cooldown , L " Right-click ability remains unaffected by other abilities. " ) ;
Assert : : AreEqual ( player - > GetAbility1 ( ) . GetCooldownTime ( ) - 3.f , player - > GetAbility1 ( ) . cooldown , L " All other abilities have cooldowns reduced by 1.5 seconds. " ) ;
Assert : : AreEqual ( player - > GetAbility2 ( ) . GetCooldownTime ( ) - 1.5f , player - > GetAbility2 ( ) . cooldown , L " All other abilities have cooldowns reduced by 1.5 seconds. " ) ;
Assert : : AreEqual ( player - > GetAbility3 ( ) . GetCooldownTime ( ) , player - > GetAbility3 ( ) . cooldown , L " Same ability used should not be affected. " ) ;
Assert : : AreEqual ( player - > GetAbility4 ( ) . GetCooldownTime ( ) - 4.5f , player - > GetAbility4 ( ) . cooldown , L " All other abilities have cooldowns reduced by 1.5 seconds. " ) ;
player - > SetState ( State : : NORMAL ) ;
player - > RestoreMana ( 100 ) ;
player - > GetAbility4 ( ) . charges = 1 ; //Reset the cooldown so it can be used.
player - > GetAbility4 ( ) . cooldown = 0.f ; //Reset the cooldown so it can be used.
player - > CheckAndPerformAbility ( player - > GetAbility4 ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( player - > GetRightClickAbility ( ) . GetCooldownTime ( ) , player - > GetRightClickAbility ( ) . cooldown , L " Right-click ability remains unaffected by other abilities. " ) ;
Assert : : AreEqual ( player - > GetAbility1 ( ) . GetCooldownTime ( ) - 3.f , player - > GetAbility1 ( ) . cooldown , L " Ability 4 isn't setup for anything and returns as unused, causing cooldowns to remain the same. " ) ;
Assert : : AreEqual ( player - > GetAbility2 ( ) . GetCooldownTime ( ) - 1.5f , player - > GetAbility2 ( ) . cooldown , L " Ability 4 isn't setup for anything and returns as unused, causing cooldowns to remain the same. " ) ;
Assert : : AreEqual ( player - > GetAbility3 ( ) . GetCooldownTime ( ) , player - > GetAbility3 ( ) . cooldown , L " Ability 4 isn't setup for anything and returns as unused, causing cooldowns to remain the same. " ) ;
Assert : : AreEqual ( player - > GetAbility4 ( ) . GetCooldownTime ( ) , player - > GetAbility4 ( ) . cooldown , L " Ability 4 isn't setup for anything and returns as unused, causing cooldowns to remain the same. " ) ;
}
TEST_METHOD ( LastReserveCheck ) {
player - > SetBaseStat ( " Attack " , 100.f ) ;
Assert : : AreEqual ( 0.0 _Pct , player - > GetDamageReductionFromBuffs ( ) , L " Damage reduction starts at 0% " ) ;
Assert : : AreEqual ( 100 , player - > GetAttack ( ) , L " Attack damage starts at 100. " ) ;
Assert : : AreEqual ( 0.0 _Pct , player - > GetCooldownReductionPct ( ) , L " Cooldown reduction starts at 0% " ) ;
Game : : GiveAndEquipEnchantedRing ( " Last Reserve " ) ;
Assert : : AreEqual ( 0.0 _Pct , player - > GetDamageReductionFromBuffs ( ) , L " Damage reduction is still 0% " ) ;
Assert : : AreEqual ( 100 , player - > GetAttack ( ) , L " Attack damage still 100. " ) ;
Assert : : AreEqual ( 0.0 _Pct , player - > GetCooldownReductionPct ( ) , L " Cooldown reduction is still 0% " ) ;
player - > Hurt ( 80 , player - > OnUpperLevel ( ) , player - > GetZ ( ) ) ;
Assert : : AreEqual ( 30.0 _Pct , player - > GetDamageReductionFromBuffs ( ) , L " Damage reduction increased to 30% " ) ;
Assert : : AreEqual ( 110 , player - > GetAttack ( ) , L " Attack damage is now 110. " ) ;
Assert : : AreEqual ( 10.0 _Pct , player - > GetCooldownReductionPct ( ) , L " Cooldown reduction increased to 10% " ) ;
}
TEST_METHOD ( QuickdrawCheck ) {
MonsterData testMonsterData { " TestName " , " Test Monster " , 30 , 10 , 5 , { MonsterDropData { " Health Potion " , 100.f , 1 , 1 } } , 200.f } ;
MONSTER_DATA [ " TestName " ] = testMonsterData ;
Monster testMonster { { } , MONSTER_DATA [ " TestName " ] } ;
player - > AutoAttack ( ) ; //Put auto attack on cooldown.
for ( int i : std : : ranges : : iota_view ( 0 , 20 ) ) {
testMonster . Hurt ( 0 , testMonster . OnUpperLevel ( ) , testMonster . GetZ ( ) ) ;
Assert : : AreEqual ( " Warrior.Auto Attack.Cooldown " _F , player - > GetAutoAttackTimer ( ) , L " The auto attack timer should not be reduced: No enchant + wasn't hit by a player ability. " ) ;
}
for ( int i : std : : ranges : : iota_view ( 0 , 20 ) ) {
testMonster . Hurt ( 0 , testMonster . OnUpperLevel ( ) , testMonster . GetZ ( ) , HurtFlag : : PLAYER_ABILITY ) ;
Assert : : AreEqual ( " Warrior.Auto Attack.Cooldown " _F , player - > GetAutoAttackTimer ( ) , L " The auto attack timer should not be reduced: No enchant. " ) ;
}
Game : : GiveAndEquipEnchantedRing ( " Quickdraw " ) ;
for ( int i : std : : ranges : : iota_view ( 0 , 20 ) ) {
testMonster . Hurt ( 0 , testMonster . OnUpperLevel ( ) , testMonster . GetZ ( ) ) ;
Assert : : AreEqual ( " Warrior.Auto Attack.Cooldown " _F , player - > GetAutoAttackTimer ( ) , L " The auto attack timer should not be reduced: Wasn't hit by a player ability. " ) ;
}
for ( int i : std : : ranges : : iota_view ( 0 , 20 ) ) {
testMonster . Hurt ( 0 , testMonster . OnUpperLevel ( ) , testMonster . GetZ ( ) , HurtFlag : : PLAYER_ABILITY ) ;
}
Assert : : AreEqual ( 0.f , player - > GetAutoAttackTimer ( ) , L " The auto attack timer should have been reset at some point. " ) ;
}
TEST_METHOD ( StealthyRetreatCheck ) {
Game : : ChangeClass ( player , RANGER ) ;
player - > CheckAndPerformAbility ( player - > GetRightClickAbility ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( " Ranger.Right Click Ability.RetreatTime " _F , player - > GetIframeTime ( ) , L " Ranger's retreat iframe time is normal. " ) ;
player - > _SetIframes ( 0.f ) ;
player - > GetRightClickAbility ( ) . charges = 1 ;
player - > SetState ( State : : NORMAL ) ;
Game : : GiveAndEquipEnchantedRing ( " Stealthy Retreat " ) ;
player - > CheckAndPerformAbility ( player - > GetRightClickAbility ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( " Ranger.Right Click Ability.RetreatTime " _F + " Stealthy Retreat " _ENC [ " INVULNERABILITY INCREASE " ] , player - > GetIframeTime ( ) , L " Ranger's retreat iframe time is much greater. " ) ;
}
TEST_METHOD ( PoisonousArrowCheck ) {
Game : : ChangeClass ( player , RANGER ) ;
Assert : : AreEqual ( false , player - > PoisonArrowAutoAttackReady ( ) , L " Poison arrow auto attack should not be ready immediately. " ) ;
Game : : GiveAndEquipEnchantedRing ( " Poisonous Arrow " ) ;
Assert : : AreEqual ( true , player - > PoisonArrowAutoAttackReady ( ) , L " Poison arrow auto attack should now be ready. " ) ;
player - > AutoAttack ( ) ;
Assert : : AreEqual ( false , player - > PoisonArrowAutoAttackReady ( ) , L " Poison arrow auto attack should now be on cooldown. " ) ;
Game : : Update ( " Poisonous Arrow " _ENC [ " POISON ARROW RESET FREQUENCY " ] ) ;
Assert : : AreEqual ( true , player - > PoisonArrowAutoAttackReady ( ) , L " Poison arrow auto attack should be ready again. " ) ;
}
TEST_METHOD ( ExtremeRapidFireCheck ) {
Game : : ChangeClass ( player , RANGER ) ;
Assert : : AreEqual ( 0 , player - > RemainingRapidFireShots ( ) , L " Player starts off with no Rapid Fire shots available. " ) ;
player - > CheckAndPerformAbility ( player - > GetAbility1 ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( " Ranger.Ability 1.ArrowCount " _I , player - > RemainingRapidFireShots ( ) , L " Player now has normal Rapid Fire shot count. " ) ;
for ( int i : std : : ranges : : iota_view ( 0 , " Ranger.Ability 1.ArrowCount " _I ) ) {
Game : : Update ( 1.f ) ;
}
player - > SetState ( State : : NORMAL ) ;
player - > GetAbility1 ( ) . charges = 1 ;
Game : : GiveAndEquipEnchantedRing ( " Extreme Rapid Fire " ) ;
player - > CheckAndPerformAbility ( player - > GetAbility1 ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( " Ranger.Ability 1.ArrowCount " _I + int ( " Extreme Rapid Fire " _ENC [ " ARROW COUNT INCREASE " ] ) , player - > RemainingRapidFireShots ( ) , L " Player now has even more Rapid Fire shots. " ) ;
}
TEST_METHOD ( MegaChargedShotCheck ) {
Game : : GiveAndEquipEnchantedRing ( " Mega Charged Shot " ) ;
Assert : : AreEqual ( " Warrior.Ability 2.Precast Time " _F , player - > GetAbility2 ( ) . precastInfo . castTime , L " Non-Ranger class' precast times should be unaffected with the item. " ) ;
Game : : ChangeClass ( player , RANGER ) ;
Assert : : AreEqual ( " Ranger.Ability 2.Precast Time " _F + " Mega Charged Shot " _ENC [ " CAST TIME INCREASE " ] , player - > GetAbility2 ( ) . precastInfo . castTime , L " Ranger class' precast time should be affected with the item. " ) ;
Inventory : : UnequipItem ( EquipSlot : : RING1 ) ;
Assert : : AreEqual ( " Ranger.Ability 2.Precast Time " _F , player - > GetAbility2 ( ) . precastInfo . castTime , L " Ranger class' precast time should be back to normal. " ) ;
}
TEST_METHOD ( MultiMultiShotCheck ) {
Game : : ChangeClass ( player , RANGER ) ;
Assert : : AreEqual ( uint8_t ( 1 ) , player - > GetAbility3 ( ) . MAX_CHARGES , L " Player starts with 1 max charge of Multishot. " ) ;
const float multishotCooldownTime { " Ranger.Ability 3.Cooldown " _F } ;
Assert : : AreEqual ( " Ranger.Ability 3.Cooldown " _F , player - > GetAbility3 ( ) . GetCooldownTime ( ) , util : : wformat ( " Player starts with {} seconds of cooldown on Multishot. " , multishotCooldownTime ) . c_str ( ) ) ;
Game : : GiveAndEquipEnchantedRing ( " Multi-Multishot " ) ;
Assert : : AreEqual ( uint8_t ( 3 ) , player - > GetAbility3 ( ) . MAX_CHARGES , L " Player now has 3 max charges of Multishot. " ) ;
const float newMultishotCooldownTime { multishotCooldownTime - multishotCooldownTime * " Multi-Multishot " _ENC [ " COOLDOWN REDUCTION PCT " ] / 100.f } ;
Assert : : AreEqual ( newMultishotCooldownTime , player - > GetAbility3 ( ) . GetCooldownTime ( ) , util : : wformat ( " Player starts with {} seconds of cooldown on Multishot. " , newMultishotCooldownTime ) . c_str ( ) ) ;
}
TEST_METHOD ( BackstabberCheck ) {
MonsterData testMonsterData { " TestName " , " Test Monster " , 30 , 10 , 5 , { MonsterDropData { " Health Potion " , 100.f , 1 , 1 } } , 200.f } ;
MONSTER_DATA [ " TestName " ] = testMonsterData ;
Monster testMonster { { } , MONSTER_DATA [ " TestName " ] } ;
testMonster . Hurt ( 10 , testMonster . OnUpperLevel ( ) , testMonster . GetZ ( ) ) ;
Assert : : AreEqual ( 20 , testMonster . GetHealth ( ) , L " Monster should have taken 10 hitpoints of damage. " ) ;
testMonster . Heal ( 10 ) ;
game - > GetPlayer ( ) - > ForceSetPos ( { 4 , 0 } ) ;
testMonster . Hurt ( 10 , testMonster . OnUpperLevel ( ) , testMonster . GetZ ( ) , HurtFlag : : PLAYER_ABILITY ) ;
Assert : : AreEqual ( 20 , testMonster . GetHealth ( ) , L " Monster should have taken 10 hitpoints of damage even if the attack was a valid backstab (no enchantment). " ) ;
Game : : GiveAndEquipEnchantedRing ( " Backstabber " ) ;
game - > GetPlayer ( ) - > ForceSetPos ( { 0 , 0 } ) ;
testMonster . Hurt ( 10 , testMonster . OnUpperLevel ( ) , testMonster . GetZ ( ) ) ;
Assert : : AreEqual ( 10 , testMonster . GetHealth ( ) , L " Monster should have taken 10 hitpoints of damage still since it wasn't flagged as a player ability. " ) ;
testMonster . Heal ( 30 ) ;
testMonster . Hurt ( 10 , testMonster . OnUpperLevel ( ) , testMonster . GetZ ( ) , HurtFlag : : PLAYER_ABILITY ) ;
Assert : : AreEqual ( 20 , testMonster . GetHealth ( ) , L " Monster should have taken 10 hitpoints of damage with the backstab bonus because the player is not behind the target. " ) ;
game - > GetPlayer ( ) - > ForceSetPos ( { 4 , 0 } ) ;
testMonster . Hurt ( 10 , testMonster . OnUpperLevel ( ) , testMonster . GetZ ( ) , HurtFlag : : PLAYER_ABILITY ) ;
Assert : : AreEqual ( 6 , testMonster . GetHealth ( ) , L " Monster should have taken 14 hitpoints of damage with the backstab bonus successfully applied. " ) ;
}
TEST_METHOD ( TumbleCheck ) {
Game : : ChangeClass ( player , THIEF ) ;
player - > CheckAndPerformAbility ( player - > GetRightClickAbility ( ) , testKeyboardInput ) ;
const float originalIframeTime { " Thief.Right Click Ability.Iframe Time " _F } ;
Assert : : AreEqual ( originalIframeTime , player - > GetIframeTime ( ) , L " Iframe time should be normal. " ) ;
const float originalMovespdIntensity { " Thief.Right Click Ability.Movespeed Buff " _f [ 0 ] / 100.f } ;
Assert : : AreEqual ( originalMovespdIntensity , player - > GetBuffs ( BuffType : : SPEEDBOOST ) [ 0 ] . intensity , L " Player should have a movespeed buff of the regular intensity. " ) ;
player - > RemoveAllBuffs ( ) ;
player - > GetRightClickAbility ( ) . charges = 1 ;
Game : : GiveAndEquipEnchantedRing ( " Tumble " ) ;
player - > CheckAndPerformAbility ( player - > GetRightClickAbility ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( originalIframeTime + " Thief.Right Click Ability.Iframe Time " _F * " Tumble " _ENC [ " BOOST PERCENTAGE " ] / 100.f , player - > GetIframeTime ( ) , L " Iframe time should be longer. " ) ;
Assert : : AreEqual ( originalMovespdIntensity + originalMovespdIntensity * " Tumble " _ENC [ " BOOST PERCENTAGE " ] / 100.f , player - > GetBuffs ( BuffType : : SPEEDBOOST ) [ 0 ] . intensity , L " Player should have a movespeed buff with greater intensity. " ) ;
}
TEST_METHOD ( TripleTossCheck ) {
Game : : ChangeClass ( player , THIEF ) ;
player - > SetTestScreenAimingLocation ( player - > GetPos ( ) + vf2d { 30.f , 0.f } ) ;
player - > CheckAndPerformAbility ( player - > GetAbility1 ( ) , testKeyboardInput ) ;
Game : : Update ( 0.5f ) ;
Assert : : AreEqual ( size_t ( 1 ) , BULLET_LIST . size ( ) , L " Only 1 dagger has spawned without the Triple Toss enchant. " ) ;
Game : : GiveAndEquipEnchantedRing ( " Triple Toss " ) ;
player - > GetAbility1 ( ) . charges + + ;
player - > CheckAndPerformAbility ( player - > GetAbility1 ( ) , testKeyboardInput ) ;
Game : : Update ( 0.5f ) ;
Assert : : AreEqual ( size_t ( 4 ) , BULLET_LIST . size ( ) , L " The Triple Toss enchant should add 3 more daggers to the list. " ) ;
}
TEST_METHOD ( DeadlyMirageCheck ) {
Game : : ChangeClass ( player , THIEF ) ;
player - > CheckAndPerformAbility ( player - > GetAbility2 ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( uint8_t ( 0 ) , Thief : : ability2 . charges , L " Deadly Dash's charges should've been used up. " ) ;
Assert : : AreEqual ( " Thief.Ability 2.Mana Cost " _I , Thief : : ability2 . manaCost , L " Deadly Dash's mana cost is normal. " ) ;
Assert : : AreEqual ( " Thief.Ability 2.Cooldown " _F , Thief : : ability2 . cooldown , L " Deadly Dash's cooldown should've been used up. " ) ;
Thief : : ability2 . charges = 1 ;
Thief : : ability2 . cooldown = 0.f ;
player - > SetState ( State : : NORMAL ) ;
Game : : GiveAndEquipEnchantedRing ( " Deadly Mirage " ) ;
player - > CheckAndPerformAbility ( player - > GetAbility2 ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( uint8_t ( 1 ) , Thief : : ability2 . charges , L " Deadly Dash should be available to use again. " ) ;
Assert : : AreEqual ( 0.f , Thief : : ability2 . cooldown , L " Deadly Dash should no longer be on cooldown. " ) ;
Assert : : AreEqual ( 0 , Thief : : ability2 . manaCost , L " Deadly Dash's mana cost should be zero. " ) ;
Assert : : AreEqual ( " Deadly Mirage " _ENC [ " REACTIVATE TIMING WINDOW " ] , player - > GetTimer ( PlayerTimerType : : DEADLY_MIRAGE_SECOND_CAST ) . RemainingTime ( ) , L " Deadly Mirage's second cast timer should have started. " ) ;
player - > SetState ( State : : NORMAL ) ;
player - > CheckAndPerformAbility ( player - > GetAbility2 ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( uint8_t ( 0 ) , Thief : : ability2 . charges , L " Deadly Dash should have been used up. " ) ;
Assert : : AreEqual ( " Thief.Ability 2.Cooldown " _F , Thief : : ability2 . cooldown , L " Deadly Dash should now be on cooldown " ) ;
Assert : : AreEqual ( " Thief.Ability 2.Mana Cost " _I , Thief : : ability2 . manaCost , L " Deadly Dash's mana cost is back to normal. " ) ;
Assert : : AreEqual ( true , player - > GetTimer ( PlayerTimerType : : DEADLY_MIRAGE_SECOND_CAST ) . IsDone ( ) , L " Deadly Mirage's second cast timer should have been cancelled. " ) ;
Thief : : ability2 . charges = 1 ;
Thief : : ability2 . cooldown = 0.f ;
player - > RestoreMana ( 100 ) ;
player - > SetState ( State : : NORMAL ) ;
player - > CheckAndPerformAbility ( player - > GetAbility2 ( ) , testKeyboardInput ) ;
Game : : Update ( " Deadly Mirage " _ENC [ " REACTIVATE TIMING WINDOW " ] + 1.f ) ;
Assert : : AreEqual ( uint8_t ( 0 ) , Thief : : ability2 . charges , L " Deadly Dash should no longer be useable. " ) ;
Assert : : AreEqual ( " Thief.Ability 2.Mana Cost " _I , Thief : : ability2 . manaCost , L " Deadly Dash's mana cost is back to normal. " ) ;
Assert : : AreEqual ( " Thief.Ability 2.Cooldown " _F - 3.f , Thief : : ability2 . cooldown , L " Deadly Dash should now be on cooldown " ) ;
}
TEST_METHOD ( AdrenalineStimCheck ) {
Game : : ChangeClass ( player , THIEF ) ;
player - > CheckAndPerformAbility ( player - > GetAbility3 ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( " Thief.Ability 3.Duration " _F , player - > GetBuffs ( BuffType : : ADRENALINE_RUSH ) [ 0 ] . duration , L " Adrenaline Rush buff duration is normal. " ) ;
Assert : : AreEqual ( 100 , player - > GetHealth ( ) , L " Adrenaline Rush does not reduce health. " ) ;
Assert : : AreEqual ( " Thief.Auto Attack.Cooldown " _F * " Thief.Ability 3.Attack Speed Increase " _F / 100.f , player - > GetAttackRecoveryRateReduction ( ) , L " Adrenaline Rush boosts attack rate normally. " ) ;
Assert : : AreEqual ( " Thief.Auto Attack.Range " _F , player - > GetAttackRange ( ) , L " Adrenaline Rush does not boost attack range. " ) ;
Thief : : ability3 . charges = 1 ;
player - > RestoreMana ( 100 ) ;
player - > RemoveAllBuffs ( ) ;
Game : : GiveAndEquipEnchantedRing ( " Adrenaline Stim " ) ;
player - > CheckAndPerformAbility ( player - > GetAbility3 ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( " Adrenaline Stim " _ENC [ " NEW ADRENALINE RUSH DURATION " ] , player - > GetBuffs ( BuffType : : ADRENALINE_RUSH ) [ 0 ] . duration , L " Adrenaline Stim enchant boosts the duration of Adrenaline Rush. " ) ;
Assert : : AreEqual ( 80 , player - > GetHealth ( ) , L " Adrenaline Stim reduces health. " ) ;
Assert : : AreEqual ( " Thief.Auto Attack.Cooldown " _F * " Thief.Ability 3.Attack Speed Increase " _F / 100.f , player - > GetAttackRecoveryRateReduction ( ) , L " Adrenaline Stim still boosts attack rate normally. " ) ;
Assert : : AreEqual ( " Thief.Auto Attack.Range " _F + " Thief.Auto Attack.Range " _F * " Adrenaline Stim " _ENC [ " ATTACK RANGE INCREASE PCT " ] / 100.f , player - > GetAttackRange ( ) , L " Adrenaline Stim boosts attack range. " ) ;
}
TEST_METHOD ( BloodlustCheck ) {
Game : : ChangeClass ( player , THIEF ) ;
player - > SetBaseStat ( " Attack " , 100 ) ;
player - > CheckAndPerformAbility ( player - > GetAbility3 ( ) , testKeyboardInput ) ;
MonsterData testMonsterData { " TestName " , " Test Monster " , 30 , 10 , 5 , { MonsterDropData { " Health Potion " , 100.f , 1 , 1 } } , 200.f } ;
MONSTER_DATA [ " TestName " ] = testMonsterData ;
for ( int i : std : : ranges : : iota_view ( 0 , 10 ) ) {
Monster testMonster { { } , MONSTER_DATA [ " TestName " ] } ;
testMonster . Hurt ( 1000 , testMonster . OnUpperLevel ( ) , testMonster . GetZ ( ) ) ;
}
Assert : : AreEqual ( 100 , player - > GetAttack ( ) , L " Bloodlust's bonus attack should not be applying here. " ) ;
Assert : : AreEqual ( " Thief.Ability 3.Duration " _F , player - > GetBuffs ( BuffType : : ADRENALINE_RUSH ) [ 0 ] . duration , L " Bloodlust's duration increase should not be applying here. " ) ;
player - > RestoreMana ( 100 ) ;
player - > RemoveAllBuffs ( ) ;
Thief : : ability3 . charges = 1 ;
Game : : GiveAndEquipEnchantedRing ( " Bloodlust " ) ;
player - > CheckAndPerformAbility ( player - > GetAbility3 ( ) , testKeyboardInput ) ;
for ( int i : std : : ranges : : iota_view ( 0 , 30 ) ) {
Monster testMonster { { } , MONSTER_DATA [ " TestName " ] } ;
testMonster . Hurt ( 1000 , testMonster . OnUpperLevel ( ) , testMonster . GetZ ( ) ) ;
}
Assert : : AreEqual ( 110 , player - > GetAttack ( ) , L " Bloodlust's bonus attacks stack only to 10. " ) ;
Assert : : AreEqual ( " Thief.Ability 3.Duration " _F + " Bloodlust " _ENC [ " BUFF TIMER INCREASE " ] * 30 , player - > GetBuffs ( BuffType : : ADRENALINE_RUSH ) [ 0 ] . duration , L " Bloodlust's duration increases per kill. " ) ;
}
TEST_METHOD ( EvasiveMovementCheck ) {
Game : : ChangeClass ( player , THIEF ) ;
player - > CheckAndPerformAbility ( player - > GetRightClickAbility ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( size_t ( 0 ) , player - > GetBuffs ( BuffType : : DAMAGE_REDUCTION ) . size ( ) , L " Roll doesn't give a damage reduction buff. " ) ;
player - > GetRightClickAbility ( ) . charges = 1 ;
Game : : GiveAndEquipEnchantedRing ( " Evasive Movement " ) ;
player - > CheckAndPerformAbility ( player - > GetRightClickAbility ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( size_t ( 1 ) , player - > GetBuffs ( BuffType : : DAMAGE_REDUCTION ) . size ( ) , L " Roll gives a damage reduction buff. " ) ;
Assert : : AreEqual ( " Evasive Movement " _ENC [ " DAMAGE REDUCTION PCT " ] / 100.f , player - > GetDamageReductionFromBuffs ( ) , L " Evasive Movement provides 50% damage reduction. " ) ;
}
TEST_METHOD ( BurningArrowCheck ) {
Game : : ChangeClass ( player , TRAPPER ) ;
player - > AutoAttack ( ) ;
Assert : : AreEqual ( size_t ( 1 ) , BULLET_LIST . size ( ) , L " Arrow projectile should now exist. " ) ;
Monster testMonster { { } , MONSTER_DATA [ " TestName " ] } ;
BULLET_LIST . back ( ) - > MonsterHit ( testMonster , testMonster . GetMarkStacks ( ) ) ;
Game : : Update ( 0.4f ) ;
Assert : : AreEqual ( size_t ( 0 ) , BULLET_LIST . size ( ) , L " No more projectiles exist. " ) ;
Assert : : AreEqual ( size_t ( 0 ) , testMonster . GetBuffs ( BuffType : : BURNING_ARROW_BURN ) . size ( ) , L " Target is not burned. " ) ;
player - > ReduceAutoAttackTimer ( INFINITE ) ;
player - > AutoAttack ( ) ;
Game : : GiveAndEquipEnchantedRing ( " Burning Arrow " ) ;
Assert : : AreEqual ( size_t ( 1 ) , BULLET_LIST . size ( ) , L " Arrow projectile should now exist. " ) ;
BULLET_LIST . back ( ) - > MonsterHit ( testMonster , testMonster . GetMarkStacks ( ) ) ;
Game : : Update ( 0.4f ) ;
Assert : : AreEqual ( size_t ( 0 ) , BULLET_LIST . size ( ) , L " No more projectiles exist. " ) ;
Assert : : AreEqual ( size_t ( 0 ) , testMonster . GetBuffs ( BuffType : : BURNING_ARROW_BURN ) . size ( ) , L " Target should still not be burned since there are no marks on the target. " ) ;
player - > ReduceAutoAttackTimer ( INFINITE ) ;
Monster & newMonster { game - > SpawnMonster ( { } , MONSTER_DATA [ " TestName " ] ) } ;
Game : : Update ( 0.01f ) ;
player - > _ForceCastSpell ( player - > GetAbility1 ( ) ) ;
Game : : Update ( " Trapper.Ability 1.Precast Time " _F ) ;
Game : : Update ( 0.6f ) ; //Wait for mark lock-on
player - > AutoAttack ( ) ;
Assert : : AreEqual ( size_t ( 1 ) , BULLET_LIST . size ( ) , L " Arrow projectile should now exist. " ) ;
BULLET_LIST . back ( ) - > MonsterHit ( newMonster , newMonster . GetMarkStacks ( ) ) ;
Game : : Update ( 0.4f ) ;
Assert : : AreEqual ( size_t ( 0 ) , BULLET_LIST . size ( ) , L " No more projectiles exist. " ) ;
Assert : : AreEqual ( size_t ( 1 ) , newMonster . GetBuffs ( BuffType : : BURNING_ARROW_BURN ) . size ( ) , L " Target should be burned since there are marks on the target and we have the Burning Arrow enchant. " ) ;
}
TEST_METHOD ( BurningArrowTripleStackCheck ) {
Game : : ChangeClass ( player , TRAPPER ) ;
Game : : GiveAndEquipEnchantedRing ( " Burning Arrow " ) ;
Monster & newMonster { game - > SpawnMonster ( { } , MONSTER_DATA [ " TestName " ] ) } ;
Game : : Update ( 0.01f ) ;
player - > _ForceCastSpell ( player - > GetAbility1 ( ) ) ;
game - > SetElapsedTime ( " Trapper.Ability 1.Precast Time " _F ) ;
game - > OnUserUpdate ( " Trapper.Ability 1.Precast Time " _F ) ;
Game : : Update ( 0.6f ) ; //Wait for mark lock-on
player - > ReduceAutoAttackTimer ( INFINITE ) ;
player - > AutoAttack ( ) ;
BULLET_LIST . back ( ) - > MonsterHit ( newMonster , newMonster . GetMarkStacks ( ) ) ;
player - > ReduceAutoAttackTimer ( INFINITE ) ;
player - > AutoAttack ( ) ;
BULLET_LIST . back ( ) - > MonsterHit ( newMonster , newMonster . GetMarkStacks ( ) ) ;
player - > ReduceAutoAttackTimer ( INFINITE ) ;
player - > AutoAttack ( ) ;
BULLET_LIST . back ( ) - > MonsterHit ( newMonster , newMonster . GetMarkStacks ( ) ) ;
player - > ReduceAutoAttackTimer ( INFINITE ) ;
player - > AutoAttack ( ) ;
BULLET_LIST . back ( ) - > MonsterHit ( newMonster , newMonster . GetMarkStacks ( ) ) ;
player - > ReduceAutoAttackTimer ( INFINITE ) ;
player - > AutoAttack ( ) ;
BULLET_LIST . back ( ) - > MonsterHit ( newMonster , newMonster . GetMarkStacks ( ) ) ;
Game : : Update ( 0.4f ) ;
Assert : : AreEqual ( size_t ( 0 ) , BULLET_LIST . size ( ) , L " No more projectiles exist. " ) ;
Assert : : AreEqual ( size_t ( " Burning Arrow " _ENC [ " MAX BURN STACK " ] ) , newMonster . GetBuffs ( BuffType : : BURNING_ARROW_BURN ) . size ( ) , L " Only 3 burn ticks maximum are allowed. " ) ;
player - > ReduceAutoAttackTimer ( INFINITE ) ;
player - > AutoAttack ( ) ;
}
TEST_METHOD ( EnfeebledTargetNoEnchantCheck ) {
Game : : ChangeClass ( player , TRAPPER ) ;
Monster & newMonster { game - > SpawnMonster ( { } , MONSTER_DATA [ " TestName " ] ) } ;
Game : : Update ( 0.01f ) ;
player - > _ForceCastSpell ( player - > GetAbility1 ( ) ) ;
Game : : Update ( " Trapper.Ability 1.Precast Time " _F ) ;
Game : : Update ( 0.6f ) ; //Wait for mark lock-on
Assert : : AreEqual ( 2.f , newMonster . GetMoveSpdMult ( ) , L " Move Spd Multiplier should not be reduced by 30% " ) ;
Assert : : AreEqual ( 10 , newMonster . GetAttack ( ) , L " Monster Attack damage should not be reduced. " ) ;
}
TEST_METHOD ( EnfeebledTargetEnchantCheck ) {
Game : : ChangeClass ( player , TRAPPER ) ;
Game : : GiveAndEquipEnchantedRing ( " Enfeebled Target " ) ;
Monster & newMonster { game - > SpawnMonster ( { } , MONSTER_DATA [ " TestName " ] ) } ;
Game : : Update ( 0.01f ) ;
player - > _ForceCastSpell ( player - > GetAbility1 ( ) ) ;
Game : : Update ( " Trapper.Ability 1.Precast Time " _F ) ;
Game : : Update ( 0.6f ) ; //Wait for mark lock-on
Assert : : AreEqual ( 1.4f , newMonster . GetMoveSpdMult ( ) , L " Move Spd Multiplier should be reduced by 30% " ) ;
Assert : : AreEqual ( 8 , newMonster . GetAttack ( ) , L " Monster Attack damage should be reduced. " ) ;
}
TEST_METHOD ( LongLastingMarkNoEnchantCheck ) {
Game : : ChangeClass ( player , TRAPPER ) ;
Monster & newMonster { game - > SpawnMonster ( { } , MONSTER_DATA [ " TestName " ] ) } ;
Game : : Update ( 0.01f ) ;
player - > _ForceCastSpell ( player - > GetAbility1 ( ) ) ;
Game : : Update ( " Trapper.Ability 1.Precast Time " _F ) ;
Game : : Update ( 0.f ) ;
Assert : : AreEqual ( 7.f , newMonster . GetBuffs ( BuffType : : TRAPPER_MARK ) [ 0 ] . duration , L " Mark duration is unaffected. " ) ;
}
TEST_METHOD ( LongLastingMarkEnchantCheck ) {
Game : : ChangeClass ( player , TRAPPER ) ;
Game : : GiveAndEquipEnchantedRing ( " Long-Lasting Mark " ) ;
Monster & newMonster { game - > SpawnMonster ( { } , MONSTER_DATA [ " TestName " ] ) } ;
Game : : Update ( 0.01f ) ;
player - > _ForceCastSpell ( player - > GetAbility1 ( ) ) ;
Game : : Update ( " Trapper.Ability 1.Precast Time " _F ) ;
Game : : Update ( 0.f ) ; //Wait for mark lock-on
Assert : : AreEqual ( 20.f , newMonster . GetBuffs ( BuffType : : TRAPPER_MARK ) [ 0 ] . duration , L " Mark duration is increased greatly. " ) ;
}
TEST_METHOD ( TrapCollectorNoEnchantCheck ) {
Game : : ChangeClass ( player , TRAPPER ) ;
Assert : : AreEqual ( uint8_t ( 1 ) , Trapper : : ability2 . MAX_CHARGES , L " Normally Bear Trap only has one charge. " ) ;
Assert : : AreEqual ( uint8_t ( 1 ) , Trapper : : ability3 . MAX_CHARGES , L " Normally Explosive Trap only has one charge. " ) ;
}
TEST_METHOD ( TrapCollectorEnchantCheck ) {
Game : : ChangeClass ( player , TRAPPER ) ;
Game : : GiveAndEquipEnchantedRing ( " Trap Collector " ) ;
Assert : : AreEqual ( uint8_t ( 2 ) , Trapper : : ability2 . MAX_CHARGES , L " Trap Collector enchant increases Bear Trap charges to two. " ) ;
Assert : : AreEqual ( uint8_t ( 2 ) , Trapper : : ability3 . MAX_CHARGES , L " Trap Collector enchant increases Explosive Trap charges to two. " ) ;
}
TEST_METHOD ( LingeringScentNoEnchantCheck ) {
Game : : ChangeClass ( player , TRAPPER ) ;
Monster & newMonster { game - > SpawnMonster ( { } , MONSTER_DATA [ " TestName " ] ) } ;
player - > CheckAndPerformAbility ( player - > GetAbility2 ( ) , testKeyboardInput ) ;
Game : : Update ( 0.5f ) ;
BearTrap trap { * ( BearTrap * ) BULLET_LIST . back ( ) . get ( ) } ;
trap . MonsterHit ( newMonster , 1 ) ; //Simulate 1 mark stack on the monster to trigger the bleed.
Assert : : AreEqual ( " Trapper.Ability 2.Marked Target Bleed " _f [ 1 ] , newMonster . GetBuffs ( BuffType : : OVER_TIME ) [ 0 ] . duration , L " Bleed duration should be 10 seconds by default. " ) ;
}
TEST_METHOD ( LingeringScentEnchantCheck ) {
Game : : ChangeClass ( player , TRAPPER ) ;
Game : : GiveAndEquipEnchantedRing ( " Lingering Scent " ) ;
Monster & newMonster { game - > SpawnMonster ( { } , MONSTER_DATA [ " TestName " ] ) } ;
player - > CheckAndPerformAbility ( player - > GetAbility2 ( ) , testKeyboardInput ) ;
Game : : Update ( 0.5f ) ;
BearTrap trap { * ( BearTrap * ) BULLET_LIST . back ( ) . get ( ) } ;
trap . MonsterHit ( newMonster , 1 ) ; //Simulate 1 mark stack on the monster to trigger the bleed.
Assert : : AreEqual ( " Trapper.Ability 2.Marked Target Bleed " _f [ 1 ] + " Lingering Scent " _ENC [ " BLEED EXTRA DURATION " ] , newMonster . GetBuffs ( BuffType : : OVER_TIME ) [ 0 ] . duration , L " Bleed duration should be 10 seconds by default. " ) ;
}
TEST_METHOD ( OpportunityShotNoEnchantCheck ) {
Game : : ChangeClass ( player , TRAPPER ) ;
Monster & newMonster { game - > SpawnMonster ( { } , MONSTER_DATA [ " TestName " ] ) } ;
for ( int i : std : : ranges : : iota_view ( 0 , 10 ) ) {
Game : : Update ( 1.f ) ;
}
Assert : : AreEqual ( size_t ( 0 ) , newMonster . GetBuffs ( BuffType : : SPECIAL_MARK ) . size ( ) , L " A special mark should not be spawned without the enchant. " ) ;
}
TEST_METHOD ( OpportunityShotEnchantCheck ) {
Game : : ChangeClass ( player , TRAPPER ) ;
player - > OnLevelStart ( ) ;
Game : : GiveAndEquipEnchantedRing ( " Opportunity Shot " ) ;
Monster & newMonster { game - > SpawnMonster ( { } , MONSTER_DATA [ " TestName " ] ) } ;
for ( int i : std : : ranges : : iota_view ( 0 , 10 ) ) {
Game : : Update ( 1.f ) ;
}
Assert : : AreEqual ( size_t ( 1 ) , newMonster . GetBuffs ( BuffType : : SPECIAL_MARK ) . size ( ) , L " A special mark should spawned with the enchant. " ) ;
}
TEST_METHOD ( ConcussiveTrapEnchantCheck ) {
Game : : ChangeClass ( player , TRAPPER ) ;
player - > SetPos ( { 120 , 120 } ) ;
player - > CheckAndPerformAbility ( player - > GetAbility3 ( ) , testKeyboardInput ) ;
Game : : Update ( 0.5f ) ;
Assert : : AreEqual ( size_t ( 1 ) , BULLET_LIST . size ( ) , L " An Explosive Trap now exists " ) ;
Monster & newMonster { game - > SpawnMonster ( { } , MONSTER_DATA [ " TestName " ] ) } ;
game - > OnUserUpdate ( 0.f ) ;
BULLET_LIST . front ( ) - > MonsterHit ( newMonster , newMonster . GetMarkStacks ( ) ) ;
Assert : : AreEqual ( 929 , newMonster . GetHealth ( ) , L " Monster takes 71 damage from an Explosive Trap normally. " ) ;
Game : : Update ( 5.5f ) ;
Game : : Update ( 5.5f ) ;
Game : : Update ( 0.5f ) ;
Assert : : AreEqual ( size_t ( 0 ) , BULLET_LIST . size ( ) , L " An Explosive Trap is gone. " ) ;
Game : : GiveAndEquipEnchantedRing ( " Concussive Trap " ) ;
player - > GetAbility3 ( ) . charges = 1 ;
player - > CheckAndPerformAbility ( player - > GetAbility3 ( ) , testKeyboardInput ) ;
Game : : Update ( 0.5f ) ;
Assert : : AreEqual ( size_t ( 1 ) , BULLET_LIST . size ( ) , L " An Explosive Trap now exists " ) ;
Game : : Update ( 5.5f ) ;
Assert : : AreEqual ( size_t ( 1 ) , BULLET_LIST . size ( ) , L " An Explosive Trap still exists (in the process of detonating a few times) " ) ;
Assert : : AreEqual ( 721 , newMonster . GetHealth ( ) , L " Monster takes 104 + 104 damage from Concussive Trap bonus (Collision+Collateral Explosion). " ) ;
Game : : Update ( 5.5f ) ;
Game : : Update ( 5.5f ) ;
Assert : : AreEqual ( size_t ( 0 ) , BULLET_LIST . size ( ) , L " Explosive Trap detonates later. " ) ;
}
TEST_METHOD ( SwordEnchantmentNoEnchantCheck ) {
Assert : : AreEqual ( 150.f , player - > GetAttackRange ( ) , L " Attack range of Warrior is normal " ) ;
player - > CheckAndPerformAbility ( player - > GetAbility3 ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( 150.f , player - > GetAttackRange ( ) , L " Attack range of Warrior remains the untouched. " ) ;
}
TEST_METHOD ( SwordEnchantmentEnchantCheck ) {
Game : : GiveAndEquipEnchantedRing ( " Sword Enchantment " ) ;
player - > CheckAndPerformAbility ( player - > GetAbility3 ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( 300.f , player - > GetAttackRange ( ) , L " Attack range of Warrior doubled. " ) ;
Game : : Update ( 0.f ) ; //Wait an extra tick for the buff to begin going down.
Game : : Update ( 8.f ) ;
Assert : : AreEqual ( 150.f , player - > GetAttackRange ( ) , L " Attack range of Warrior is normal again. " ) ;
}
TEST_METHOD ( ImprovedGroundSlamNoEnchantCheck ) {
player - > CheckAndPerformAbility ( player - > GetAbility2 ( ) , testKeyboardInput ) ;
Monster & newMonster { game - > SpawnMonster ( { } , MONSTER_DATA [ " TestName " ] ) } ;
Game : : Update ( 0.f ) ;
Game : : Update ( 1.f ) ;
Game : : Update ( 0.f ) ;
Assert : : AreEqual ( 975 , newMonster . GetHealth ( ) , L " Monsters take normal damage from Ground Slam. " ) ;
}
TEST_METHOD ( ImprovedGroundSlamEnchantCheck ) {
std : : weak_ptr < Item > leatherArmor { Inventory : : AddItem ( " Leather Armor " s ) } ;
Inventory : : EquipItem ( leatherArmor , EquipSlot : : ARMOR ) ;
Game : : GiveAndEquipEnchantedRing ( " Improved Ground Slam " ) ;
player - > CheckAndPerformAbility ( player - > GetAbility2 ( ) , testKeyboardInput ) ;
Monster & newMonster { game - > SpawnMonster ( { } , MONSTER_DATA [ " TestName " ] ) } ;
Game : : Update ( 0.f ) ;
Game : : Update ( 1.f ) ;
Game : : Update ( 0.f ) ;
Assert : : AreEqual ( 973 , newMonster . GetHealth ( ) , L " Monsters take extra damage from defense from Improved Ground Slam. " ) ;
}
TEST_METHOD ( HeavyGuardNoEnchantCheck ) {
player - > CheckAndPerformAbility ( player - > GetRightClickAbility ( ) , testKeyboardInput ) ;
player - > Hurt ( 5 , player - > OnUpperLevel ( ) , player - > GetZ ( ) ) ;
Assert : : AreEqual ( 100 , player - > GetHealth ( ) , L " Player does not take damage while blocking. " ) ;
Game : : Update ( 4.f ) ;
player - > Hurt ( 5 , player - > OnUpperLevel ( ) , player - > GetZ ( ) ) ;
Assert : : AreEqual ( 95 , player - > GetHealth ( ) , L " Player takes normal damage once block expires. " ) ;
}
TEST_METHOD ( HeavyGuardEnchantCheck ) {
Game : : GiveAndEquipEnchantedRing ( " Heavy Guard " ) ;
player - > CheckAndPerformAbility ( player - > GetRightClickAbility ( ) , testKeyboardInput ) ;
Game : : Update ( 5.f ) ;
player - > Hurt ( 5 , player - > OnUpperLevel ( ) , player - > GetZ ( ) ) ;
Assert : : AreEqual ( 100 , player - > GetHealth ( ) , L " Player should still be blocking at this time with Heavy Guard. " ) ;
}
TEST_METHOD ( AdvanceShieldNoEnchantCheck ) {
player - > CheckAndPerformAbility ( player - > GetRightClickAbility ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( 0U , player - > GetShield ( ) , L " Without the Advance Shield enchant, shield amount remains at 0. " ) ;
}
TEST_METHOD ( AdvanceShieldEnchantCheck ) {
Game : : GiveAndEquipEnchantedRing ( " Advance Shield " ) ;
player - > CheckAndPerformAbility ( player - > GetRightClickAbility ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( int ( player - > GetMaxHealth ( ) * 0.2f ) , int ( player - > GetShield ( ) ) , L " The Advance Shield enchant provides a 20% health player shield. " ) ;
Game : : Update ( 9.f ) ;
Assert : : AreEqual ( 0U , player - > GetShield ( ) , L " The Advance Shield enchant shield lasts 9 seconds. It should have worn off after that time. " ) ;
player - > GetRightClickAbility ( ) . charges = 1 ;
player - > CheckAndPerformAbility ( player - > GetRightClickAbility ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( int ( player - > GetMaxHealth ( ) * 0.2f ) , int ( player - > GetShield ( ) ) , L " The Advance Shield enchant provides a 20% health player shield. " ) ;
Game : : Update ( 9.f ) ;
Assert : : AreEqual ( 0U , player - > GetShield ( ) , L " The Advance Shield enchant shield lasts 9 seconds. It should have worn off after that time. " ) ; //Double check that reapplication still works for applying shields, since it's possible the timer already existing in the array could be bugged.... Cover this edge case!
}
TEST_METHOD ( BattleShoutNoEnchantCheck ) {
Monster & newMonster { game - > SpawnMonster ( { } , MONSTER_DATA [ " TestName " ] ) } ;
player - > CheckAndPerformAbility ( player - > GetAbility1 ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( newMonster . GetHealth ( ) , newMonster . GetMaxHealth ( ) , L " Monster does not take damage from Battlecry normally. " ) ;
}
TEST_METHOD ( BattleShoutEnchantCheck ) {
Game : : GiveAndEquipEnchantedRing ( " Battle Shout " ) ;
Monster & newMonster { game - > SpawnMonster ( { } , MONSTER_DATA [ " TestName " ] ) } ;
player - > CheckAndPerformAbility ( player - > GetAbility1 ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( newMonster . GetHealth ( ) - player - > GetDefense ( ) , newMonster . GetMaxHealth ( ) , L " Monster takes damage from Battlecry with the Battle Shout enchant equal to 100% of the player's Defense. " ) ;
}
TEST_METHOD ( SlamShockNoEnchantCheck ) {
Monster & newMonster { game - > SpawnMonster ( { } , MONSTER_DATA [ " TestName " ] ) } ;
player - > CheckAndPerformAbility ( player - > GetAbility2 ( ) , testKeyboardInput ) ;
Game : : Update ( 2.f ) ;
Game : : Update ( 0.f ) ; //The next tick should cause the ground slam to occur.
Assert : : IsTrue ( newMonster . CanMove ( ) , L " Monster should still be running its AI. " ) ;
}
TEST_METHOD ( SlamShockEnchantCheck ) {
Monster & newMonster { game - > SpawnMonster ( { } , MONSTER_DATA [ " TestName " ] ) } ;
Game : : GiveAndEquipEnchantedRing ( " Slam Shock " ) ;
player - > CheckAndPerformAbility ( player - > GetAbility2 ( ) , testKeyboardInput ) ;
Game : : Update ( 2.f ) ;
Game : : Update ( 0.f ) ; //The next tick should cause the ground slam to occur.
Assert : : IsFalse ( newMonster . CanMove ( ) , L " Monster should be stunned by Slam Shock enchant and unable to run its AI. " ) ;
Game : : Update ( 5.f ) ;
Assert : : IsTrue ( newMonster . CanMove ( ) , L " Monster should no longer be stunned. " ) ;
}
TEST_METHOD ( SonicUpgradeNoEnchantCheck ) {
Monster & newMonster { game - > SpawnMonster ( { } , MONSTER_DATA [ " TestName " ] ) } ;
Assert : : AreEqual ( " Warrior.Ability 3.Cooldown " _F , player - > GetAbility3 ( ) . GetCooldownTime ( ) , L " Player's Sonic Slash cooldown time is normal. " ) ;
Assert : : AreEqual ( " Warrior.Ability 3.Mana Cost " _I , player - > GetAbility3 ( ) . manaCost , L " Player's Sonic Slash mana cost is normal. " ) ;
Game : : Update ( 0.f ) ;
player - > CheckAndPerformAbility ( player - > GetAbility3 ( ) , testKeyboardInput ) ;
Game : : Update ( 0.5f ) ;
Assert : : AreEqual ( 920 , newMonster . GetHealth ( ) , L " Monster has taken the normal amount of 80 health. " ) ;
}
TEST_METHOD ( SonicUpgradeEnchantCheck ) {
Monster & newMonster { game - > SpawnMonster ( { } , MONSTER_DATA [ " TestName " ] ) } ;
Game : : GiveAndEquipEnchantedRing ( " Sonic Upgrade " ) ;
Assert : : AreEqual ( " Warrior.Ability 3.Cooldown " _F * 0.85f , player - > GetAbility3 ( ) . GetCooldownTime ( ) , L " Player's Sonic Slash cooldown time is normal. " ) ;
Assert : : AreEqual ( int ( " Warrior.Ability 3.Mana Cost " _I * 0.85f ) , player - > GetAbility3 ( ) . manaCost , L " Player's Sonic Slash mana cost is normal. " ) ;
Game : : Update ( 0.f ) ;
player - > CheckAndPerformAbility ( player - > GetAbility3 ( ) , testKeyboardInput ) ;
Game : : Update ( 0.5f ) ;
Assert : : AreEqual ( 910 , newMonster . GetHealth ( ) , L " Monster now takes 90 health with the Sonic Upgrade (10% of player's Max HP). " ) ;
}
TEST_METHOD ( BouncingOrbNoEnchantCheck ) {
Game : : ChangeClass ( player , WITCH ) ;
Monster & newMonster { game - > SpawnMonster ( { } , MONSTER_DATA [ " TestName " ] ) } ;
Monster & newMonster2 { game - > SpawnMonster ( { } , MONSTER_DATA [ " TestName " ] ) } ;
Assert : : AreEqual ( 1000 , newMonster . GetHealth ( ) , L " Monster 1 is at 1000 HP. " ) ;
Assert : : AreEqual ( 1000 , newMonster2 . GetHealth ( ) , L " Monster 2 is at 1000 HP. " ) ;
player - > AutoAttack ( ) ;
for ( int i : std : : ranges : : iota_view ( 0 , 50 ) ) {
Game : : Update ( 0.1f ) ;
}
Assert : : AreEqual ( 985 , newMonster . GetHealth ( ) , L " Monster 1 should have been hit. " ) ;
Assert : : AreEqual ( 1000 , newMonster2 . GetHealth ( ) , L " Monster 2 should not have been hit. Target limit is 1. " ) ;
}
TEST_METHOD ( BouncingOrbEnchantCheck ) {
Game : : ChangeClass ( player , WITCH ) ;
player - > ForceSetPos ( { 20.f , 50.f } ) ;
Monster & newMonster { game - > SpawnMonster ( { 30.f , 50.f } , MONSTER_DATA [ " TestName " ] ) } ;
Monster & newMonster2 { game - > SpawnMonster ( { 50.f , 50.f } , MONSTER_DATA [ " TestName " ] ) } ;
Game : : GiveAndEquipEnchantedRing ( " Bouncing Orb " ) ;
Assert : : AreEqual ( 1000 , newMonster . GetHealth ( ) , L " Monster 1 is at 1000 HP. " ) ;
Assert : : AreEqual ( 1000 , newMonster2 . GetHealth ( ) , L " Monster 2 is at 1000 HP. " ) ;
player - > SetTestScreenAimingLocation ( player - > GetPos ( ) + vf2d { 30.f , 0.f } ) ;
player - > AutoAttack ( ) ;
for ( int i : std : : ranges : : iota_view ( 0 , 50 ) ) {
game - > SetElapsedTime ( 0.1f ) ;
game - > OnUserUpdate ( 0.1f ) ;
}
Assert : : AreEqual ( 986 , newMonster . GetHealth ( ) , L " Monster 1 should have been hit. Since we can have 4 bounces, this got hit twice. Damage should be halved. " ) ;
Assert : : AreEqual ( 986 , newMonster2 . GetHealth ( ) , L " Monster 2 should have been hit. Since we can have 4 bounces, this got hit twice. Damage should be halved. " ) ;
}
TEST_METHOD ( NineLivesNoEnchantCheck ) {
Game : : ChangeClass ( player , WITCH ) ;
Assert : : AreEqual ( " Witch.Right Click Ability.Cooldown " _F , player - > GetRightClickAbility ( ) . GetCooldownTime ( ) , L " Cooldown time should be normal. " ) ;
player - > CheckAndPerformAbility ( player - > GetRightClickAbility ( ) , testKeyboardInput ) ;
Game : : Update ( 10.f ) ;
player - > Hurt ( 10 , player - > OnUpperLevel ( ) , player - > GetZ ( ) ) ;
Assert : : AreEqual ( 70 , player - > GetHealth ( ) , L " Player should take normal damage when cat form expires. " ) ;
}
TEST_METHOD ( NineLivesEnchantCheck ) {
Game : : ChangeClass ( player , WITCH ) ;
Game : : GiveAndEquipEnchantedRing ( " Nine Lives " ) ;
Assert : : AreEqual ( " Nine Lives " _ENC [ " TRANSFORM COOLDOWN " ] , player - > GetRightClickAbility ( ) . GetCooldownTime ( ) , L " Cooldown time should be drastically increased. " ) ;
player - > CheckAndPerformAbility ( player - > GetRightClickAbility ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( player - > GetRightClickAbility ( ) . cooldown , " Nine Lives " _ENC [ " TRANSFORM COOLDOWN " ] , L " Cooldown time should be 20s when not in cat form already. " ) ;
Game : : Update ( 10.f ) ;
player - > Hurt ( 10 , player - > OnUpperLevel ( ) , player - > GetZ ( ) ) ;
Assert : : AreEqual ( 80 , player - > GetHealth ( ) , L " Player should absorb the damage since they were in cat form. " ) ;
player - > Hurt ( 10 , player - > OnUpperLevel ( ) , player - > GetZ ( ) ) ;
Assert : : AreEqual ( 70 , player - > GetHealth ( ) , L " Now player should take normal damage after reverting forms. " ) ;
}
TEST_METHOD ( NineLivesCooldownReducedInCatFormEnchantCheck ) {
Game : : ChangeClass ( player , WITCH ) ;
Game : : GiveAndEquipEnchantedRing ( " Nine Lives " ) ;
Assert : : AreEqual ( " Nine Lives " _ENC [ " TRANSFORM COOLDOWN " ] , player - > GetRightClickAbility ( ) . GetCooldownTime ( ) , L " Cooldown time should be drastically increased. " ) ;
player - > CheckAndPerformAbility ( player - > GetRightClickAbility ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( player - > GetRightClickAbility ( ) . cooldown , " Nine Lives " _ENC [ " TRANSFORM COOLDOWN " ] , L " Cooldown time should be 20s when not in cat form already. " ) ;
player - > GetRightClickAbility ( ) . charges = 1 ;
Game : : Update ( 1.f ) ;
player - > CheckAndPerformAbility ( player - > GetRightClickAbility ( ) , testKeyboardInput ) ;
Assert : : AreEqual ( " Witch.Right Click Ability.Cooldown " _F , player - > GetRightClickAbility ( ) . cooldown , L " Cooldown time should be 8s when already in cat form. " ) ;
}
TEST_METHOD ( SpreadingPainNoEnchantCheck ) {
Game : : ChangeClass ( player , WITCH ) ;
MonsterData testMonsterData { " TestName2 " , " Test Monster2 " , 1 , 10 , 5 , { MonsterDropData { " Health Potion " , 100.f , 1 , 1 } } , 200.f } ;
MONSTER_DATA [ " TestName2 " ] = testMonsterData ;
Monster & newMonster { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName2 " ] ) } ;
Monster & newMonster2 { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName2 " ] ) } ;
Monster & newMonster3 { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName2 " ] ) } ;
Monster & newMonster4 { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName2 " ] ) } ;
Game : : Update ( 0.f ) ;
Game : : CastAbilityAtLocation ( player - > GetAbility1 ( ) , player - > GetPos ( ) + vf2d { 30.f , 0.f } ) ;
Assert : : IsTrue ( newMonster . GetBuffs ( BuffType : : CURSE_OF_PAIN ) . size ( ) > 0 , L " The first monster should have been targeted with Curse of Pain. " ) ;
Game : : Update ( 3.f ) ;
Assert : : IsTrue ( newMonster . IsDead ( ) , L " The first monster has died to Curse of Pain's tick. " ) ;
Assert : : IsTrue ( newMonster2 . GetBuffs ( BuffType : : CURSE_OF_PAIN ) . size ( ) = = 0 , L " Without the enchant, Curse of Pain should not have spread to Monster 2. " ) ;
Assert : : IsTrue ( newMonster3 . GetBuffs ( BuffType : : CURSE_OF_PAIN ) . size ( ) = = 0 , L " Without the enchant, Curse of Pain should not have spread to Monster 3. " ) ;
Assert : : IsTrue ( newMonster4 . GetBuffs ( BuffType : : CURSE_OF_PAIN ) . size ( ) = = 0 , L " Without the enchant, Curse of Pain should not have spread to Monster 4. " ) ;
}
TEST_METHOD ( SpreadingPainEnchantCheck ) {
Game : : ChangeClass ( player , WITCH ) ;
Game : : GiveAndEquipEnchantedRing ( " Spreading Pain " ) ;
MonsterData testMonsterData { " TestName2 " , " Test Monster2 " , 1 , 10 , 5 , { } , 200.f } ;
MONSTER_DATA [ " TestName2 " ] = testMonsterData ;
Monster & newMonster5 { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName2 " ] ) } ;
Monster & newMonster { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName2 " ] ) } ;
Monster & newMonster2 { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName2 " ] ) } ;
Monster & newMonster3 { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName2 " ] ) } ;
Monster & newMonster4 { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName2 " ] ) } ;
Game : : Update ( 0.f ) ;
newMonster5 . Hurt ( 1 , newMonster5 . OnUpperLevel ( ) , newMonster5 . GetZ ( ) ) ;
Assert : : AreEqual ( size_t ( 0 ) , newMonster . GetBuffs ( BuffType : : CURSE_OF_PAIN ) . size ( ) , L " If a target without Curse of Pain dies, it should not spread onto other targets. " ) ;
Assert : : AreEqual ( size_t ( 0 ) , newMonster2 . GetBuffs ( BuffType : : CURSE_OF_PAIN ) . size ( ) , L " If a target without Curse of Pain dies, it should not spread onto other targets. " ) ;
Assert : : AreEqual ( size_t ( 0 ) , newMonster3 . GetBuffs ( BuffType : : CURSE_OF_PAIN ) . size ( ) , L " If a target without Curse of Pain dies, it should not spread onto other targets. " ) ;
Assert : : AreEqual ( size_t ( 0 ) , newMonster4 . GetBuffs ( BuffType : : CURSE_OF_PAIN ) . size ( ) , L " If a target without Curse of Pain dies, it should not spread onto other targets. " ) ;
Game : : CastAbilityAtLocation ( player - > GetAbility1 ( ) , player - > GetPos ( ) + vf2d { 30.f , 0.f } ) ;
Assert : : AreEqual ( size_t ( 1 ) , newMonster . GetBuffs ( BuffType : : CURSE_OF_PAIN ) . size ( ) , L " The first monster should have been targeted with Curse of Pain. " ) ;
Game : : Update ( 3.f ) ;
Assert : : IsTrue ( newMonster . IsDead ( ) , L " The first monster has died to Curse of Pain's tick. " ) ;
Assert : : IsTrue ( ! newMonster2 . IsDead ( ) , L " The other monsters should not be dead. " ) ;
Assert : : IsTrue ( ! newMonster3 . IsDead ( ) , L " The other monsters should not be dead. " ) ;
Assert : : IsTrue ( ! newMonster4 . IsDead ( ) , L " The other monsters should not be dead. " ) ;
Assert : : AreEqual ( size_t ( 1 ) , newMonster2 . GetBuffs ( BuffType : : CURSE_OF_PAIN ) . size ( ) , L " With the enchant, Curse of Pain should have spread to Monster 2. " ) ;
newMonster2 . Hurt ( 1 , newMonster2 . OnUpperLevel ( ) , newMonster2 . GetZ ( ) ) ;
Assert : : IsTrue ( newMonster2 . IsDead ( ) , L " Monster 2 should be dead. " ) ;
Assert : : IsTrue ( ! newMonster3 . IsDead ( ) , L " The other monsters should not be dead. " ) ;
Assert : : IsTrue ( ! newMonster4 . IsDead ( ) , L " The other monsters should not be dead. " ) ;
Assert : : AreEqual ( size_t ( 1 ) , newMonster3 . GetBuffs ( BuffType : : CURSE_OF_PAIN ) . size ( ) , L " With the enchant, Curse of Pain should have spread to Monster 3 and only 1 stack should have been applied. " ) ;
Assert : : AreEqual ( " Witch.Ability 1.Curse Debuff " _f [ 2 ] , newMonster3 . GetBuffs ( BuffType : : CURSE_OF_PAIN ) [ 0 ] . duration , L " When Curse of Pain is reapplied to a monster that already has Curse of Pain, it refreshes the duration. " ) ;
Assert : : AreEqual ( size_t ( 1 ) , newMonster4 . GetBuffs ( BuffType : : CURSE_OF_PAIN ) . size ( ) , L " With the enchant, Curse of Pain should have spread to Monster 4 and only 1 stack should have been applied. " ) ;
Assert : : AreEqual ( " Witch.Ability 1.Curse Debuff " _f [ 2 ] , newMonster4 . GetBuffs ( BuffType : : CURSE_OF_PAIN ) [ 0 ] . duration , L " When Curse of Pain is reapplied to a monster that already has Curse of Pain, it refreshes the duration. " ) ;
}
TEST_METHOD ( PoolingPoisonNoEnchantCheck ) {
Game : : ChangeClass ( player , WITCH ) ;
Monster & newMonster { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName " ] ) } ;
Game : : Update ( 0.f ) ;
Game : : CastAbilityAtLocation ( player - > GetAbility2 ( ) , player - > GetPos ( ) + vf2d { 30.f , 0.f } ) ;
while ( BULLET_LIST . size ( ) > 0 ) Game : : Update ( 1 / 30.f ) ;
Assert : : AreEqual ( 925 , newMonster . GetHealth ( ) , L " Monster should have lost 75 health from Poison Pool. " ) ;
Game : : Update ( 2.f ) ;
Assert : : AreEqual ( 925 , newMonster . GetHealth ( ) , L " Monster should still have 925 health. " ) ;
}
TEST_METHOD ( PoolingPoisonEnchantCheck ) {
Game : : ChangeClass ( player , WITCH ) ;
Game : : GiveAndEquipEnchantedRing ( " Pooling Poison " ) ;
Monster & newMonster { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName " ] ) } ;
Game : : Update ( 0.f ) ;
Game : : CastAbilityAtLocation ( player - > GetAbility2 ( ) , player - > GetPos ( ) + vf2d { 30.f , 0.f } ) ;
while ( BULLET_LIST . size ( ) > 0 ) Game : : Update ( 1 / 30.f ) ;
Assert : : AreEqual ( 925 , newMonster . GetHealth ( ) , L " Monster should have lost 75 health from Poison Pool. " ) ;
Game : : Update ( 2.f ) ;
Assert : : AreEqual ( 910 , newMonster . GetHealth ( ) , L " Monster should have lost an additional 15 health from lingering Pooling Poison. " ) ;
}
TEST_METHOD ( PoisonBounceNoEnchantCheck ) {
Game : : ChangeClass ( player , WITCH ) ;
Monster & newMonster { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName " ] ) } ;
Game : : Update ( 0.f ) ;
Game : : CastAbilityAtLocation ( player - > GetAbility2 ( ) , player - > GetPos ( ) + vf2d { 30.f , 0.f } ) ;
while ( BULLET_LIST . size ( ) > 0 ) Game : : Update ( 1 / 30.f ) ;
Assert : : AreEqual ( 925 , newMonster . GetHealth ( ) , L " Monster should have lost 75 health from Poison Pool. " ) ;
}
TEST_METHOD ( PoisonBounceEnchantCheck ) {
Game : : ChangeClass ( player , WITCH ) ;
Game : : GiveAndEquipEnchantedRing ( " Poison Bounce " ) ;
Monster & newMonster { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName " ] ) } ;
Game : : Update ( 0.f ) ;
Game : : CastAbilityAtLocation ( player - > GetAbility2 ( ) , player - > GetPos ( ) + vf2d { 30.f , 0.f } ) ;
while ( BULLET_LIST . size ( ) > 0 ) Game : : Update ( 1 / 30.f ) ;
Assert : : AreEqual ( 895 , newMonster . GetHealth ( ) , L " Monster should have lost 105 health from Poison Pool. " ) ;
}
TEST_METHOD ( ExpungeNoEnchantCheck ) {
Game : : ChangeClass ( player , WITCH ) ;
Monster & newMonster { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName " ] ) } ;
Game : : Update ( 0.f ) ;
Game : : CastAbilityAtLocation ( player - > GetAbility3 ( ) , player - > GetPos ( ) + vf2d { 30.f , 0.f } ) ;
player - > AutoAttack ( ) ;
while ( BULLET_LIST . size ( ) > 0 ) Game : : Update ( 1 / 30.f ) ;
Assert : : AreEqual ( 970 , newMonster . GetHealth ( ) , L " Monster should have taken double damage from Curse of Death. " ) ;
}
TEST_METHOD ( ExpungeEnchantCheck ) {
Game : : ChangeClass ( player , WITCH ) ;
Game : : GiveAndEquipEnchantedRing ( " Expunge " ) ;
Monster & newMonster { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName " ] ) } ;
Game : : Update ( 0.f ) ;
Game : : CastAbilityAtLocation ( player - > GetAbility3 ( ) , player - > GetPos ( ) + vf2d { 30.f , 0.f } ) ;
player - > AutoAttack ( ) ;
while ( BULLET_LIST . size ( ) > 0 ) Game : : Update ( 1 / 30.f ) ;
Assert : : AreEqual ( 962 , newMonster . GetHealth ( ) , L " Monster should have taken 150% more damage with Curse of Death. " ) ;
}
TEST_METHOD ( CurseOfDoomNoEnchantCheck ) {
Game : : ChangeClass ( player , WITCH ) ;
Monster & newMonster { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName " ] ) } ;
Monster & newMonster2 { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName " ] ) } ;
Monster & newMonster3 { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName " ] ) } ;
Monster & newMonster4 { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName " ] ) } ;
Game : : Update ( 0.f ) ;
Game : : CastAbilityAtLocation ( player - > GetAbility3 ( ) , player - > GetPos ( ) + vf2d { 30.f , 0.f } ) ;
newMonster . Hurt ( 1000 , newMonster . OnUpperLevel ( ) , newMonster . GetZ ( ) ) ;
Assert : : AreEqual ( true , newMonster . IsDead ( ) , L " Monster 1 has died. " ) ;
Assert : : AreEqual ( size_t ( 1 ) , newMonster . GetBuffs ( BuffType : : CURSE_OF_DEATH ) . size ( ) , L " Monster 1 has a Curse of Death debuff. " ) ;
Assert : : AreEqual ( newMonster2 . GetMaxHealth ( ) , newMonster2 . GetHealth ( ) , L " Monster 2 is healthy and has not been hit by collateral damage. " ) ;
Assert : : AreEqual ( newMonster3 . GetMaxHealth ( ) , newMonster3 . GetHealth ( ) , L " Monster 3 is healthy and has not been hit by collateral damage. " ) ;
Assert : : AreEqual ( newMonster4 . GetMaxHealth ( ) , newMonster4 . GetHealth ( ) , L " Monster 4 is healthy and has not been hit by collateral damage. " ) ;
}
TEST_METHOD ( CurseOfDoomEnchantCheck ) {
Game : : ChangeClass ( player , WITCH ) ;
Game : : GiveAndEquipEnchantedRing ( " Curse of Doom " ) ;
Monster & newMonster { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName " ] ) } ;
Monster & newMonster2 { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName " ] ) } ;
Monster & newMonster3 { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName " ] ) } ;
Monster & newMonster4 { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName " ] ) } ;
Game : : Update ( 0.f ) ;
newMonster . Hurt ( 750 , newMonster . OnUpperLevel ( ) , newMonster . GetZ ( ) ) ;
Game : : CastAbilityAtLocation ( player - > GetAbility3 ( ) , player - > GetPos ( ) + vf2d { 30.f , 0.f } ) ;
newMonster . Hurt ( 250 , newMonster . OnUpperLevel ( ) , newMonster . GetZ ( ) ) ;
Assert : : AreEqual ( true , newMonster . IsDead ( ) , L " Monster 1 has died. " ) ;
Assert : : AreEqual ( size_t ( 1 ) , newMonster . GetBuffs ( BuffType : : CURSE_OF_DEATH ) . size ( ) , L " Monster 1 has a Curse of Death debuff. " ) ;
Assert : : AreEqual ( newMonster2 . GetMaxHealth ( ) - 500 , newMonster2 . GetHealth ( ) , L " Monster 2 takes collateral damage from Curse of Doom enchant based on the amount of damage dealt during Curse of Death debuff " ) ;
Assert : : AreEqual ( newMonster3 . GetMaxHealth ( ) - 500 , newMonster3 . GetHealth ( ) , L " Monster 3 takes collateral damage from Curse of Doom enchant based on the amount of damage dealt during Curse of Death debuff. " ) ;
Assert : : AreEqual ( newMonster4 . GetMaxHealth ( ) - 500 , newMonster4 . GetHealth ( ) , L " Monster 4 takes collateral damage from Curse of Doom enchant based on the amount of damage dealt during Curse of Death debuff. " ) ;
}
TEST_METHOD ( PiercingBoltNoEnchantCheck ) {
Game : : ChangeClass ( player , WIZARD ) ;
Monster & newMonster { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName " ] ) } ;
Monster & newMonster2 { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName " ] ) } ;
Monster & newMonster3 { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName " ] ) } ;
Monster & newMonster4 { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName " ] ) } ;
player - > SetTestScreenAimingLocation ( player - > GetPos ( ) + vf2d { 30.f , 0.f } ) ;
Game : : Update ( 0.f ) ;
player - > AutoAttack ( ) ;
Game : : Update ( 0.5f ) ;
Assert : : AreEqual ( 985 , newMonster . GetHealth ( ) , L " Monster 1 takes normal damage from Wizard auto attack. " ) ;
Assert : : AreEqual ( 1000 , newMonster2 . GetHealth ( ) , L " Monster 2 should still be full health. " ) ;
Assert : : AreEqual ( 1000 , newMonster3 . GetHealth ( ) , L " Monster 3 should still be full health. " ) ;
Assert : : AreEqual ( 1000 , newMonster4 . GetHealth ( ) , L " Monster 4 should still be full health. " ) ;
}
TEST_METHOD ( PiercingBoltEnchantCheck ) {
Game : : ChangeClass ( player , WIZARD ) ;
Game : : GiveAndEquipEnchantedRing ( " Piercing Bolt " ) ;
Monster & newMonster { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName " ] ) } ;
Monster & newMonster2 { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName " ] ) } ;
Monster & newMonster3 { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName " ] ) } ;
Monster & newMonster4 { game - > SpawnMonster ( { 30.f , 0.f } , MONSTER_DATA [ " TestName " ] ) } ;
player - > SetTestScreenAimingLocation ( player - > GetPos ( ) + vf2d { 30.f , 0.f } ) ;
Game : : Update ( 0.f ) ;
player - > AutoAttack ( ) ;
Game : : Update ( 0.5f ) ;
Assert : : AreEqual ( 985 , newMonster . GetHealth ( ) , L " Monster 1 takes normal damage from Wizard auto attack. " ) ;
Assert : : AreEqual ( 992 , newMonster2 . GetHealth ( ) , L " Monster 2 should take half the damage the first target does with the Percing Bolt Enchant. " ) ;
Assert : : AreEqual ( 992 , newMonster3 . GetHealth ( ) , L " Monster 3 should take half the damage the first target does with the Percing Bolt Enchant " ) ;
Assert : : AreEqual ( 992 , newMonster4 . GetHealth ( ) , L " Monster 4 should take half the damage the first target does with the Percing Bolt Enchant " ) ;
}
TEST_METHOD ( BlinkPortalNoEnchantCheck ) {
Game : : ChangeClass ( player , WIZARD ) ;
Assert : : AreEqual ( " Wizard.Right Click Ability.Cooldown " _F , player - > GetRightClickAbility ( ) . GetCooldownTime ( ) , L " The original cooldown time should be normal. " ) ;
player - > SetTestScreenAimingLocation ( player - > GetPos ( ) + vf2d { 16.f , 0.f } ) ;
player - > CheckAndPerformAbility ( player - > GetRightClickAbility ( ) , testKeyboardInput ) ;
Game : : Update ( 0.f ) ;
Assert : : AreEqual ( size_t ( 0 ) , game - > GetEffect ( EffectType : : BLINK_PORTAL ) . size ( ) , L " There should be no teleport portals spawned. " ) ;
Assert : : AreEqual ( " Wizard.Right Click Ability.Cooldown " _F , player - > GetRightClickAbility ( ) . cooldown , L " The cooldown should be normal. " ) ;
Assert : : AreEqual ( " Wizard.Right Click Ability.Mana Cost " _I , player - > GetRightClickAbility ( ) . manaCost , L " The mana cost should be normal. " ) ;
}
TEST_METHOD ( BlinkPortalEnchantCheck ) {
Game : : ChangeClass ( player , WIZARD ) ;
Game : : GiveAndEquipEnchantedRing ( " Blink Portal " ) ;
Assert : : AreEqual ( " Blink Portal " _ENC [ " COOLDOWN " ] , player - > GetRightClickAbility ( ) . GetCooldownTime ( ) , L " The original cooldown time should have been modified by the enchant. " ) ;
player - > SetTestScreenAimingLocation ( player - > GetPos ( ) + vf2d { 16.f , 0.f } ) ;
player - > CheckAndPerformAbility ( player - > GetRightClickAbility ( ) , testKeyboardInput ) ;
Game : : Update ( 0.f ) ;
Assert : : AreEqual ( size_t ( 1 ) , game - > GetEffect ( EffectType : : BLINK_PORTAL ) . size ( ) , L " There should be a teleport portal spawned. " ) ;
Assert : : AreEqual ( 0.f , player - > GetRightClickAbility ( ) . cooldown , L " The cooldown should be zero since we can activate Teleport again. " ) ;
Assert : : AreEqual ( 0 , player - > GetRightClickAbility ( ) . manaCost , L " The mana cost should be zero. " ) ;
player - > CheckAndPerformAbility ( player - > GetRightClickAbility ( ) , testKeyboardInput ) ;
Game : : Update ( 0.25f ) ;
Assert : : AreEqual ( size_t ( 0 ) , game - > GetEffect ( EffectType : : BLINK_PORTAL ) . size ( ) , L " Teleport portal should be despawned. " ) ;
Assert : : AreEqual ( player - > GetRightClickAbility ( ) . GetCooldownTime ( ) - 0.25f , player - > GetRightClickAbility ( ) . cooldown , L " The cooldown should be normal again. " ) ;
Assert : : AreEqual ( " Wizard.Right Click Ability.Mana Cost " _I , player - > GetRightClickAbility ( ) . manaCost , L " The mana cost should be normal again. " ) ;
}
TEST_METHOD ( BlackHoleNoEnchantCheck ) {
Game : : ChangeClass ( player , WIZARD ) ;
player - > SetTestScreenAimingLocation ( player - > GetPos ( ) + vf2d { 16.f , 0.f } ) ;
player - > CheckAndPerformAbility ( player - > GetRightClickAbility ( ) , testKeyboardInput ) ;
Game : : Update ( 0.f ) ;
Assert : : AreEqual ( size_t ( 0 ) , game - > GetBackgroundEffects ( ) . size ( ) , L " There should be no background effects (i.e. Black Holes). " ) ;
}
TEST_METHOD ( BlackHoleEnchantCheck ) {
Game : : ChangeClass ( player , WIZARD ) ;
Game : : GiveAndEquipEnchantedRing ( " Black Hole " ) ;
player - > SetTestScreenAimingLocation ( player - > GetPos ( ) + vf2d { 16.f , 0.f } ) ;
player - > CheckAndPerformAbility ( player - > GetRightClickAbility ( ) , testKeyboardInput ) ;
Game : : Update ( 0.f ) ;
Assert : : AreEqual ( size_t ( 1 ) , game - > GetBackgroundEffects ( ) . size ( ) , L " There should be a background effect (i.e. the Black Hole). " ) ;
}
} ;
}