Worked on Pirate Captain base AI. (Mounted Parrot AI still needs implemented).

master
sigonasr2 2 months ago
parent 4e1fa8d4e3
commit d432966e3e
  1. 3
      Adventures in Lestoria/Monster.cpp
  2. 2
      Adventures in Lestoria/Monster.h
  3. 48
      Adventures in Lestoria/Pirate_Captain.cpp
  4. 2
      Adventures in Lestoria/TODO.txt
  5. 20
      Adventures in Lestoria/assets/config/MonsterStrategies.txt
  6. 7
      Adventures in Lestoria/assets/config/Monsters.txt

@ -1411,8 +1411,9 @@ const bool Monster::_DealTrueDamage(const uint32_t damageAmt,HurtFlag::HurtFlag
return _Hurt(damageAmt,OnUpperLevel(),GetZ(),TrueDamageFlag::IGNORE_DAMAGE_RULES,hurtFlags); return _Hurt(damageAmt,OnUpperLevel(),GetZ(),TrueDamageFlag::IGNORE_DAMAGE_RULES,hurtFlags);
} }
void Monster::Heal(const int healAmt){ void Monster::Heal(const int healAmt,const bool displayDamageNumber){
hp=std::clamp(hp+healAmt,0,int(GetMaxHealth())); hp=std::clamp(hp+healAmt,0,int(GetMaxHealth()));
if(displayDamageNumber)DAMAGENUMBER_LIST.emplace_back(std::make_shared<DamageNumber>(GetPos(),healAmt,false,DamageNumberType::HEALTH_GAIN);
} }
const float Monster::GetModdedStatBonuses(std::string_view stat)const{ const float Monster::GetModdedStatBonuses(std::string_view stat)const{

@ -203,7 +203,7 @@ public:
const bool ReachedTargetPos(const float maxDistanceFromTarget=4.f)const; const bool ReachedTargetPos(const float maxDistanceFromTarget=4.f)const;
const float GetHealthRatio()const; const float GetHealthRatio()const;
const bool _DealTrueDamage(const uint32_t damageAmt,HurtFlag::HurtFlag hurtFlags=HurtFlag::NONE); const bool _DealTrueDamage(const uint32_t damageAmt,HurtFlag::HurtFlag hurtFlags=HurtFlag::NONE);
void Heal(const int healAmt); void Heal(const int healAmt,const bool displayDamageNumber=false);
const float GetModdedStatBonuses(std::string_view stat)const; const float GetModdedStatBonuses(std::string_view stat)const;
//The collision rectangle is only used currently for determining the safe spots for the stone golem boss fight. //The collision rectangle is only used currently for determining the safe spots for the stone golem boss fight.
const std::optional<geom2d::rect<float>>&GetRectangleCollision()const; const std::optional<geom2d::rect<float>>&GetRectangleCollision()const;

@ -50,15 +50,61 @@ void Monster::STRATEGY::PIRATE_CAPTAIN(Monster&m,float fElapsedTime,std::string
enum PhaseName{ enum PhaseName{
INIT, INIT,
MOVE, MOVE,
PREPARE_SHOOT,
SHOOT_RELOAD,
DRINK_RUM,
}; };
switch(m.phase){ switch(m.phase){
case INIT:{ case INIT:{
m.F(A::TARGET_TIMER)= m.F(A::TARGET_TIMER)=ConfigFloat("Shooting Frequency");
m.phase=MOVE; m.phase=MOVE;
}break; }break;
case MOVE:{ case MOVE:{
m.F(A::TARGET_TIMER)-=fElapsedTime;
GOBLIN_DAGGER(m,fElapsedTime,"Goblin Dagger"); GOBLIN_DAGGER(m,fElapsedTime,"Goblin Dagger");
if(m.F(A::TARGET_TIMER)<=0.f){
const float diceRoll{util::random(100)};
if(diceRoll<=ConfigFloat("Shooting Chance")){
const float distToPlayer{util::distance(game->GetPlayer()->GetPos(),m.GetPos())};
if(distToPlayer<=ConfigFloat("Shoot Max Range")/100.f*24){
m.F(A::SHOOT_TIMER)=ConfigFloat("Shooting Delay");
m.phase=PREPARE_SHOOT;
m.PerformAnimation("SHOOT",game->GetPlayer()->GetPos());
m.V(A::LOCKON_POS)=game->GetPlayer()->GetPos();
}
}
m.F(A::TARGET_TIMER)=ConfigFloat("Shooting Frequency");
}else
if(m.GetHealth()<ConfigInt("Rum Drink Threshold")){
m.PerformAnimation("DRINK");
m.F(A::BREAK_TIME)=m.GetCurrentAnimation().GetTotalAnimationDuration();
m.phase=DRINK_RUM;
}
}break;
case PREPARE_SHOOT:{
m.F(A::SHOOT_TIMER)-=fElapsedTime;
if(m.F(A::SHOOT_TIMER)<=0.f){
CreateBullet(Bullet)(m.GetPos(),util::pointTo(m.GetPos(),m.V(A::LOCKON_POS))*ConfigFloat("Bullet Speed"),ConfigFloat("Bullet Radius"),m.GetAttack(),m.OnUpperLevel(),false,ConfigPixel("Bullet Color"),vf2d{1.f,1.f}*ConfigFloat("Bullet Radius")/3.f)EndBullet;
m.PerformAnimation("SHOOTING");
m.F(A::SHOOT_ANIMATION_TIME)=m.GetCurrentAnimation().GetTotalAnimationDuration();
m.phase=SHOOT_RELOAD;
}
}break;
case SHOOT_RELOAD:{
m.F(A::SHOOT_ANIMATION_TIME)-=fElapsedTime;
if(m.F(A::SHOOT_ANIMATION_TIME)<=0.f){
m.PerformAnimation("IDLE");
m.phase=MOVE;
}
}break;
case DRINK_RUM:{
m.F(A::BREAK_TIME)-=fElapsedTime;
if(m.F(A::BREAK_TIME)<=0.f){
m.Heal(ConfigInt("Rum Health Recovery"),true);
m.phase=MOVE;
}
}break; }break;
} }
} }

@ -3,7 +3,7 @@ Add unconscious monster state.
DEMO DEMO
==== ====
Save file backup and rolling back on failure

@ -1091,7 +1091,22 @@ MonsterStrategy
} }
Pirate Captain Pirate Captain
{ {
Shooting Frequency = 6s
Shoot Max Range = 400
Shooting Chance = 60%
# How long to stand still/wait for the shot.
Shooting Delay = 0.5s
Bullet Color = 82r, 86g, 110b, 255a
Bullet Speed = 350
Bullet Radius = 6px
Rum Drink Threshold = 300hp
Rum Health Recovery = 150hp
# Number of drinks available to be consumed.
Rum Drink Count = 1
# Amount of time after Captain spawn parrot flies up to begin attacking.
Parrot Fly Wait Time = 2s
} }
Seagull Seagull
{ {
@ -1126,7 +1141,8 @@ MonsterStrategy
} }
Parrot Parrot
{ {
# Amount of time parrot remains stunned on death.
Stun Time = 5s
} }
Crab Crab
{ {

@ -1434,6 +1434,10 @@ Monsters
######## ########
# For monsters that have a mounted portion, this will specify the animation to use.
Mounted Animation = PARROT_MOUNTED
Mounted Animation Offset = 0,-10
Animations Animations
{ {
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse,ReverseOneShot) # Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse,ReverseOneShot)
@ -1448,7 +1452,8 @@ Monsters
STAB = 1, 0.1, OneShot STAB = 1, 0.1, OneShot
SHOOTING = 3, 0.2, OneShot SHOOTING = 3, 0.2, OneShot
SHOOT = 1, 0.1, OneShot SHOOT = 1, 0.1, OneShot
DRINK = 3, 0.5, PingPong # Drink is approximately 2 seconds long.
DRINK = 3, 0.65, PingPong
} }
# Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity # Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity

Loading…
Cancel
Save