Implemented Sandworm AI. Change added velocity function to be a standalone velocity variable added to original player velocity. Release Build 11725.

master
sigonasr2 1 month ago
parent 446be1e02f
commit b11d209813
  1. 2
      Adventures in Lestoria/MonsterAttribute.h
  2. 12
      Adventures in Lestoria/Player.cpp
  3. 3
      Adventures in Lestoria/Player.h
  4. 75
      Adventures in Lestoria/Sandworm.cpp
  5. 2
      Adventures in Lestoria/Version.h
  6. 9
      Adventures in Lestoria/assets/Campaigns/3_1.tmx
  7. 15
      Adventures in Lestoria/assets/config/MonsterStrategies.txt
  8. 6
      Adventures in Lestoria/assets/config/Monsters.txt
  9. BIN
      Adventures in Lestoria/assets/gamepack.pak
  10. BIN
      x64/Release/Adventures in Lestoria.exe

@ -150,4 +150,6 @@ enum class Attribute{
MID_PHASE, MID_PHASE,
RUM_DRINK_COUNT, RUM_DRINK_COUNT,
SPEED_RAMPUP_TIMER, SPEED_RAMPUP_TIMER,
BULLET_HAS_BEEN_SHOT,
SUCTION_TIMER,
}; };

@ -674,9 +674,11 @@ void Player::Update(float fElapsedTime){
game->GetPlayer()->SetPos(game->GetPlayer()->GetPos()+finalWindSpd*game->GetElapsedTime(),MoveFlag::PREVENT_CAST_CANCELLING); game->GetPlayer()->SetPos(game->GetPlayer()->GetPos()+finalWindSpd*game->GetElapsedTime(),MoveFlag::PREVENT_CAST_CANCELLING);
if(vel!=vf2d{0,0}){ const vf2d totalVel{vel+addedVel};
float newX=pos.x+vel.x*fElapsedTime;
float newY=pos.y+vel.y*fElapsedTime; if(totalVel!=vf2d{}){
float newX=pos.x+totalVel.x*fElapsedTime;
float newY=pos.y+totalVel.y*fElapsedTime;
SetX(newX); SetX(newX);
SetY(newY); SetY(newY);
if(vel.x>0){ if(vel.x>0){
@ -691,6 +693,8 @@ void Player::Update(float fElapsedTime){
} }
} }
addedVel={};
if(Menu::stack.empty()){ if(Menu::stack.empty()){
if(CanAct()&&attack_cooldown_timer==0&&AiL::KEY_ATTACK.Held()){ if(CanAct()&&attack_cooldown_timer==0&&AiL::KEY_ATTACK.Held()){
@ -1915,7 +1919,7 @@ void Player::ProximityKnockback(const vf2d centerPoint,const float knockbackFact
} }
void Player::AddVelocity(vf2d vel){ void Player::AddVelocity(vf2d vel){
this->vel+=vel*game->GetElapsedTime(); this->addedVel+=vel;
} }
const float Player::GetHealthRatio()const{ const float Player::GetHealthRatio()const{

@ -294,7 +294,7 @@ public:
const float GetAtkGrowthRate()const; const float GetAtkGrowthRate()const;
const float GetIframeTime()const; const float GetIframeTime()const;
const Renderable&GetMinimapImage()const; const Renderable&GetMinimapImage()const;
void AddVelocity(vf2d vel); void AddVelocity(vf2d vel); //Use to add more applied velocity to the player on top of what is already happening. Resets every frame. Good for pulling in/pushing out forces.
const float GetHealthRatio()const; const float GetHealthRatio()const;
const bool IsAlive()const; const bool IsAlive()const;
//An all-in-one function that applies a stat plus any % modifiers the stat may have as well. //An all-in-one function that applies a stat plus any % modifiers the stat may have as well.
@ -431,6 +431,7 @@ private:
std::vector<std::pair<PlayerTimerType,ShieldAmount>>shield; std::vector<std::pair<PlayerTimerType,ShieldAmount>>shield;
bool catForm{false}; bool catForm{false};
std::optional<vf2d>testAimingLoc{}; std::optional<vf2d>testAimingLoc{};
vf2d addedVel{};
protected: protected:
const float ATTACK_COOLDOWN="Warrior.Auto Attack.Cooldown"_F; const float ATTACK_COOLDOWN="Warrior.Auto Attack.Cooldown"_F;
const float MAGIC_ATTACK_COOLDOWN="Wizard.Auto Attack.Cooldown"_F; const float MAGIC_ATTACK_COOLDOWN="Wizard.Auto Attack.Cooldown"_F;

@ -50,19 +50,90 @@ void Monster::STRATEGY::SANDWORM(Monster&m,float fElapsedTime,std::string strate
enum PhaseName{ enum PhaseName{
INITIALIZE, INITIALIZE,
UNDERGROUND, UNDERGROUND,
SURFACING,
ATTACK,
SHOOTING,
BURROWING,
};
m.F(A::ATTACK_COOLDOWN)-=fElapsedTime;
m.F(A::SUCTION_TIMER)-=fElapsedTime;
const float distToPlayer{util::distance(game->GetPlayer()->GetPos(),m.GetPos())};
if(m.F(A::SUCTION_TIMER)>0.f&&distToPlayer<=ConfigPixels("Suction Radius")){
game->GetPlayer()->AddVelocity(util::pointTo(game->GetPlayer()->GetPos(),m.GetPos())*100.f*ConfigFloat("Suction Pull Amount")/100.f);
}
const auto AcquireNewUndergroundTarget=[&](){
const float randomRange=util::random_range(0,ConfigPixels("Burrow Target Range"));
m.target=game->GetPlayer()->GetPos()+vf2d{randomRange,util::random(2*PI)}.cart();
}; };
switch(PHASE()){ switch(PHASE()){
case INITIALIZE:{ case INITIALIZE:{
SETPHASE(UNDERGROUND); SETPHASE(UNDERGROUND);
const float randomRange=util::random_range(0,ConfigFloat("Burrow Target Range")/100.f*24); AcquireNewUndergroundTarget();
m.V(A::LOCKON_POS)=game->GetPlayer()->GetPos()+vf2d{randomRange,util::random(2*PI)}.cart();
}break; }break;
case UNDERGROUND:{ case UNDERGROUND:{
m.SetCollisionRadius(0.f); m.SetCollisionRadius(0.f);
RUN_TOWARDS(m,fElapsedTime,"Run Towards"); RUN_TOWARDS(m,fElapsedTime,"Run Towards");
m.PerformAnimation("SWIM",m.GetFacingDirection()); m.PerformAnimation("SWIM",m.GetFacingDirection());
if(m.ReachedTargetPos()){
m.PerformAnimation("EMERGE",game->GetPlayer()->GetPos());
m.F(A::RECOVERY_TIME)=m.GetCurrentAnimation().GetTotalAnimationDuration();
game->AddEffect(std::make_unique<Effect>(m.GetPos(),ConfigInt("Suction Duration"),"sand_suction.png",m.OnUpperLevel(),0.25f,0.25f,ConfigFloat("Suction Animation Size")/300.f*vf2d{1.f,1.f},vf2d{},WHITE,util::random(),-PI/8),true);
SETPHASE(SURFACING);
m.F(A::SUCTION_TIMER)=ConfigFloat("Suction Duration")+0.25f;
}
}break; }break;
case SURFACING:{
m.F(A::RECOVERY_TIME)-=fElapsedTime;
if(m.F(A::RECOVERY_TIME)<=0.f){
SETPHASE(ATTACK);
m.PerformAnimation("IDLE",game->GetPlayer()->GetPos());
m.SetCollisionRadius(m.GetOriginalCollisionRadius());
m.I(A::ATTACK_COUNT)=ConfigInt("Max Attack Count");
}
}break;
case ATTACK:{
if(m.I(A::ATTACK_COUNT)<=0||distToPlayer>=ConfigPixels("Max Attack Range")){
m.SetCollisionRadius(0.f);
m.PerformAnimation("BURROW");
m.F(A::CASTING_TIMER)=m.GetCurrentAnimation().GetTotalAnimationDuration();
SETPHASE(BURROWING);
break;
}
if(m.F(A::ATTACK_COOLDOWN)<=0.f){
m.PerformAnimation("SAND ATTACK",game->GetPlayer()->GetPos());
m.F(A::CASTING_TIMER)=ConfigFloat("Shoot Delay");
m.F(A::SHOOT_ANIMATION_TIME)=m.GetCurrentAnimation().GetTotalAnimationDuration();
m.B(A::BULLET_HAS_BEEN_SHOT)=false;
SETPHASE(SHOOTING);
}
}break;
case SHOOTING:{
const auto ShootBullet=[&](){
m.B(A::BULLET_HAS_BEEN_SHOT)=true;
m.I(A::ATTACK_COUNT)--;
CreateBullet(Bullet)(m.GetPos(),vf2d{ConfigPixels("Bullet Speed"),util::angleTo(m.GetPos(),game->GetPlayer()->GetPos())}.cart(),ConfigFloat("Bullet Radius"),m.GetAttack(),m.OnUpperLevel(),false,ConfigPixel("Bullet Color"),ConfigFloat("Bullet Radius")*vf2d{1.f,1.f}/2.f)EndBullet;
};
m.F(A::CASTING_TIMER)-=fElapsedTime;
m.F(A::SHOOT_ANIMATION_TIME)-=fElapsedTime;
if(m.F(A::CASTING_TIMER)<=0.f&&!m.B(A::BULLET_HAS_BEEN_SHOT)){
ShootBullet();
}
if(m.F(A::SHOOT_ANIMATION_TIME)<=0.f){
if(!m.B(A::BULLET_HAS_BEEN_SHOT))ShootBullet();
m.PerformAnimation("IDLE",game->GetPlayer()->GetPos());
SETPHASE(ATTACK);
}
}break;
case BURROWING:{
m.F(A::CASTING_TIMER)-=fElapsedTime;
if(m.F(A::CASTING_TIMER)<=0.f){
AcquireNewUndergroundTarget();
SETPHASE(UNDERGROUND);
}
}break;
} }
} }

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 1 #define VERSION_MAJOR 1
#define VERSION_MINOR 3 #define VERSION_MINOR 3
#define VERSION_PATCH 0 #define VERSION_PATCH 0
#define VERSION_BUILD 11714 #define VERSION_BUILD 11725
#define stringify(a) stringify_(a) #define stringify(a) stringify_(a)
#define stringify_(a) #a #define stringify_(a) #a

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.10.2" class="Map" orientation="orthogonal" renderorder="right-down" width="335" height="165" tilewidth="24" tileheight="24" infinite="0" nextlayerid="8" nextobjectid="102"> <map version="1.10" tiledversion="1.11.0" class="Map" orientation="orthogonal" renderorder="right-down" width="335" height="165" tilewidth="24" tileheight="24" infinite="0" nextlayerid="8" nextobjectid="104">
<properties> <properties>
<property name="Background Music" propertytype="BGM" value="beach"/> <property name="Background Music" propertytype="BGM" value="beach"/>
<property name="Level Type" type="int" propertytype="LevelType" value="0"/> <property name="Level Type" type="int" propertytype="LevelType" value="0"/>
@ -1243,7 +1243,12 @@
</properties> </properties>
<point/> <point/>
</object> </object>
<object id="101" template="../maps/Monsters/Giant Crab.tx" x="594" y="1590"> <object id="102" template="../maps/Monsters/Sandworm.tx" x="768" y="1488">
<properties>
<property name="spawner" type="object" value="8"/>
</properties>
</object>
<object id="103" template="../maps/Monsters/Sandworm.tx" x="528" y="1320">
<properties> <properties>
<property name="spawner" type="object" value="8"/> <property name="spawner" type="object" value="8"/>
</properties> </properties>

@ -1123,6 +1123,21 @@ MonsterStrategy
{ {
# Furthest distance sandworm travels from the player while burrowing. # Furthest distance sandworm travels from the player while burrowing.
Burrow Target Range = 400 Burrow Target Range = 400
# The distance from the monster the suction effect will occur.
Suction Radius = 600
# The size of the suction animation.
Suction Animation Size = 300
# The larger the value the more of % of movespd it affects.
Suction Pull Amount = 30%
Suction Duration = 3s
# Amount of time to wait before the bullet comes out (animation starts playing while waiting)
Shoot Delay = 0.4s
# Maximum number of attacks to fire before burrowing again.
Max Attack Count = 6
Max Attack Range = 1500
Bullet Radius = 6px
Bullet Speed = 450
Bullet Color = 47r, 23g, 8b, 255a
} }
Pirate Buccaneer Pirate Buccaneer
{ {

@ -1511,7 +1511,7 @@ Monsters
Health = 430 Health = 430
Attack = 45 Attack = 45
CollisionDmg = 10 CollisionDmg = 45
MoveSpd = 120% MoveSpd = 120%
Size = 60% Size = 60%
@ -1552,7 +1552,7 @@ Monsters
Health = 1800 Health = 1800
Attack = 49 Attack = 49
CollisionDmg = 20 CollisionDmg = 49
MoveSpd = 90% MoveSpd = 90%
Size = 180% Size = 180%
@ -1634,7 +1634,7 @@ Monsters
Health = 400 Health = 400
Attack = 33 Attack = 33
CollisionDmg = 10 CollisionDmg = 33
MoveSpd = 200% MoveSpd = 200%
Size = 90% Size = 90%

Loading…
Cancel
Save