|
|
|
#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 "BulletTypes.h"
|
|
|
|
#include <ranges>
|
|
|
|
#include "util.h"
|
|
|
|
|
|
|
|
INCLUDE_MONSTER_LIST
|
|
|
|
INCLUDE_BULLET_LIST
|
|
|
|
INCLUDE_game
|
|
|
|
|
|
|
|
void Trapper::Initialize(){
|
|
|
|
READFROMCONFIG(Trapper,TRAPPER);
|
|
|
|
Trapper::idle_n="TRAPPER_IDLE_N";
|
|
|
|
Trapper::idle_e="TRAPPER_IDLE_E";
|
|
|
|
Trapper::idle_s="TRAPPER_IDLE_S";
|
|
|
|
Trapper::idle_w="TRAPPER_IDLE_W";
|
|
|
|
Trapper::walk_n="TRAPPER_WALK_N";
|
|
|
|
Trapper::walk_e="TRAPPER_WALK_E";
|
|
|
|
Trapper::walk_s="TRAPPER_WALK_S";
|
|
|
|
Trapper::walk_w="TRAPPER_WALK_W";
|
|
|
|
}
|
|
|
|
|
|
|
|
SETUP_CLASS(Trapper)
|
|
|
|
|
|
|
|
void Trapper::OnUpdate(float fElapsedTime){
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Trapper::AutoAttack(){
|
|
|
|
geom2d::line pointTowardsCursor(GetPos(),GetWorldAimingLocation());
|
|
|
|
vf2d extendedLine=pointTowardsCursor.upoint(1.1f);
|
|
|
|
float angleToCursor=atan2(extendedLine.y-GetPos().y,extendedLine.x-GetPos().x);
|
|
|
|
attack_cooldown_timer=ARROW_ATTACK_COOLDOWN-GetAttackRecoveryRateReduction();
|
|
|
|
CreateBullet(Arrow)(GetPos(),extendedLine,vf2d{cos(angleToCursor)*"Ranger.Auto Attack.ArrowSpd"_F,float(sin(angleToCursor)*"Ranger.Auto Attack.ArrowSpd"_F-PI/8*"Ranger.Auto Attack.ArrowSpd"_F)}+movementVelocity/1.5f,"Ranger.Auto Attack.Radius"_F,int(GetAttack()*"Ranger.Auto Attack.DamageMult"_F),OnUpperLevel(),true)EndBullet;
|
|
|
|
BULLET_LIST.back()->SetIsPlayerAutoAttackProjectile();
|
|
|
|
SetState(State::SHOOT_ARROW);
|
|
|
|
SetAnimationBasedOnTargetingDirection("SHOOT",angleToCursor);
|
|
|
|
SoundEffect::PlaySFX("Ranger.Auto Attack.Sound"_S,SoundEffect::CENTERED);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
void Trapper::InitializeClassAbilities(){
|
|
|
|
#pragma region Trapper Right-click Ability (Sprint)
|
|
|
|
Trapper::rightClickAbility.action=
|
|
|
|
[](Player*p,vf2d pos={}){
|
|
|
|
SoundEffect::PlaySFX("Sprint",SoundEffect::CENTERED);
|
|
|
|
p->AddBuff(BuffType::SPEEDBOOST,"Trapper.Right Click Ability.Movement Speed Buff"_f[1],"Trapper.Right Click Ability.Movement Speed Buff"_f[0]/100.f);
|
|
|
|
for(int i:std::ranges::iota_view(0,50)){
|
|
|
|
float size{util::random_range(0.4f,0.8f)};
|
|
|
|
game->AddEffect(std::make_unique<Effect>(p->GetPos()+vf2d{8,util::random(2*PI)}.cart(),util::random_range(0.1f,0.4f),"circle.png",p->OnUpperLevel(),vf2d{size,size},0.3f,vf2d{util::random_range(-6.f,6.f),util::random_range(-8.f,-1.f)},PixelLerp(BLACK,RED,util::random(1))));
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
#pragma endregion
|
|
|
|
#pragma region Trapper Ability 1 (Mark Target)
|
|
|
|
Trapper::ability1.action=
|
|
|
|
[](Player*p,vf2d pos={}){
|
|
|
|
std::optional<std::weak_ptr<Monster>>nearestMonster{Monster::GetNearestMonster(pos,Trapper::ability1.precastInfo.range,p->OnUpperLevel(),p->GetZ())};
|
|
|
|
vf2d targetPos{pos};
|
|
|
|
if(nearestMonster.has_value()){
|
|
|
|
targetPos=nearestMonster.value().lock()->GetPos();
|
|
|
|
nearestMonster.value().lock()->ApplyMark("Trapper.Ability 1.Duration"_F,"Trapper.Ability 1.Stack Count"_I);
|
|
|
|
for(int i:std::ranges::iota_view(0,int(util::distance(p->GetPos(),targetPos)/16))){
|
|
|
|
float drawDist{i*16.f};
|
|
|
|
float fadeInTime{i*0.05f};
|
|
|
|
float fadeOutTime{0.5f+i*0.05f};
|
|
|
|
float effectSize{util::random(0.4f)};
|
|
|
|
game->AddEffect(std::make_unique<Effect>(geom2d::line<float>(p->GetPos(),targetPos).rpoint(drawDist),0.f,"mark_trail.png",p->OnUpperLevel(),fadeInTime,fadeOutTime,vf2d{effectSize,effectSize},vf2d{},Pixel{255,255,255,uint8_t(util::random_range(60,150))},0.f,0.f,true),true);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
#pragma endregion
|
|
|
|
#pragma region Trapper Ability 2 (Bear Trap)
|
|
|
|
Trapper::ability2.action=
|
|
|
|
[](Player*p,vf2d pos={}){
|
|
|
|
CreateBullet(BearTrap)(p->GetPos(),"Trapper.Ability 2.Trap Radius"_I,"Trapper.Ability 2.DamageMult"_F*p->GetAttack(),0.2f,0.5f,p->OnUpperLevel(),false,INFINITE,true,WHITE,{1.f,1.f})EndBullet;
|
|
|
|
SoundEffect::PlaySFX("Place Down Trap",p->GetPos());
|
|
|
|
p->SetAnimationBasedOnTargetingDirection("SETTRAP",p->GetFacingDirection());
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
#pragma endregion
|
|
|
|
#pragma region Trapper Ability 3 (Explosive Trap)
|
|
|
|
Trapper::ability3.action=
|
|
|
|
[](Player*p,vf2d pos={}){
|
|
|
|
CreateBullet(ExplosiveTrap)(p->GetPos(),"Trapper.Ability 3.Trap Radius"_I,"Trapper.Ability 3.Explosion Radius"_F/100.f*24,"Trapper.Ability 3.Trap Auto Detonate Time"_F,"Trapper.Ability 3.DamageMult"_F*p->GetAttack(),0.2f,0.5f,"Trapper.Ability 3.Trap Activation Time"_F,p->OnUpperLevel(),false,INFINITE,true,WHITE,{1.f,1.f})EndBullet;
|
|
|
|
SoundEffect::PlaySFX("Place Down Trap",p->GetPos());
|
|
|
|
p->SetAnimationBasedOnTargetingDirection("SETTRAP",p->GetFacingDirection());
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
#pragma endregion
|
|
|
|
}
|