|
|
|
#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 "Class.h"
|
|
|
|
#include "DEFINES.h"
|
|
|
|
#include "Player.h"
|
|
|
|
#include "Effect.h"
|
|
|
|
#include "AdventuresInLestoria.h"
|
|
|
|
#include "config.h"
|
|
|
|
#include "SoundEffect.h"
|
|
|
|
|
|
|
|
INCLUDE_MONSTER_LIST
|
|
|
|
INCLUDE_BULLET_LIST
|
|
|
|
INCLUDE_game
|
|
|
|
|
|
|
|
void Warrior::Initialize(){
|
|
|
|
READFROMCONFIG(Warrior,WARRIOR);
|
|
|
|
Warrior::idle_n="WARRIOR_IDLE_N";
|
|
|
|
Warrior::idle_e="WARRIOR_IDLE_E";
|
|
|
|
Warrior::idle_s="WARRIOR_IDLE_S";
|
|
|
|
Warrior::idle_w="WARRIOR_IDLE_W";
|
|
|
|
Warrior::walk_n="WARRIOR_WALK_N";
|
|
|
|
Warrior::walk_e="WARRIOR_WALK_E";
|
|
|
|
Warrior::walk_s="WARRIOR_WALK_S";
|
|
|
|
Warrior::walk_w="WARRIOR_WALK_W";
|
|
|
|
}
|
|
|
|
|
|
|
|
SETUP_CLASS(Warrior)
|
|
|
|
|
|
|
|
void Warrior::OnUpdate(float fElapsedTime){
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Warrior::AutoAttack(){
|
|
|
|
if(GetState()!=State::SPIN){
|
|
|
|
bool attack=false;
|
|
|
|
Monster*closest=nullptr;
|
|
|
|
float closest_dist=999999;
|
|
|
|
for(Monster&m:MONSTER_LIST){
|
|
|
|
if(m.IsAlive()
|
|
|
|
&&geom2d::overlaps(geom2d::circle<float>(GetPos(),attack_range*GetSizeMult()*12),geom2d::circle<float>(m.GetPos(),m.GetSizeMult()*12))
|
|
|
|
&&geom2d::line<float>(GetWorldAimingLocation(),m.GetPos()).length()<closest_dist){
|
|
|
|
closest_dist=geom2d::line<float>(GetWorldAimingLocation(),m.GetPos()).length();
|
|
|
|
closest=&m;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(closest!=nullptr){
|
|
|
|
closest->Hurt(int(GetAttack()*"Warrior.Auto Attack.DamageMult"_F),OnUpperLevel(),GetZ());
|
|
|
|
float dirToEnemy=geom2d::line<float>(GetPos(),closest->GetPos()).vector().polar().y;
|
|
|
|
SetAnimationBasedOnTargetingDirection(dirToEnemy);
|
|
|
|
}else{
|
|
|
|
float dirToMouse=geom2d::line<float>(GetPos(),GetWorldAimingLocation()).vector().polar().y;
|
|
|
|
SetAnimationBasedOnTargetingDirection(dirToMouse);
|
|
|
|
}
|
|
|
|
attack_cooldown_timer=ATTACK_COOLDOWN-GetAttackRecoveryRateReduction();
|
|
|
|
swordSwingTimer="Warrior.Auto Attack.SwordSwingTime"_F;
|
|
|
|
|
|
|
|
SetState(State::SWING_SWORD);
|
|
|
|
SoundEffect::PlaySFX("Warrior Auto Attack",SoundEffect::CENTERED);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
void Warrior::InitializeClassAbilities(){
|
|
|
|
#pragma region Warrior Right-click Ability (Block)
|
|
|
|
Warrior::rightClickAbility.action=
|
|
|
|
[](Player*p,vf2d pos={}){
|
|
|
|
if(p->GetState()==State::NORMAL){
|
|
|
|
rightClickAbility.cooldown=rightClickAbility.COOLDOWN_TIME;
|
|
|
|
p->SetState(State::BLOCK);
|
|
|
|
p->blockTimer="Warrior.Right Click Ability.Duration"_F;
|
|
|
|
p->AddBuff(BuffType::BLOCK_SLOWDOWN,"Warrior.Right Click Ability.Duration"_F,"Warrior.Right Click Ability.SlowAmt"_F);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
#pragma endregion
|
|
|
|
#pragma region Warrior Ability 1 (Battlecry)
|
|
|
|
Warrior::ability1.action=
|
|
|
|
[](Player*p,vf2d pos={}){
|
|
|
|
game->AddEffect(std::make_unique<Effect>(p->GetPos(),"Warrior.Ability 1.EffectLifetime"_F,"battlecry_effect.png",p->upperLevel,"Warrior.Ability 1.Range"_F/350,"Warrior.Ability 1.EffectFadetime"_F));
|
|
|
|
p->AddBuff(BuffType::STAT_UP,"Warrior.Ability 1.AttackUpDuration"_F,"Warrior.Ability 1.AttackIncrease"_F,{"Attack %"});
|
|
|
|
p->AddBuff(BuffType::DAMAGE_REDUCTION,"Warrior.Ability 1.DamageReductionDuration"_F,"Warrior.Ability 1.DamageReduction"_F);
|
|
|
|
for(Monster&m:MONSTER_LIST){
|
|
|
|
if(m.GetSizeMult()>="Warrior.Ability 1.AffectedSizeRange"_f[0]&&m.GetSizeMult()<="Warrior.Ability 1.AffectedSizeRange"_f[1]&&geom2d::overlaps(geom2d::circle<float>(p->GetPos(),12*"Warrior.Ability 1.Range"_I/100.f),geom2d::circle<float>(m.GetPos(),m.GetSizeMult()*12))){
|
|
|
|
m.AddBuff(BuffType::SLOWDOWN,"Warrior.Ability 1.SlowdownDuration"_F,"Warrior.Ability 1.SlowdownAmt"_F);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SoundEffect::PlaySFX("Warrior Battlecry",SoundEffect::CENTERED);
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
#pragma endregion
|
|
|
|
#pragma region Warrior Ability 2 (Ground Slam)
|
|
|
|
Warrior::ability2.action=
|
|
|
|
[](Player*p,vf2d pos={}){
|
|
|
|
p->Spin(GROUND_SLAM_SPIN_TIME,"Warrior.Ability 2.SpinSpd"_F*PI);
|
|
|
|
p->iframe_time="Warrior.Ability 2.IframeTime"_F;
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
#pragma endregion
|
|
|
|
#pragma region Warrior Ability 3 (Sonic Slash)
|
|
|
|
Warrior::ability3.action=
|
|
|
|
[](Player*p,vf2d pos={}){
|
|
|
|
p->SetState(State::SWING_SONIC_SWORD);
|
|
|
|
p->AddBuff(BuffType::SLOWDOWN,"Warrior.Ability 3.StuckTime"_F,1);
|
|
|
|
vf2d bulletVel={};
|
|
|
|
switch(p->GetFacingDirection()){
|
|
|
|
case UP:{
|
|
|
|
p->vel.y="Warrior.Ability 3.AbilityPushback"_F;
|
|
|
|
bulletVel.y=-"Warrior.Ability 3.BulletSpd"_F;
|
|
|
|
p->UpdateAnimation("WARRIOR_SWINGSONICSWORD_N",WARRIOR);
|
|
|
|
}break;
|
|
|
|
case LEFT:{
|
|
|
|
p->vel.x="Warrior.Ability 3.AbilityPushback"_F;
|
|
|
|
bulletVel.x=-"Warrior.Ability 3.BulletSpd"_F;
|
|
|
|
p->UpdateAnimation("WARRIOR_SWINGSONICSWORD_W",WARRIOR);
|
|
|
|
}break;
|
|
|
|
case RIGHT:{
|
|
|
|
p->vel.x=-"Warrior.Ability 3.AbilityPushback"_F;
|
|
|
|
bulletVel.x="Warrior.Ability 3.BulletSpd"_F;
|
|
|
|
p->UpdateAnimation("WARRIOR_SWINGSONICSWORD_E",WARRIOR);
|
|
|
|
}break;
|
|
|
|
case DOWN:{
|
|
|
|
p->vel.y=-"Warrior.Ability 3.AbilityPushback"_F;
|
|
|
|
bulletVel.y="Warrior.Ability 3.BulletSpd"_F;
|
|
|
|
p->UpdateAnimation("WARRIOR_SWINGSONICSWORD_S",WARRIOR);
|
|
|
|
}break;
|
|
|
|
}
|
|
|
|
BULLET_LIST.push_back(std::make_unique<Bullet>(p->GetPos(),bulletVel,"Warrior.Ability 3.Radius"_F,p->GetAttack()*"Warrior.Ability 3.DamageMult"_F,"sonicslash.png",p->upperLevel,true,"Warrior.Ability 3.Lifetime"_F,true,true,WHITE,vf2d{"Warrior.Ability 3.Radius"_F/30,"Warrior.Ability 3.Radius"_F/30}));
|
|
|
|
game->SetupWorldShake("Warrior.Ability 3.ShakeTime"_F);
|
|
|
|
SoundEffect::PlaySFX("Warrior Sonic Slash",SoundEffect::CENTERED);
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
#pragma endregion
|
|
|
|
}
|