diff --git a/Adventures in Lestoria/FrogTongue.cpp b/Adventures in Lestoria/FrogTongue.cpp index 4f240633..3c4259d6 100644 --- a/Adventures in Lestoria/FrogTongue.cpp +++ b/Adventures in Lestoria/FrogTongue.cpp @@ -61,8 +61,9 @@ void FrogTongue::Update(float fElapsedTime){ vf2d tongueEndPos=geom2d::line(pos+drawVec,targetPos).upoint(pow(sin((lifetime*PI)/duration),20.f)); geom2d::linetongueLine(pos+drawVec,tongueEndPos); - if(!friendly&&geom2d::overlaps(game->GetPlayer()->Hitbox(),tongueLine)){ + if(!friendly&&hitList.find(game->GetPlayer())==hitList.end()&&geom2d::overlaps(game->GetPlayer()->Hitbox(),tongueLine)){ _PlayerHit(game->GetPlayer()); + hitList.insert(game->GetPlayer()); } if(friendly){ for(std::shared_ptr&m:MONSTER_LIST){ diff --git a/Adventures in Lestoria/GiantOctopus.cpp b/Adventures in Lestoria/GiantOctopus.cpp index cc353097..1bd074d2 100644 --- a/Adventures in Lestoria/GiantOctopus.cpp +++ b/Adventures in Lestoria/GiantOctopus.cpp @@ -49,19 +49,28 @@ INCLUDE_MONSTER_LIST void Monster::STRATEGY::GIANT_OCTOPUS(Monster&m,float fElapsedTime,std::string strategy){ enum PhaseName{ + INIT, IDENTIFY_ARMS, NORMAL, }; switch(PHASE()){ + case INIT:{ + m.F(A::BREAK_TIME)=0.5f; + SETPHASE(IDENTIFY_ARMS); + }break; case IDENTIFY_ARMS:{ - m.F(A::CASTING_TIMER)=util::random_range(ConfigFloatArr("Tentacle Move Timer",0),ConfigFloatArr("Tentacle Move Timer",1)); - for(std::shared_ptr&arm:MONSTER_LIST){ - const std::string OCTOPUS_ARM_NAME{"Octopus Arm"}; - if(arm->GetName()==OCTOPUS_ARM_NAME){ - std::weak_ptrarmPtr{arm}; - m.VEC(A::ARM_LIST).emplace_back(armPtr); - m.VEC(A::ARM_LOCATIONS).emplace_back(armPtr.lock()->GetPos()); + m.F(A::BREAK_TIME)-=fElapsedTime; + if(m.F(A::BREAK_TIME)<=0.f){ + m.F(A::CASTING_TIMER)=util::random_range(ConfigFloatArr("Tentacle Move Timer",0),ConfigFloatArr("Tentacle Move Timer",1)); + for(std::shared_ptr&arm:MONSTER_LIST){ + const std::string OCTOPUS_ARM_NAME{"Octopus Arm"}; + if(arm->GetName()==OCTOPUS_ARM_NAME){ + std::weak_ptrarmPtr{arm}; + m.VEC(A::ARM_LIST).emplace_back(armPtr); + m.VEC(A::ARM_LOCATIONS).emplace_back(armPtr.lock()->GetPos()); + } } + SETPHASE(NORMAL); } }break; case NORMAL:{ @@ -69,16 +78,29 @@ void Monster::STRATEGY::GIANT_OCTOPUS(Monster&m,float fElapsedTime,std::string s if(m.F(A::CASTING_TIMER)<=0.f){ int deadMonsterCount{0}; std::vectortempArmLocs; - for(size_t i=0U;std::any&arm:m.VEC(A::ARM_LIST)){ + std::vectorliveArms{std::find_if(m.VEC(A::ARM_LIST).begin(),m.VEC(A::ARM_LIST).end(),[](const std::any&arm){ const std::weak_ptr&m{std::any_cast>(arm)}; - if(m.expired()||m.lock()->IsDead()){ + return !m.expired()&&m.lock()->IsAlive(); + })}; + for(int index{0};std::any&arm:m.VEC(A::ARM_LIST)){ + const std::weak_ptr&armM{std::any_cast>(arm)}; + if(armM.expired()||armM.lock()->IsDead()){ deadMonsterCount++; - tempArmLocs.emplace_back(std::any_cast(m.lock()->VEC(A::ARM_LOCATIONS))); + if(!armM.expired())tempArmLocs.emplace_back(std::any_cast(armM.lock()->VEC(A::ARM_LOCATIONS)[index])); } + index++; } - if(deadMonsterCount>0){ - + const bool AtLeastOneArmAlive{deadMonsterCount!=m.VEC(A::ARM_LIST).size()}; + if(deadMonsterCount>0&&AtLeastOneArmAlive){ + const std::weak_ptr&randomArm{std::any_cast>(liveArms[util::random()%liveArms.size()])}; + const vf2d&randomLoc{std::any_cast(randomArm.lock()->VEC(A::ARM_LOCATIONS))}; + randomArm.lock()->PerformAnimation("SUBMERGE"); + randomArm.lock()->SetPhase(strategy,randomArm.lock()->I(A::SUBMERGE_STRAT_ID)); + randomArm.lock()->GetFloat(A::RECOVERY_TIME)=randomArm.lock()->GetCurrentAnimation().GetTotalAnimationDuration(); + randomArm.lock()->SetCollisionRadius(0.f); + randomArm.lock()->V(A::JUMP_TARGET_POS)=randomLoc; } + m.F(A::CASTING_TIMER)=util::random_range(ConfigFloatArr("Tentacle Move Timer",0),ConfigFloatArr("Tentacle Move Timer",1)); } }break; } diff --git a/Adventures in Lestoria/Monster.cpp b/Adventures in Lestoria/Monster.cpp index 0328459c..42681564 100644 --- a/Adventures in Lestoria/Monster.cpp +++ b/Adventures in Lestoria/Monster.cpp @@ -1668,4 +1668,7 @@ const float Monster::GetOriginalCollisionRadius()const{ } void Monster::SetCollisionRadius(const float collisionRadius){ this->collisionRadius=collisionRadius; +} +void Monster::SetLifetime(const float lifetime){ + this->lifetime=lifetime; } \ No newline at end of file diff --git a/Adventures in Lestoria/Monster.h b/Adventures in Lestoria/Monster.h index 7dff52a3..89bb65e8 100644 --- a/Adventures in Lestoria/Monster.h +++ b/Adventures in Lestoria/Monster.h @@ -198,6 +198,7 @@ public: //If an object has a lifetime set, returns it. const std::optionalGetLifetime()const; const std::optionalGetTotalLifetime()const; + void SetLifetime(const float lifetime); //If an object has a collision radius, returns it. const float GetCollisionRadius()const; const bool IsDead()const; diff --git a/Adventures in Lestoria/MonsterAttribute.h b/Adventures in Lestoria/MonsterAttribute.h index f74b0a63..3f847cfb 100644 --- a/Adventures in Lestoria/MonsterAttribute.h +++ b/Adventures in Lestoria/MonsterAttribute.h @@ -156,4 +156,6 @@ enum class Attribute{ SWING_OCCURRED, ARM_LOCATIONS, ARM_LIST, + SUBMERGE_LOCATION, + SUBMERGE_STRAT_ID, }; \ No newline at end of file diff --git a/Adventures in Lestoria/OctopusArm.cpp b/Adventures in Lestoria/OctopusArm.cpp index 74266579..f0ba6b2a 100644 --- a/Adventures in Lestoria/OctopusArm.cpp +++ b/Adventures in Lestoria/OctopusArm.cpp @@ -74,11 +74,12 @@ void Monster::STRATEGY::OCTOPUS_ARM(Monster&m,float fElapsedTime,std::string str switch(PHASE()){ case INIT:{ + m.I(A::SUBMERGE_STRAT_ID)=SUBMERGE; if(ConfigFloat("Attack Swing Damage Wait Time")>m.GetAnimation("ATTACKING").GetTotalAnimationDuration())ERR(std::format("The Attack Swing Damage Wait Time ({}s) should not be greater than the total attack time animation duration! ({}s)",ConfigFloat("Attack Swing Damage Wait Time"),m.GetAnimation("ATTACKING").GetTotalAnimationDuration())); m.PerformAnimation("RISE",game->GetPlayer()->GetPos()); m.F(A::CASTING_TIMER)=m.GetCurrentAnimation().GetTotalAnimationDuration(); SETPHASE(RISE_ANIMATION); - m.SetStrategyDeathFunction([bossDamageOnDeath=ConfigInt("Boss Damage On Death")](GameEvent&event,Monster&m,const StrategyName&strategyName){ + m.SetStrategyDeathFunction([deathFadeTime=ConfigFloat("Death Fade Time"),bossDamageOnDeath=ConfigInt("Boss Damage On Death")](GameEvent&event,Monster&m,const StrategyName&strategyName){ m.SetStrategyDrawFunction([](AiL*game,Monster&monster,const std::string&strategy){}); const std::string GIANT_OCTOPUS_NAME{"Giant Octopus"}; const std::string OCTOPUS_ARM_NAME{"Octopus Arm"}; @@ -96,9 +97,12 @@ void Monster::STRATEGY::OCTOPUS_ARM(Monster&m,float fElapsedTime,std::string str if(m->GetName()==OCTOPUS_ARM_NAME){ m->PerformAnimation("SUBMERGE"); m->SetPhase(strategyName,SUBMERGE); + m->V(A::JUMP_TARGET_POS)=m->GetPos(); m->GetFloat(A::RECOVERY_TIME)=m->GetCurrentAnimation().GetTotalAnimationDuration(); } }); + + m.SetLifetime(deathFadeTime); return false; }); }break; @@ -171,6 +175,7 @@ void Monster::STRATEGY::OCTOPUS_ARM(Monster&m,float fElapsedTime,std::string str m.F(A::RECOVERY_TIME)-=fElapsedTime; if(m.F(A::RECOVERY_TIME)<=0.f){ m.PerformAnimation("RISE"); + m.SetPos(m.V(A::JUMP_TARGET_POS)); m.F(A::CASTING_TIMER)=m.GetCurrentAnimation().GetTotalAnimationDuration(); SETPHASE(RISE_ANIMATION); } diff --git a/Adventures in Lestoria/Pirate_Buccaneer.cpp b/Adventures in Lestoria/Pirate_Buccaneer.cpp index b149864d..0dc53e26 100644 --- a/Adventures in Lestoria/Pirate_Buccaneer.cpp +++ b/Adventures in Lestoria/Pirate_Buccaneer.cpp @@ -49,6 +49,7 @@ INCLUDE_game void Monster::STRATEGY::PIRATE_BUCCANEER(Monster&m,float fElapsedTime,std::string strategy){ #pragma region Phase, Animation, and Helper function setup enum PhaseName{ + INIT, MOVE, LOCKON, WINDUP, @@ -57,6 +58,13 @@ void Monster::STRATEGY::PIRATE_BUCCANEER(Monster&m,float fElapsedTime,std::strin #pragma endregion switch(PHASE()){ + case INIT:{ + m.SetStrategyDeathFunction([](GameEvent&ev,Monster&m,const std::string&strategy){ + m.SetStrategyDrawFunction([](AiL*game,Monster&monster,const std::string&strategy){}); + return false; + }); + SETPHASE(MOVE); + }break; case MOVE:{ m.F(A::ATTACK_COOLDOWN)+=fElapsedTime; @@ -100,10 +108,13 @@ void Monster::STRATEGY::PIRATE_BUCCANEER(Monster&m,float fElapsedTime,std::strin m.PerformAnimation("SHOOT",m.GetFacingDirectionToTarget(game->GetPlayer()->GetPos())); const float arrowHitboxRadius{ConfigFloat("Arrow Hitbox Radius")}; m.SetStrategyDrawFunction([arrowHitboxRadius](AiL*game,Monster&monster,const std::string&strategy){ + const float alphaTimer{float(std::fmod(game->GetRunTime(),2.f))}; + uint8_t alpha{util::lerp(uint8_t(0),uint8_t(255),alphaTimer)}; + if(alphaTimer>1.f)alpha=util::lerp(0,255,1-(alphaTimer-1)); vf2d midpoint{geom2d::line(monster.GetPos(),monster.V(A::LOCKON_POS)).rpoint(800.f)}; float shootingAngle{util::angleTo(monster.GetPos(),monster.V(A::LOCKON_POS))+PI/2}; vf2d imgSize{arrowHitboxRadius*2.f,800.f}; - game->view.DrawPartialRotatedDecal(midpoint,GFX["line_indicator.png"].Decal(),shootingAngle,GFX["line_indicator.png"].Sprite()->Size()/2,{},GFX["line_indicator.png"].Sprite()->Size(),imgSize/GFX["line_indicator.png"].Sprite()->Size()); + game->view.DrawPartialRotatedDecal(midpoint,GFX["line_indicator.png"].Decal(),shootingAngle,GFX["line_indicator.png"].Sprite()->Size()/2,{},GFX["line_indicator.png"].Sprite()->Size(),imgSize/GFX["line_indicator.png"].Sprite()->Size(),{255,255,255,uint8_t(alpha)}); }); } }break; diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h index 012cec1d..c4ee1da5 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 3 #define VERSION_PATCH 0 -#define VERSION_BUILD 11808 +#define VERSION_BUILD 11815 #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 80908e38..6c13862d 100644 --- a/Adventures in Lestoria/assets/config/MonsterStrategies.txt +++ b/Adventures in Lestoria/assets/config/MonsterStrategies.txt @@ -1217,6 +1217,8 @@ MonsterStrategy # Amount of time the spreading aftershock effect appears for. Attack Effect Time = 0.4s + + Death Fade Time = 1s } Giant Octopus { diff --git a/x64/Release/Adventures in Lestoria.exe b/x64/Release/Adventures in Lestoria.exe index f0163b55..7aad82d8 100644 Binary files a/x64/Release/Adventures in Lestoria.exe and b/x64/Release/Adventures in Lestoria.exe differ