diff --git a/Adventures in Lestoria/AdventuresInLestoria.cpp b/Adventures in Lestoria/AdventuresInLestoria.cpp index 527a80ff..40aa8d4b 100644 --- a/Adventures in Lestoria/AdventuresInLestoria.cpp +++ b/Adventures in Lestoria/AdventuresInLestoria.cpp @@ -1266,94 +1266,214 @@ void AiL::RenderWorld(float fElapsedTime){ m.strategyDraw(this,m,MONSTER_DATA[m.GetName()].GetAIStrategy()); } + #pragma region Rendering before Tile Depth Rendering + if(tilesWithCollision.size()>0){ + const float topTileY=(*tilesWithCollision.begin())->group->GetCollisionRange().middle().y; + #pragma region Depth Ordered Rendering + { + auto it=monstersBeforeLower.begin(); + while(it!=monstersBeforeLower.end()){ + Monster&m=**it; + if(m.pos.yrendered&&!player->upperLevel&&player->GetPos().yrendered=true; + if(player->GetZ()>0){ + vf2d shadowScale=vf2d{8*player->GetSizeMult()/3.f,1}/std::max(1.f,player->GetZ()/24); + view.DrawDecal(player->GetPos()-vf2d{3,3}*shadowScale/2+vf2d{0,6*player->GetSizeMult()},GFX["circle.png"].Decal(),shadowScale,BLACK); + } + RenderPlayer(player->GetPos(),{1,1}); + } + { + auto it=monstersAfterLower.begin(); + while(it!=monstersAfterLower.end()){ + Monster&m=**it; + if(m.pos.ygroup->GetCollisionRange().middle().y){ m.Draw(); it=monstersBeforeLower.erase(it); if(it==monstersBeforeLower.end())break; - if(it!=monstersBeforeLower.begin())--it; continue; } break; } - for(auto it=bulletsLower.begin();it!=bulletsLower.end();++it){ + } + { + auto it=bulletsLower.begin(); + while(it!=bulletsLower.end()){ const Bullet&b=**it; if(b.pos.ygroup->GetCollisionRange().middle().y){ b.Draw(); it=bulletsLower.erase(it); if(it==bulletsLower.end())break; - if(it!=bulletsLower.begin())--it; continue; } break; } - for(auto it=backgroundEffectsLower.begin();it!=backgroundEffectsLower.end();++it){ + } + { + auto it=backgroundEffectsLower.begin(); + while(it!=backgroundEffectsLower.end()){ const Effect&e=**it; if(e.pos.ygroup->GetCollisionRange().middle().y){ e.Draw(); it=backgroundEffectsLower.erase(it); if(it==backgroundEffectsLower.end())break; - if(it!=backgroundEffectsLower.begin())--it; continue; } break; } - for(auto it=dropsBeforeLower.begin();it!=dropsBeforeLower.end();++it){ + } + { + auto it=dropsBeforeLower.begin(); + while(it!=dropsBeforeLower.end()){ const ItemDrop&drop=ItemDrop::drops[*it]; if(drop.pos.ygroup->GetCollisionRange().middle().y){ drop.Draw(); it=dropsBeforeLower.erase(it); if(it==dropsBeforeLower.end())break; - if(it!=dropsBeforeLower.begin())--it; continue; } break; } - if(!player->rendered&&!player->upperLevel&&player->GetPos().ygroup->GetCollisionRange().middle().y){ - player->rendered=true; - if(player->GetZ()>0){ - vf2d shadowScale=vf2d{8*player->GetSizeMult()/3.f,1}/std::max(1.f,player->GetZ()/24); - view.DrawDecal(player->GetPos()-vf2d{3,3}*shadowScale/2+vf2d{0,6*player->GetSizeMult()},GFX["circle.png"].Decal(),shadowScale,BLACK); - } - RenderPlayer(player->GetPos(),{1,1}); + } + if(!player->rendered&&!player->upperLevel&&player->GetPos().ygroup->GetCollisionRange().middle().y){ + player->rendered=true; + if(player->GetZ()>0){ + vf2d shadowScale=vf2d{8*player->GetSizeMult()/3.f,1}/std::max(1.f,player->GetZ()/24); + view.DrawDecal(player->GetPos()-vf2d{3,3}*shadowScale/2+vf2d{0,6*player->GetSizeMult()},GFX["circle.png"].Decal(),shadowScale,BLACK); } - for(auto it=monstersAfterLower.begin();it!=monstersAfterLower.end();++it){ + RenderPlayer(player->GetPos(),{1,1}); + } + { + auto it=monstersAfterLower.begin(); + while(it!=monstersAfterLower.end()){ Monster&m=**it; if(m.pos.ygroup->GetCollisionRange().middle().y){ m.Draw(); it=monstersAfterLower.erase(it); if(it==monstersAfterLower.end())break; - if(it!=monstersAfterLower.begin())--it; continue; } break; } - for(auto it=dropsAfterLower.begin();it!=dropsAfterLower.end();++it){ + } + { + auto it=dropsAfterLower.begin(); + while(it!=dropsAfterLower.end()){ const ItemDrop&drop=ItemDrop::drops[*it]; if(drop.pos.ygroup->GetCollisionRange().middle().y){ drop.Draw(); it=dropsAfterLower.erase(it); if(it==dropsAfterLower.end())break; - if(it!=dropsAfterLower.begin())--it; continue; } break; } - for(auto it=foregroundEffectsLower.begin();it!=foregroundEffectsLower.end();++it){ + } + { + auto it=foregroundEffectsLower.begin(); + while(it!=foregroundEffectsLower.end()){ const Effect&e=**it; if(e.pos.ygroup->GetCollisionRange().middle().y){ e.Draw(); it=foregroundEffectsLower.erase(it); if(it==foregroundEffectsLower.end())break; - if(it!=foregroundEffectsLower.begin())--it; continue; } break; } + } #pragma endregion RenderTile(*tile,{255,255,255,uint8_t(255-tile->tileOpacity/TileGroup::FADE_TIME*TileGroup::FADE_AMT)}); float distToPlayer=geom2d::line(player->GetPos(),tile->pos+vf2d{12,12}).length(); @@ -1521,95 +1641,216 @@ void AiL::RenderWorld(float fElapsedTime){ Monster&m=**it; m.strategyDraw(this,m,MONSTER_DATA[m.GetName()].GetAIStrategy()); } - + + #pragma region Rendering before Tile Depth Rendering + if(tilesWithCollision.size()>0){ + const float topTileY=(*tilesWithCollision.begin())->group->GetCollisionRange().middle().y; + #pragma region Depth Ordered Rendering + { + auto it=monstersBeforeUpper.begin(); + while(it!=monstersBeforeUpper.end()){ + Monster&m=**it; + if(m.pos.yrendered&&!player->upperLevel&&player->GetPos().yrendered=true; + if(player->GetZ()>0){ + vf2d shadowScale=vf2d{8*player->GetSizeMult()/3.f,1}/std::max(1.f,player->GetZ()/24); + view.DrawDecal(player->GetPos()-vf2d{3,3}*shadowScale/2+vf2d{0,6*player->GetSizeMult()},GFX["circle.png"].Decal(),shadowScale,BLACK); + } + RenderPlayer(player->GetPos(),{1,1}); + } + { + auto it=monstersAfterUpper.begin(); + while(it!=monstersAfterUpper.end()){ + Monster&m=**it; + if(m.pos.ygroup->GetCollisionRange().middle().y){ m.Draw(); it=monstersBeforeUpper.erase(it); if(it==monstersBeforeUpper.end())break; - if(it!=monstersBeforeUpper.begin())--it; continue; } break; } - for(auto it=bulletsUpper.begin();it!=bulletsUpper.end();++it){ + } + { + auto it=bulletsUpper.begin(); + while(it!=bulletsUpper.end()){ const Bullet&b=**it; if(b.pos.ygroup->GetCollisionRange().middle().y){ b.Draw(); it=bulletsUpper.erase(it); if(it==bulletsUpper.end())break; - if(it!=bulletsUpper.begin())--it; continue; } break; } - for(auto it=backgroundEffectsUpper.begin();it!=backgroundEffectsUpper.end();++it){ + } + { + auto it=backgroundEffectsUpper.begin(); + while(it!=backgroundEffectsUpper.end()){ const Effect&e=**it; if(e.pos.ygroup->GetCollisionRange().middle().y){ e.Draw(); it=backgroundEffectsUpper.erase(it); if(it==backgroundEffectsUpper.end())break; - if(it!=backgroundEffectsUpper.begin())--it; continue; } break; } - for(auto it=dropsBeforeUpper.begin();it!=dropsBeforeUpper.end();++it){ + } + { + auto it=dropsBeforeUpper.begin(); + while(it!=dropsBeforeUpper.end()){ const ItemDrop&drop=ItemDrop::drops[*it]; if(drop.pos.ygroup->GetCollisionRange().middle().y){ drop.Draw(); it=dropsBeforeUpper.erase(it); if(it==dropsBeforeUpper.end())break; - if(it!=dropsBeforeUpper.begin())--it; continue; } break; } - if(!player->rendered&&player->upperLevel&&player->GetPos().ygroup->GetCollisionRange().middle().y){ - player->rendered=true; - if(player->GetZ()>0){ - vf2d shadowScale=vf2d{8*player->GetSizeMult()/3.f,1}/std::max(1.f,player->GetZ()/24); - view.DrawDecal(player->GetPos()-vf2d{3,3}*shadowScale/2+vf2d{0,6*player->GetSizeMult()},GFX["circle.png"].Decal(),shadowScale,BLACK); - } - RenderPlayer(player->GetPos(),{1,1}); + } + if(!player->rendered&&player->upperLevel&&player->GetPos().ygroup->GetCollisionRange().middle().y){ + player->rendered=true; + if(player->GetZ()>0){ + vf2d shadowScale=vf2d{8*player->GetSizeMult()/3.f,1}/std::max(1.f,player->GetZ()/24); + view.DrawDecal(player->GetPos()-vf2d{3,3}*shadowScale/2+vf2d{0,6*player->GetSizeMult()},GFX["circle.png"].Decal(),shadowScale,BLACK); } - for(auto it=monstersAfterUpper.begin();it!=monstersAfterUpper.end();++it){ + RenderPlayer(player->GetPos(),{1,1}); + } + { + auto it=monstersAfterUpper.begin(); + while(it!=monstersAfterUpper.end()){ Monster&m=**it; if(m.pos.ygroup->GetCollisionRange().middle().y){ m.Draw(); it=monstersAfterUpper.erase(it); if(it==monstersAfterUpper.end())break; - if(it!=monstersAfterUpper.begin())--it; continue; } break; } - for(auto it=dropsAfterUpper.begin();it!=dropsAfterUpper.end();++it){ + } + { + auto it=dropsAfterUpper.begin(); + while(it!=dropsAfterUpper.end()){ const ItemDrop&drop=ItemDrop::drops[*it]; if(drop.pos.ygroup->GetCollisionRange().middle().y){ drop.Draw(); it=dropsAfterUpper.erase(it); if(it==dropsAfterUpper.end())break; - if(it!=dropsAfterUpper.begin())--it; continue; } break; } - for(auto it=foregroundEffectsUpper.begin();it!=foregroundEffectsUpper.end();++it){ + } + { + auto it=foregroundEffectsUpper.begin(); + while(it!=foregroundEffectsUpper.end()){ const Effect&e=**it; if(e.pos.ygroup->GetCollisionRange().middle().y){ e.Draw(); it=foregroundEffectsUpper.erase(it); if(it==foregroundEffectsUpper.end())break; - if(it!=foregroundEffectsUpper.begin())--it; continue; } break; } + } #pragma endregion RenderTile(*tile,{255,255,255,uint8_t(255-tile->tileOpacity/TileGroup::FADE_TIME*TileGroup::FADE_AMT)}); float distToPlayer=geom2d::line(player->GetPos(),tile->pos+vf2d{12,12}).length(); @@ -2451,7 +2692,7 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){ for(NPCData data:game->MAP_DATA[game->GetCurrentLevel()].npcs){ if(Unlock::IsUnlocked(data.unlockCondition)){ MONSTER_LIST.push_back(std::make_unique(data.spawnPos,MONSTER_DATA[data.name])); - MONSTER_LIST.back()->iframe_timer=INFINITE; + MONSTER_LIST.back()->SetIframes(INFINITE); MONSTER_LIST.back()->npcData=data; } } diff --git a/Adventures in Lestoria/LevitatingRock.cpp b/Adventures in Lestoria/LevitatingRock.cpp index 850ab006..89111daf 100644 --- a/Adventures in Lestoria/LevitatingRock.cpp +++ b/Adventures in Lestoria/LevitatingRock.cpp @@ -91,6 +91,7 @@ bool LevitatingRock::PlayerHit(Player*player){ deactivated=true; fadeOutTime=0.5f; + player->Knockback(vel/3.f); return true; } bool LevitatingRock::MonsterHit(Monster&monster){ @@ -98,6 +99,8 @@ bool LevitatingRock::MonsterHit(Monster&monster){ deactivated=true; fadeOutTime=0.5f; + monster.Knockback(vel/3.f); + return true; } void LevitatingRock::Draw()const{ diff --git a/Adventures in Lestoria/Monster.cpp b/Adventures in Lestoria/Monster.cpp index 7f1a11fc..e15a66de 100644 --- a/Adventures in Lestoria/Monster.cpp +++ b/Adventures in Lestoria/Monster.cpp @@ -408,6 +408,7 @@ void Monster::UpdateFacingDirection(vf2d facingTargetPoint){ } } void Monster::Draw()const{ + if(markedForDeletion)return; Pixel blendCol=GetBuffs(BuffType::SLOWDOWN).size()>0?Pixel{uint8_t(255*abs(sin(1.4*GetBuffs(BuffType::SLOWDOWN)[0].duration))),uint8_t(255*abs(sin(1.4*GetBuffs(BuffType::SLOWDOWN)[0].duration))),uint8_t(128+127*abs(sin(1.4*GetBuffs(BuffType::SLOWDOWN)[0].duration)))}:WHITE; if(GetZ()>0){ @@ -632,7 +633,7 @@ bool Monster::Hurt(int damage,bool onUpperLevel,float z){ game->BossDamageDealt(int(mod_dmg)); } GetInt(Attribute::HITS_UNTIL_DEATH)=std::max(0,GetInt(Attribute::HITS_UNTIL_DEATH)-1); - iframe_timer=GetFloat(Attribute::IFRAME_TIME_UPON_HIT); + SetIframes(GetFloat(Attribute::IFRAME_TIME_UPON_HIT)); return true; } @@ -950,6 +951,10 @@ const Animate2D::FrameSequence&Monster::GetCurrentAnimation()const{ return ANIMATION_DATA[std::format("{}_{}",name,animation.currentStateName)]; } +const Animate2D::FrameSequence&Monster::GetAnimation(const std::string_view animationName)const{ + return ANIMATION_DATA[std::format("{}_{}_{}",name,animationName,int(GetFacingDirection()))]; +} + const bool Monster::HasLineOfSight(vf2d targetPos)const{ geom2d::linelosLine=geom2d::line(GetPos(),targetPos); float losLineLength=losLine.length(); @@ -1002,7 +1007,7 @@ DeathSpawnInfo::DeathSpawnInfo(const std::string_view monsterName,const uint8_t void DeathSpawnInfo::Spawn(const vf2d monsterDeathPos,const bool onUpperLevel){ for(uint8_t i=0;iSpawnMonster(monsterDeathPos+spawnLocOffset,MONSTER_DATA.at(monsterSpawnName),onUpperLevel).iframe_timer=0.25f; + game->SpawnMonster(monsterDeathPos+spawnLocOffset,MONSTER_DATA.at(monsterSpawnName),onUpperLevel).SetIframes(0.25f); } } @@ -1047,4 +1052,8 @@ void Monster::MarkForDeletion(){ const bool Monster::IsDead()const{ return !IsAlive(); +} + +void Monster::SetIframes(const float iframeTime){ + iframe_timer=iframeTime; } \ No newline at end of file diff --git a/Adventures in Lestoria/Monster.h b/Adventures in Lestoria/Monster.h index e995c6ac..462cbaab 100644 --- a/Adventures in Lestoria/Monster.h +++ b/Adventures in Lestoria/Monster.h @@ -120,6 +120,7 @@ public: void PerformAnimation(const std::string_view animationName); void PerformAnimation(const std::string_view animationName,const Direction facingDir); const Animate2D::FrameSequence&GetCurrentAnimation()const; + const Animate2D::FrameSequence&GetAnimation(const std::string_view animationName)const; const bool OnUpperLevel()const; void Moved(); //Returns false if a path could not be found. @@ -133,6 +134,7 @@ public: void SetState(State::State newState); static void InitializeStrategies(); const bool HasIframes()const; + void SetIframes(const float iframeTime); const float GetZ()const; void SetZ(float z); const std::function&GetStrategy()const; diff --git a/Adventures in Lestoria/Player.cpp b/Adventures in Lestoria/Player.cpp index 9b248039..c4afc045 100644 --- a/Adventures in Lestoria/Player.cpp +++ b/Adventures in Lestoria/Player.cpp @@ -1487,7 +1487,7 @@ const vf2d Player::GetAimingLocation(bool useWalkDir,bool invert){ //Find the closest monster target. vf2d closestPoint={std::numeric_limits::max(),std::numeric_limits::max()}; for(std::unique_ptr&m:MONSTER_LIST){ - if(m->IsAlive()){ + if(m->IsAlive()&&!m->Invulnerable()){ geom2d::lineaimingLine=geom2d::line(GetPos(),m->GetPos()); float distToMonster=aimingLine.length(); float distToClosestPoint=geom2d::line(GetPos(),closestPoint).length(); diff --git a/Adventures in Lestoria/SlimeKing.cpp b/Adventures in Lestoria/SlimeKing.cpp index 2957aa76..34fea963 100644 --- a/Adventures in Lestoria/SlimeKing.cpp +++ b/Adventures in Lestoria/SlimeKing.cpp @@ -248,7 +248,7 @@ void Monster::STRATEGY::SLIMEKING(Monster&m,float fElapsedTime,std::string strat m.size=ConfigInt("Phase1.Size")/100.f; m.diesNormally=false; m.F(A::IFRAME_TIME_UPON_HIT)=0; - m.iframe_timer=ConfigFloat("Phase5.IframeTimePerHit"); + m.SetIframes(ConfigFloat("Phase5.IframeTimePerHit")); m.phase=ConfigInt("StartPhase"); }break; case 1:{ diff --git a/Adventures in Lestoria/Stone_Elemental.cpp b/Adventures in Lestoria/Stone_Elemental.cpp index f0e10877..115f65d9 100644 --- a/Adventures in Lestoria/Stone_Elemental.cpp +++ b/Adventures in Lestoria/Stone_Elemental.cpp @@ -65,18 +65,25 @@ void Monster::STRATEGY::STONE_ELEMENTAL(Monster&m,float fElapsedTime,std::string STONE_PILLAR_CAST, SHOOT_STONE_CAST, DIVE_UNDERGROUND_DIG, + DIVE_UNDERGROUND_MOVE, DIVE_UNDERGROUND_SURFACE, }; + auto ReturnToWaitingPhase=[&](){ + m.phase=WAITING; + m.PerformIdleAnimation(); + m.F(A::ATTACK_COOLDOWN)=0.f; + }; + switch(m.phase){ case WAITING:{ m.F(A::ATTACK_COOLDOWN)+=fElapsedTime; if(m.F(A::ATTACK_COOLDOWN)>=ConfigFloat("Attack Wait Time")){ - int randomAttackChoice=util::random()%2; + int randomAttackChoice=util::random()%3; float distToPlayer=util::distance(m.GetPos(),game->GetPlayer()->GetPos()); - //if(distToPlayer>=ConfigPixels("Auto Dive Range"))randomAttackChoice=2; //Force dig attack if too far away. + if(distToPlayer>=ConfigPixels("Auto Dive Range"))randomAttackChoice=2; //Force dig attack if too far away. switch(randomAttackChoice){ case 0:{ @@ -84,7 +91,7 @@ void Monster::STRATEGY::STONE_ELEMENTAL(Monster&m,float fElapsedTime,std::string m.phase=STONE_PILLAR_CAST; m.F(A::CASTING_TIMER)=ConfigFloat("Stone Pillar Cast Time"); m.V(A::LOCKON_POS)=game->GetPlayer()->GetPos(); - game->AddEffect(std::make_unique(m.V(A::LOCKON_POS),ConfigFloat("Stone Pillar Cast Time"),"range_indicator.png",m.OnUpperLevel(),vf2d{1.f,1.f}*(MONSTER_DATA.at("Stone Pillar").GetCollisionRadius()/12.f),0.3f,vf2d{},ConfigPixel("Stone Pillar Spell Circle Color"),util::random(2*PI),util::degToRad(ConfigFloat("Stone Pillar Spell Circle Rotation Spd"))),true); + game->AddEffect(std::make_unique(m.V(A::LOCKON_POS),ConfigFloat("Stone Pillar Cast Time"),"range_indicator.png",m.OnUpperLevel(),vf2d{1.f,1.f}*(MONSTER_DATA.at("Stone Pillar").GetCollisionRadius()/12.f)*1.1f,0.3f,vf2d{},ConfigPixel("Stone Pillar Spell Circle Color"),util::random(2*PI),util::degToRad(ConfigFloat("Stone Pillar Spell Circle Rotation Spd"))),true); game->AddEffect(std::make_unique(m.V(A::LOCKON_POS),ConfigFloat("Stone Pillar Cast Time"),"spell_insignia.png",m.OnUpperLevel(),vf2d{1.f,1.f}*(MONSTER_DATA.at("Stone Pillar").GetCollisionRadius()/12.f)*0.75f,0.3f,vf2d{},ConfigPixel("Stone Pillar Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Stone Pillar Spell Insignia Rotation Spd"))),true); }break; case 1:{ @@ -104,9 +111,9 @@ void Monster::STRATEGY::STONE_ELEMENTAL(Monster&m,float fElapsedTime,std::string } }break; case 2:{ - m.PerformAnimation("BURROW UNDEGROUND"); + m.PerformAnimation("BURROW UNDERGROUND"); m.phase=DIVE_UNDERGROUND_DIG; - m.F(A::CASTING_TIMER)=ConfigFloat("Burrow Wait Time"); + m.F(A::CASTING_TIMER)=m.GetCurrentAnimation().GetTotalAnimationDuration(); }break; } } @@ -114,10 +121,8 @@ void Monster::STRATEGY::STONE_ELEMENTAL(Monster&m,float fElapsedTime,std::string case STONE_PILLAR_CAST:{ m.F(A::CASTING_TIMER)-=fElapsedTime; if(m.F(A::CASTING_TIMER)<=0.f){ - m.phase=WAITING; game->SpawnMonster(m.V(A::LOCKON_POS),MONSTER_DATA.at("Stone Pillar"),m.OnUpperLevel()); - m.PerformIdleAnimation(); - m.F(A::ATTACK_COOLDOWN)=0.f; + ReturnToWaitingPhase(); game->Hurt(m.V(A::LOCKON_POS),MONSTER_DATA.at("Stone Pillar").GetCollisionRadius(),m.GetAttack(),m.OnUpperLevel(),0.f,HurtType::PLAYER); } if(geom2d::overlaps(geom2d::circle{m.V(A::LOCKON_POS),MONSTER_DATA.at("Stone Pillar").GetCollisionRadius()},geom2d::circle{m.GetPos(),m.GetCollisionRadius()})){ @@ -125,25 +130,66 @@ void Monster::STRATEGY::STONE_ELEMENTAL(Monster&m,float fElapsedTime,std::string const vf2d targetWalkPos=stonePillarCastLine.rpoint(stonePillarCastLine.length()+48.f); m.target=targetWalkPos; RUN_TOWARDS(m,fElapsedTime,"Run Towards"); - m.PerformAnimation("ROCK TOSS CAST"); + m.PerformAnimation("STONE PILLAR CAST"); + m.UpdateFacingDirection(game->GetPlayer()->GetPos()); } }break; case SHOOT_STONE_CAST:{ m.F(A::CASTING_TIMER)-=fElapsedTime; + if(m.F(A::CASTING_TIMER)>=ConfigFloat("Rock Toss Wait Time")-ConfigFloat("Rock Toss Track Time"))m.UpdateFacingDirection(game->GetPlayer()->GetPos()); if(m.F(A::CASTING_TIMER)<=0.f){ - m.phase=WAITING; - m.PerformIdleAnimation(); - m.F(A::ATTACK_COOLDOWN)=0.f; + ReturnToWaitingPhase(); } }break; case DIVE_UNDERGROUND_DIG:{ m.F(A::CASTING_TIMER)-=fElapsedTime; if(m.F(A::CASTING_TIMER)<=0.f){ + m.phase=DIVE_UNDERGROUND_MOVE; + float randomAngle=util::random(2*PI); + + const float minDist=ConfigPixelsArr("Burrow Teleport Distance",0); + const float maxDist=ConfigPixelsArr("Burrow Teleport Distance",1); + const float distRange=maxDist-minDist; + + float randomDist=util::random(distRange)+minDist; + + m.V(A::LOCKON_POS)=game->GetPlayer()->GetPos()+vf2d{randomDist,randomAngle}.cart(); + m.target=m.V(A::LOCKON_POS); + m.targetAcquireTimer=INFINITY; + m.SetState(State::MOVE_TOWARDS); + + const float baseMoveSpd=100.f*m.GetMoveSpdMult(); + const float distToTarget=geom2d::line(m.GetPos(),m.V(A::LOCKON_POS)).length(); + const float targetMoveSpdRatio=std::max(0.f,distToTarget/baseMoveSpd/ConfigFloat("Burrow Wait Time")-1); + m.AddBuff(BuffType::SPEEDBOOST,ConfigFloat("Burrow Wait Time"),targetMoveSpdRatio); + m.F(A::CASTING_TIMER)=ConfigFloat("Burrow Wait Time"); + m.B(A::IGNORE_DEFAULT_ANIMATIONS)=true; + m.SetIframes(ConfigFloat("Burrow Wait Time")+m.GetAnimation("RISE FROM UNDERGROUND").GetTotalAnimationDuration()); + } + }break; + case DIVE_UNDERGROUND_MOVE:{ + m.F(A::CASTING_TIMER)-=fElapsedTime; + RUN_TOWARDS(m,fElapsedTime,"Run Towards"); + + if(m.F(A::CASTING_TIMER)<=0.f){ + m.B(A::IGNORE_DEFAULT_ANIMATIONS)=false; + m.PerformAnimation("RISE FROM UNDERGROUND"); m.phase=DIVE_UNDERGROUND_SURFACE; + m.targetAcquireTimer=0; + m.F(A::CASTING_TIMER)=m.GetCurrentAnimation().GetTotalAnimationDuration(); + + const float bulletAngRandomOffset{util::random(PI/2)}; + for(int i=0;i - + @@ -1882,52 +1882,17 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + diff --git a/Adventures in Lestoria/assets/maps/Monsters/Stone Pillar.tx b/Adventures in Lestoria/assets/maps/Monsters/Stone Pillar.tx new file mode 100644 index 00000000..f1931f3a --- /dev/null +++ b/Adventures in Lestoria/assets/maps/Monsters/Stone Pillar.tx @@ -0,0 +1,9 @@ + + diff --git a/x64/Release/Adventures in Lestoria.exe b/x64/Release/Adventures in Lestoria.exe index 1ea7678a..15d2290f 100644 Binary files a/x64/Release/Adventures in Lestoria.exe and b/x64/Release/Adventures in Lestoria.exe differ