diff --git a/Adventures in Lestoria/Adventures in Lestoria.vcxproj b/Adventures in Lestoria/Adventures in Lestoria.vcxproj
index cf94dce3..0b369131 100644
--- a/Adventures in Lestoria/Adventures in Lestoria.vcxproj
+++ b/Adventures in Lestoria/Adventures in Lestoria.vcxproj
@@ -993,6 +993,10 @@
+
+
+
+
diff --git a/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters b/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters
index c9366ff7..41dddc8f 100644
--- a/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters
+++ b/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters
@@ -1121,6 +1121,9 @@
Source Files\Effects
+
+ Source Files\Bullet Types
+
diff --git a/Adventures in Lestoria/BulletTypes.h b/Adventures in Lestoria/BulletTypes.h
index e4f7313c..695be991 100644
--- a/Adventures in Lestoria/BulletTypes.h
+++ b/Adventures in Lestoria/BulletTypes.h
@@ -38,6 +38,7 @@ All rights reserved.
#pragma once
#include "Bullet.h"
#include "Direction.h"
+#include "Effect.h"
struct EnergyBolt:public Bullet{
float lastParticleSpawn=0;
@@ -245,4 +246,19 @@ private:
float moveTimer; //Counts down to 0, when it hits zero sets the velocity to futurevel.
const float initialMoveWaitTime;
const float knockbackAmt;
+};
+
+struct FallingStone:public Bullet{
+ //The position for this bullet represents where the falling stone should land.
+ FallingStone(vf2d targetPos,vf2d vel,float zVel,float indicatorDisplayTime,float radius,int damage,bool upperLevel,bool hitsMultiple=false,float knockbackAmt=0.f,float lifetime=INFINITE,bool friendly=false,Pixel col=WHITE,vf2d scale={1,1},float image_angle=0.f,float spellCircleRotation=0.f,float spellCircleRotationSpd=0.f,Pixel insigniaCol=WHITE,float insigniaRotation=0.f,float insigniaRotationSpd=0.f);
+protected:
+ void Update(float fElapsedTime)override;
+ void Draw(const Pixel blendCol)const override;
+private:
+ const vf2d targetPos;
+ const float zVel{};
+ const float indicatorDisplayTime;
+ SpellCircle indicator;
+ const float knockbackAmt;
+ float lastTrailEffect{};
};
\ No newline at end of file
diff --git a/Adventures in Lestoria/Chapter_2_Boss.txt b/Adventures in Lestoria/Chapter_2_Boss.txt
index d4b4cf67..4ff8c1e7 100644
--- a/Adventures in Lestoria/Chapter_2_Boss.txt
+++ b/Adventures in Lestoria/Chapter_2_Boss.txt
@@ -40,7 +40,7 @@ Size: 800%
>Like previously every pillar appears with 2,5 seconds delay from each other. (2 sec with an indicator, 0,5 seconds delay after a pillar got created)
-The Boss continues with its normal behaviour while the pillars are getting casted.
+>The Boss continues with its normal behaviour while the pillars are getting casted.
diff --git a/Adventures in Lestoria/Effect.h b/Adventures in Lestoria/Effect.h
index 8220d5ed..b4173d8c 100644
--- a/Adventures in Lestoria/Effect.h
+++ b/Adventures in Lestoria/Effect.h
@@ -50,6 +50,7 @@ enum class EffectType{
struct Effect{
friend class AiL;
+ friend class FallingStone;
vf2d pos={0,0};
float lifetime=0;
float fadeout=0;
@@ -110,8 +111,8 @@ struct ForegroundEffect:Effect{
};
struct SpellCircle:Effect{
- SpellCircle(vf2d pos,float lifetime,std::string imgFile,std::string spellInsigniaFile,bool upperLevel,float size=1.0f,float fadeout=0.0f,vf2d spd={},Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false,float insigniaSize=1.0f,float insigniaFadeout=0.0f,vf2d insigniaSpd={},Pixel insigniaCol=WHITE,float insigniaSotation=0,float insigniaRotationSpd=0,bool insigniaAdditiveBlending=false);
- SpellCircle(vf2d pos,float lifetime,std::string imgFile,std::string spellInsigniaFile,bool upperLevel,vf2d size={1,1},float fadeout=0.0f,vf2d spd={},Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false,vf2d insigniaSize={1,1},float insigniaFadeout=0.0f,vf2d insigniaSpd={},Pixel insigniaCol=WHITE,float insigniaSotation=0,float insigniaRotationSpd=0,bool insigniaAdditiveBlending=false);
+ SpellCircle(vf2d pos,float lifetime,std::string imgFile,std::string spellInsigniaFile,bool upperLevel,float size=1.0f,float fadeout=0.0f,vf2d spd={},Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false,float insigniaSize=1.0f,float insigniaFadeout=0.0f,vf2d insigniaSpd={},Pixel insigniaCol=WHITE,float insigniaRotation=0,float insigniaRotationSpd=0,bool insigniaAdditiveBlending=false);
+ SpellCircle(vf2d pos,float lifetime,std::string imgFile,std::string spellInsigniaFile,bool upperLevel,vf2d size={1,1},float fadeout=0.0f,vf2d spd={},Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false,vf2d insigniaSize={1,1},float insigniaFadeout=0.0f,vf2d insigniaSpd={},Pixel insigniaCol=WHITE,float insigniaRotation=0,float insigniaRotationSpd=0,bool insigniaAdditiveBlending=false);
Effect spellInsignia{vf2d{},0.f,"spell_insignia.png",false,{}};
virtual bool Update(float fElapsedTime)override final;
virtual void Draw()const override final;
diff --git a/Adventures in Lestoria/FallingStone.cpp b/Adventures in Lestoria/FallingStone.cpp
new file mode 100644
index 00000000..f68eaaff
--- /dev/null
+++ b/Adventures in Lestoria/FallingStone.cpp
@@ -0,0 +1,90 @@
+#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 "DEFINES.h"
+#include "AdventuresInLestoria.h"
+#include "util.h"
+#include
+#include "SoundEffect.h"
+
+INCLUDE_game
+
+FallingStone::FallingStone(vf2d targetPos,vf2d vel,float zVel,float indicatorDisplayTime,float radius,int damage,bool upperLevel,bool hitsMultiple,float knockbackAmt,float lifetime,bool friendly,Pixel col,vf2d scale,float image_angle,float spellCircleRotation,float spellCircleRotationSpd,Pixel insigniaCol,float insigniaRotation,float insigniaRotationSpd)
+:Bullet(targetPos,vel,radius,damage,"rock.png",upperLevel,false,lifetime+0.1f,false,friendly,col,scale,image_angle),targetPos(targetPos),zVel(zVel),indicatorDisplayTime(indicatorDisplayTime),knockbackAmt(knockbackAmt),
+indicator(targetPos,lifetime+0.1f,"range_indicator.png","spell_insignia.png",upperLevel,radius/12.f,0.5f,{},col,spellCircleRotation,spellCircleRotationSpd,false,radius/12.f,0.f,{},insigniaCol,insigniaRotation,insigniaRotationSpd,false){
+ pos+=-vel*lifetime;
+ z=-zVel*lifetime;
+}
+
+void FallingStone::Update(float fElapsedTime){
+ z+=zVel*fElapsedTime;
+ lastTrailEffect-=fElapsedTime;
+ if(z<=0.f){
+ z=0.f;
+ vel={};
+ if(IsActivated()){
+ fadeOutTime=0.5f;
+ SoundEffect::PlaySFX("Stone Land",pos);
+ if(friendly){
+ for(auto&[monsterPtr,hurt]:game->Hurt(targetPos,radius,damage,OnUpperLevel(),z,HurtType::MONSTER)){
+ if(hurt)std::get(monsterPtr)->ApplyIframes(0.1f);
+ }
+ }
+ else{
+ for(auto&[playerPtr,hurt]:game->Hurt(targetPos,radius,damage,OnUpperLevel(),z,HurtType::PLAYER)){
+ if(hurt)std::get(playerPtr)->ApplyIframes(0.1f);
+ }
+ }
+ game->ProximityKnockback(targetPos,radius,knockbackAmt,HurtType::PLAYER|HurtType::MONSTER);
+ for(int i:std::ranges::iota_view(0,30))game->AddEffect(std::make_unique(pos-vf2d{0.f,GetZ()},util::random_range(0.05f,0.2f),"circle_outline.png",OnUpperLevel(),util::random_range(0.5f,1.f),0.2f,vf2d{util::random_range(-10.f,10.f),util::random_range(-3.f,0.f)},PixelLerp(BLACK,col,util::random(1.f)),0.f,0.f,true));
+ Deactivate();
+ }
+ }else{
+ if(lastTrailEffect<=0.f){
+ game->AddEffect(std::make_unique(pos-vf2d{0.f,GetZ()},util::random_range(0.05f,0.2f),"circle_outline.png",OnUpperLevel(),util::random_range(0.5f,1.f),0.2f,vf2d{util::random_range(-3.f,3.f),util::random_range(-3.f,3.f)},PixelLerp(BLACK,col,util::random(1.f)),0.f,0.f,true));
+ }
+ }
+ indicator.Update(fElapsedTime);
+}
+void FallingStone::Draw(const Pixel blendCol)const{
+ if(lifetime<=indicatorDisplayTime){
+ indicator.Draw();
+ }
+ Bullet::Draw(blendCol);
+}
\ No newline at end of file
diff --git a/Adventures in Lestoria/MonsterAttribute.h b/Adventures in Lestoria/MonsterAttribute.h
index a366b8e1..830353db 100644
--- a/Adventures in Lestoria/MonsterAttribute.h
+++ b/Adventures in Lestoria/MonsterAttribute.h
@@ -140,7 +140,6 @@ enum class Attribute{
SAFE_AREA_WAIT_TIMER,
PREVIOUS_MONSTER_COUNT,
CHASE_TIMER,
- STONE_RAIN_COUNT,
STONE_TOSS_COUNT,
STONE_TOSS_TIMER,
};
\ No newline at end of file
diff --git a/Adventures in Lestoria/StoneGolem.cpp b/Adventures in Lestoria/StoneGolem.cpp
index 82565f2c..06d7a9bd 100644
--- a/Adventures in Lestoria/StoneGolem.cpp
+++ b/Adventures in Lestoria/StoneGolem.cpp
@@ -45,6 +45,7 @@ All rights reserved.
#include "SoundEffect.h"
#include "StageMaskPolygon.h"
#include "ExpandingRing.h"
+#include
INCLUDE_game
INCLUDE_MONSTER_LIST
@@ -323,11 +324,21 @@ void Monster::STRATEGY::STONE_GOLEM(Monster&m,float fElapsedTime,std::string str
game->AddEffect(std::make_unique(m.GetPos()+vf2d{util::random_range(throwPos.GetReal(0),throwPos.GetReal(2)),util::random_range(throwPos.GetReal(1),throwPos.GetReal(3))},10.f,"rock.png",ConfigFloat("Stone Rain.Stone Toss Delay"),ConfigFloat("Stone Rain.Stone Toss Rock Size Mult"),0.1f,vf2d{0.f,-ConfigFloat("Stone Rain.Stone Toss Throw Speed")},WHITE,util::random(2*PI),0.f));
if(m.I(A::STONE_TOSS_COUNT)<=0){
- m.I(A::STONE_RAIN_COUNT)=ConfigInt("Stone Rain.Stone Count");
m.phase=STONE_RAIN;
+ m.F(A::BREAK_TIME)=ConfigFloat("Stone Rain.Stone Golem Wait Time");
m.PerformAnimation("CAST");
+
+ for(int i:std::ranges::iota_view(0,ConfigInt("Stone Rain.Stone Count"))){
+ CreateBullet(FallingStone)(game->camera.GetViewPosition()+vf2d{util::random(game->ScreenWidth()),util::random(game->ScreenHeight())},ConfigVec("Stone Rain.Stone Vel"),ConfigFloatArr("Stone Rain.Stone Vel",2),ConfigFloat("Stone Rain.Indicator Time"),ConfigPixels("Stone Rain.Stone Radius"),ConfigInt("Stone Rain.Stone Damage"),m.OnUpperLevel(),false,ConfigFloat("Stone Rain.Stone Knockback Amt"),util::random_range(ConfigFloatArr("Stone Rain.Stone Fall Delay",0),ConfigFloatArr("Stone Rain.Stone Fall Delay",1)),false,ConfigPixel("Stone Rain.Stone Spell Circle Color"),vf2d{ConfigFloat("Stone Rain.Stone Radius")/100.f*2.f,ConfigFloat("Stone Rain.Stone Radius")/100.f*2.f},util::random(2*PI),util::random(2*PI),util::degToRad(ConfigFloat("Stone Rain.Stone Spell Circle Rotation Spd")),ConfigPixel("Stone Rain.Stone Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Stone Rain.Stone Spell Insignia Rotation Spd")))EndBullet;
+ }
}
}
}break;
+ case STONE_RAIN:{
+ m.F(A::BREAK_TIME)-=fElapsedTime;
+ if(m.F(A::BREAK_TIME)<=0.f){
+ m.phase=STANDARD;
+ }
+ }break;
}
}
\ No newline at end of file
diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h
index 04c774a6..849704a0 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 9994
+#define VERSION_BUILD 10015
#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 64af6fa8..2f7da5d4 100644
--- a/Adventures in Lestoria/assets/config/MonsterStrategies.txt
+++ b/Adventures in Lestoria/assets/config/MonsterStrategies.txt
@@ -970,6 +970,9 @@ MonsterStrategy
}
Stone Rain
{
+ # How long to wait upon launching the stone rain attack before resuming normal AI.
+ Stone Golem Wait Time = 4.0s
+
# How many stones the boss throws in the air.
Initial Stone Toss Count = 2
# Provide a Min X, Min Y, Max X, Max Y relative to the boss' position for where the stones appear prior to being tossed.
@@ -986,8 +989,18 @@ MonsterStrategy
Stone Fall Delay = 2.5s, 4.0s
# How long the indicator will appear before the rock drops down.
Indicator Time = 1s
+ # Provide an X,Y,Z falling velocity
+ Stone Vel = -40.0, 0.0, -250.0
Stone Damage = 30
Stone Radius = 50
+ Stone Knockback Amt = 150
+
+ Stone Spell Circle Color = 255, 40, 40, 160
+ Stone Spell Insignia Color = 72, 66, 80, 255
+ # Degrees/sec. Positive is CW, Negative is CCW.
+ Stone Spell Circle Rotation Spd = -30
+ # Degrees/sec. Positive is CW, Negative is CCW.
+ Stone Spell Insignia Rotation Spd = 50
}
}
Breaking Pillar
diff --git a/Adventures in Lestoria/assets/config/audio/events.txt b/Adventures in Lestoria/assets/config/audio/events.txt
index d2bad7dd..7899e219 100644
--- a/Adventures in Lestoria/assets/config/audio/events.txt
+++ b/Adventures in Lestoria/assets/config/audio/events.txt
@@ -270,6 +270,12 @@ Events
File[1] = slime_walk2.ogg, 10%
File[2] = slime_walk3.ogg, 10%
}
+ Stone Land
+ {
+ CombatSound = True
+ # Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
+ File[0] = rockland.ogg, 40%
+ }
Toggle On
{
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
diff --git a/Adventures in Lestoria/assets/sounds/rockland.ogg b/Adventures in Lestoria/assets/sounds/rockland.ogg
new file mode 100644
index 00000000..d3ed5237
Binary files /dev/null and b/Adventures in Lestoria/assets/sounds/rockland.ogg differ
diff --git a/Adventures in Lestoria/olcUTIL_Animate2D.h b/Adventures in Lestoria/olcUTIL_Animate2D.h
index 14498445..de8bbb49 100644
--- a/Adventures in Lestoria/olcUTIL_Animate2D.h
+++ b/Adventures in Lestoria/olcUTIL_Animate2D.h
@@ -147,14 +147,17 @@ namespace olc::utils::Animate2D
{
case Style::Repeat:
case Style::OneShot:
- case Style::ReverseOneShot:
+ case Style::ReverseOneShot:{
return m_vFrames.size()*m_fFrameDuration;
+ }break;
case Style::PingPong:
- case Style::Reverse: //These two require twice as much time (minus one frame) to complete a full animation cycle.
+ case Style::Reverse:{ //These two require twice as much time (minus one frame) to complete a full animation cycle.
return m_vFrames.size()*m_fFrameDuration*2.f-m_fFrameDuration;
- default:
+ }break;
+ default:{
ERR(std::format("WARNING! Animation style {} was not found! THIS SHOULD NOT BE HAPPENING!",int(m_nStyle)));
return 0.f;
+ }
}
}
@@ -163,14 +166,17 @@ namespace olc::utils::Animate2D
{
case Style::Repeat:
case Style::OneShot:
- case Style::ReverseOneShot:
+ case Style::ReverseOneShot:{
return m_vFrames.size();
+ }break;
case Style::PingPong:
- case Style::Reverse: //These two require twice as much time (minus one frame) to complete a full animation cycle.
+ 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:
+ }break;
+ default:{
ERR(std::format("WARNING! Animation style {} was not found! THIS SHOULD NOT BE HAPPENING!",int(m_nStyle)));
return 0;
+ }
}
}
@@ -180,18 +186,22 @@ namespace olc::utils::Animate2D
{
switch (m_nStyle)
{
- case Style::Repeat:
+ case Style::Repeat:{
return size_t(fTime * m_fFrameRate) % m_vFrames.size();
- case Style::OneShot:
+ }break;
+ case Style::OneShot:{
return std::clamp(size_t(fTime * m_fFrameRate), size_t(0), m_vFrames.size() - 1);
+ }break;
case Style::PingPong:{
size_t frame=size_t(m_fFrameRate*fTime) % (m_vFrames.size()*size_t(2)-size_t(1));
return frame>=m_vFrames.size()?m_vFrames.size()-frame%m_vFrames.size()-1:frame;
}break;
- case Style::ReverseOneShot:
+ case Style::ReverseOneShot:{
return std::clamp((m_vFrames.size() - 1) - size_t(fTime * m_fFrameRate), size_t(0), m_vFrames.size() - 1);
- case Style::Reverse:
+ }break;
+ case Style::Reverse:{
return (m_vFrames.size() - 1) - (size_t(fTime * m_fFrameRate) % m_vFrames.size());
+ }break;
}
return 0;
diff --git a/x64/Release/Adventures in Lestoria.exe b/x64/Release/Adventures in Lestoria.exe
index b428b232..73561f59 100644
Binary files a/x64/Release/Adventures in Lestoria.exe and b/x64/Release/Adventures in Lestoria.exe differ