Implemented Pirate Buccaneer AI. Remove unnecessary Run Towards overrides in monsters list. Fix Charged Arrow to use proper last graphic when a custom one is specified. Release Build 11621.

master
sigonasr2 2 months ago
parent d6c2b6c87f
commit 0e3a4c0ba7
  1. 3
      Adventures in Lestoria/BulletTypes.h
  2. 11
      Adventures in Lestoria/ChargedArrow.cpp
  3. 71
      Adventures in Lestoria/Pirate_Buccaneer.cpp
  4. 2
      Adventures in Lestoria/Version.h
  5. 16
      Adventures in Lestoria/assets/Campaigns/3_1.tmx
  6. 19
      Adventures in Lestoria/assets/config/MonsterStrategies.txt
  7. 18
      Adventures in Lestoria/assets/config/Monsters.txt
  8. 3
      Adventures in Lestoria/assets/config/gfx/gfx.txt
  9. BIN
      Adventures in Lestoria/assets/gamepack.pak
  10. BIN
      Adventures in Lestoria/assets/line_indicator.png
  11. BIN
      Adventures in Lestoria/assets/musket_bullet.png
  12. BIN
      Adventures in Lestoria/assets/musket_trail.png
  13. BIN
      x64/Release/Adventures in Lestoria.exe

