diff --git a/Adventures in Lestoria Tests/EnchantTests.cpp b/Adventures in Lestoria Tests/EnchantTests.cpp index 939f051e..d4a45a49 100644 --- a/Adventures in Lestoria Tests/EnchantTests.cpp +++ b/Adventures in Lestoria Tests/EnchantTests.cpp @@ -97,7 +97,7 @@ namespace EnchantTests #pragma region Setup a fake test map and test monster game->MAP_DATA["CAMPAIGN_1_1"]; - game->MAP_DATA["CAMPAIGN_1_1"]._SetMapData(MapTag{50,50,24,24}); + 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; @@ -577,6 +577,7 @@ namespace EnchantTests } 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."); @@ -839,6 +840,7 @@ namespace EnchantTests 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){ @@ -966,12 +968,13 @@ namespace EnchantTests } TEST_METHOD(BouncingOrbEnchantCheck){ Game::ChangeClass(player,WITCH); - player->ForceSetPos({50.f,0.f}); - Monster&newMonster{game->SpawnMonster({30.f,0.f},MONSTER_DATA["TestName"])}; - Monster&newMonster2{game->SpawnMonster({50.f,0.f},MONSTER_DATA["TestName"])}; + 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); @@ -1150,5 +1153,36 @@ namespace EnchantTests 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"); + } }; } diff --git a/Adventures in Lestoria Tests/GameHelper.h b/Adventures in Lestoria Tests/GameHelper.h index e1db6eb2..73a323b5 100644 --- a/Adventures in Lestoria Tests/GameHelper.h +++ b/Adventures in Lestoria Tests/GameHelper.h @@ -50,8 +50,8 @@ namespace Game{ game->SetElapsedTime(fElapsedTime); game->OnUserUpdate(fElapsedTime); } - inline void CastAbilityAtLocation(Ability&ability,const vf2d&screenLoc,const CastWaitProperty castWaitTime=CastWaitProperty::WAIT_FOR_CAST_TIME){ //NOTE: screenLoc is the actual screen coordinates, NOT the world coordinates! You are defining the mouse position essentially. - game->GetPlayer()->SetTestScreenAimingLocation(screenLoc); + inline void CastAbilityAtLocation(Ability&ability,const vf2d&worldLoc,const CastWaitProperty castWaitTime=CastWaitProperty::WAIT_FOR_CAST_TIME){ //NOTE: screenLoc is the actual screen coordinates, NOT the world coordinates! You are defining the mouse position essentially. + game->GetPlayer()->SetTestScreenAimingLocation(worldLoc); game->GetPlayer()->PrepareCast(ability); game->GetPlayer()->CastSpell(ability); Game::Update(ability.precastInfo.castTime); diff --git a/Adventures in Lestoria/EnergyBolt.cpp b/Adventures in Lestoria/EnergyBolt.cpp index 0893ad13..6647a910 100644 --- a/Adventures in Lestoria/EnergyBolt.cpp +++ b/Adventures in Lestoria/EnergyBolt.cpp @@ -45,7 +45,7 @@ INCLUDE_game EnergyBolt::EnergyBolt(vf2d pos,vf2d vel,float radius,int damage,bool upperLevel,bool friendly,Pixel col) :Bullet(pos,vel,radius,damage, - "energy_bolt.png",upperLevel,false,INFINITE,true,friendly,col){} + "energy_bolt.png",upperLevel,game->GetPlayer()->HasEnchant("Piercing Bolt")?true:false,INFINITE,true,friendly,col){} void EnergyBolt::Update(float fElapsedTime){ lastParticleSpawn=std::max(0.f,lastParticleSpawn-fElapsedTime); @@ -67,8 +67,9 @@ BulletDestroyState EnergyBolt::PlayerHit(Player*player) BulletDestroyState EnergyBolt::MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit) { - fadeOutTime="Wizard.Auto Attack.BulletHitFadeoutTime"_F; + if(!game->GetPlayer()->HasEnchant("Piercing Bolt"))fadeOutTime="Wizard.Auto Attack.BulletHitFadeoutTime"_F; game->AddEffect(std::make_unique(monster.GetPos(),0,"splash_effect.png",upperLevel,monster.GetSizeMult(),"Wizard.Auto Attack.SplashEffectFadeoutTime"_F)); + if(hitList.size()==1)damage=ceil(float(damage)/2); return BulletDestroyState::KEEP_ALIVE; } diff --git a/Adventures in Lestoria/ExplosiveTrap.cpp b/Adventures in Lestoria/ExplosiveTrap.cpp index 9d939d31..8b9dd9ce 100644 --- a/Adventures in Lestoria/ExplosiveTrap.cpp +++ b/Adventures in Lestoria/ExplosiveTrap.cpp @@ -96,8 +96,10 @@ void ExplosiveTrap::Detonate(){ for(const auto&[targetPtr,wasHit]:list){ if(wasHit){ std::get(targetPtr)->ApplyMark("Trapper.Ability 3.Explosion Mark Stack Time"_F,"Trapper.Ability 3.Explosion Mark Stack Increase"_I); - std::get(targetPtr)->ProximityKnockback(pos,"Trapper.Ability 3.Explosion Knockback Amount"_F); - std::get(targetPtr)->Knockup("Trapper.Ability 3.Explosion Knockup Amount"_F); + if(explosionCount==1)std::get(targetPtr)->ProximityKnockback(pos,"Trapper.Ability 3.Explosion Knockback Amount"_F); + else std::get(targetPtr)->ProximityKnockback(pos,20.f); + if(explosionCount==1)std::get(targetPtr)->Knockup("Trapper.Ability 3.Explosion Knockup Amount"_F); + else std::get(targetPtr)->Knockup(0.1f); } } @@ -119,9 +121,6 @@ BulletDestroyState ExplosiveTrap::MonsterHit(Monster&monster,const uint8_t markS monster.Hurt(0,monster.OnUpperLevel(),monster.GetZ(),HurtFlag::PLAYER_ABILITY);//Triggers mark multiple times after the first mark. } - monster.ProximityKnockback(pos,"Trapper.Ability 3.Explosion Knockback Amount"_F); - monster.Knockup("Trapper.Ability 3.Explosion Knockup Amount"_F); - Detonate(); return BulletDestroyState::KEEP_ALIVE; diff --git a/Adventures in Lestoria/IBullet.cpp b/Adventures in Lestoria/IBullet.cpp index 39355032..8858e512 100644 --- a/Adventures in Lestoria/IBullet.cpp +++ b/Adventures in Lestoria/IBullet.cpp @@ -106,13 +106,13 @@ void IBullet::_Update(const float fElapsedTime){ ModifyOutgoingDamageData(damageData); uint8_t markStacksBeforeHit{m->GetMarkStacks()}; if(m->Hurt(damageData)){ + hitList.insert(&*m); if(!hitsMultiple){ if(_MonsterHit(*m,markStacksBeforeHit)==BulletDestroyState::DESTROY){ dead=true; } return false; }else _MonsterHit(*m,markStacksBeforeHit); - hitList.insert(&*m); if(!CollisionCheckRequired())return false; } } @@ -125,13 +125,13 @@ void IBullet::_Update(const float fElapsedTime){ //NOTE: OnHurt() will potentially change the Damage Data, passing it along to bullet children that might need to modify the flags! ModifyOutgoingDamageData(damageData); if(game->GetPlayer()->Hurt(damageData)){ + hitList.insert(game->GetPlayer()); if(!hitsMultiple){ if(_PlayerHit(&*game->GetPlayer())==BulletDestroyState::DESTROY){ dead=true; } return false; }else _PlayerHit(&*game->GetPlayer()); - hitList.insert(game->GetPlayer()); if(!CollisionCheckRequired())return false; } } diff --git a/Adventures in Lestoria/Player.cpp b/Adventures in Lestoria/Player.cpp index eaf537e6..ee0950b6 100644 --- a/Adventures in Lestoria/Player.cpp +++ b/Adventures in Lestoria/Player.cpp @@ -1760,7 +1760,9 @@ void Player::Knockup(float duration){ } const vf2d Player::GetWorldAimingLocation(bool useWalkDir,bool invert){ - const vf2d screenAimingLoc{game->view.ScreenToWorld(GetAimingLocation(useWalkDir,invert))}; + vf2d screenAimingLoc{game->view.ScreenToWorld(GetAimingLocation(useWalkDir,invert))}; + + if(game->TestingModeEnabled())screenAimingLoc=testAimingLoc.value_or(GetPos()+vf2d{}); if(screenAimingLoc==GetPos())return GetPos()+vf2d{0,-1.f}; else return screenAimingLoc; diff --git a/Adventures in Lestoria/PurpleEnergyBall.cpp b/Adventures in Lestoria/PurpleEnergyBall.cpp index d297c71a..7eaf0924 100644 --- a/Adventures in Lestoria/PurpleEnergyBall.cpp +++ b/Adventures in Lestoria/PurpleEnergyBall.cpp @@ -104,6 +104,7 @@ BulletDestroyState PurpleEnergyBall::MonsterHit(Monster&monster,const uint8_t ma bounceCount--; hitList.clear(); lastHitTarget=monster.GetWeakPointer(); + hitList.emplace(&monster); if(bounceCount<=0)fadeOutTime="Witch.Auto Attack.BulletHitFadeoutTime"_F; else lastHitTimer=0.1f; Deactivate(); diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h index 21dbec4b..587f2263 100644 --- a/Adventures in Lestoria/Version.h +++ b/Adventures in Lestoria/Version.h @@ -39,7 +39,7 @@ All rights reserved. #define VERSION_MAJOR 1 #define VERSION_MINOR 2 #define VERSION_PATCH 5 -#define VERSION_BUILD 11188 +#define VERSION_BUILD 11200 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/x64/Release/Adventures in Lestoria.exe b/x64/Release/Adventures in Lestoria.exe index d7483418..488512f4 100644 Binary files a/x64/Release/Adventures in Lestoria.exe and b/x64/Release/Adventures in Lestoria.exe differ