diff --git a/Adventures in Lestoria/Ability.cpp b/Adventures in Lestoria/Ability.cpp index 09825825..33d354b6 100644 --- a/Adventures in Lestoria/Ability.cpp +++ b/Adventures in Lestoria/Ability.cpp @@ -46,7 +46,7 @@ PrecastData::PrecastData(float castTime) :castTime(castTime),range(0),size(0){precastTargetingRequired=true;}; PrecastData::PrecastData(float castTime,float range,float size) :castTime(castTime),range(range),size(size){ - if(castTime>0)precastTargetingRequired=true; + if(range>0||castTime>0)precastTargetingRequired=true; }; InputGroup Ability::DEFAULT; diff --git a/Adventures in Lestoria/AdventuresInLestoria.cpp b/Adventures in Lestoria/AdventuresInLestoria.cpp index c1e4c421..f8b9185b 100644 --- a/Adventures in Lestoria/AdventuresInLestoria.cpp +++ b/Adventures in Lestoria/AdventuresInLestoria.cpp @@ -448,7 +448,7 @@ void AiL::HandleUserInput(float fElapsedTime){ } float animationSpd=0.f; player->movementVelocity={}; - if(player->GetVelocity().mag()<"Player.Move Allowed Velocity Lower Limit"_F&&player->CanMove()){ + if((player->GetVelocity().mag()<"Player.Move Allowed Velocity Lower Limit"_F&&player->CanMove())||(player->GetState()==State::ROLL&&"Thief.Right Click Ability.Roll Time"_F-player->rolling_timer>=0.2f)){ auto GetPlayerStaircaseDirection=[&](){ for(LayerTag&layer:MAP_DATA[GetCurrentLevel()].LayerData){ int truncatedPlayerX=int(player->GetX())/game->GetCurrentMapData().tilewidth; @@ -559,6 +559,11 @@ void AiL::HandleUserInput(float fElapsedTime){ } } if(heldDownMovementKey){ + if(player->GetState()==State::ROLL&&"Thief.Right Click Ability.Roll Time"_F-player->rolling_timer>=0.2f){ + player->SetState(State::NORMAL); + player->ResetVelocity(); + } + if(player->movementVelocity.x!=0.f||player->movementVelocity.y!=0.f){ if(abs(player->movementVelocity.x)>abs(player->movementVelocity.y)){ //Greater Horizontal movement. if(player->movementVelocity.x!=0.f){ @@ -1034,8 +1039,14 @@ void AiL::RenderWorld(float fElapsedTime){ playerScale.x=120*float(abs(pow(player->teleportAnimationTimer-"Wizard.Right Click Ability.AnimationTime"_F/2,3))); pos=player->teleportStartPosition.lerp(player->teleportTarget,("Wizard.Right Click Ability.AnimationTime"_F-player->teleportAnimationTimer)/"Wizard.Right Click Ability.AnimationTime"_F); } - const std::vectorattackBuffs=player->GetStatBuffs({"Attack","Attack %"}); - view.DrawPartialRotatedDecal(pos+vf2d{0,-player->GetZ()*(std::signbit(scale.y)?-1:1)},player->GetFrame().GetSourceImage()->Decal(),player->GetSpinAngle(),{12,12},player->GetFrame().GetSourceRect().pos,player->GetFrame().GetSourceRect().size,playerScale*scale,attackBuffs.size()>0?Pixel{255,uint8_t(255*abs(sin(1.4*attackBuffs[0].duration))),uint8_t(255*abs(sin(1.4*attackBuffs[0].duration)))}:WHITE); + const std::vectorattackBuffs{player->GetStatBuffs({"Attack","Attack %"})}; + const std::vectormovespeedBuffs{player->GetBuffs(BuffType::SPEEDBOOST)}; + + Pixel playerCol{WHITE}; + if(attackBuffs.size()>0)playerCol={255,uint8_t(255*abs(sin(1.4f*attackBuffs[0].duration))),uint8_t(255*abs(sin(1.4f*attackBuffs[0].duration)))}; + else if(movespeedBuffs.size()>0)playerCol={uint8_t(255*abs(sin(2.f*movespeedBuffs[0].duration))),255,uint8_t(255*abs(sin(2.f*movespeedBuffs[0].duration)))}; + + view.DrawPartialSquishedRotatedDecal(pos+vf2d{0,-player->GetZ()*(std::signbit(scale.y)?-1:1)},player->GetFrame().GetSourceImage()->Decal(),player->GetSpinAngle(),{12,12},player->GetFrame().GetSourceRect().pos,player->GetFrame().GetSourceRect().size,playerScale*scale,{1.f,player->ySquishFactor},playerCol); SetDecalMode(DecalMode::NORMAL); if(player->GetState()==State::BLOCK){ view.DrawDecal(player->GetPos()+vf2d{0,-player->GetZ()*(std::signbit(scale.y)?-1:1)}-vf2d{12,12},GFX["block.png"].Decal()); diff --git a/Adventures in Lestoria/Player.cpp b/Adventures in Lestoria/Player.cpp index 7283091b..a7c149f8 100644 --- a/Adventures in Lestoria/Player.cpp +++ b/Adventures in Lestoria/Player.cpp @@ -353,7 +353,11 @@ void Player::Update(float fElapsedTime){ CheckEndZoneCollision(); - if(castInfo.castTimer>0){ + if(state==State::CASTING){ + if(!Audio::Engine().IsPlaying(cooldownSoundInstance)){ + Audio::Engine().SetVolume(cooldownSoundInstance,Audio::GetCalculatedSFXVolume("Audio.Casting Sound Volume"_F/100.f)); + Audio::Engine().Play(cooldownSoundInstance,true); + } castInfo.castTimer-=fElapsedTime; if(castInfo.castTimer<=0){ bool allowed=castPrepAbility->actionPerformedDuringCast; @@ -365,13 +369,6 @@ void Player::Update(float fElapsedTime){ } castInfo.castTimer=0; } - } - - if(state==State::CASTING){ - if(!Audio::Engine().IsPlaying(cooldownSoundInstance)){ - Audio::Engine().SetVolume(cooldownSoundInstance,Audio::GetCalculatedSFXVolume("Audio.Casting Sound Volume"_F/100.f)); - Audio::Engine().Play(cooldownSoundInstance,true); - } }else{ Audio::Engine().Stop(cooldownSoundInstance); } @@ -480,7 +477,20 @@ void Player::Update(float fElapsedTime){ } animation.UpdateState(internal_animState,fElapsedTime); }break; + case State::ROLL:{ + rolling_timer-=fElapsedTime; + if(facingDirection==RIGHT)spin_angle+=util::degToRad("Thief.Right Click Ability.Roll Rotation Speed"_F)*fElapsedTime; + else spin_angle-=util::degToRad("Thief.Right Click Ability.Roll Rotation Speed"_F)*fElapsedTime; + ySquishFactor=0.5f*sin((PI*fElapsedTime)/"Thief.Right Click Ability.Bounce Period Time"_F)+0.5f; + if(rolling_timer<=0.f){ + spin_angle=0.f; + ySquishFactor=1.f; + SetState(State::NORMAL); + } + }break; default:{ + spin_angle=0.f; + ySquishFactor=1.f; //Update animations normally. animation.UpdateState(internal_animState,fElapsedTime); } @@ -1001,7 +1011,7 @@ bool Player::CanPathfindTo(vf2d pos,vf2d targetPos,float range){ void Player::PrepareCast(Ability&ability){ castPrepAbility=&ability; - if(ability.precastInfo.range>0){ + if(ability.precastInfo.castTime>0||ability.precastInfo.range>0){ SetState(State::PREP_CAST); }else{ CastSpell(ability); diff --git a/Adventures in Lestoria/Player.h b/Adventures in Lestoria/Player.h index 82358fa7..c67d1aad 100644 --- a/Adventures in Lestoria/Player.h +++ b/Adventures in Lestoria/Player.h @@ -295,6 +295,7 @@ private: float z=0; float size=1.0f; float spin_attack_timer=0; + float rolling_timer{}; float spin_spd=0; float spin_angle=0; float lastAnimationFlip=0; @@ -391,6 +392,7 @@ protected: const float RAPID_FIRE_SHOOT_DELAY="Ranger.Ability 1.ArrowDelay"_F; const int RAPID_FIRE_SHOOT_AMOUNT="Ranger.Ability 1.ArrowCount"_I; float footstepTimer=0.f; + float ySquishFactor{1.f}; size_t cooldownSoundInstance=std::numeric_limits::max(); }; diff --git a/Adventures in Lestoria/State.h b/Adventures in Lestoria/State.h index 04e3abb7..59ca8930 100644 --- a/Adventures in Lestoria/State.h +++ b/Adventures in Lestoria/State.h @@ -57,5 +57,6 @@ namespace State{ RECOVERY, FORCE_WALK, DEATH, + ROLL, }; } \ No newline at end of file diff --git a/Adventures in Lestoria/Thief.cpp b/Adventures in Lestoria/Thief.cpp index 5aee21f4..d933697c 100644 --- a/Adventures in Lestoria/Thief.cpp +++ b/Adventures in Lestoria/Thief.cpp @@ -42,6 +42,7 @@ All rights reserved. #include "AdventuresInLestoria.h" #include "config.h" #include "SoundEffect.h" +#include "util.h" INCLUDE_MONSTER_LIST INCLUDE_BULLET_LIST @@ -62,7 +63,7 @@ void Thief::Initialize(){ SETUP_CLASS(Thief) void Thief::OnUpdate(float fElapsedTime){ - + } bool Thief::AutoAttack(){ @@ -100,10 +101,17 @@ bool Thief::AutoAttack(){ return true; } void Thief::InitializeClassAbilities(){ - #pragma region Thief Right-click Ability (???) + #pragma region Thief Right-click Ability (Roll) Thief::rightClickAbility.action= [](Player*p,vf2d pos={}){ - return false; + p->SetState(State::ROLL); + p->rolling_timer="Thief.Right Click Ability.Roll Time"_F; + p->AddBuff(BuffType::SPEEDBOOST,"Thief.Right Click Ability.Movespeed Buff"_f[1],"Thief.Right Click Ability.Movespeed Buff"_f[0]/100.f); + geom2d::line mouseDir{p->GetPos(),p->GetWorldAimingLocation(Player::USE_WALK_DIR)}; + float velocity=(0.5f*-p->friction*"Thief.Right Click Ability.Roll Time"_F*"Thief.Right Click Ability.Roll Time"_F-std::clamp(mouseDir.length(),24.f,24.f*"Thief.Right Click Ability.Max Roll Range"_F/100))/-"Thief.Right Click Ability.Roll Time"_F; //Derived from kinetic motion formula. + p->SetVelocity(mouseDir.vector().norm()*velocity); + p->ApplyIframes("Thief.Right Click Ability.Iframe Time"_F); + return true; }; #pragma endregion #pragma region Thief Ability 1 (Hidden Dagger) diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h index 8c4d9254..72705c2a 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 10068 +#define VERSION_BUILD 10093 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/Adventures in Lestoria/assets/config/classes/Thief.txt b/Adventures in Lestoria/assets/config/classes/Thief.txt index 16b48cdc..27a57275 100644 --- a/Adventures in Lestoria/assets/config/classes/Thief.txt +++ b/Adventures in Lestoria/assets/config/classes/Thief.txt @@ -39,6 +39,14 @@ Thief # % speed increase, duration Movespeed Buff = 30%, 2s + Roll Time = 0.3s + Iframe Time = 0.5s + # How fast one period of the roll bounce cycle is. + Bounce Period Time = 0.045s + # How much to squish the sprite + Bounce Max Squish Amount = 60% + Roll Rotation Speed = 1280deg/s + Max Roll Range = 250 #RGB Values. Color 1 is the circle at full cooldown, Color 2 is the color at empty cooldown. Cooldown Bar Color 1 = 0, 0, 64, 192 @@ -46,7 +54,7 @@ Thief Precast Time = 0 Casting Range = 0 - Casting Size = 0 + Casting Size = 100 } Ability 1 { diff --git a/Adventures in Lestoria/olcPGEX_TransformedView.h b/Adventures in Lestoria/olcPGEX_TransformedView.h index 10201b3c..a009cd6b 100644 --- a/Adventures in Lestoria/olcPGEX_TransformedView.h +++ b/Adventures in Lestoria/olcPGEX_TransformedView.h @@ -177,6 +177,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::vf2d& squishScale = { 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 olc::Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f },const float width=std::numeric_limits::max()); void DrawStringPropDecal(const olc::vf2d& pos, std::string_view sText, const olc::Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f },const float width=std::numeric_limits::max()); @@ -624,6 +625,10 @@ namespace olc pge->DrawPartialRotatedDecal(WorldToScreen(pos), decal, fAngle, center, source_pos, source_size, scale * m_vWorldScale * m_vRecipPixel, tint); } + void TransformedView::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::vf2d& squishScale, const olc::Pixel& tint){ + pge->DrawPartialSquishedRotatedDecal(WorldToScreen(pos),decal,fAngle,center,source_pos,source_size,scale,squishScale,tint); + } + void TransformedView::DrawStringDecal(const olc::vf2d & pos, std::string_view sText, const olc::Pixel col, const olc::vf2d & scale,const float width) { pge->DrawStringDecal(WorldToScreen(pos), sText, col, scale * m_vWorldScale * m_vRecipPixel,width); diff --git a/Adventures in Lestoria/olcPixelGameEngine.h b/Adventures in Lestoria/olcPixelGameEngine.h index 5d1f127b..b8faf47f 100644 --- a/Adventures in Lestoria/olcPixelGameEngine.h +++ b/Adventures in Lestoria/olcPixelGameEngine.h @@ -1144,7 +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); + 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::vf2d& squishScale = { 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 }); @@ -3322,7 +3322,7 @@ 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) + 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::vf2d& squishScale, const olc::Pixel& tint) { DecalInstance di; di.decal = decal; @@ -3330,10 +3330,10 @@ namespace olc 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); + di.pos[0] = (olc::vf2d(0.0f, 0.0f) - center)*scale; + di.pos[1] = (olc::vf2d(0.0f, source_size.y) - center)*scale; + di.pos[2] = (olc::vf2d(source_size.x, source_size.y) - center)*scale; + di.pos[3] = (olc::vf2d(source_size.x, 0.0f) - center)*scale; float c = cos(fAngle), s = sin(fAngle); for (int i = 0; i < 4; i++) { @@ -3341,10 +3341,10 @@ namespace olc 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; + di.pos[0] *= squishScale; + di.pos[1] *= squishScale; + di.pos[2] *= squishScale; + di.pos[3] *= squishScale; olc::vf2d uvtl = source_pos * decal->vUVScale; olc::vf2d uvbr = uvtl + (source_size * decal->vUVScale); diff --git a/emscripten_build.ps1 b/emscripten_build.ps1 index c2c18e80..2868617f 100755 --- a/emscripten_build.ps1 +++ b/emscripten_build.ps1 @@ -1,6 +1,22 @@ git update-index --assume-unchanged "Adventures in Lestoria/packkey.cpp" clear +rm -R bin mkdir bin +mkdir bin/assets +cp -R 'Adventures in Lestoria/buildtemplate.html' bin/index.html +cp -R "Adventures in Lestoria/assets/Campaigns" bin/assets +cp -R "Adventures in Lestoria/assets/config" bin/assets +cp -R "Adventures in Lestoria/assets/maps" bin/assets +cp -R "Adventures in Lestoria/assets/backgrounds" bin/assets +rm -R bin/assets/backgrounds/commercial_assets +rm -R bin/assets/maps/commercial_assets +cp -R "Adventures in Lestoria/assets/monsters" bin/assets +cp -R "Adventures in Lestoria/assets/music" bin/assets +cp -R "Adventures in Lestoria/assets/npcs" bin/assets +cp -R "Adventures in Lestoria/assets/sounds" bin/assets +cp -R "Adventures in Lestoria/assets/gamepack.pak" bin/assets +cp -R "Adventures in Lestoria/assets/themes" bin/assets +cp -R "Adventures in Lestoria/assets/*.ttf" bin/assets $ErrorActionPreference = "Stop" emcmake cmake -DCMAKE_BUILD_TYPE=Release . diff --git a/x64/Release/Adventures in Lestoria.exe b/x64/Release/Adventures in Lestoria.exe index 2f34b8cc..017c7f6e 100644 Binary files a/x64/Release/Adventures in Lestoria.exe and b/x64/Release/Adventures in Lestoria.exe differ