diff --git a/Adventures in Lestoria/Monster.cpp b/Adventures in Lestoria/Monster.cpp index 45ec6fe8..d64a8802 100644 --- a/Adventures in Lestoria/Monster.cpp +++ b/Adventures in Lestoria/Monster.cpp @@ -51,6 +51,7 @@ All rights reserved. #ifndef __EMSCRIPTEN__ #include "steam/isteamuserstats.h" #endif +#include "GameSettings.h" INCLUDE_ANIMATION_DATA INCLUDE_MONSTER_DATA @@ -265,6 +266,10 @@ bool Monster::Update(float fElapsedTime){ lastPathfindingCooldown=std::max(0.f,lastPathfindingCooldown-fElapsedTime); lastFacingDirectionChange+=fElapsedTime; timeSpentAlive+=fElapsedTime; + if(IsSolid()){ + if(GetPos().y>=game->GetPlayer()->GetPos().y)solidFadeTimer=std::min(TileGroup::FADE_TIME,solidFadeTimer+game->GetElapsedTime()); + else solidFadeTimer=std::max(0.f,solidFadeTimer-game->GetElapsedTime()); + } if(HasArrowIndicator()&&IsAlive())game->SetBossIndicatorPos(GetPos()); @@ -330,8 +335,10 @@ bool Monster::Update(float fElapsedTime){ } if(!HasIframes()){ for(std::unique_ptr&m:MONSTER_LIST){ + const float monsterRadius{GetCollisionRadius()}; + const float otherMonsterRadius{m->GetCollisionRadius()}; if(&*m==this)continue; - if(!m->HasIframes()&&OnUpperLevel()==m->OnUpperLevel()&&abs(m->GetZ()-GetZ())<=1&&geom2d::overlaps(geom2d::circle(pos,GetCollisionRadius()),geom2d::circle(m->GetPos(),m->GetCollisionRadius()))){ + if(!m->HasIframes()&&OnUpperLevel()==m->OnUpperLevel()&&abs(m->GetZ()-GetZ())<=1&&geom2d::overlaps(geom2d::circle(pos,monsterRadius),geom2d::circle(m->GetPos(),otherMonsterRadius))){ m->Collision(*this); geom2d::line line(pos,m->GetPos()); float dist = line.length(); @@ -339,24 +346,21 @@ bool Monster::Update(float fElapsedTime){ line={pos+vf2d{util::random(0.2f)-0.1f,util::random(0.2f)-0.1f},m->GetPos()}; dist=line.length(); } - m->SetPos(line.rpoint(dist*1.1f)); - if(!Immovable()&&m->IsAlive()){ - float knockbackStrength=1.f; - std::vector knockbackBuffs=m->GetBuffs(COLLISION_KNOCKBACK_STRENGTH); - for(Buff&b:knockbackBuffs){ - knockbackStrength+=b.intensity; + const float displacementDist=(otherMonsterRadius+monsterRadius)-dist; + if(m->IsAlive()){ + if(!m->IsSolid()){ + float knockbackStrength=1.f; + std::vector knockbackBuffs=m->GetBuffs(COLLISION_KNOCKBACK_STRENGTH); + for(Buff&b:knockbackBuffs){ + knockbackStrength+=b.intensity; + } + Knockback(line.vector().norm()*-128*knockbackStrength); + }else{ + SetPos(line.rpoint(-displacementDist)); } - Knockback(line.vector().norm()*-128*knockbackStrength); } } } - if(!Immovable()&& - !game->GetPlayer()->HasIframes()&&abs(game->GetPlayer()->GetZ()-GetZ())<=1&&game->GetPlayer()->OnUpperLevel()==OnUpperLevel()&&geom2d::overlaps(geom2d::circle(pos,GetCollisionRadius()),geom2d::circle(game->GetPlayer()->GetPos(),12*game->GetPlayer()->GetSizeMult()/2))){ - geom2d::line line(pos,game->GetPlayer()->GetPos()); - float dist = line.length(); - SetPos(line.rpoint(-0.1f)); - vel=line.vector().norm()*-128; - } } if(GetState()==State::NORMAL){ UpdateFacingDirection(game->GetPlayer()->GetPos()); @@ -439,12 +443,14 @@ void Monster::Draw()const{ } const bool NotOnTitleScreen=GameState::STATE!=GameState::states[States::MAIN_MENU]; - uint8_t blendColAlpha=255U; - - if(NotOnTitleScreen - &&(game->GetPlayer()->HasIframes()||OnUpperLevel()!=game->GetPlayer()->OnUpperLevel()||abs(GetZ()-game->GetPlayer()->GetZ())>1))blendColAlpha=160; + uint8_t blendColAlpha=blendCol.a; if(fadeTimer>0.f)blendColAlpha=uint8_t(util::lerp(0,blendCol.a,fadeTimer)); //Fade timer goes from 1 to 0 seconds. + else + if(NotOnTitleScreen + &&(game->GetPlayer()->HasIframes()||OnUpperLevel()!=game->GetPlayer()->OnUpperLevel()||abs(GetZ()-game->GetPlayer()->GetZ())>1))blendColAlpha=blendCol.a*0.62f; + else + if(IsSolid()&&solidFadeTimer>0.f)blendColAlpha=uint8_t(util::lerp(blendCol.a,255-TileGroup::FADE_AMT,solidFadeTimer/TileGroup::FADE_TIME)); blendCol.a=blendColAlpha; @@ -458,6 +464,17 @@ void Monster::Draw()const{ if(shieldBuffs.size()>0){ game->view.DrawRotatedDecal(drawPos,GFX["block.png"].Decal(),0.f,GFX["block.png"].Sprite()->Size()/2,{GetSizeMult(),GetSizeMult()}); } + + if(GameSettings::TerrainCollisionBoxesEnabled()&&IsSolid()&&solidFadeTimer>0.f){ + float distToPlayer=geom2d::line(game->GetPlayer()->GetPos(),GetPos()).length(); + const float collisionRadiusFactor=GetCollisionRadius()/12.f; + if(distToPlayer<24*3*collisionRadiusFactor){ + game->DrawPie(game->view.WorldToScreen(GetPos()),GetCollisionRadius(),0.f,{255,0,0,uint8_t(128*(blendColAlpha/255.f)/sqrt(distToPlayer*collisionRadiusFactor))}); + game->SetDecalMode(DecalMode::WIREFRAME); + game->DrawPie(game->view.WorldToScreen(GetPos()),GetCollisionRadius(),0.f,{128,0,0,255}); + game->SetDecalMode(DecalMode::NORMAL); + } + } #pragma region Debug Pathfinding #ifdef _DEBUG @@ -1090,4 +1107,8 @@ const bool Monster::ReachedTargetPos(const float maxDistanceFromTarget)const{ const float Monster::GetHealthRatio()const{ return GetHealth()/float(GetMaxHealth()); +} + +const bool Monster::IsSolid()const{ + return Immovable(); } \ No newline at end of file diff --git a/Adventures in Lestoria/Monster.h b/Adventures in Lestoria/Monster.h index d1fd5afc..a82ab757 100644 --- a/Adventures in Lestoria/Monster.h +++ b/Adventures in Lestoria/Monster.h @@ -169,6 +169,7 @@ public: const bool IgnoresTerrainCollision()const; const float TimeSpentAlive()const; const bool Immovable()const; + const bool IsSolid()const; const bool Invulnerable()const; //If an object has a lifetime set, returns it. const std::optionalGetLifetime()const; @@ -256,6 +257,7 @@ private: std::optionallifetime{}; float fadeTimer{0.f}; bool markedForDeletion{false}; //DO NOT MODIFY DIRECTLY. Use MarkForDeletion() if this monster needs to be marked. NOTE: Marking a monster for deletion does not trigger any death events. It just simply removes the monster from the field!! + float solidFadeTimer{0.f}; private: struct STRATEGY{ static std::string ERR; diff --git a/Adventures in Lestoria/Player.cpp b/Adventures in Lestoria/Player.cpp index d27e7ccb..bc818bb5 100644 --- a/Adventures in Lestoria/Player.cpp +++ b/Adventures in Lestoria/Player.cpp @@ -521,7 +521,9 @@ void Player::Update(float fElapsedTime){ item3.cooldown=0; } for(std::unique_ptr&m:MONSTER_LIST){ - if(!HasIframes()&&abs(m->GetZ()-GetZ())<=1&&OnUpperLevel()==m->OnUpperLevel()&&geom2d::overlaps(geom2d::circle(pos,12*size/2),geom2d::circle(m->GetPos(),m->GetCollisionRadius()))){ + const float playerRadius{12*GetSizeMult()/2}; + const float monsterRadius{m->GetCollisionRadius()}; + if(!HasIframes()&&abs(m->GetZ()-GetZ())<=1&&OnUpperLevel()==m->OnUpperLevel()&&geom2d::overlaps(geom2d::circle(pos,playerRadius),geom2d::circle(m->GetPos(),monsterRadius))){ if(m->IsAlive()){ m->Collision(this); } @@ -531,16 +533,22 @@ void Player::Update(float fElapsedTime){ line={pos+vf2d{util::random(0.2f)-0.1f,util::random(0.2f)-0.1f},m->GetPos()}; dist=line.length(); } - if(!m->Immovable()){ + const float displacementDist=(playerRadius+monsterRadius)-dist; + if(!m->IsSolid()){ m->SetPos(line.rpoint(dist*1.1f)); } if(m->IsAlive()&&!m->IsNPC()){ //Don't set the knockback if this monster is actually an NPC. Let's just push them around. - float knockbackStrength=1.f; - std::vectorknockbackBuffs=m->GetBuffs(COLLISION_KNOCKBACK_STRENGTH); - for(Buff&b:knockbackBuffs){ - knockbackStrength+=b.intensity; + if(!m->IsSolid()){ + float knockbackStrength=1.f; + std::vectorknockbackBuffs=m->GetBuffs(COLLISION_KNOCKBACK_STRENGTH); + for(Buff&b:knockbackBuffs){ + knockbackStrength+=b.intensity; + } + m->Knockback(line.vector().norm()*128.f); + Knockback(line.vector().norm()*-128.f*knockbackStrength); + }else{ + SetPos(line.rpoint(-displacementDist)); } - Knockback(line.vector().norm()*-128.f*knockbackStrength); } } } diff --git a/Adventures in Lestoria/StoneGolem.cpp b/Adventures in Lestoria/StoneGolem.cpp index 0674544a..25b1362a 100644 --- a/Adventures in Lestoria/StoneGolem.cpp +++ b/Adventures in Lestoria/StoneGolem.cpp @@ -64,7 +64,7 @@ void Monster::STRATEGY::STONE_GOLEM(Monster&m,float fElapsedTime,std::string str m.F(A::RECOVERY_TIME)-=fElapsedTime; if(m.F(A::RECOVERY_TIME)<=0.f){ m.V(A::LOCKON_POS)=game->GetPlayer()->GetPos(); - m.PerformAnimation("STONE PILLAR CAST",m.GetFacingDirectionToTarget(m.V(A::LOCKON_POS))); + m.PerformAnimation("CAST",m.GetFacingDirectionToTarget(m.V(A::LOCKON_POS))); game->AddEffect(std::make_unique(m.V(A::LOCKON_POS),ConfigFloat("Beginning Phase.Pillar Cast Time"),"range_indicator.png",m.OnUpperLevel(),vf2d{1.f,1.f}*(MONSTER_DATA.at("Stone Golem Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Golem Pillar").GetSizeMult()/12.f)*1.25f,0.3f,vf2d{},ConfigPixel("Beginning Phase.Pillar Spell Circle Color"),util::random(2*PI),util::degToRad(ConfigFloat("Beginning Phase.Pillar Spell Circle Rotation Spd"))),true); game->AddEffect(std::make_unique(m.V(A::LOCKON_POS),ConfigFloat("Beginning Phase.Pillar Cast Time"),"spell_insignia.png",m.OnUpperLevel(),vf2d{1.f,1.f}*(MONSTER_DATA.at("Stone Golem Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Golem Pillar").GetSizeMult()/12.f)*0.9f,0.3f,vf2d{},ConfigPixel("Beginning Phase.Pillar Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Beginning Phase.Pillar Spell Insignia Rotation Spd"))),true); m.F(A::CASTING_TIMER)=ConfigFloat("Beginning Phase.Pillar Cast Time"); @@ -75,6 +75,8 @@ void Monster::STRATEGY::STONE_GOLEM(Monster&m,float fElapsedTime,std::string str m.F(A::CASTING_TIMER)-=fElapsedTime; if(m.F(A::CASTING_TIMER)<=0.f){ m.I(A::PATTERN_REPEAT_COUNT)--; + game->SpawnMonster(m.V(A::LOCKON_POS),MONSTER_DATA.at("Stone Golem Pillar"),m.OnUpperLevel()); + game->Hurt(m.V(A::LOCKON_POS),MONSTER_DATA.at("Stone Golem Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Golem Pillar").GetSizeMult(),m.GetAttack(),m.OnUpperLevel(),0.f,HurtType::PLAYER); if(m.I(A::PATTERN_REPEAT_COUNT)<=0){ m.phase=STANDARD; }else{ diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h index 812fe17b..78c0dbd0 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 9585 +#define VERSION_BUILD 9610 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/Adventures in Lestoria/assets/config/Monsters.txt b/Adventures in Lestoria/assets/config/Monsters.txt index 92b3e258..69703245 100644 --- a/Adventures in Lestoria/assets/config/Monsters.txt +++ b/Adventures in Lestoria/assets/config/Monsters.txt @@ -988,7 +988,7 @@ Monsters CollisionDmg = 40 - MoveSpd = 180% + MoveSpd = 50% Size = 400% XP = 5 @@ -1011,12 +1011,13 @@ Monsters # The First Four animations must represent a standing, walking, attack, and death animation. Their names are up to the creator. IDLE = 2, 0.6, Repeat WALK = 4, 0.2, Repeat - TOSS ROCK = 4, 0.2, OneShot + CAST = 2, 0.3, Repeat DEATH = 4, 0.15, OneShot BURROW UNDERGROUND = 5, 0.15, OneShot RISE FROM UNDERGROUND = 5, 0.15, OneShot - ROCK TOSS CAST = 2, 0.3, Repeat - STONE PILLAR CAST = 2, 0.3, Repeat + TOSS ROCK Cast = 2, 0.2, Repeat + SLAM = 3, 0.2, OneShot + TOSS ROCK = 4, 0.2, OneShot } Ignore Collisions = False @@ -1040,7 +1041,7 @@ Monsters MoveSpd = 0% # The Pillar is supposed to be 350 radius. - Size = 300% + Size = 600% Collision Radius = 7 XP = 0 diff --git a/Adventures in Lestoria/assets/gamepack.pak b/Adventures in Lestoria/assets/gamepack.pak index 449ba452..55cffab9 100644 Binary files a/Adventures in Lestoria/assets/gamepack.pak and b/Adventures in Lestoria/assets/gamepack.pak differ diff --git a/x64/Release/Adventures in Lestoria.exe b/x64/Release/Adventures in Lestoria.exe index e274a459..b1c0c87c 100644 Binary files a/x64/Release/Adventures in Lestoria.exe and b/x64/Release/Adventures in Lestoria.exe differ