diff --git a/Adventures in Lestoria/Adventures in Lestoria.vcxproj b/Adventures in Lestoria/Adventures in Lestoria.vcxproj index c13cd6c0..4ca6cc91 100644 --- a/Adventures in Lestoria/Adventures in Lestoria.vcxproj +++ b/Adventures in Lestoria/Adventures in Lestoria.vcxproj @@ -798,6 +798,7 @@ + diff --git a/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters b/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters index 6970af1d..f92c4214 100644 --- a/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters +++ b/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters @@ -1037,9 +1037,6 @@ Source Files - - Source Files - Source Files @@ -1103,6 +1100,18 @@ Source Files\Engine + + Source Files + + + Source Files + + + Source Files\Bullet Types + + + Source Files\Bullet Types + diff --git a/Adventures in Lestoria/Bullet.cpp b/Adventures in Lestoria/Bullet.cpp index 3fff5c7b..4e052ecf 100644 --- a/Adventures in Lestoria/Bullet.cpp +++ b/Adventures in Lestoria/Bullet.cpp @@ -61,6 +61,7 @@ Animate2D::Frame Bullet::GetFrame()const{ } void Bullet::UpdateFadeTime(float fElapsedTime) { + aliveTime+=fElapsedTime; if(fadeInTime>0){ if(fadeInTimer0.f; + return deactivated||fadeOutTime>0.f; +} + +void Bullet::Deactivate(){ + deactivated=true; +} + +const double Bullet::GetTimeAlive()const{ + return aliveTime; } \ No newline at end of file diff --git a/Adventures in Lestoria/Bullet.h b/Adventures in Lestoria/Bullet.h index 24e7469f..ba575564 100644 --- a/Adventures in Lestoria/Bullet.h +++ b/Adventures in Lestoria/Bullet.h @@ -72,24 +72,28 @@ struct Bullet{ protected: float distanceTraveled=0.f; vf2d scale={1,1}; - float fadeOutTimer=0; float fadeInTime=0; //Setting the fade in time causes the bullet to be disabled and the bullet's alpha will fade in from zero to the actual alpha of the bullet. When the fade in timer reaches the fade in time automatically, the bullet will be enabled. - float fadeInTimer=0; - void UpdateFadeTime(float fElapsedTime); virtual void Update(float fElapsedTime); + void Deactivate(); private: + float fadeOutTimer=0; + float fadeInTimer=0; + void UpdateFadeTime(float fElapsedTime); bool dead=false; //When marked as dead it wil be removed by the next frame. bool simulated=false; //A simulated bullet cannot interact / damage things in the world. It's simply used for simulating the trajectory and potential path of the bullet float iframeTimerOnHit{0.f}; bool playerAutoAttackProjectile=false; //Set to true for bullets that are auto attack projectiles to identify them. void _Draw()const; BulletType type{BulletType::UNDEFINED}; + bool deactivated{false}; + double aliveTime{}; protected: float drawOffsetY{}; BulletDestroyState _PlayerHit(Player*player); //Return true to destroy the bullet on hit, return false otherwise. THE BULLET HIT HAS ALREADY OCCURRED. BulletDestroyState _MonsterHit(Monster&monster); //Return true to destroy the bullet on hit, return false otherwise. THE BULLET HIT HAS ALREADY OCCURRED. const float&GetFadeoutTimer()const; void SetBulletType(const BulletType type); + const double GetTimeAlive()const; public: Animate2D::Animationanimation; Animate2D::AnimationState internal_animState; diff --git a/Adventures in Lestoria/BulletTypes.h b/Adventures in Lestoria/BulletTypes.h index 89abaec2..1b8d0487 100644 --- a/Adventures in Lestoria/BulletTypes.h +++ b/Adventures in Lestoria/BulletTypes.h @@ -225,4 +225,23 @@ struct LargeTornado:public Bullet{ struct Feather:public Bullet{ Feather(vf2d pos,vf2d vel,float radius,int damage,bool upperLevel,bool hitsMultiple=false,float lifetime=INFINITE,bool friendly=false,Pixel col=WHITE,vf2d scale={1,1},float image_angle=0.f); +}; + +struct LargeStone:public Bullet{ +public: + LargeStone(vf2d pos,const float stoneThrowTime,const vf2d landingPos,float moveVelWaitTimer,float radius,float z,float gravity,int damage,bool upperLevel,bool hitsMultiple=false,float lifetime=INFINITE,bool friendly=false,Pixel col=WHITE,vf2d scale={1,1},float image_angle=0.f); +protected: + void Update(float fElapsedTime)override; + BulletDestroyState PlayerHit(Player*player)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _PlayerHit()!! + BulletDestroyState MonsterHit(Monster&monster)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! +private: + const float gravity; + const float fixedTimeStep{1/30.f}; + const float stoneThrowTime; + const vf2d landingPos; + const vf2d startingPos; + float fixedTimeStepAcc{}; + float zVel{}; + float moveTimer; //Counts down to 0, when it hits zero sets the velocity to futurevel. + const float initialMoveWaitTime; }; \ No newline at end of file diff --git a/Adventures in Lestoria/ItemDrop.cpp b/Adventures in Lestoria/ItemDrop.cpp index c3346f5f..e9b598dd 100644 --- a/Adventures in Lestoria/ItemDrop.cpp +++ b/Adventures in Lestoria/ItemDrop.cpp @@ -58,8 +58,8 @@ ItemDrop::ItemDrop(const ItemInfo*item,const vf2d pos,const bool isUpper) this->pos.x=std::clamp(this->pos.x,float(arenaBounds.pos.x),float(arenaBounds.pos.x+arenaBounds.size.x)); this->pos.y=std::clamp(this->pos.y,float(arenaBounds.pos.y),float(arenaBounds.pos.y+arenaBounds.size.y)); } - speed.x=util::random("ItemDrop.Item Drop Horizontal Speed"_f[1]-"ItemDrop.Item Drop Horizontal Speed"_f[0])+"ItemDrop.Item Drop Horizontal Speed"_f[0]; - speed.y=util::random("ItemDrop.Item Drop Vertical Speed"_f[1]-"ItemDrop.Item Drop Vertical Speed"_f[0])+"ItemDrop.Item Drop Vertical Speed"_f[0]; + speed.x=util::random_range("ItemDrop.Item Drop Horizontal Speed"_f[0],"ItemDrop.Item Drop Horizontal Speed"_f[1]); + speed.y=util::random_range("ItemDrop.Item Drop Vertical Speed"_f[0],"ItemDrop.Item Drop Vertical Speed"_f[1]); zSpeed="ItemDrop.Item Drop Initial Rise Speed"_F; randomSpinOffset=util::random(PI/2); } diff --git a/Adventures in Lestoria/LargeStone.cpp b/Adventures in Lestoria/LargeStone.cpp new file mode 100644 index 00000000..61621754 --- /dev/null +++ b/Adventures in Lestoria/LargeStone.cpp @@ -0,0 +1,78 @@ +#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 "AdventuresInLestoria.h" + +INCLUDE_game + +LargeStone::LargeStone(vf2d pos,const float stoneThrowTime,const vf2d landingPos,float moveVelWaitTimer,float radius,float z,float gravity,int damage,bool upperLevel,bool hitsMultiple,float lifetime,bool friendly,Pixel col,vf2d scale,float image_angle) +:stoneThrowTime(stoneThrowTime),startingPos(pos),landingPos(landingPos),gravity(gravity),initialMoveWaitTime(moveVelWaitTimer),moveTimer(moveVelWaitTimer),Bullet(pos,{},radius,damage,"large_rock.png",upperLevel,false,INFINITE,false,friendly,col,scale,image_angle){ + this->z=z; + Deactivate(); +} + +void LargeStone::Update(float fElapsedTime){ + fixedTimeStepAcc+=fElapsedTime; + while(fixedTimeStepAcc>fixedTimeStep){ + Bullet::Update(fixedTimeStep); + + if(moveTimer>0.f)moveTimer-=fixedTimeStep; + if(moveTimer<=0.f){ + if(z<=0.f&&fadeOutTime==0.f){ + game->Hurt(pos,radius,damage,OnUpperLevel(),0.f,friendly?HurtType::MONSTER:HurtType::PLAYER); + fadeOutTime=0.5f; + }else + if(z>0.f&&fadeOutTime>=0.f){ + pos=startingPos.lerp(landingPos,(GetTimeAlive()-initialMoveWaitTime)/stoneThrowTime); + + zVel+=gravity*fixedTimeStep; + z+=zVel*fixedTimeStep; + } + } + fixedTimeStepAcc-=fixedTimeStep; + } +} + +BulletDestroyState LargeStone::PlayerHit(Player*player){ + return BulletDestroyState::KEEP_ALIVE; +} + +BulletDestroyState LargeStone::MonsterHit(Monster&monster){ + return BulletDestroyState::KEEP_ALIVE; +} \ No newline at end of file diff --git a/Adventures in Lestoria/Monster.cpp b/Adventures in Lestoria/Monster.cpp index 099c8dec..e05d8e32 100644 --- a/Adventures in Lestoria/Monster.cpp +++ b/Adventures in Lestoria/Monster.cpp @@ -356,7 +356,8 @@ bool Monster::Update(float fElapsedTime){ knockbackStrength+=b.intensity; } Knockback(line.vector().norm()*-128*knockbackStrength); - }else{ + }else + if(!IgnoresTerrainCollision()){ SetPos(line.rpoint(-displacementDist)); } } diff --git a/Adventures in Lestoria/StoneGolem.cpp b/Adventures in Lestoria/StoneGolem.cpp index 3e31b6de..3d90aeeb 100644 --- a/Adventures in Lestoria/StoneGolem.cpp +++ b/Adventures in Lestoria/StoneGolem.cpp @@ -41,6 +41,7 @@ All rights reserved. #include "AdventuresInLestoria.h" #include "DEFINES.h" #include "util.h" +#include "BulletTypes.h" INCLUDE_game @@ -97,10 +98,17 @@ void Monster::STRATEGY::STONE_GOLEM(Monster&m,float fElapsedTime,std::string str m.PerformAnimation("TOSS ROCK CAST"); m.F(A::CASTING_TIMER)=ConfigFloat("Standard Attack.Stone Throw Cast Time"); game->AddEffect(std::make_unique(m.V(A::LOCKON_POS),ConfigFloat("Standard Attack.Stone Throw Cast Time")+4.f,"range_indicator.png","spell_insignia.png",m.OnUpperLevel(),vf2d{1.f,1.f}*(ConfigPixels("Standard Attack.Stone Radius")/12.f)*1.25f,0.3f,vf2d{},ConfigPixel("Standard Attack.Stone Throw Spell Circle Color"),util::random(2*PI),util::degToRad(ConfigFloat("Standard Attack.Stone Throw Spell Circle Rotation Spd")),false,vf2d{1.f,1.f}*(ConfigPixels("Standard Attack.Stone Radius")/12.f)*0.9f,0.3f,vf2d{},ConfigPixel("Standard Attack.Stone Throw Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Standard Attack.Stone Throw Spell Insignia Rotation Spd"))),true); + + //Use acceleration equation to determine how much time it takes for the stone to land based on gravity. + const float stoneTossTime{ConfigFloat("Standard Attack.Stone Throw Time")}; + //Physics!! Kinematic equation from https://openstax.org/books/physics/pages/3-2-representing-acceleration-with-equations-and-graphs a=(2d)/(t^2) + const float acc{(2*-ConfigFloat("Standard Attack.Stone Throw Height Offset"))/std::pow(stoneTossTime,2.f)}; + + CreateBullet(LargeStone)(m.GetPos()+ConfigFloat("Standard Attack.Stone Throw Height Offset")/2.f,ConfigFloat("Standard Attack.Stone Throw Time"),m.V(A::LOCKON_POS),m.F(A::CASTING_TIMER),ConfigPixels("Standard Attack.Stone Radius"),ConfigFloat("Standard Attack.Stone Throw Height Offset"),acc,ConfigInt("Standard Attack.Stone Damage"),m.OnUpperLevel(),false,INFINITY,false,WHITE,vf2d{1,1}*m.GetSizeMult(),util::random(2*PI))EndBullet; } }break; case STONE_THROW_CAST:{ - + }break; } } \ No newline at end of file diff --git a/Adventures in Lestoria/TODO.txt b/Adventures in Lestoria/TODO.txt index b3547cd0..09539482 100644 --- a/Adventures in Lestoria/TODO.txt +++ b/Adventures in Lestoria/TODO.txt @@ -10,15 +10,9 @@ Upon the second time entering a stage, the game will spawn a timer that the play Upon completion of a stage in time trial mode if the player beat their previous time (which they likely will) the record will update. For each class and stage combination there will be a "dev time" -Settings menu doesn't scroll back up properly while the scrollbar does? Traveling merchants of different colors/looks. -Steel Weapons appear in the demo for Chapter 2. Look into removing OVERRIDE from rumble settings. It looks like it was used to purposefully disable rumble, but looks very unnecessary. -Move old maps from master branch into demo branch (has boundary changes) - -When a monster spawns, if it spawns inside a collision tile, attempt to set it outside somewhere and make a warning popup. - New Monster Sound Effects DEMO diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h index 49e9bbf2..a028ebeb 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 9622 +#define VERSION_BUILD 9630 #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 b995b935..13c481d8 100644 --- a/Adventures in Lestoria/assets/config/MonsterStrategies.txt +++ b/Adventures in Lestoria/assets/config/MonsterStrategies.txt @@ -917,9 +917,12 @@ MonsterStrategy Stone Throw Chance = 25% Stone Radius = 250 Stone Damage = 55 - Stone Pillar Damage = 3 Stone Throw Cast Time = 2.5s + # How high in the air the rock starts at from the GROUND. + Stone Throw Height Offset = 160pixels + Stone Throw Time = 0.75s + Stone Throw Spell Circle Color = 40, 40, 40, 80 Stone Throw Spell Insignia Color = 144, 137, 160, 255 # Degrees/sec. Positive is CW, Negative is CCW. diff --git a/x64/Release/Adventures in Lestoria.exe b/x64/Release/Adventures in Lestoria.exe index 2ebe7c0f..bfa3e9c0 100644 Binary files a/x64/Release/Adventures in Lestoria.exe and b/x64/Release/Adventures in Lestoria.exe differ