|
|
|
@ -56,6 +56,7 @@ void Monster::STRATEGY::OCTOPUS_ARM(Monster&m,float fElapsedTime,std::string str |
|
|
|
|
SEARCH, |
|
|
|
|
PREPARE_ATTACK, |
|
|
|
|
ATTACK_ANIMATION, |
|
|
|
|
ATTACK_RECOVERY, |
|
|
|
|
SUBMERGE, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
@ -64,6 +65,7 @@ void Monster::STRATEGY::OCTOPUS_ARM(Monster&m,float fElapsedTime,std::string str |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
if(m.ANY(A::STORED_ARC).has_value()){ |
|
|
|
|
game->DrawShadowStringDecal({100,100},std::format("Stored Arc Active: {}",std::any_cast<Arc>(m.ANY(A::STORED_ARC)).pos.str())); |
|
|
|
|
const float growthRate=((ConfigFloat("Attack Radius")/100.f*24)/ConfigFloat("Attack Effect Time"))*fElapsedTime; |
|
|
|
|
std::any_cast<Arc>(m.ANY(A::STORED_ARC)).GrowRadius(growthRate); |
|
|
|
|
m.F(A::ENVIRONMENT_TIMER)-=fElapsedTime; |
|
|
|
@ -77,6 +79,7 @@ void Monster::STRATEGY::OCTOPUS_ARM(Monster&m,float fElapsedTime,std::string str |
|
|
|
|
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.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"}; |
|
|
|
|
|
|
|
|
@ -115,12 +118,11 @@ void Monster::STRATEGY::OCTOPUS_ARM(Monster&m,float fElapsedTime,std::string str |
|
|
|
|
|
|
|
|
|
Arc attackArc{GetAttackArc(m)}; |
|
|
|
|
|
|
|
|
|
m.SetStrategyDrawFunction([&attackArc,&storedArc=m.ANY(A::STORED_ARC),&alphaTimer=m.F(A::ENVIRONMENT_TIMER),attackEffectTime=ConfigFloat("Attack Effect Time")](AiL*game,Monster&monster,const std::string&strategy){ |
|
|
|
|
m.SetStrategyDrawFunction([arc=attackArc,&storedArc=m.ANY(A::STORED_ARC),&alphaTimer=m.F(A::ENVIRONMENT_TIMER),attackEffectTime=ConfigFloat("Attack Effect Time")](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)); |
|
|
|
|
game->DrawShadowStringDecal({100,100},std::format("{} - {}",alpha,alphaTimer)); |
|
|
|
|
attackArc.Draw(game,{0,0,255,uint8_t(alpha)}); |
|
|
|
|
const_cast<Arc&>(arc).Draw(game,{0,0,255,uint8_t(alpha)}); |
|
|
|
|
if(storedArc.has_value()){ |
|
|
|
|
const uint8_t effectAlpha{util::lerp(uint8_t(0),uint8_t(255),alphaTimer/attackEffectTime)}; |
|
|
|
|
std::any_cast<Arc>(storedArc).Draw(game,{255,255,255,effectAlpha}); |
|
|
|
@ -131,27 +133,37 @@ void Monster::STRATEGY::OCTOPUS_ARM(Monster&m,float fElapsedTime,std::string str |
|
|
|
|
case PREPARE_ATTACK:{ |
|
|
|
|
m.F(A::ATTACK_COOLDOWN)-=fElapsedTime; |
|
|
|
|
if(m.F(A::ATTACK_COOLDOWN)<=0.f){ |
|
|
|
|
SETPHASE(ATTACK_ANIMATION); |
|
|
|
|
m.PerformAnimation("ATTACKING"); |
|
|
|
|
m.F(A::ENVIRONMENT_TIMER)=ConfigFloat("Attack Effect Time"); |
|
|
|
|
m.F(A::ENVIRONMENT_TIMER)=m.F(A::RECOVERY_TIME)=ConfigFloat("Attack Effect Time"); |
|
|
|
|
m.F(A::SWING_OCCURRED)=ConfigFloat("Attack Swing Damage Wait Time"); |
|
|
|
|
} |
|
|
|
|
}break; |
|
|
|
|
case ATTACK_ANIMATION:{ |
|
|
|
|
m.F(A::RECOVERY_TIME)-=fElapsedTime; |
|
|
|
|
if(m.F(A::SWING_OCCURRED)>0.f){ |
|
|
|
|
m.F(A::SWING_OCCURRED)-=fElapsedTime; |
|
|
|
|
if(m.F(A::SWING_OCCURRED)<=0.f){ |
|
|
|
|
Arc attackArc{GetAttackArc(m)}; |
|
|
|
|
if(attackArc.overlaps(game->GetPlayer()->GetPos())){ |
|
|
|
|
game->GetPlayer()->Knockback(util::pointTo(m.GetPos(),game->GetPlayer()->GetPos())*ConfigFloat("Attack Knockback")); |
|
|
|
|
game->GetPlayer()->Hurt(m.GetAttack(),m.OnUpperLevel(),m.GetZ()); |
|
|
|
|
} |
|
|
|
|
m.F(A::RECOVERY_TIME)=m.GetCurrentAnimation().GetTotalAnimationDuration(); |
|
|
|
|
m.ANY(A::STORED_ARC)=GetAttackArc(m); |
|
|
|
|
m.F(A::SWING_OCCURRED)-=fElapsedTime; |
|
|
|
|
if(m.F(A::SWING_OCCURRED)<=0.f){ |
|
|
|
|
Arc attackArc{GetAttackArc(m)}; |
|
|
|
|
if(attackArc.overlaps(game->GetPlayer()->GetPos())){ |
|
|
|
|
game->GetPlayer()->Knockback(util::pointTo(m.GetPos(),game->GetPlayer()->GetPos())*ConfigFloat("Attack Knockback")); |
|
|
|
|
game->GetPlayer()->Hurt(m.GetAttack(),m.OnUpperLevel(),m.GetZ()); |
|
|
|
|
} |
|
|
|
|
m.F(A::RECOVERY_TIME)=m.GetCurrentAnimation().GetTotalAnimationDuration(); |
|
|
|
|
m.ANY(A::STORED_ARC)=GetAttackArc(m); |
|
|
|
|
m.SetStrategyDrawFunction([&storedArc=m.ANY(A::STORED_ARC),attackEffectTime=ConfigFloat("Attack Effect Time")](AiL*game,Monster&monster,const std::string&strategy){ |
|
|
|
|
const float alphaTimer{float(std::fmod(game->GetRunTime(),2.f))}; |
|
|
|
|
if(storedArc.has_value()){ |
|
|
|
|
const uint8_t effectAlpha{util::lerp(uint8_t(0),uint8_t(255),alphaTimer/attackEffectTime)}; |
|
|
|
|
std::any_cast<Arc>(storedArc).Draw(game,{255,255,255,effectAlpha}); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
SETPHASE(ATTACK_RECOVERY); |
|
|
|
|
} |
|
|
|
|
}break; |
|
|
|
|
case ATTACK_RECOVERY:{ |
|
|
|
|
m.F(A::RECOVERY_TIME)-=fElapsedTime; |
|
|
|
|
if(m.F(A::RECOVERY_TIME)<=0.f){ |
|
|
|
|
m.PerformIdleAnimation(); |
|
|
|
|
m.SetStrategyDrawFunction([](AiL*game,Monster&monster,const std::string&strategy){}); |
|
|
|
|
SETPHASE(SEARCH); |
|
|
|
|
} |
|
|
|
|
}break; |
|
|
|
|