Class abilities are statically set so they are initialized on load to allow for proper swapping.

pull/28/head
sigonasr2 1 year ago
parent 1faf121bb9
commit 3a880c55a2
  1. 4
      Crawler/Ability.h
  2. 12
      Crawler/Crawler.cpp
  3. 1
      Crawler/Crawler.h
  4. 4
      Crawler/DEFINES.h
  5. 5
      Crawler/Player.cpp
  6. 19
      Crawler/Player.h
  7. 8
      Crawler/Ranger.cpp
  8. 8
      Crawler/Thief.cpp
  9. 8
      Crawler/Trapper.cpp
  10. 2
      Crawler/Version.h
  11. 50
      Crawler/Warrior.cpp
  12. 8
      Crawler/Witch.cpp
  13. 47
      Crawler/Wizard.cpp

@ -1,6 +1,8 @@
#pragma once
#include "olcPixelGameEngine.h"
struct Player;
struct PrecastData{
float castTime;
float range;
@ -19,7 +21,7 @@ struct Ability{
int manaCost=0;
Pixel barColor1,barColor2;
PrecastData precastInfo;
std::function<bool(vf2d)>action=[&](vf2d){return false;};
std::function<bool(Player*,vf2d)>action=[](Player*,vf2d){return false;};
Ability();
Ability(std::string name,float cooldownTime,int manaCost,Pixel barColor1=VERY_DARK_RED,Pixel barColor2=DARK_RED,PrecastData precastInfo={});
};

@ -87,7 +87,9 @@ bool Crawler::OnUserCreate(){
view=TileTransformedView{GetScreenSize(),{1,1}};
LoadLevel(CAMPAIGN_1_1);
InitializeClassAbilities();
ChangePlayerClass(WARRIOR);
//Warrior::ability4=Wizard::ability3; //Class ability swapping demonstration.
return true;
}
@ -1040,10 +1042,18 @@ void Crawler::ChangePlayerClass(Class cl){
}break;
}
sig::Animation::SetupPlayerAnimations();
GetPlayer()->InitializeClassAbilities();
GetPlayer()->UpdateIdleAnimation(DOWN);
}
void Crawler::InitializeClassAbilities(){
Warrior::InitializeClassAbilities();
Thief::InitializeClassAbilities();
Ranger::InitializeClassAbilities();
Trapper::InitializeClassAbilities();
Wizard::InitializeClassAbilities();
Witch::InitializeClassAbilities();
}
int main()
{
Crawler demo;

@ -49,6 +49,7 @@ private:
std::vector<TileGroup>upperForegroundTileGroups;
int bridgeLayerIndex=-1;
float bridgeFadeFactor=0.f;
void InitializeClassAbilities();
public:
Crawler();

@ -14,9 +14,9 @@
#define INFINITE 999999
#define SETUP_CLASS(class) \
class::class(){InitializeClassAbilities();} \
class::class(){} \
class::class(Player*player) \
:Player::Player(player){InitializeClassAbilities();} \
:Player::Player(player){} \
Class class::GetClass(){return cl;} \
std::string class::GetClassName(){return name;} \
Ability&class::GetRightClickAbility(){return rightClickAbility;}; \

@ -166,7 +166,7 @@ void Player::Update(float fElapsedTime){
if(castInfo.castTimer>0){
castInfo.castTimer-=fElapsedTime;
if(castInfo.castTimer<=0){
if(castPrepAbility->action(castInfo.castPos)){
if(castPrepAbility->action(this,castInfo.castPos)){
castPrepAbility->cooldown=castPrepAbility->COOLDOWN_TIME;
mana-=castPrepAbility->manaCost;
}
@ -269,6 +269,7 @@ void Player::Update(float fElapsedTime){
ability.cooldown=std::max(0.f,ability.cooldown-fElapsedTime);
ability2.cooldown=std::max(0.f,ability2.cooldown-fElapsedTime);
ability3.cooldown=std::max(0.f,ability3.cooldown-fElapsedTime);
ability4.cooldown=std::max(0.f,ability4.cooldown-fElapsedTime);
for(Monster&m:MONSTER_LIST){
if(iframe_time==0&&OnUpperLevel()==m.OnUpperLevel()&&geom2d::overlaps(geom2d::circle(pos,12*size/2),geom2d::circle(m.GetPos(),12*m.GetSizeMult()/2))){
if(m.IsAlive()){
@ -309,7 +310,7 @@ void Player::Update(float fElapsedTime){
if(ability.name!="???"){
if(ability.cooldown==0&&GetMana()>=ability.manaCost){
if(key.bHeld||key.bReleased&&&ability==castPrepAbility&&GetState()==State::PREP_CAST){
if(AllowedToCast(ability)&&ability.action({})){
if(AllowedToCast(ability)&&ability.action(this,{})){
ability.cooldown=ability.COOLDOWN_TIME;
mana-=ability.manaCost;
}else

@ -19,6 +19,12 @@ struct CastInfo{
struct Player{
friend class Crawler;
friend class sig::Animation;
friend class Warrior;
friend class Thief;
friend class Ranger;
friend class Trapper;
friend class Wizard;
friend class Witch;
private:
int hp=100,maxhp=hp;
int mana=100,maxmana=mana;
@ -119,7 +125,6 @@ public:
virtual Class GetClass()=0;
virtual bool AutoAttack()=0;
virtual void OnUpdate(float fElapsedTime)=0;
virtual void InitializeClassAbilities()=0;
virtual std::string GetClassName()=0;
virtual Ability&GetRightClickAbility()=0;
virtual Ability&GetAbility1()=0;
@ -148,7 +153,7 @@ struct Warrior:Player{
Class GetClass()override;
bool AutoAttack()override;
void OnUpdate(float fElapsedTime)override;
void InitializeClassAbilities()override;
static void InitializeClassAbilities();
std::string GetClassName()override;
Ability&GetRightClickAbility()override;
Ability&GetAbility1()override;
@ -175,7 +180,7 @@ struct Thief:Player{
Class GetClass()override;
bool AutoAttack()override;
void OnUpdate(float fElapsedTime)override;
void InitializeClassAbilities()override;
static void InitializeClassAbilities();
std::string GetClassName()override;
Ability&GetRightClickAbility()override;
Ability&GetAbility1()override;
@ -202,7 +207,7 @@ struct Ranger:Player{
Class GetClass()override;
bool AutoAttack()override;
void OnUpdate(float fElapsedTime)override;
void InitializeClassAbilities()override;
static void InitializeClassAbilities();
std::string GetClassName()override;
Ability&GetRightClickAbility()override;
Ability&GetAbility1()override;
@ -229,7 +234,7 @@ struct Trapper:Player{
Class GetClass()override;
bool AutoAttack()override;
void OnUpdate(float fElapsedTime)override;
void InitializeClassAbilities()override;
static void InitializeClassAbilities();
std::string GetClassName()override;
Ability&GetRightClickAbility()override;
Ability&GetAbility1()override;
@ -256,7 +261,7 @@ struct Wizard:Player{
Class GetClass()override;
bool AutoAttack()override;
void OnUpdate(float fElapsedTime)override;
void InitializeClassAbilities()override;
static void InitializeClassAbilities();
std::string GetClassName()override;
Ability&GetRightClickAbility()override;
Ability&GetAbility1()override;
@ -283,7 +288,7 @@ struct Witch:Player{
Class GetClass()override;
bool AutoAttack()override;
void OnUpdate(float fElapsedTime)override;
void InitializeClassAbilities()override;
static void InitializeClassAbilities();
std::string GetClassName()override;
Ability&GetRightClickAbility()override;
Ability&GetAbility1()override;

@ -37,25 +37,25 @@ bool Ranger::AutoAttack(){
void Ranger::InitializeClassAbilities(){
#pragma region Ranger Right-click Ability (???)
Ranger::rightClickAbility.action=
[&](vf2d pos={}){
[](Player*p,vf2d pos={}){
return false;
};
#pragma endregion
#pragma region Ranger Ability 1 (???)
Ranger::ability1.action=
[&](vf2d pos={}){
[](Player*p,vf2d pos={}){
return false;
};
#pragma endregion
#pragma region Ranger Ability 2 (???)
Ranger::ability2.action=
[&](vf2d pos={}){
[](Player*p,vf2d pos={}){
return false;
};
#pragma endregion
#pragma region Ranger Ability 3 (???)
Ranger::ability3.action=
[&](vf2d pos={}){
[](Player*p,vf2d pos={}){
return false;
};
#pragma endregion

@ -37,25 +37,25 @@ bool Thief::AutoAttack(){
void Thief::InitializeClassAbilities(){
#pragma region Thief Right-click Ability (???)
Thief::rightClickAbility.action=
[&](vf2d pos={}){
[](Player*p,vf2d pos={}){
return false;
};
#pragma endregion
#pragma region Thief Ability 1 (???)
Thief::ability1.action=
[&](vf2d pos={}){
[](Player*p,vf2d pos={}){
return false;
};
#pragma endregion
#pragma region Thief Ability 2 (???)
Thief::ability2.action=
[&](vf2d pos={}){
[](Player*p,vf2d pos={}){
return false;
};
#pragma endregion
#pragma region Thief Ability 3 (???)
Thief::ability3.action=
[&](vf2d pos={}){
[](Player*p,vf2d pos={}){
return false;
};
#pragma endregion

@ -37,25 +37,25 @@ bool Trapper::AutoAttack(){
void Trapper::InitializeClassAbilities(){
#pragma region Trapper Right-click Ability (???)
Trapper::rightClickAbility.action=
[&](vf2d pos={}){
[](Player*p,vf2d pos={}){
return false;
};
#pragma endregion
#pragma region Trapper Ability 1 (???)
Trapper::ability1.action=
[&](vf2d pos={}){
[](Player*p,vf2d pos={}){
return false;
};
#pragma endregion
#pragma region Trapper Ability 2 (???)
Trapper::ability2.action=
[&](vf2d pos={}){
[](Player*p,vf2d pos={}){
return false;
};
#pragma endregion
#pragma region Trapper Ability 3 (???)
Trapper::ability3.action=
[&](vf2d pos={}){
[](Player*p,vf2d pos={}){
return false;
};
#pragma endregion

@ -2,7 +2,7 @@
#define VERSION_MAJOR 0
#define VERSION_MINOR 2
#define VERSION_PATCH 0
#define VERSION_BUILD 747
#define VERSION_BUILD 759
#define stringify(a) stringify_(a)
#define stringify_(a) #a

@ -70,11 +70,11 @@ bool Warrior::AutoAttack(){
void Warrior::InitializeClassAbilities(){
#pragma region Warrior Right-click Ability (Block)
Warrior::rightClickAbility.action=
[&](vf2d pos={}){
if(GetState()==State::NORMAL){
[](Player*p,vf2d pos={}){
if(p->GetState()==State::NORMAL){
rightClickAbility.cooldown=rightClickAbility.COOLDOWN_TIME;
SetState(State::BLOCK);
AddBuff(BuffType::SLOWDOWN,3,0.3);
p->SetState(State::BLOCK);
p->AddBuff(BuffType::SLOWDOWN,3,0.3);
return true;
}
return false;
@ -82,12 +82,12 @@ void Warrior::InitializeClassAbilities(){
#pragma endregion
#pragma region Warrior Ability 1 (Battlecry)
Warrior::ability1.action=
[&](vf2d pos={}){
game->AddEffect(std::make_unique<Effect>(GetPos(),0.1,AnimationState::BATTLECRY_EFFECT,upperLevel,1,0.3));
AddBuff(BuffType::ATTACK_UP,10,0.1);
AddBuff(BuffType::DAMAGE_REDUCTION,10,0.1);
[](Player*p,vf2d pos={}){
game->AddEffect(std::make_unique<Effect>(p->GetPos(),0.1,AnimationState::BATTLECRY_EFFECT,p->upperLevel,1,0.3));
p->AddBuff(BuffType::ATTACK_UP,10,0.1);
p->AddBuff(BuffType::DAMAGE_REDUCTION,10,0.1);
for(Monster&m:MONSTER_LIST){
if(m.GetSizeMult()<=1&&geom2d::overlaps(geom2d::circle<float>(GetPos(),12*3.5),geom2d::circle<float>(m.GetPos(),m.GetSizeMult()*12))){
if(m.GetSizeMult()<=1&&geom2d::overlaps(geom2d::circle<float>(p->GetPos(),12*3.5),geom2d::circle<float>(m.GetPos(),m.GetSizeMult()*12))){
m.AddBuff(BuffType::SLOWDOWN,5,0.3);
}
}
@ -96,41 +96,41 @@ void Warrior::InitializeClassAbilities(){
#pragma endregion
#pragma region Warrior Ability 2 (Ground Slam)
Warrior::ability2.action=
[&](vf2d pos={}){
Spin(GROUND_SLAM_SPIN_TIME,14*PI);
iframe_time=GROUND_SLAM_SPIN_TIME+0.1;
[](Player*p,vf2d pos={}){
p->Spin(GROUND_SLAM_SPIN_TIME,14*PI);
p->iframe_time=GROUND_SLAM_SPIN_TIME+0.1;
return true;
};
#pragma endregion
#pragma region Warrior Ability 3 (Sonic Slash)
Warrior::ability3.action=
[&](vf2d pos={}){
SetState(State::SWING_SONIC_SWORD);
AddBuff(BuffType::SLOWDOWN,0.5,1);
[](Player*p,vf2d pos={}){
p->SetState(State::SWING_SONIC_SWORD);
p->AddBuff(BuffType::SLOWDOWN,0.5,1);
vf2d bulletVel={};
switch(GetFacingDirection()){
switch(p->GetFacingDirection()){
case UP:{
vel.y=70;
p->vel.y=70;
bulletVel.y=-400;
UpdateAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_N,WARRIOR);
p->UpdateAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_N,WARRIOR);
}break;
case LEFT:{
vel.x=70;
p->vel.x=70;
bulletVel.x=-400;
UpdateAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_W,WARRIOR);
p->UpdateAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_W,WARRIOR);
}break;
case RIGHT:{
vel.x=-70;
p->vel.x=-70;
bulletVel.x=400;
UpdateAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_E,WARRIOR);
p->UpdateAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_E,WARRIOR);
}break;
case DOWN:{
vel.y=-70;
p->vel.y=-70;
bulletVel.y=400;
UpdateAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_S,WARRIOR);
p->UpdateAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_S,WARRIOR);
}break;
}
BULLET_LIST.push_back(std::make_unique<Bullet>(GetPos(),bulletVel,30,GetAttack()*8,AnimationState::SONICSLASH,upperLevel,true,2.25,true,true,WHITE));
BULLET_LIST.push_back(std::make_unique<Bullet>(p->GetPos(),bulletVel,30,p->GetAttack()*8,AnimationState::SONICSLASH,p->upperLevel,true,2.25,true,true,WHITE));
game->SetupWorldShake(0.5);
return true;
};

@ -37,25 +37,25 @@ bool Witch::AutoAttack(){
void Witch::InitializeClassAbilities(){
#pragma region Witch Right-click Ability (???)
Witch::rightClickAbility.action=
[&](vf2d pos={}){
[](Player*p,vf2d pos={}){
return false;
};
#pragma endregion
#pragma region Witch Ability 1 (???)
Witch::ability1.action=
[&](vf2d pos={}){
[](Player*p,vf2d pos={}){
return false;
};
#pragma endregion
#pragma region Witch Ability 2 (???)
Witch::ability2.action=
[&](vf2d pos={}){
[](Player*p,vf2d pos={}){
return false;
};
#pragma endregion
#pragma region Witch Ability 3 (???)
Witch::ability3.action=
[&](vf2d pos={}){
[](Player*p,vf2d pos={}){
return false;
};
#pragma endregion

@ -75,53 +75,54 @@ bool Wizard::AutoAttack(){
void Wizard::InitializeClassAbilities(){
#pragma region Wizard Right-click Ability (Teleport)
Wizard::rightClickAbility.action=
[&](vf2d pos={}){
float pointMouseDirection=atan2(game->GetWorldMousePos().y-GetPos().y,game->GetWorldMousePos().x-GetPos().x);
[](Player*p,vf2d pos={}){
if(p->GetState()==State::CASTING)return false;
float pointMouseDirection=atan2(game->GetWorldMousePos().y-p->GetPos().y,game->GetWorldMousePos().x-p->GetPos().x);
vf2d pointTowardsMouse={cos(pointMouseDirection),sin(pointMouseDirection)};
float dist=std::clamp(geom2d::line<float>{GetPos(),game->GetWorldMousePos()}.length(),0.f,6.5f*24);
float dist=std::clamp(geom2d::line<float>{p->GetPos(),game->GetWorldMousePos()}.length(),0.f,6.5f*24);
if(dist<12)return false;
vf2d teleportPoint=GetPos()+pointTowardsMouse*dist;
while(dist>0&&game->HasTileCollision(game->GetCurrentLevel(),teleportPoint)&&CanPathfindTo(GetPos(),teleportPoint)){
vf2d teleportPoint=p->GetPos()+pointTowardsMouse*dist;
while(dist>0&&game->HasTileCollision(game->GetCurrentLevel(),teleportPoint)&&p->CanPathfindTo(p->GetPos(),teleportPoint)){
dist-=24;
teleportPoint=GetPos()+pointTowardsMouse*dist;
teleportPoint=p->GetPos()+pointTowardsMouse*dist;
}
if(dist>0&&CanPathfindTo(GetPos(),teleportPoint)){
SetState(State::TELEPORT);
teleportAnimationTimer=0.35;
teleportTarget=teleportPoint;
teleportStartPosition=GetPos();
iframe_time=0.35;
if(dist>0&&p->CanPathfindTo(p->GetPos(),teleportPoint)){
p->SetState(State::TELEPORT);
p->teleportAnimationTimer=0.35;
p->teleportTarget=teleportPoint;
p->teleportStartPosition=p->GetPos();
p->iframe_time=0.35;
for(int i=0;i<16;i++){
game->AddEffect(std::make_unique<Effect>(GetPos()+vf2d{(rand()%160-80)/10.f,(rand()%160-80)/10.f},float(rand()%300)/1000,AnimationState::DOT_PARTICLE,upperLevel,0.3,0.2,vf2d{float(rand()%1000-500)/100,float(rand()%1000-500)/100},BLACK));
game->AddEffect(std::make_unique<Effect>(p->GetPos()+vf2d{(rand()%160-80)/10.f,(rand()%160-80)/10.f},float(rand()%300)/1000,AnimationState::DOT_PARTICLE,p->upperLevel,0.3,0.2,vf2d{float(rand()%1000-500)/100,float(rand()%1000-500)/100},BLACK));
}
return true;
} else {
notificationDisplay={"Cannot Teleport to that location!",0.5};
p->notificationDisplay={"Cannot Teleport to that location!",0.5};
return false;
}
};
#pragma endregion
#pragma region Wizard Ability 1 (Fire Bolt)
Wizard::ability1.action=
[&](vf2d pos={}){
float angleToCursor=atan2(game->GetWorldMousePos().y-GetPos().y,game->GetWorldMousePos().x-GetPos().x);
BULLET_LIST.push_back(std::make_unique<FireBolt>(FireBolt(GetPos(),{cos(angleToCursor)*275,sin(angleToCursor)*275},12,GetAttack(),upperLevel,true,{240,120,60})));
[](Player*p,vf2d pos={}){
float angleToCursor=atan2(game->GetWorldMousePos().y-p->GetPos().y,game->GetWorldMousePos().x-p->GetPos().x);
BULLET_LIST.push_back(std::make_unique<FireBolt>(FireBolt(p->GetPos(),{cos(angleToCursor)*275,sin(angleToCursor)*275},12,p->GetAttack(),p->upperLevel,true,{240,120,60})));
return true;
};
#pragma endregion
#pragma region Wizard Ability 2 (Lightning Bolt)
Wizard::ability2.action=
[&](vf2d pos={}){
float angleToCursor=atan2(game->GetWorldMousePos().y-GetPos().y,game->GetWorldMousePos().x-GetPos().x);
BULLET_LIST.push_back(std::make_unique<LightningBolt>(LightningBolt(GetPos(),{cos(angleToCursor)*230,sin(angleToCursor)*230},12,GetAttack()*4,upperLevel,true,WHITE)));
[](Player*p,vf2d pos={}){
float angleToCursor=atan2(game->GetWorldMousePos().y-p->GetPos().y,game->GetWorldMousePos().x-p->GetPos().x);
BULLET_LIST.push_back(std::make_unique<LightningBolt>(LightningBolt(p->GetPos(),{cos(angleToCursor)*230,sin(angleToCursor)*230},12,p->GetAttack()*4,p->upperLevel,true,WHITE)));
return true;
};
#pragma endregion
#pragma region Wizard Ability 3 (Meteor)
Wizard::ability3.action=
[&](vf2d pos={}){
CastSpell(Wizard::ability3);
game->AddEffect(std::make_unique<Meteor>(pos,3,AnimationState::METEOR,OnUpperLevel(),vf2d{1,1},2));
[](Player*p,vf2d pos={}){
p->CastSpell(Wizard::ability3);
game->AddEffect(std::make_unique<Meteor>(pos,3,AnimationState::METEOR,p->OnUpperLevel(),vf2d{1,1},2));
return true;
};
#pragma endregion

Loading…
Cancel
Save