Added a timer class. Added timers and helper functions to the Player class. Implemented Deadly Mirage enchant. Release Build 10966.
This commit is contained in:
parent
ab98adf094
commit
2e95355fb9
@ -664,5 +664,41 @@ namespace EnchantTests
|
||||
game->OnUserUpdate(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){
|
||||
testKey->bHeld=true; //Force the key to be held down for testing purposes.
|
||||
game->ChangePlayerClass(THIEF);
|
||||
player=game->GetPlayer();
|
||||
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);
|
||||
std::weak_ptr<Item>nullRing{Inventory::AddItem("Null Ring"s)};
|
||||
Inventory::EquipItem(nullRing,EquipSlot::RING1);
|
||||
nullRing.lock()->EnchantItem("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(Player::TimerType::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(Player::TimerType::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);
|
||||
testGame->SetElapsedTime("Deadly Mirage"_ENC["REACTIVATE TIMING WINDOW"]+1.f);
|
||||
testGame->OnUserUpdate("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");
|
||||
}
|
||||
};
|
||||
}
|
@ -704,6 +704,7 @@
|
||||
<SubType>
|
||||
</SubType>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Timer.h" />
|
||||
<ClInclude Include="TitleScreen.h">
|
||||
<SubType>
|
||||
</SubType>
|
||||
@ -1128,6 +1129,10 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="Test.cpp" />
|
||||
<ClCompile Include="Thief.cpp" />
|
||||
<ClCompile Include="Timer.cpp">
|
||||
<SubType>
|
||||
</SubType>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TitleScreen.cpp" />
|
||||
<ClCompile Include="Tornado.cpp">
|
||||
<SubType>
|
||||
|
@ -678,6 +678,9 @@
|
||||
<ClInclude Include="ItemEnchant.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Timer.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Player.cpp">
|
||||
@ -1193,6 +1196,9 @@
|
||||
<ClCompile Include="MonsterSoul.cpp">
|
||||
<Filter>Source Files\Effects</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Timer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="cpp.hint" />
|
||||
|
@ -362,6 +362,7 @@ void Player::Update(float fElapsedTime){
|
||||
hpRecoveryTimer=std::max(0.f,hpRecoveryTimer-fElapsedTime);
|
||||
hp6RecoveryTimer=std::max(0.f,hp6RecoveryTimer-fElapsedTime);
|
||||
hp4RecoveryTimer=std::max(0.f,hp4RecoveryTimer-fElapsedTime);
|
||||
RunTimers();
|
||||
|
||||
PerformHPRecovery();
|
||||
|
||||
@ -1952,6 +1953,9 @@ const bool Player::HasEnchant(const std::string_view enchantName)const{
|
||||
|
||||
void Player::OnAbilityUse(const Ability&ability){
|
||||
if(ability.itemAbility||ability.name==GetRightClickAbility().name)return;
|
||||
|
||||
const auto UsedAbility=[&ability](const std::string_view abilityName){return ability.name==abilityName;};
|
||||
|
||||
if(HasEnchant("Wizard's Soul")){
|
||||
const auto ReduceCooldown=[this,&ability](Ability&a){
|
||||
if(ability.name==a.name)return;
|
||||
@ -1962,6 +1966,25 @@ void Player::OnAbilityUse(const Ability&ability){
|
||||
ReduceCooldown(GetAbility3());
|
||||
ReduceCooldown(GetAbility4());
|
||||
}
|
||||
|
||||
if(UsedAbility("Deadly Dash")){
|
||||
const bool IsFirstDash{Thief::ability2.manaCost!=0.f};
|
||||
if(HasEnchant("Deadly Mirage")&&IsFirstDash){
|
||||
Thief::ability2.charges++;
|
||||
Thief::ability2.manaCost=0;
|
||||
Thief::ability2.cooldown=0.f;
|
||||
AddTimer(TimerType::DEADLY_MIRAGE_SECOND_CAST,Timer{"Deadly Mirage Second Cast","Deadly Mirage"_ENC["REACTIVATE TIMING WINDOW"],[](){
|
||||
Thief::ability2.manaCost="Thief.Ability 2.Mana Cost"_I;
|
||||
Thief::ability2.cooldown="Thief.Ability 2.Cooldown"_F;
|
||||
Thief::ability2.charges--;
|
||||
},Timer::MANUAL});
|
||||
}
|
||||
if(!IsFirstDash){
|
||||
Thief::ability2.manaCost="Thief.Ability 2.Mana Cost"_I;
|
||||
Thief::ability2.cooldown="Thief.Ability 2.Cooldown"_F;
|
||||
CancelTimer(TimerType::DEADLY_MIRAGE_SECOND_CAST);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ability&Player::GetItem1(){
|
||||
@ -2023,3 +2046,24 @@ const std::vector<std::reference_wrapper<Ability>>Player::GetAbilities(){
|
||||
const bool Player::HasEnchantWithAbilityAffected(const std::string_view abilityName)const{
|
||||
return enchantAbilityList.count(std::string(abilityName));
|
||||
}
|
||||
|
||||
Timer&Player::AddTimer(const TimerType type,const Timer&timer){
|
||||
auto timerReturnResult{timers.insert({type,timer})};
|
||||
Timer&newTimer{(*(timerReturnResult.first)).second};
|
||||
newTimer=timer;
|
||||
return newTimer;
|
||||
}
|
||||
|
||||
Timer&Player::GetTimer(const TimerType type){
|
||||
return timers.at(type);
|
||||
}
|
||||
|
||||
void Player::CancelTimer(const TimerType type){
|
||||
GetTimer(type).Cancel();
|
||||
}
|
||||
|
||||
void Player::RunTimers(){
|
||||
for(auto&[type,timer]:timers){
|
||||
timer.Update(game->GetElapsedTime());
|
||||
}
|
||||
}
|
@ -48,6 +48,7 @@ All rights reserved.
|
||||
#include "Class.h"
|
||||
#include "Item.h"
|
||||
#include "AttributableStat.h"
|
||||
#include "Timer.h"
|
||||
|
||||
|
||||
#undef GetClassName
|
||||
@ -106,6 +107,10 @@ class Player{
|
||||
friend class ItemInfo;
|
||||
friend void ItemOverlay::Draw();
|
||||
public:
|
||||
enum class TimerType{
|
||||
DEADLY_MIRAGE_SECOND_CAST,
|
||||
};
|
||||
|
||||
Player();
|
||||
//So this is rather fascinating and only exists because we have the ability to change classes which means we need to initialize a class
|
||||
//using a new object type... Because of that we'll take the pointer reference to the old object and copy some of its properties to this new
|
||||
@ -309,6 +314,9 @@ public:
|
||||
const int RemainingRapidFireShots()const;
|
||||
const std::vector<std::reference_wrapper<Ability>>GetAbilities();//Returns player defensive, core abilities (1-4) and item abilities.
|
||||
const bool HasEnchantWithAbilityAffected(const std::string_view abilityName)const; //Returns whether or not the player has an enchant that affects the provided name.
|
||||
Timer&AddTimer(const TimerType type,const Timer&timer);
|
||||
Timer&GetTimer(const TimerType type);
|
||||
void CancelTimer(const TimerType type);
|
||||
private:
|
||||
int hp="Warrior.BaseHealth"_I;
|
||||
int mana="Player.BaseMana"_I;
|
||||
@ -391,6 +399,8 @@ private:
|
||||
const bool LastReserveEnchantConditionsMet()const;
|
||||
float poisonArrowLastParticleTimer{};
|
||||
const vf2d GetAimingLocation(bool useWalkDir=false,bool invert=false);
|
||||
std::unordered_map<TimerType,Timer>timers;
|
||||
void RunTimers();
|
||||
protected:
|
||||
const float ATTACK_COOLDOWN="Warrior.Auto Attack.Cooldown"_F;
|
||||
const float MAGIC_ATTACK_COOLDOWN="Wizard.Auto Attack.Cooldown"_F;
|
||||
|
71
Adventures in Lestoria/Timer.cpp
Normal file
71
Adventures in Lestoria/Timer.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
#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 © 2024 The FreeType
|
||||
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
|
||||
All rights reserved.
|
||||
*/
|
||||
#pragma endregion
|
||||
|
||||
#include "Timer.h"
|
||||
|
||||
Timer::Timer(const std::string timerName,const float timer,const std::function<void()>callback,const TimerType autoRepeat)
|
||||
:timerName(timerName),callback(callback),autoRepeat(autoRepeat),originalVal(timer),timer(originalVal){}
|
||||
const bool Timer::Update(const float fElapsedTime){
|
||||
if(IsDone())return false;
|
||||
|
||||
timer=std::max(0.f,timer-fElapsedTime);
|
||||
if(IsDone()){
|
||||
callback();
|
||||
if(autoRepeat==TimerType::REPEAT)timer=originalVal+(timer-fElapsedTime);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void Timer::Reset(){
|
||||
timer=originalVal;
|
||||
}
|
||||
void Timer::Reset(const float newTime){
|
||||
timer=newTime;
|
||||
}
|
||||
const bool Timer::IsRunning()const{
|
||||
return timer>0.f;
|
||||
}
|
||||
const bool Timer::IsDone()const{
|
||||
return !IsRunning();
|
||||
}
|
||||
void Timer::Cancel(){
|
||||
timer=0.f;
|
||||
}
|
||||
const float Timer::RemainingTime()const{
|
||||
return timer;
|
||||
}
|
39
Adventures in Lestoria/Timer.h
Normal file
39
Adventures in Lestoria/Timer.h
Normal file
@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
class Timer{
|
||||
friend struct std::hash<Timer>;
|
||||
public:
|
||||
enum class TimerType{
|
||||
REPEAT,
|
||||
MANUAL,
|
||||
};
|
||||
|
||||
using enum TimerType;
|
||||
private:
|
||||
std::string timerName;
|
||||
float originalVal;
|
||||
float timer;
|
||||
TimerType autoRepeat;
|
||||
std::function<void()>callback;
|
||||
public:
|
||||
Timer(const std::string timerName,const float timer,const std::function<void()>callback,const TimerType autoRepeat=MANUAL);
|
||||
const bool Update(const float fElapsedTime); //Returns false when the timer is completed.
|
||||
void Reset(); //Resets the timer to the original given time it had.
|
||||
void Reset(const float newTime); //Resets the timer to the specified time.
|
||||
void Cancel(); //Stops the timer such that it is no longer running. (Doesn't invoke the callback)
|
||||
const bool IsRunning()const;
|
||||
const bool IsDone()const;
|
||||
const float RemainingTime()const;
|
||||
bool operator==(const Timer&timer){return timerName==timer.timerName;};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::hash<Timer>
|
||||
{
|
||||
std::size_t operator()(const Timer&timer) const
|
||||
{
|
||||
return std::hash<std::string>()(timer.timerName);
|
||||
}
|
||||
};
|
@ -39,7 +39,7 @@ All rights reserved.
|
||||
#define VERSION_MAJOR 1
|
||||
#define VERSION_MINOR 2
|
||||
#define VERSION_PATCH 3
|
||||
#define VERSION_BUILD 10952
|
||||
#define VERSION_BUILD 10966
|
||||
|
||||
#define stringify(a) stringify_(a)
|
||||
#define stringify_(a) #a
|
||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user