diff --git a/Adventures in Lestoria/Animation.cpp b/Adventures in Lestoria/Animation.cpp index ace62e6c..c4b86dd5 100644 --- a/Adventures in Lestoria/Animation.cpp +++ b/Adventures in Lestoria/Animation.cpp @@ -211,6 +211,26 @@ void sig::Animation::InitializeAnimations(){ } ANIMATION_DATA["WIZARD_CAST_W"]=pl_wizard_cast_w; + //Thief animations. + SetupClassWalkIdleAnimations(GFX["nico-thief.png"],"THIEF"); + Animate2D::FrameSequence pl_thief_swing_s(0.05f),pl_thief_swing_n(0.05f),pl_thief_swing_e(0.05f),pl_thief_swing_w(0.05f); + for (int i=0;i<4;i++){ + pl_thief_swing_s.AddFrame({&GFX["nico-thief.png"],{vi2d{4+i,0}*24,{24,24}}}); + } + for (int i=0;i<4;i++){ + pl_thief_swing_n.AddFrame({&GFX["nico-thief.png"],{vi2d{4+i,1}*24,{24,24}}}); + } + for (int i=0;i<4;i++){ + pl_thief_swing_w.AddFrame({&GFX["nico-thief.png"],{vi2d{4+i,2}*24,{24,24}}}); + } + for (int i=0;i<4;i++){ + pl_thief_swing_e.AddFrame({&GFX["nico-thief.png"],{vi2d{4+i,3}*24,{24,24}}}); + } + ANIMATION_DATA["THIEF_SWINGSWORD_N"]=pl_thief_swing_n; + ANIMATION_DATA["THIEF_SWINGSWORD_E"]=pl_thief_swing_e; + ANIMATION_DATA["THIEF_SWINGSWORD_S"]=pl_thief_swing_s; + ANIMATION_DATA["THIEF_SWINGSWORD_W"]=pl_thief_swing_w; + CreateHorizontalAnimationSequence("ground-slam-attack-back.png",5,{64,64},{0.02f,Animate2D::Style::OneShot}); CreateHorizontalAnimationSequence("ground-slam-attack-front.png",5,{64,64},{0.02f,Animate2D::Style::OneShot}); CreateHorizontalAnimationSequence("battlecry_effect.png",5,{84,84},{0.02f,Animate2D::Style::OneShot}); diff --git a/Adventures in Lestoria/Effect.h b/Adventures in Lestoria/Effect.h index 664eaca6..3fec6fab 100644 --- a/Adventures in Lestoria/Effect.h +++ b/Adventures in Lestoria/Effect.h @@ -97,10 +97,12 @@ struct PulsatingFire:Effect{ }; struct SwordSlash:Effect{ - SwordSlash(float lifetime,std::string imgFile,vf2d size={1,1},float fadeout=0.0f,vf2d spd={},Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false); + SwordSlash(float lifetime,std::string imgFile,float damageMult, float swordSweepAngle,vf2d size={1,1},float fadeout=0.0f,vf2d spd={},Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false); bool Update(float fElapsedTime)override; private: HitList hitList; + const float damageMult; + const float swordSweepAngle; }; //This draws effects using screen coordinates instead of world coordinates, useful for applying effects directly on the screen. diff --git a/Adventures in Lestoria/Player.cpp b/Adventures in Lestoria/Player.cpp index bb0e136d..7283091b 100644 --- a/Adventures in Lestoria/Player.cpp +++ b/Adventures in Lestoria/Player.cpp @@ -1019,8 +1019,7 @@ void Player::SetAnimationBasedOnTargetingDirection(float targetDirection){ auto FacingNorth=[&](){return targetDirection>=-3*PI/4&&targetDirection<-PI/4;}; switch(GetClass()){ - case Class::WARRIOR: - case Class::THIEF:{ + case Class::WARRIOR:{ if(FacingNorth()){ UpdateAnimation("WARRIOR_SWINGSWORD_N"); }else @@ -1049,6 +1048,20 @@ void Player::SetAnimationBasedOnTargetingDirection(float targetDirection){ UpdateAnimation("RANGER_SHOOT_E"); } }break; + case Class::THIEF:{ + if(FacingNorth()){ + UpdateAnimation("THIEF_SWINGSWORD_N"); + }else + if(FacingSouth()){ + UpdateAnimation("THIEF_SWINGSWORD_S"); + }else + if(FacingWest()){ + UpdateAnimation("THIEF_SWINGSWORD_W"); + }else + if(FacingEast()){ + UpdateAnimation("THIEF_SWINGSWORD_E"); + } + }break; } } diff --git a/Adventures in Lestoria/SwordSlash.cpp b/Adventures in Lestoria/SwordSlash.cpp index 1ad65e69..dd5e7c6a 100644 --- a/Adventures in Lestoria/SwordSlash.cpp +++ b/Adventures in Lestoria/SwordSlash.cpp @@ -41,12 +41,12 @@ All rights reserved. INCLUDE_game -SwordSlash::SwordSlash(float lifetime, std::string imgFile, vf2d size, float fadeout, vf2d spd, Pixel col, float rotation, float rotationSpd, bool additiveBlending) - :Effect(game->GetPlayer()->GetPos(),lifetime,imgFile,game->GetPlayer()->OnUpperLevel(),size,fadeout,spd,col,rotation,rotationSpd,additiveBlending){} +SwordSlash::SwordSlash(float lifetime, std::string imgFile,float damageMult, float swordSweepAngle,vf2d size, float fadeout, vf2d spd, Pixel col, float rotation, float rotationSpd, bool additiveBlending) + :damageMult(damageMult),swordSweepAngle(swordSweepAngle),Effect(game->GetPlayer()->GetPos(),lifetime,imgFile,game->GetPlayer()->OnUpperLevel(),size,fadeout,spd,col,rotation,rotationSpd,additiveBlending){} bool SwordSlash::Update(float fElapsedTime){ if(lifetime>0){ - game->HurtConeNotHit(game->GetPlayer()->GetPos(),game->GetPlayer()->GetAttackRangeMult()*12.f,rotation,util::degToRad("Warrior.Auto Attack.SwordSlashSweepAngle"_F),game->GetPlayer()->GetAttack(),hitList,game->GetPlayer()->OnUpperLevel(),game->GetPlayer()->GetZ(),HurtType::MONSTER); + game->HurtConeNotHit(game->GetPlayer()->GetPos(),game->GetPlayer()->GetAttackRangeMult()*12.f,rotation,util::degToRad(swordSweepAngle),game->GetPlayer()->GetAttack()*damageMult,hitList,game->GetPlayer()->OnUpperLevel(),game->GetPlayer()->GetZ(),HurtType::MONSTER); } pos=game->GetPlayer()->GetPos(); diff --git a/Adventures in Lestoria/TODO.txt b/Adventures in Lestoria/TODO.txt index 4764a729..2fe5491e 100644 --- a/Adventures in Lestoria/TODO.txt +++ b/Adventures in Lestoria/TODO.txt @@ -26,4 +26,13 @@ Add Spell Names on info screen. PGETinker notes =============== Changing zoom size does not affect the indentation breadcumb immediately (requires scrolling to change the view) -Enabling javid mode does not immediately re-evaluate code. \ No newline at end of file +Enabling javid mode does not immediately re-evaluate code. + + + +Adding new class animations +=========================== +Player.txt contains animation names the player has to have loaded. +.cpp contains walk and idle animation references that must be loaded in the Initialize() function. +Animation.cpp contains the SetupClassWalkIdleAnimations() function which all classes need to implement with their spritesheet and class name (all caps) to create the WALK and IDLE animations in the animation database. + All other custom player class animations must be added here too. \ No newline at end of file diff --git a/Adventures in Lestoria/Thief.cpp b/Adventures in Lestoria/Thief.cpp index c818373d..d6121147 100644 --- a/Adventures in Lestoria/Thief.cpp +++ b/Adventures in Lestoria/Thief.cpp @@ -41,6 +41,7 @@ All rights reserved. #include "Effect.h" #include "AdventuresInLestoria.h" #include "config.h" +#include "SoundEffect.h" INCLUDE_MONSTER_LIST INCLUDE_BULLET_LIST @@ -48,14 +49,14 @@ INCLUDE_game void Thief::Initialize(){ READFROMCONFIG(Thief,THIEF); - Thief::idle_n="WARRIOR_IDLE_N"; - Thief::idle_e="WARRIOR_IDLE_E"; - Thief::idle_s="WARRIOR_IDLE_S"; - Thief::idle_w="WARRIOR_IDLE_W"; - Thief::walk_n="WARRIOR_WALK_N"; - Thief::walk_e="WARRIOR_WALK_E"; - Thief::walk_s="WARRIOR_WALK_S"; - Thief::walk_w="WARRIOR_WALK_W"; + Thief::idle_n="THIEF_IDLE_N"; + Thief::idle_e="THIEF_IDLE_E"; + Thief::idle_s="THIEF_IDLE_S"; + Thief::idle_w="THIEF_IDLE_W"; + Thief::walk_n="THIEF_WALK_N"; + Thief::walk_e="THIEF_WALK_E"; + Thief::walk_s="THIEF_WALK_S"; + Thief::walk_w="THIEF_WALK_W"; } SETUP_CLASS(Thief) @@ -65,7 +66,38 @@ void Thief::OnUpdate(float fElapsedTime){ } bool Thief::AutoAttack(){ - return false; + bool attack=false; + Monster*closest=nullptr; + float closest_dist=999999; + for(std::unique_ptr&m:MONSTER_LIST){ + if(m->IsAlive()&& + geom2d::overlaps(geom2d::circle(GetPos(),attack_range*GetSizeMult()*12),geom2d::circle(m->GetPos(),m->GetSizeMult()*12))&& + geom2d::line(GetWorldAimingLocation(),m->GetPos()).length()(GetWorldAimingLocation(),m->GetPos()).length(); + closest=&*m; + } + } + + float targetDirection; + + if(closest!=nullptr){ + float dirToEnemy=geom2d::line(GetPos(),closest->GetPos()).vector().polar().y; + targetDirection=dirToEnemy; + SetAnimationBasedOnTargetingDirection(dirToEnemy); + }else{ + float dirToMouse=geom2d::line(GetPos(),GetWorldAimingLocation()).vector().polar().y; + targetDirection=dirToMouse; + SetAnimationBasedOnTargetingDirection(dirToMouse); + } + + attack_cooldown_timer=ATTACK_COOLDOWN-GetAttackRecoveryRateReduction(); + swordSwingTimer="Thief.Auto Attack.SwordAnimationSwingTime"_F; + + game->AddEffect(std::make_unique(0.125f,"swordslash.png"s,"Thief.Auto Attack.DamageMult"_F,"Thief.Auto Attack.SwordSlashSweepAngle"_F,vf2d{0.9f,0.9f}*"Thief.Auto Attack.Range"_F/100.f,0.1f,vf2d{0.f,0.f},WHITE,targetDirection)); + + SetState(State::SWING_SWORD); + SoundEffect::PlaySFX("Warrior Auto Attack",SoundEffect::CENTERED); + return true; } void Thief::InitializeClassAbilities(){ #pragma region Thief Right-click Ability (???) diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h index c2b7763e..0ef28a42 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 3 -#define VERSION_BUILD 10050 +#define VERSION_BUILD 10053 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/Adventures in Lestoria/Warrior.cpp b/Adventures in Lestoria/Warrior.cpp index bc96d8b5..0d1875bd 100644 --- a/Adventures in Lestoria/Warrior.cpp +++ b/Adventures in Lestoria/Warrior.cpp @@ -94,7 +94,7 @@ bool Warrior::AutoAttack(){ attack_cooldown_timer=ATTACK_COOLDOWN-GetAttackRecoveryRateReduction(); swordSwingTimer="Warrior.Auto Attack.SwordAnimationSwingTime"_F; - game->AddEffect(std::make_unique(0.125f,"swordslash.png"s,vf2d{0.9f,0.9f}*"Warrior.Auto Attack.Range"_F/100.f,0.1f,vf2d{0.f,0.f},WHITE,targetDirection)); + game->AddEffect(std::make_unique(0.125f,"swordslash.png"s,"Warrior.Auto Attack.DamageMult"_F,"Warrior.Auto Attack.SwordSlashSweepAngle"_F,vf2d{0.9f,0.9f}*"Warrior.Auto Attack.Range"_F/100.f,0.1f,vf2d{0.f,0.f},WHITE,targetDirection)); SetState(State::SWING_SWORD); SoundEffect::PlaySFX("Warrior Auto Attack",SoundEffect::CENTERED); diff --git a/Adventures in Lestoria/assets/config/Player.txt b/Adventures in Lestoria/assets/config/Player.txt index 70391c8e..f8120732 100644 --- a/Adventures in Lestoria/assets/config/Player.txt +++ b/Adventures in Lestoria/assets/config/Player.txt @@ -83,6 +83,9 @@ Player PLAYER_ANIMATION[9] = WIZARD_ATTACK PLAYER_ANIMATION[10] = WIZARD_CAST PLAYER_ANIMATION[11] = WIZARD_IDLE + PLAYER_ANIMATION[12] = THIEF_IDLE + PLAYER_ANIMATION[13] = THIEF_WALK + PLAYER_ANIMATION[14] = THIEF_SWINGSWORD } diff --git a/Adventures in Lestoria/assets/config/classes/Warrior.txt b/Adventures in Lestoria/assets/config/classes/Warrior.txt index a9dd266b..870fadca 100644 --- a/Adventures in Lestoria/assets/config/classes/Warrior.txt +++ b/Adventures in Lestoria/assets/config/classes/Warrior.txt @@ -14,7 +14,7 @@ Warrior Auto Attack { - DamageMult = 1 + DamageMult = 1x Range = 150 Cooldown = 0.35 # Whether or not this ability cancels casts. diff --git a/Adventures in Lestoria/assets/config/gfx/gfx.txt b/Adventures in Lestoria/assets/config/gfx/gfx.txt index a6935985..7a137ed3 100644 --- a/Adventures in Lestoria/assets/config/gfx/gfx.txt +++ b/Adventures in Lestoria/assets/config/gfx/gfx.txt @@ -108,6 +108,8 @@ Images GFX_Feather = feather.png GFX_LargeRock = large_rock.png + GFX_Thief_Sheet = nico-thief.png + # Ability Icons GFX_Warrior_BattleCry_Icon = Ability Icons/battlecry.png GFX_Warrior_Block_Icon = Ability Icons/block.png diff --git a/Adventures in Lestoria/assets/gamepack.pak b/Adventures in Lestoria/assets/gamepack.pak index 23eb5b59..be6552c5 100644 Binary files a/Adventures in Lestoria/assets/gamepack.pak and b/Adventures in Lestoria/assets/gamepack.pak differ diff --git a/Adventures in Lestoria/assets/nico-thief.png b/Adventures in Lestoria/assets/nico-thief.png new file mode 100644 index 00000000..ca261f2b Binary files /dev/null and b/Adventures in Lestoria/assets/nico-thief.png differ diff --git a/Adventures in Lestoria/assets/nico-thief.xcf b/Adventures in Lestoria/assets/nico-thief.xcf new file mode 100644 index 00000000..e8087475 Binary files /dev/null and b/Adventures in Lestoria/assets/nico-thief.xcf differ diff --git a/Adventures in Lestoria/olcPixelGameEngine.h b/Adventures in Lestoria/olcPixelGameEngine.h index c51b9c38..5d1f127b 100644 --- a/Adventures in Lestoria/olcPixelGameEngine.h +++ b/Adventures in Lestoria/olcPixelGameEngine.h @@ -1144,6 +1144,7 @@ namespace olc // Draws a decal rotated to specified angle, wit point of rotation offset void DrawRotatedDecal(const olc::vf2d& pos, olc::Decal* decal, const float fAngle, const olc::vf2d& center = { 0.0f, 0.0f }, const olc::vf2d& scale = { 1.0f,1.0f }, const olc::Pixel& tint = olc::WHITE); void DrawPartialRotatedDecal(const olc::vf2d& pos, olc::Decal* decal, const float fAngle, const olc::vf2d& center, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::vf2d& scale = { 1.0f, 1.0f }, const olc::Pixel& tint = olc::WHITE); + void DrawPartialSquishedRotatedDecal(const olc::vf2d& pos, olc::Decal* decal, const float fAngle, const olc::vf2d& center, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::vf2d& scale = { 1.0f, 1.0f }, const olc::Pixel& tint = olc::WHITE); // Draws a multiline string as a decal, with tiniting and scaling void DrawStringDecal(const olc::vf2d& pos, std::string_view sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f },const float width=std::numeric_limits::max(),const bool disableDynamicScaling=false); void DrawOGStringDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f }); @@ -3321,6 +3322,37 @@ namespace olc di.structure = nDecalStructure; vLayers[nTargetLayer].vecDecalInstance.push_back(di); } + void PixelGameEngine::DrawPartialSquishedRotatedDecal(const olc::vf2d& pos, olc::Decal* decal, const float fAngle, const olc::vf2d& center, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::vf2d& scale, const olc::Pixel& tint) + { + DecalInstance di; + di.decal = decal; + di.points = 4; + di.tint = { tint, tint, tint, tint }; + di.w = { 1, 1, 1, 1 }; + di.pos.resize(4); + di.pos[0] = (olc::vf2d(0.0f, 0.0f) - center); + di.pos[1] = (olc::vf2d(0.0f, source_size.y) - center); + di.pos[2] = (olc::vf2d(source_size.x, source_size.y) - center); + di.pos[3] = (olc::vf2d(source_size.x, 0.0f) - center); + float c = cos(fAngle), s = sin(fAngle); + for (int i = 0; i < 4; i++) + { + di.pos[i] = pos + olc::vf2d(di.pos[i].x * c - di.pos[i].y * s, di.pos[i].x * s + di.pos[i].y * c); + di.pos[i] = di.pos[i] * vInvScreenSize * 2.0f - olc::vf2d(1.0f, 1.0f); + di.pos[i].y *= -1.0f; + } + di.pos[0] *= scale; + di.pos[1] *= scale; + di.pos[2] *= scale; + di.pos[3] *= scale; + + olc::vf2d uvtl = source_pos * decal->vUVScale; + olc::vf2d uvbr = uvtl + (source_size * decal->vUVScale); + di.uv = { { uvtl.x, uvtl.y }, { uvtl.x, uvbr.y }, { uvbr.x, uvbr.y }, { uvbr.x, uvtl.y } }; + di.mode = nDecalMode; + di.structure = nDecalStructure; + vLayers[nTargetLayer].vecDecalInstance.push_back(di); + } void PixelGameEngine::DrawPartialWarpedDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::Pixel& tint) { diff --git a/x64/Release/Adventures in Lestoria.exe b/x64/Release/Adventures in Lestoria.exe index 23d2e33b..389b6a11 100644 Binary files a/x64/Release/Adventures in Lestoria.exe and b/x64/Release/Adventures in Lestoria.exe differ