diff --git a/Adventures in Lestoria/Adventures in Lestoria.vcxproj b/Adventures in Lestoria/Adventures in Lestoria.vcxproj index ed89c350..d367d789 100644 --- a/Adventures in Lestoria/Adventures in Lestoria.vcxproj +++ b/Adventures in Lestoria/Adventures in Lestoria.vcxproj @@ -658,6 +658,10 @@ + + + + diff --git a/Adventures in Lestoria/Animation.cpp b/Adventures in Lestoria/Animation.cpp index 34164081..1c036e3f 100644 --- a/Adventures in Lestoria/Animation.cpp +++ b/Adventures in Lestoria/Animation.cpp @@ -234,6 +234,7 @@ void sig::Animation::InitializeAnimations(){ CreateStillAnimation("chain_lightning.png",{1,9}); CreateHorizontalAnimationSequence("lightning_splash_effect.png",5,{24,24}); + CreateHorizontalAnimationSequence("dagger_stab.png",2,{24,24},AnimationData{0.1f,Animate2D::Style::PingPong}); CreateStillAnimation("meteor.png",{192,192}); diff --git a/Adventures in Lestoria/BulletTypes.h b/Adventures in Lestoria/BulletTypes.h index f748d374..bd7d292e 100644 --- a/Adventures in Lestoria/BulletTypes.h +++ b/Adventures in Lestoria/BulletTypes.h @@ -37,6 +37,7 @@ All rights reserved. #pragma endregion #pragma once #include "Bullet.h" +#include "Direction.h" struct EnergyBolt:public Bullet{ float lastParticleSpawn=0; @@ -98,4 +99,31 @@ struct Wisp:public Bullet{ void Update(float fElapsedTime)override; bool PlayerHit(Player*player)override; bool MonsterHit(Monster&monster)override; +}; + +struct DaggerStab:public Bullet{ + struct DirectionOffsets{ + std::unordered_mapoffsets; + DirectionOffsets(const vf2d upOffset,const vf2d downOffset,const vf2d leftOffset){ + offsets[Direction::NORTH]=upOffset; + offsets[Direction::SOUTH]=downOffset; + offsets[Direction::EAST]=offsets[Direction::WEST]=leftOffset; //Both east and west use one offset because the sprite flipping system will handle flipping the position of the dagger for the other side. + } + }; + + enum class HorizontalFlip{ + NONE, + FLIPPED, + }; + + Monster&sourceMonster; + Direction facingDir; + float frameDuration; + float daggerStabDistance; + DirectionOffsets daggerPositionOffsets; + HorizontalFlip horizontalFlip; + DaggerStab(Monster&sourceMonster,float radius,int damage,bool upperLevel,const Direction facingDir,const float daggerFrameDuration,const float daggerStabDistance,const HorizontalFlip horizontalFlip,const DirectionOffsets offsets,bool friendly=false,Pixel col=WHITE); + void Update(float fElapsedTime)override; + bool PlayerHit(Player*player)override; + bool MonsterHit(Monster&monster)override; }; \ No newline at end of file diff --git a/Adventures in Lestoria/DaggerStab.cpp b/Adventures in Lestoria/DaggerStab.cpp new file mode 100644 index 00000000..f20b47e5 --- /dev/null +++ b/Adventures in Lestoria/DaggerStab.cpp @@ -0,0 +1,104 @@ +#pragma region License +/* +License (OLC-3) +~~~~~~~~~~~~~~~ + +Copyright 2024 Joshua Sigona + +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 "BulletTypes.h" +#include "SoundEffect.h" +#include "AdventuresInLestoria.h" +#include "DEFINES.h" + +INCLUDE_game +INCLUDE_ANIMATION_DATA + +DaggerStab::DaggerStab(Monster&sourceMonster,float radius,int damage,bool upperLevel,const Direction facingDir,const float daggerFrameDuration,const float daggerStabDistance,const HorizontalFlip horizontalFlip,const DirectionOffsets offsets,bool friendly,Pixel col) + :Bullet(sourceMonster.GetPos(),{},radius,damage,"dagger_stab.png",upperLevel,false,daggerFrameDuration*ANIMATION_DATA["dagger_stab.png"].GetFrameCountBasedOnAnimationStyle(),true,friendly,col), + sourceMonster(sourceMonster),frameDuration(daggerFrameDuration),daggerStabDistance(daggerStabDistance),facingDir(facingDir),daggerPositionOffsets(offsets),horizontalFlip(horizontalFlip){} +void DaggerStab::Update(float fElapsedTime){ + ANIMATION_DATA["dagger_stab.png"].ChangeFrameDuration(frameDuration); + #pragma region Dagger Position Offset + vf2d daggerOffset=daggerPositionOffsets.offsets[facingDir]; + if(horizontalFlip==HorizontalFlip::FLIPPED)daggerOffset.x*=-1; + pos=sourceMonster.GetPos()+daggerOffset; + #pragma endregion + #pragma region Dagger stabbing + if(lifetime<=ANIMATION_DATA["dagger_stab.png"].GetTotalAnimationDuration()*0.6667f&& + lifetime>=ANIMATION_DATA["dagger_stab.png"].GetTotalAnimationDuration()*0.3333f){ + switch(facingDir){ + case Direction::NORTH:{ + pos+=vf2d{0,-daggerStabDistance}; + }break; + case Direction::EAST:{ + pos+=vf2d{daggerStabDistance,0}; + }break; + case Direction::SOUTH:{ + pos+=vf2d{0,daggerStabDistance}; + }break; + case Direction::WEST:{ + pos+=vf2d{-daggerStabDistance,0}; + }break; + default:ERR(std::format("WARNING! Unknown direction value {} was supplied! THIS SHOULD NOT BE HAPPENING!",int(facingDir))); + } + } + #pragma endregion + #pragma region Dagger rotation handling + switch(facingDir){ + case Direction::NORTH:{ + vel={0,-0.001f}; + }break; + case Direction::EAST:{ + vel={0.001f,0}; + }break; + case Direction::SOUTH:{ + vel={0,0.001f}; + }break; + case Direction::WEST:{ + vel={-0.001f,0}; + }break; + default:ERR(std::format("WARNING! Unknown direction value {} was supplied! THIS SHOULD NOT BE HAPPENING!",int(facingDir))); + } + #pragma endregion +} +bool DaggerStab::PlayerHit(Player*player){ + deactivated=true; + game->AddEffect(std::make_unique(pos,0,"lightning_splash_effect.png",upperLevel,player->GetSizeMult()*0.25f,0.25,vf2d{})); + return false; +} +bool DaggerStab::MonsterHit(Monster&monster){ + deactivated=true; + game->AddEffect(std::make_unique(pos,0,"lightning_splash_effect.png",upperLevel,monster.GetSizeMult()*0.25f,0.25,vf2d{})); + return false; +} \ No newline at end of file diff --git a/Adventures in Lestoria/Goblin_Dagger.cpp b/Adventures in Lestoria/Goblin_Dagger.cpp index 84eeb055..fa318aad 100644 --- a/Adventures in Lestoria/Goblin_Dagger.cpp +++ b/Adventures in Lestoria/Goblin_Dagger.cpp @@ -39,6 +39,7 @@ All rights reserved. #include "DEFINES.h" #include "Monster.h" #include "MonsterStrategyHelpers.h" +#include "BulletTypes.h" /* Attack Strategie: Runs infront of player, @@ -49,6 +50,7 @@ and either slashes with the dagger or stabs with it. INCLUDE_game INCLUDE_ANIMATION_DATA +INCLUDE_BULLET_LIST using A=Attribute; void Monster::STRATEGY::GOBLIN_DAGGER(Monster&m,float fElapsedTime,std::string strategy){ @@ -74,6 +76,7 @@ void Monster::STRATEGY::GOBLIN_DAGGER(Monster&m,float fElapsedTime,std::string s auto SetFacingAnimation=[&](ANIMATION_OFFSET animation,vf2d target){ m.PerformOtherAnimation(int(animation)+int(m.GetFacingDirectionToTarget(target))); }; + auto IsSpriteFlipped=[&](){return m.GetFacingDirection()==RIGHT;}; using enum ANIMATION_OFFSET; switch(m.phase){ @@ -102,7 +105,10 @@ void Monster::STRATEGY::GOBLIN_DAGGER(Monster&m,float fElapsedTime,std::string s m.phase=RECOVERY; switch(m.I(A::ATTACK_TYPE)){ case STAB:{ - SetFacingAnimation(STAB_ANIMATION,game->GetPlayer()->GetPos()); + vf2d stabTarget=game->GetPlayer()->GetPos(); + SetFacingAnimation(STAB_ANIMATION,stabTarget); + CreateBullet(DaggerStab)(m,ConfigFloat("Dagger Hit Radius"),m.GetAttack(),m.OnUpperLevel(),m.GetFacingDirectionToTarget(stabTarget),ConfigFloat("Dagger Frame Duration"),ConfigFloat("Dagger Stab Distance"),IsSpriteFlipped()?DaggerStab::HorizontalFlip::FLIPPED:DaggerStab::HorizontalFlip::NONE, + DaggerStab::DirectionOffsets{ConfigVec("Dagger Up Offset"),ConfigVec("Dagger Down Offset"),ConfigVec("Dagger Left Offset")})EndBullet; }break; case SLASH:{ SetFacingAnimation(SLASH_ANIMATION,game->GetPlayer()->GetPos()); diff --git a/Adventures in Lestoria/Monster.h b/Adventures in Lestoria/Monster.h index 84c89ff9..d47af050 100644 --- a/Adventures in Lestoria/Monster.h +++ b/Adventures in Lestoria/Monster.h @@ -219,6 +219,7 @@ private: static int _GetInt(Monster&m,std::string param,std::string strategy,int index=0); static float _GetFloat(Monster&m,std::string param,std::string strategy,int index=0); static Pixel _GetPixel(Monster&m,std::string param,std::string strategy,int index=0); + static vf2d _GetVec(Monster&m,std::string param,std::string strategy,int index=0); static const std::string&_GetString(Monster&m,std::string param,std::string strategy,int index=0); static datafile _Get(Monster&m,std::string param,std::string strategy); static void RUN_STRATEGY(Monster&m,float fElapsedTime); diff --git a/Adventures in Lestoria/MonsterStrategyHelpers.h b/Adventures in Lestoria/MonsterStrategyHelpers.h index 48bf0c81..47288b61 100644 --- a/Adventures in Lestoria/MonsterStrategyHelpers.h +++ b/Adventures in Lestoria/MonsterStrategyHelpers.h @@ -40,7 +40,9 @@ All rights reserved. #define ConfigFloat(param) _GetFloat(m,param,strategy) #define ConfigPixel(param) _GetPixel(m,param,strategy) #define ConfigString(param) _GetString(m,param,strategy) +#define ConfigVec(param) _GetVec(m,param,strategy) #define Config(param) _Get(m,param,strategy) #define ConfigIntArr(param,ind) _GetInt(m,param,strategy,ind) #define ConfigFloatArr(param,ind) _GetFloat(m,param,strategy,ind) -#define ConfigStringArr(param,ind) _GetString(m,param,strategy,ind) \ No newline at end of file +#define ConfigStringArr(param,ind) _GetString(m,param,strategy,ind) +#define ConfigVecArr(param,ind) _GetVec(m,param,strategy,ind) \ No newline at end of file diff --git a/Adventures in Lestoria/RUN_STRATEGY.cpp b/Adventures in Lestoria/RUN_STRATEGY.cpp index f361fd89..88c21311 100644 --- a/Adventures in Lestoria/RUN_STRATEGY.cpp +++ b/Adventures in Lestoria/RUN_STRATEGY.cpp @@ -89,6 +89,16 @@ const std::string&Monster::STRATEGY::_GetString(Monster&m,std::string param,std: return DATA["MonsterStrategy"][strategy].GetProperty(param).GetString(index); } } +vf2d Monster::STRATEGY::_GetVec(Monster&m,std::string param,std::string strategy,int index){ + if(m.IsNPC()&&DATA["NPCs"][m.name].HasProperty(param)){ + return {DATA["NPCs"][m.name].GetProperty(param).GetReal(index),DATA["NPCs"][m.name].GetProperty(param).GetReal(index+1)}; + }else + if(!m.IsNPC()&&DATA["Monsters"][m.name].HasProperty(param)){ + return {DATA["Monsters"][m.name].GetProperty(param).GetReal(index),DATA["Monsters"][m.name].GetProperty(param).GetReal(index+1)}; + } else { + return {DATA["MonsterStrategy"][strategy].GetProperty(param).GetReal(index),DATA["MonsterStrategy"][strategy].GetProperty(param).GetReal(index+1)}; + } +} datafile Monster::STRATEGY::_Get(Monster&m,std::string param,std::string strategy){ if(m.IsNPC()&&DATA["NPCs"][m.name].HasProperty(param)){ return DATA["NPCs"][m.name].GetProperty(param); diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h index 013bcfe2..fd88effa 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 0 -#define VERSION_BUILD 9027 +#define VERSION_BUILD 9033 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/Adventures in Lestoria/assets/config/MonsterStrategies.txt b/Adventures in Lestoria/assets/config/MonsterStrategies.txt index 86d96aa0..61c0e7fb 100644 --- a/Adventures in Lestoria/assets/config/MonsterStrategies.txt +++ b/Adventures in Lestoria/assets/config/MonsterStrategies.txt @@ -562,5 +562,19 @@ MonsterStrategy # Amount of time where nothing happens after an attack. Attack Recovery Time = 1.0s + + # Number of pixels from the dagger's center that the player would be hit by. + Dagger Hit Radius = 12 + + # Number of pixels of reach the dagger stab has. + Dagger Stab Distance = 2 + + # How long between each dagger stab frame. + Dagger Frame Duration = 0.1s + + # Offset for the dagger stab effect per direction from the monster's center. + Dagger Up Offset = 6,-5 + Dagger Down Offset = -5,11 + Dagger Left Offset = -10,6 } } \ No newline at end of file diff --git a/Adventures in Lestoria/assets/config/gfx/gfx.txt b/Adventures in Lestoria/assets/config/gfx/gfx.txt index 9179f1b4..627c5aa9 100644 --- a/Adventures in Lestoria/assets/config/gfx/gfx.txt +++ b/Adventures in Lestoria/assets/config/gfx/gfx.txt @@ -86,6 +86,7 @@ Images GFX_CustomFont = font.png GFX_Vignette = vignette.png GFX_Checkmark = checkmark.png + GFX_DaggerStab = dagger_stab.png # Ability Icons GFX_Warrior_BattleCry_Icon = Ability Icons/battlecry.png diff --git a/Adventures in Lestoria/assets/dagger_stab.png b/Adventures in Lestoria/assets/dagger_stab.png new file mode 100644 index 00000000..368cbd46 Binary files /dev/null and b/Adventures in Lestoria/assets/dagger_stab.png differ diff --git a/Adventures in Lestoria/assets/gamepack.pak b/Adventures in Lestoria/assets/gamepack.pak index 7255574d..1a74141e 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/monsters/Goblin (Dagger).png b/Adventures in Lestoria/assets/monsters/Goblin (Dagger).png index 17645ac4..2a6146b8 100644 Binary files a/Adventures in Lestoria/assets/monsters/Goblin (Dagger).png and b/Adventures in Lestoria/assets/monsters/Goblin (Dagger).png differ diff --git a/Adventures in Lestoria/olcUTIL_Animate2D.h b/Adventures in Lestoria/olcUTIL_Animate2D.h index db05b86f..578078af 100644 --- a/Adventures in Lestoria/olcUTIL_Animate2D.h +++ b/Adventures in Lestoria/olcUTIL_Animate2D.h @@ -116,6 +116,11 @@ namespace olc::utils::Animate2D m_nStyle = nStyle; } + inline void ChangeFrameDuration(const float fFrameDuration){ + m_fFrameDuration = fFrameDuration; + m_fFrameRate = 1.0f / m_fFrameDuration; + } + // Adds a frame to this sequence inline void AddFrame(const Frame& frame) { @@ -150,6 +155,21 @@ namespace olc::utils::Animate2D } } + inline const size_t GetFrameCountBasedOnAnimationStyle()const{ + switch (m_nStyle) + { + case Style::Repeat: + case Style::OneShot: + return m_vFrames.size(); + case Style::PingPong: + case Style::Reverse: //These two require twice as much time (minus one frame) to complete a full animation cycle. + return m_vFrames.size()*2.f-1; + default: + ERR(std::format("WARNING! Animation style {} was not found! THIS SHOULD NOT BE HAPPENING!",int(m_nStyle))); + return 0; + } + } + private: inline const size_t ConvertTimeToFrame(const float fTime) const diff --git a/x64/Release/Adventures in Lestoria.exe b/x64/Release/Adventures in Lestoria.exe index 45118e21..d9ff4788 100644 Binary files a/x64/Release/Adventures in Lestoria.exe and b/x64/Release/Adventures in Lestoria.exe differ