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