Phase 4 implemented.
This commit is contained in:
parent
76d45f2563
commit
de04905983
@ -308,6 +308,7 @@
|
||||
<ClCompile Include="LightningBoltEmitter.cpp" />
|
||||
<ClCompile Include="Map.cpp" />
|
||||
<ClCompile Include="Meteor.cpp" />
|
||||
<ClCompile Include="RunAway.cpp" />
|
||||
<ClCompile Include="RunTowards.cpp" />
|
||||
<ClCompile Include="Pathfinding.cpp" />
|
||||
<ClCompile Include="pixelGameEngine.cpp" />
|
||||
|
@ -242,6 +242,9 @@
|
||||
<ClCompile Include="FallingDebris.h">
|
||||
<Filter>Source Files\Effects</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="RunAway.cpp">
|
||||
<Filter>Source Files\Monster Strategies</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="cpp.hint" />
|
||||
|
@ -83,7 +83,7 @@ bool Monster::SetX(float x){
|
||||
} else {
|
||||
geom2d::rect<float>collision={collisionRect.pos,collisionRect.size};
|
||||
collision.pos+=tilePos;
|
||||
if(!geom2d::overlaps(newPos,collision)){
|
||||
if(!geom2d::overlaps(geom2d::circle<float>(newPos,12*GetSizeMult()),collision)){
|
||||
pos.x=std::clamp(x,12.f*GetSizeMult(),float(game->WORLD_SIZE.x*24-12*GetSizeMult()));
|
||||
Moved();
|
||||
return true;
|
||||
@ -102,7 +102,7 @@ bool Monster::SetY(float y){
|
||||
} else {
|
||||
geom2d::rect<float>collision={collisionRect.pos,collisionRect.size};
|
||||
collision.pos+=tilePos;
|
||||
if(!geom2d::overlaps(newPos,collision)){
|
||||
if(!geom2d::overlaps(geom2d::circle<float>(newPos,12*GetSizeMult()),collision)){
|
||||
pos.y=std::clamp(y,12.f*GetSizeMult(),float(game->WORLD_SIZE.y*24-12*GetSizeMult()));
|
||||
Moved();
|
||||
return true;
|
||||
|
@ -156,6 +156,7 @@ private:
|
||||
static void SHOOT_AFAR(Monster&m,float fElapsedTime,int strategyNumber);
|
||||
static void TURRET(Monster&m,float fElapsedTime,int strategyNumber);
|
||||
static void SLIMEKING(Monster&m,float fElapsedTime,int strategyNumber);
|
||||
static void RUN_AWAY(Monster&m,float fElapsedTime,int strategyNumber);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -26,4 +26,6 @@ enum class Attribute{
|
||||
JUMP_COUNT,
|
||||
CASTING_TIMER,
|
||||
TELEPORT_TO_PLAYER,
|
||||
RUN_AWAY_TIMER,
|
||||
PHASE_REPEAT_COUNT,
|
||||
};
|
@ -40,5 +40,8 @@ void Monster::STRATEGY::RUN_STRATEGY(Monster&m,float fElapsedTime){
|
||||
case 3:{//Slime King
|
||||
Monster::STRATEGY::SLIMEKING(m,fElapsedTime,m.strategy);
|
||||
}break;
|
||||
case 4:{//Run Away Strategy
|
||||
Monster::STRATEGY::RUN_AWAY(m,fElapsedTime,m.strategy);
|
||||
}break;
|
||||
}
|
||||
}
|
80
Crawler/RunAway.cpp
Normal file
80
Crawler/RunAway.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
#include "Monster.h"
|
||||
#include "DEFINES.h"
|
||||
#include "Crawler.h"
|
||||
#include "MonsterStrategyHelpers.h"
|
||||
|
||||
INCLUDE_BULLET_LIST
|
||||
INCLUDE_game
|
||||
|
||||
void Monster::STRATEGY::RUN_AWAY(Monster&m,float fElapsedTime,int strategyNumber){
|
||||
m.targetAcquireTimer=std::max(0.f,m.targetAcquireTimer-fElapsedTime);
|
||||
m.attackCooldownTimer=std::max(0.f,m.attackCooldownTimer-fElapsedTime);
|
||||
geom2d::line line(m.pos,game->GetPlayer()->GetPos());
|
||||
if(m.targetAcquireTimer==0&&m.queueShotTimer==0){
|
||||
m.targetAcquireTimer=1;
|
||||
if(line.length()<24.f*ConfigInt("Range")/100.f){
|
||||
m.target=line.upoint(-1.2);
|
||||
if(m.canMove){
|
||||
m.SetState(State::MOVE_AWAY);
|
||||
} else {
|
||||
m.SetState(State::NORMAL);
|
||||
}
|
||||
} else
|
||||
if(line.length()>24.f*ConfigInt("CloseInRange")/100.0f){
|
||||
m.target=line.upoint(1.2);
|
||||
m.SetState(State::MOVE_TOWARDS);
|
||||
} else {
|
||||
m.SetState(State::NORMAL);
|
||||
}
|
||||
}
|
||||
m.canMove=true;
|
||||
geom2d::line moveTowardsLine=geom2d::line(m.pos,m.target);
|
||||
bool pathfindingDecision=false;
|
||||
switch(m.state){
|
||||
case State::MOVE_TOWARDS:{
|
||||
if(moveTowardsLine.length()>1){
|
||||
vf2d newPos=m.pos+moveTowardsLine.vector().norm()*100*fElapsedTime*m.GetMoveSpdMult();
|
||||
bool movedX=m.SetX(newPos.x);
|
||||
bool movedY=m.SetY(newPos.y);
|
||||
pathfindingDecision=movedX|movedY;
|
||||
m.canMove=movedX&&movedY;
|
||||
}
|
||||
if(!pathfindingDecision){
|
||||
m.StartPathfinding(2.5);
|
||||
}else
|
||||
if(line.length()<=24.f*ConfigInt("CloseInRange")/100.0f){
|
||||
m.SetState(State::NORMAL);
|
||||
}
|
||||
if(moveTowardsLine.vector().x>0){
|
||||
m.facingDirection=RIGHT;
|
||||
} else {
|
||||
m.facingDirection=LEFT;
|
||||
}
|
||||
m.PerformJumpAnimation();
|
||||
}break;
|
||||
case State::MOVE_AWAY:{
|
||||
if(moveTowardsLine.length()>1){
|
||||
vf2d newPos=m.pos+moveTowardsLine.vector().norm()*100*fElapsedTime*m.GetMoveSpdMult();
|
||||
bool movedX=m.SetX(newPos.x);
|
||||
bool movedY=m.SetY(newPos.y);
|
||||
pathfindingDecision=movedX|movedY;
|
||||
m.canMove=movedX&&movedY;
|
||||
}
|
||||
if(!pathfindingDecision){
|
||||
m.StartPathfinding(2.5);
|
||||
}else
|
||||
if(line.length()>=24.f*ConfigInt("Range")/100.f){
|
||||
m.SetState(State::NORMAL);
|
||||
}
|
||||
if(moveTowardsLine.vector().x>0){
|
||||
m.facingDirection=RIGHT;
|
||||
} else {
|
||||
m.facingDirection=LEFT;
|
||||
}
|
||||
m.PerformJumpAnimation();
|
||||
}break;
|
||||
case State::PATH_AROUND:{
|
||||
m.PathAroundBehavior(fElapsedTime);
|
||||
}break;
|
||||
}
|
||||
}
|
@ -24,6 +24,7 @@ void Monster::STRATEGY::SLIMEKING(Monster&m,float fElapsedTime,int strategyNumbe
|
||||
m.F(A::SHOOT_RING_DELAY)=std::max(0.f,m.F(A::SHOOT_RING_DELAY)-fElapsedTime);
|
||||
m.F(A::JUMP_LANDING_TIMER)=std::max(0.f,m.F(A::JUMP_LANDING_TIMER)-fElapsedTime);
|
||||
m.F(A::CASTING_TIMER)=std::max(0.f,m.F(A::CASTING_TIMER)-fElapsedTime);
|
||||
m.F(A::RUN_AWAY_TIMER)=std::max(0.f,m.F(A::RUN_AWAY_TIMER)-fElapsedTime);
|
||||
|
||||
const auto ShootBulletRing=[&](float angleOffset){
|
||||
int bulletCount=ConfigInt("Phase1.RingBulletCount");
|
||||
@ -42,6 +43,7 @@ void Monster::STRATEGY::SLIMEKING(Monster&m,float fElapsedTime,int strategyNumbe
|
||||
const auto TransitionPhase=[&](int newPhase){
|
||||
const int MAX_ATTEMPTS=100; //Maximum number of tries to find a valid location.
|
||||
Player*player=game->GetPlayer();
|
||||
m.I(A::PATTERN_REPEAT_COUNT)=0;
|
||||
const auto PositionInRangeOfPlayer=[&player](vf2d&pos,float radius){
|
||||
return geom2d::line<float>(player->GetPos(),pos).length()<=player->GetSizeMult()*12*2+radius;
|
||||
};
|
||||
@ -105,6 +107,12 @@ void Monster::STRATEGY::SLIMEKING(Monster&m,float fElapsedTime,int strategyNumbe
|
||||
}
|
||||
};
|
||||
|
||||
if(m.F(A::RUN_AWAY_TIMER)>0){
|
||||
Monster::STRATEGY::RUN_AWAY(m,fElapsedTime,4);
|
||||
/*HACK ALERT!! This is kind of a hack. If the Run Away script changes the 4 would be inaccurate, but the run away script doesn't use this value so it's probably fine.*/
|
||||
return;
|
||||
}
|
||||
|
||||
if(m.GetState()==State::RECOVERY){
|
||||
m.F(A::RECOVERY_TIME)=std::max(0.f,m.F(A::RECOVERY_TIME)-fElapsedTime);
|
||||
if(m.F(A::RECOVERY_TIME)==0){
|
||||
@ -116,17 +124,17 @@ void Monster::STRATEGY::SLIMEKING(Monster&m,float fElapsedTime,int strategyNumbe
|
||||
|
||||
if(m.GetState()==State::JUMP){
|
||||
float jumpLandingTimerRatio=m.F(A::JUMP_LANDING_TIMER)/m.F(A::JUMP_ORIGINAL_LANDING_TIMER);
|
||||
if(m.GetPos().x>game->GetPlayer()->GetPos().x){
|
||||
m.SetX(std::max(game->GetPlayer()->GetPos().x,m.GetPos().x-m.F(A::JUMP_MOVE_SPD)*game->GetElapsedTime()));
|
||||
if(m.GetPos().x>m.V(A::JUMP_TARGET_POS).x){
|
||||
m.SetX(std::max(m.V(A::JUMP_TARGET_POS).x,m.GetPos().x-m.F(A::JUMP_MOVE_SPD)*game->GetElapsedTime()));
|
||||
} else
|
||||
if(m.GetPos().x<game->GetPlayer()->GetPos().x){
|
||||
m.SetX(std::min(game->GetPlayer()->GetPos().x,m.GetPos().x+m.F(A::JUMP_MOVE_SPD)*game->GetElapsedTime()));
|
||||
if(m.GetPos().x<m.V(A::JUMP_TARGET_POS).x){
|
||||
m.SetX(std::min(m.V(A::JUMP_TARGET_POS).x,m.GetPos().x+m.F(A::JUMP_MOVE_SPD)*game->GetElapsedTime()));
|
||||
}
|
||||
if(m.GetPos().y>game->GetPlayer()->GetPos().y){
|
||||
m.SetY(std::max(game->GetPlayer()->GetPos().y,m.GetPos().y-m.F(A::JUMP_MOVE_SPD)*game->GetElapsedTime()));
|
||||
if(m.GetPos().y>m.V(A::JUMP_TARGET_POS).y){
|
||||
m.SetY(std::max(m.V(A::JUMP_TARGET_POS).y,m.GetPos().y-m.F(A::JUMP_MOVE_SPD)*game->GetElapsedTime()));
|
||||
} else
|
||||
if(m.GetPos().y<game->GetPlayer()->GetPos().y){
|
||||
m.SetY(std::min(game->GetPlayer()->GetPos().y,m.GetPos().y+m.F(A::JUMP_MOVE_SPD)*game->GetElapsedTime()));
|
||||
if(m.GetPos().y<m.V(A::JUMP_TARGET_POS).y){
|
||||
m.SetY(std::min(m.V(A::JUMP_TARGET_POS).y,m.GetPos().y+m.F(A::JUMP_MOVE_SPD)*game->GetElapsedTime()));
|
||||
}
|
||||
if(m.F(A::JUMP_LANDING_TIMER)>=m.F(A::JUMP_ORIGINAL_LANDING_TIMER)/2){
|
||||
m.SetZ(util::lerp(0,ConfigInt("JumpHeight"),1-jumpLandingTimerRatio));
|
||||
@ -250,6 +258,7 @@ void Monster::STRATEGY::SLIMEKING(Monster&m,float fElapsedTime,int strategyNumbe
|
||||
if(m.hp<=m.maxhp*ConfigFloat("Phase4.Change")/100){
|
||||
m.phase=4;
|
||||
m.SetSize(ConfigFloat("Phase4.Size")/100,false);
|
||||
m.AddBuff(BuffType::SLOWDOWN,9999999,ConfigFloat("Phase4.MoveSpdModifier")/100);
|
||||
TransitionPhase(m.phase);
|
||||
return;
|
||||
}
|
||||
@ -280,6 +289,31 @@ void Monster::STRATEGY::SLIMEKING(Monster&m,float fElapsedTime,int strategyNumbe
|
||||
TransitionPhase(m.phase);
|
||||
return;
|
||||
}
|
||||
if(m.I(A::PHASE_REPEAT_COUNT)>=5){
|
||||
m.I(A::PHASE_REPEAT_COUNT)=0;
|
||||
float jumpAngle=util::angleTo(m.GetPos(),game->GetWorldSize()*24/2); //We jump towards the center to keep the player from constantly dealing with a stuck boss.
|
||||
float jumpDistance=ConfigFloat("Phase4.JumpDistance")/100*24;
|
||||
float jumpSpd=jumpDistance/ConfigFloat("Phase4.JumpDuration");
|
||||
StartJump(ConfigFloat("Phase4.JumpDuration"),m.GetPos()+vf2d{cos(jumpAngle)*jumpDistance,sin(jumpAngle)*jumpDistance},0,jumpSpd);
|
||||
}else
|
||||
if(m.I(A::PATTERN_REPEAT_COUNT)<5&&m.F(A::SHOOT_TIMER)==0){
|
||||
m.I(A::PATTERN_REPEAT_COUNT)++;
|
||||
m.F(A::SHOOT_TIMER)=ConfigFloat("Phase4.ShootRate");
|
||||
float bulletAngle=util::angleTo(m.GetPos(),game->GetPlayer()->GetPos());
|
||||
float spreadAngle=util::degToRad(ConfigFloat("Phase4.RandomOffsetAngle"));
|
||||
bulletAngle+=util::random(spreadAngle*2)-spreadAngle;
|
||||
BULLET_LIST.emplace_back(std::make_unique<Bullet>(m.GetPos(),vf2d{cos(bulletAngle),sin(bulletAngle)}*bulletSpd,6,ConfigInt("ProjectileDamage"),m.OnUpperLevel(),false,YELLOW,vf2d{6,6}));
|
||||
}else
|
||||
if(m.I(A::PATTERN_REPEAT_COUNT)==5){
|
||||
m.I(A::PATTERN_REPEAT_COUNT)++;
|
||||
m.F(A::RUN_AWAY_TIMER)=ConfigFloat("Phase4.RunAwayTime");
|
||||
}else
|
||||
if(m.I(A::PATTERN_REPEAT_COUNT)==6&&m.F(A::RUN_AWAY_TIMER)==0){
|
||||
m.F(A::RECOVERY_TIME)=ConfigFloat("Phase4.WaitTime");
|
||||
m.SetState(State::RECOVERY);
|
||||
m.I(A::PATTERN_REPEAT_COUNT)=0;
|
||||
m.I(A::PHASE_REPEAT_COUNT)++;
|
||||
}
|
||||
}break;
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 2
|
||||
#define VERSION_PATCH 0
|
||||
#define VERSION_BUILD 1390
|
||||
#define VERSION_BUILD 1400
|
||||
|
||||
#define stringify(a) stringify_(a)
|
||||
#define stringify_(a) #a
|
||||
|
@ -145,9 +145,15 @@ MonsterStrategy
|
||||
# Percentage of health to transition to Phase 4
|
||||
Change = 25%
|
||||
MonsterSpawnOnChange = Blue Slime, 2
|
||||
# Percentage of normal move spd the Slime King will move.
|
||||
MoveSpdModifier = 50%
|
||||
ShootRate = 0.1
|
||||
RandomOffsetAngle = 75
|
||||
RandomOffsetAngle = 35
|
||||
|
||||
RunAwayTime = 2.5
|
||||
WaitTime = 1.0
|
||||
|
||||
JumpDuration = 3.0
|
||||
JumpDistance = 1000
|
||||
}
|
||||
Phase5
|
||||
@ -159,4 +165,12 @@ MonsterStrategy
|
||||
Change = 0%
|
||||
}
|
||||
}
|
||||
4
|
||||
{
|
||||
Name = Run Away
|
||||
# How far away the monster attempts to distance itself from the player
|
||||
Range = 700
|
||||
# If the player is farther than this distance, close in on them.
|
||||
CloseInRange = 850
|
||||
}
|
||||
}
|
@ -135,11 +135,11 @@ Monsters
|
||||
|
||||
CollisionDmg = 0
|
||||
|
||||
MoveSpd = 0
|
||||
MoveSpd = 100
|
||||
Size = 800
|
||||
|
||||
Strategy = Slime King
|
||||
StartPhase = 3
|
||||
StartPhase = 1
|
||||
|
||||
#Size of each animation frame
|
||||
SheetFrameSize = 24,24
|
||||
|
Loading…
x
Reference in New Issue
Block a user