@ -98,10 +98,13 @@ struct Arrow:public Bullet{
struct ChargedArrow:public Bullet{
vf2d lastLaserPos;
ChargedArrow(vf2d pos,vf2d vel,float radius,int damage,bool upperLevel,bool friendly=false,Pixel col=WHITE);
ChargedArrow(const std::string&shotArrowGraphic,const std::string&laserGraphic,vf2d pos,vf2d vel,float radius,int damage,bool upperLevel,bool friendly=false,Pixel col=WHITE);
void Update(float fElapsedTime)override;
BulletDestroyState PlayerHit(Player*player)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _PlayerHit()!!
BulletDestroyState MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!!
void ModifyOutgoingDamageData(HurtDamageInfo&data);
private:
std::string laserGraphic;
};
struct FrogTongue:public Bullet{

@ -45,9 +45,12 @@ All rights reserved.
INCLUDE_game
ChargedArrow::ChargedArrow(vf2d pos,vf2d vel,float radius,int damage,bool upperLevel,bool friendly,Pixel col)
:lastLaserPos(pos),
Bullet(pos,vel,radius,damage,
"charged_shot_arrow.png",upperLevel,true,INFINITE,true,friendly,col){}
:lastLaserPos(pos),laserGraphic("laser.png"),
Bullet(pos,vel,radius,damage,"charged_shot_arrow.png",upperLevel,true,INFINITE,true,friendly,col){}
ChargedArrow::ChargedArrow(const std::string&shotArrowGraphic,const std::string&laserGraphic,vf2d pos,vf2d vel,float radius,int damage,bool upperLevel,bool friendly,Pixel col)
:lastLaserPos(pos),laserGraphic(laserGraphic),
Bullet(pos,vel,radius,damage,shotArrowGraphic,upperLevel,true,INFINITE,true,friendly,col){}
void ChargedArrow::Update(float fElapsedTime){
geom2d::line lineToCurrentPos(geom2d::line(lastLaserPos,pos));
@ -58,7 +61,7 @@ void ChargedArrow::Update(float fElapsedTime){
const float normalBeamRadius{12*"Ranger.Ability 2.Radius"_F/100/5};
float laserWidth{radius/normalBeamRadius};
game->AddEffect(std::make_unique<Effect>(midpoint,0.1f,"laser.png",upperLevel,vf2d{laserWidth,dist*2},0.3f,vf2d{},Pixel{192,128,238},atan2(pos.y-lastLaserPos.y,pos.x-lastLaserPos.x)+PI/2,0,true));
game->AddEffect(std::make_unique<Effect>(midpoint,0.1f,laserGraphic,upperLevel,vf2d{laserWidth,dist*2},0.3f,vf2d{},Pixel{192,128,238},atan2(pos.y-lastLaserPos.y,pos.x-lastLaserPos.x)+PI/2,0,true));
lastLaserPos=pos;
}
}

@ -47,5 +47,76 @@ using A=Attribute;
INCLUDE_game
void Monster::STRATEGY::PIRATE_BUCCANEER(Monster&m,float fElapsedTime,std::string strategy){
#pragma region Phase, Animation, and Helper function setup
enum PhaseName{
INIT,
MOVE,
LOCKON,
WINDUP,
FIRE_ANIMATION,
};
#pragma endregion
switch(m.phase){
case INIT:{
m.phase=MOVE;
}break;
case MOVE:{
m.F(A::ATTACK_COOLDOWN)+=fElapsedTime;
float distToPlayer=m.GetDistanceFrom(game->GetPlayer()->GetPos());
const bool outsideMaxShootingRange=distToPlayer>=ConfigPixelsArr("Stand Still and Shoot Range",1);
auto PrepareToShoot=[&](){
m.phase=WINDUP;
m.F(A::SHOOT_TIMER)=ConfigFloat("Attack Windup Time");
m.PerformAnimation("SHOOT",m.GetFacingDirectionToTarget(game->GetPlayer()->GetPos()));
};
if(outsideMaxShootingRange){
m.target=game->GetPlayer()->GetPos();
RUN_TOWARDS(m,fElapsedTime,"Run Towards");
}else
if(m.F(A::ATTACK_COOLDOWN)>=ConfigFloat("Attack Reload Time")){
PrepareToShoot();
}else
if(distToPlayer<ConfigPixels("Run Away Range")){
m.target=geom2d::line<float>(m.GetPos(),game->GetPlayer()->GetPos()).upoint(-1);
RUN_TOWARDS(m,fElapsedTime,"Run Towards");
}else
if(m.F(A::ATTACK_COOLDOWN)>=ConfigFloat("Attack Reload Time")/2.f){ //Only the stand still and shoot range remains, which is twice as fast...
PrepareToShoot();
}
}break;
case WINDUP:{
m.F(A::SHOOT_TIMER)-=fElapsedTime;
if(m.F(A::SHOOT_TIMER)<=0){
m.F(A::ATTACK_COOLDOWN)=0.f;
CreateBullet(ChargedArrow)("musket_bullet.png","musket_trail.png",m.GetPos(),util::pointTo(m.GetPos(),m.V(A::LOCKON_POS))*ConfigFloat("Arrow Spd"),ConfigFloat("Arrow Hitbox Radius"),m.GetAttack(),m.OnUpperLevel())EndBullet;
m.PerformAnimation("SHOOTING",m.GetFacingDirectionToTarget(game->GetPlayer()->GetPos()));
m.SetStrategyDrawFunction([](AiL*game,Monster&monster,const std::string&strategy){});
m.phase=FIRE_ANIMATION;
m.F(A::SHOOT_TIMER)=m.GetCurrentAnimation().GetTotalAnimationDuration();
}else
if(m.F(A::SHOOT_TIMER)>=ConfigFloat("Attack Lockon Time")){
m.V(A::LOCKON_POS)=game->GetPlayer()->GetPos();
m.PerformAnimation("SHOOT",m.GetFacingDirectionToTarget(game->GetPlayer()->GetPos()));
const float arrowHitboxRadius{ConfigFloat("Arrow Hitbox Radius")};
m.SetStrategyDrawFunction([arrowHitboxRadius](AiL*game,Monster&monster,const std::string&strategy){
vf2d midpoint{geom2d::line<float>(monster.GetPos(),monster.V(A::LOCKON_POS)).rpoint(800.f)};
float shootingAngle{util::angleTo(monster.GetPos(),monster.V(A::LOCKON_POS))+PI/2};
vf2d imgSize{arrowHitboxRadius*2.f,800.f};
game->view.DrawPartialRotatedDecal(midpoint,GFX["line_indicator.png"].Decal(),shootingAngle,GFX["line_indicator.png"].Sprite()->Size()/2,{},GFX["line_indicator.png"].Sprite()->Size(),imgSize/GFX["line_indicator.png"].Sprite()->Size());
});
}
}break;
case FIRE_ANIMATION:{
m.F(A::SHOOT_TIMER)-=fElapsedTime;
if(m.F(A::SHOOT_TIMER)<=0.f){
m.PerformAnimation("IDLE",m.GetFacingDirectionToTarget(game->GetPlayer()->GetPos()));
m.phase=MOVE;
}
}break;
}
}

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

@ -1,5 +1,5 @@
<?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="13">
<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="15">
<properties>
<property name="Background Music" propertytype="BGM" value="mountain"/>
<property name="Level Type" type="int" propertytype="LevelType" value="0"/>
@ -865,22 +865,12 @@
<object id="8" name="Spawn Zone" type="SpawnGroup" x="180" y="1326" width="426" height="306">
<ellipse/>
</object>
<object id="9" template="../maps/Monsters/Pirate Marauder.tx" x="474" y="1398">
<object id="13" template="../maps/Monsters/Pirate Buccaneer.tx" x="492" y="1458">
<properties>
<property name="spawner" type="object" value="8"/>
</properties>
</object>
<object id="10" template="../maps/Monsters/Pirate Marauder.tx" x="474" y="1350">
<properties>
<property name="spawner" type="object" value="8"/>
</properties>
</object>
<object id="11" template="../maps/Monsters/Pirate Marauder.tx" x="456" y="1494">
<properties>
<property name="spawner" type="object" value="8"/>
</properties>
</object>
<object id="12" template="../maps/Monsters/Pirate Marauder.tx" x="480" y="1566">
<object id="14" template="../maps/Monsters/Goblin (Bow).tx" x="474" y="1530">
<properties>
<property name="spawner" type="object" value="8"/>
</properties>

@ -1103,7 +1103,26 @@ MonsterStrategy
}
Pirate Buccaneer
{
Attack Reload Time = 2.0s
# How long it takes to prepare the attack once an attack is queued.
Attack Windup Time = 1.0s
# How much of the windup time is spent without the aiming direction changing.
Attack Lockon Time = 0.3s
Arrow Spd = 800
Arrow Hitbox Radius = 6
# How long the monster must stop turning their aim and lock in the target. The longer, the easier it is to dodge.
Bow Steadying Time = 0.33s
# When the monster will attempt to run away from target.
Run Away Range = 1000
# Does not move and shoots from anywhere in these ranges.
Stand Still and Shoot Range = 800,1200
# Anything outside the max "Stand Still and Shoot Range" will cause the monster to move towards the target instead.
}
Parrot
{

@ -1391,9 +1391,6 @@ Monsters
Strategy = Pirate Captain
# Wait time override for Run Towards strategy.
WaitTime = 0
#Size of each animation frame
SheetFrameSize = 36,36
@ -1440,9 +1437,6 @@ Monsters
Strategy = Pirate Buccaneer
# Wait time override for Run Towards strategy.
WaitTime = 0
#Size of each animation frame
SheetFrameSize = 48,48
@ -1484,9 +1478,6 @@ Monsters
Strategy = Crab
# Wait time override for Run Towards strategy.
WaitTime = 0
#Size of each animation frame
SheetFrameSize = 48,48
@ -1527,9 +1518,6 @@ Monsters
Strategy = Crab
# Wait time override for Run Towards strategy.
WaitTime = 0
#Size of each animation frame
SheetFrameSize = 48,48
@ -1570,9 +1558,6 @@ Monsters
Strategy = Seagull
# Wait time override for Run Towards strategy.
WaitTime = 0
#Size of each animation frame
SheetFrameSize = 48,48
@ -1613,9 +1598,6 @@ Monsters
Strategy = Sandworm
# Wait time override for Run Towards strategy.
WaitTime = 0
#Size of each animation frame
SheetFrameSize = 96,96

@ -133,6 +133,9 @@ Images
GFX_Comet = comet.png
GFX_CometFlare = comet_flare.png
GFX_DownArrow = downarrow.png
GFX_MusketTrail = musket_trail.png
GFX_LineIndicator = line_indicator.png
GFX_MusketBullet = musket_bullet.png
GFX_Thief_Sheet = nico-thief.png
GFX_Trapper_Sheet = nico-trapper.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 669 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Loading…
Cancel
Save