Add in initial cannonball attack. Setup Chapter 3 boss spawn. Release Build 11946.

master
sigonasr2 3 weeks ago
parent 1a9d5b12d0
commit e2b6e9318a
  1. 2
      Adventures in Lestoria/Adventures in Lestoria.vcxproj
  2. 2
      Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters
  3. 3
      Adventures in Lestoria/BulletTypes.h
  4. 3
      Adventures in Lestoria/FallingBullet.cpp
  5. 37
      Adventures in Lestoria/GhostOfPirateCaptain.cpp
  6. 1
      Adventures in Lestoria/MonsterAttribute.h
  7. 2
      Adventures in Lestoria/StoneGolem.cpp
  8. 2
      Adventures in Lestoria/Version.h
  9. 13
      Adventures in Lestoria/assets/Campaigns/Boss_3.tmx
  10. BIN
      Adventures in Lestoria/assets/cannonball.png
  11. 21
      Adventures in Lestoria/assets/config/MonsterStrategies.txt
  12. 2
      Adventures in Lestoria/assets/config/Monsters.txt
  13. 1
      Adventures in Lestoria/assets/config/gfx/gfx.txt
  14. BIN
      Adventures in Lestoria/assets/gamepack.pak
  15. 3
      Adventures in Lestoria/assets/maps/Monster_Presets.tmx
  16. 5
      Adventures in Lestoria/assets/maps/Monsters/Ghost of Pirate Captain.tx
  17. BIN
      Adventures in Lestoria/assets/maps/monsters-tileset.png
  18. BIN
      x64/Release/Adventures in Lestoria.exe

@ -1181,7 +1181,7 @@
<SubType>
</SubType>
</ClCompile>
<ClCompile Include="FallingStone.cpp">
<ClCompile Include="FallingBullet.cpp">
<SubType>
</SubType>
</ClCompile>

@ -1172,7 +1172,7 @@
<ClCompile Include="RockLaunch.cpp">
<Filter>Source Files\Effects</Filter>
</ClCompile>
<ClCompile Include="FallingStone.cpp">
<ClCompile Include="FallingBullet.cpp">
<Filter>Source Files\Bullet Types</Filter>
</ClCompile>
<ClCompile Include="ShineEffect.cpp">

@ -282,8 +282,7 @@ private:
};
struct FallingBullet:public Bullet{
//The position for this bullet represents where the falling stone should land.
FallingBullet(vf2d targetPos,vf2d vel,float zVel,float indicatorDisplayTime,float radius,int damage,bool upperLevel,bool hitsMultiple=false,float knockbackAmt=0.f,float lifetime=INFINITE,bool friendly=false,Pixel col=WHITE,vf2d scale={1,1},float image_angle=0.f,float spellCircleRotation=0.f,float spellCircleRotationSpd=0.f,Pixel insigniaCol=WHITE,float insigniaRotation=0.f,float insigniaRotationSpd=0.f);
//The position for this bullet represents where the falling bullet should land.
FallingBullet(const std::string&imgName,vf2d targetPos,vf2d vel,float zVel,float indicatorDisplayTime,float radius,int damage,bool upperLevel,bool hitsMultiple=false,float knockbackAmt=0.f,float lifetime=INFINITE,bool friendly=false,Pixel col=WHITE,vf2d scale={1,1},float image_angle=0.f,float spellCircleRotation=0.f,float spellCircleRotationSpd=0.f,Pixel insigniaCol=WHITE,float insigniaRotation=0.f,float insigniaRotationSpd=0.f);
protected:
void Update(float fElapsedTime)override;

@ -52,9 +52,6 @@ indicator(targetPos,lifetime+0.1f,"range_indicator.png","spell_insignia.png",upp
z=-zVel*lifetime;
}
FallingBullet::FallingBullet(vf2d targetPos,vf2d vel,float zVel,float indicatorDisplayTime,float radius,int damage,bool upperLevel,bool hitsMultiple,float knockbackAmt,float lifetime,bool friendly,Pixel col,vf2d scale,float image_angle,float spellCircleRotation,float spellCircleRotationSpd,Pixel insigniaCol,float insigniaRotation,float insigniaRotationSpd)
:FallingBullet("rock.png",targetPos,vel,zVel,indicatorDisplayTime,radius,damage,upperLevel,hitsMultiple,knockbackAmt,lifetime,friendly,col,scale,image_angle,spellCircleRotation,spellCircleRotationSpd,insigniaCol,insigniaRotation,insigniaRotationSpd){}
void FallingBullet::Update(float fElapsedTime){
z+=zVel*fElapsedTime;
lastTrailEffect-=fElapsedTime;

@ -53,8 +53,15 @@ void Monster::STRATEGY::GHOST_OF_PIRATE_CAPTAIN(Monster&m,float fElapsedTime,std
NORMAL,
};
static const uint8_t PHASE_COUNT{DATA.GetProperty("MonsterStrategy.Ghost of Pirate Captain").GetValueCount()};
static std::vector<uint8_t>PHASES{};
enum CannonShotType{
BOMBARDMENT,//every shot is at a random location within 900 Range of the player. (This is also the move during hide and seek.)
PRECISE_BOMBARDMENT,//same as before but within 700 range of the player.
LINE,//the 4th or 5th hit would hit the player if the player doesnt move at all.
SHARPSHOOTER,//aiming directly at the player, skipping every 2nd shot. (only 4 instead of 8 shots)
PREDICTION,//shoots in the direction of the current or last players movement and predicts where the player would be in 2.8 seconds. (slightly further then where the player would be at impact. thats why 2.8 instead of 2.5 seconds)
};
static const uint8_t PHASE_COUNT{uint8_t(DATA.GetProperty("MonsterStrategy.Ghost of Pirate Captain.Cannon Cycle").GetValueCount())};
const auto AdvanceCannonPhase{[&m,&strategy](){
m.GetFloat(A::CANNON_TIMER)=0.f;
@ -64,30 +71,29 @@ void Monster::STRATEGY::GHOST_OF_PIRATE_CAPTAIN(Monster&m,float fElapsedTime,std
switch(PHASE()){
case INIT:{
for(int i:std::ranges::iota_view(PHASE_COUNT)){
PHASES.emplace_back(DATA.GetProperty("MonsterStrategy.Ghost of Pirate Captain").GetInt(i));
for(int i:std::ranges::iota_view(0U,PHASE_COUNT)){
m.VEC(A::CANNON_PHASES).emplace_back(DATA.GetProperty("MonsterStrategy.Ghost of Pirate Captain.Cannon Cycle").GetInt(i));
}
m.I(A::CANNON_SHOT_TYPE)=util::random()%5;
m.I(A::CANNON_SHOT_TYPE)=BOMBARDMENT;
SETPHASE(NORMAL);
}break;
case NORMAL:{
m.F(A::CANNON_TIMER)+=fElapsedTime;
switch(PHASES[m.I(A::CANNON_PHASE)]){
const int phase{std::any_cast<int>(m.VEC(A::CANNON_PHASES)[m.I(A::CANNON_PHASE)])};
switch(phase){
enum CannonPhaseType{
CANNON_SHOT,
SILENCE,
SHRAPNEL_SHOT,
};
case CANNON_SHOT:{//Normal Cannon Shot. Takes on one of five varieties.
enum CannonShotType{
BOMBARDMENT,//every shot is at a random location within 900 Range of the player. (This is also the move during hide and seek.)
PRECISE_BOMBARDMENT,//same as before but within 700 range of the player.
LINE,//the 4th or 5th hit would hit the player if the player doesnt move at all.
SHARPSHOOTER,//aiming directly at the player, skipping every 2nd shot. (only 4 instead of 8 shots)
PREDICTION,//shoots in the direction of the current or last players movement and predicts where the player would be in 2.8 seconds. (slightly further then where the player would be at impact. thats why 2.8 instead of 2.5 seconds)
};
if(m.F(A::CANNON_TIMER)>=ConfigFloat("Cannon Shot Delay")){
switch(m.I(A::CANNON_SHOT_TYPE)){
case BOMBARDMENT:{
const float randomAng{util::random_range(0,2*PI)};
const float range{util::random_range(0,ConfigPixels("Bombardment Max Distance"))};
const vf2d targetPos{game->camera.GetTarget()-ConfigPixels("Bombardment Max Distance")/2.f+vf2d{range,randomAng}.cart()};
CreateBullet(FallingBullet)("cannonball.png",targetPos,ConfigVec("Cannon Vel"),ConfigFloatArr("Cannon Vel",2),ConfigFloat("Indicator Time"),ConfigPixels("Cannon Radius"),ConfigInt("Cannon Damage"),m.OnUpperLevel(),false,ConfigFloat("Cannon Knockback Amt"),0.4f,false,ConfigPixel("Cannon Spell Circle Color"),vf2d{ConfigFloat("Cannon Radius")/100.f*2.f,ConfigFloat("Cannon Radius")/100.f*2.f},util::random(2*PI),util::random(2*PI),util::degToRad(ConfigFloat("Cannon Spell Circle Rotation Spd")),ConfigPixel("Cannon Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Cannon Spell Insignia Rotation Spd")))EndBullet;
}break;
case PRECISE_BOMBARDMENT:{
@ -102,7 +108,8 @@ void Monster::STRATEGY::GHOST_OF_PIRATE_CAPTAIN(Monster&m,float fElapsedTime,std
}break;
}
if(m.F(A::CANNON_TIMER)>=ConfigFloat("Cannon Shot Delay"))AdvanceCannonPhase();
AdvanceCannonPhase();
}
}break;
case SILENCE:{
if(m.F(A::CANNON_TIMER)>=ConfigFloat("Silence Time"))AdvanceCannonPhase();

@ -166,4 +166,5 @@ enum class Attribute{
CANNON_TIMER,
CANNON_PHASE,
CANNON_SHOT_TYPE,
CANNON_PHASES,
};

@ -330,7 +330,7 @@ void Monster::STRATEGY::STONE_GOLEM(Monster&m,float fElapsedTime,std::string str
m.PerformAnimation("CAST");
for(int i:std::ranges::iota_view(0,ConfigInt("Stone Rain.Stone Count"))){
CreateBullet(FallingBullet)(game->camera.GetViewPosition()+vf2d{util::random(game->ScreenWidth()),util::random(game->ScreenHeight())},ConfigVec("Stone Rain.Stone Vel"),ConfigFloatArr("Stone Rain.Stone Vel",2),ConfigFloat("Stone Rain.Indicator Time"),ConfigPixels("Stone Rain.Stone Radius"),ConfigInt("Stone Rain.Stone Damage"),m.OnUpperLevel(),false,ConfigFloat("Stone Rain.Stone Knockback Amt"),util::random_range(ConfigFloatArr("Stone Rain.Stone Fall Delay",0),ConfigFloatArr("Stone Rain.Stone Fall Delay",1)),false,ConfigPixel("Stone Rain.Stone Spell Circle Color"),vf2d{ConfigFloat("Stone Rain.Stone Radius")/100.f*2.f,ConfigFloat("Stone Rain.Stone Radius")/100.f*2.f},util::random(2*PI),util::random(2*PI),util::degToRad(ConfigFloat("Stone Rain.Stone Spell Circle Rotation Spd")),ConfigPixel("Stone Rain.Stone Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Stone Rain.Stone Spell Insignia Rotation Spd")))EndBullet;
CreateBullet(FallingBullet)("rock.png",game->camera.GetViewPosition()+vf2d{util::random(game->ScreenWidth()),util::random(game->ScreenHeight())},ConfigVec("Stone Rain.Stone Vel"),ConfigFloatArr("Stone Rain.Stone Vel",2),ConfigFloat("Stone Rain.Indicator Time"),ConfigPixels("Stone Rain.Stone Radius"),ConfigInt("Stone Rain.Stone Damage"),m.OnUpperLevel(),false,ConfigFloat("Stone Rain.Stone Knockback Amt"),util::random_range(ConfigFloatArr("Stone Rain.Stone Fall Delay",0),ConfigFloatArr("Stone Rain.Stone Fall Delay",1)),false,ConfigPixel("Stone Rain.Stone Spell Circle Color"),vf2d{ConfigFloat("Stone Rain.Stone Radius")/100.f*2.f,ConfigFloat("Stone Rain.Stone Radius")/100.f*2.f},util::random(2*PI),util::random(2*PI),util::degToRad(ConfigFloat("Stone Rain.Stone Spell Circle Rotation Spd")),ConfigPixel("Stone Rain.Stone Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Stone Rain.Stone Spell Insignia Rotation Spd")))EndBullet;
}
}
}

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 1
#define VERSION_MINOR 3
#define VERSION_PATCH 0
#define VERSION_BUILD 11936
#define VERSION_BUILD 11946
#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="76" height="85" tilewidth="24" tileheight="24" infinite="0" nextlayerid="7" nextobjectid="30">
<map version="1.10" tiledversion="1.10.2" class="Map" orientation="orthogonal" renderorder="right-down" width="76" height="85" tilewidth="24" tileheight="24" infinite="0" nextlayerid="7" nextobjectid="32">
<properties>
<property name="Background Music" propertytype="BGM" value="beach_boss"/>
<property name="Level Type" type="int" propertytype="LevelType" value="1"/>
@ -564,5 +564,16 @@
<object id="28" name="Hiding Spot" x="1146" y="1176">
<point/>
</object>
<object id="30" name="Ghost of Pirate Captain Spawn" type="SpawnGroup" x="288" y="792" width="1176" height="552">
<properties>
<property name="Boss Title Display" value="Ghost of Pirate Captain"/>
</properties>
<ellipse/>
</object>
<object id="31" template="../maps/Monsters/Ghost of Pirate Captain.tx" x="774" y="1212">
<properties>
<property name="spawner" type="object" value="30"/>
</properties>
</object>
</objectgroup>
</map>

Binary file not shown.

After

Width:  |  Height:  |  Size: 742 B

@ -1004,8 +1004,8 @@ MonsterStrategy
Stone Radius = 50
Stone Knockback Amt = 150
Stone Spell Circle Color = 255, 40, 40, 160
Stone Spell Insignia Color = 72, 66, 80, 255
Stone Spell Circle Color = 24, 16, 79, 160
Stone Spell Insignia Color = 135, 151, 143, 255
# Degrees/sec. Positive is CW, Negative is CCW.
Stone Spell Circle Rotation Spd = -30
# Degrees/sec. Positive is CW, Negative is CCW.
@ -1307,5 +1307,22 @@ MonsterStrategy
Cannon Shot Delay = 2.5s
Silence Time = 2s
Shrapnel Shot Delay = 2.5s
Bombardment Max Distance = 900
Precise Bombardment Max Distance = 700
# Provide an X,Y,Z falling velocity
Cannon Vel = -40.0, 0.0, -250.0
# How long the indicator will appear before the cannon drops down.
Indicator Time = 1s
Cannon Radius = 175
Cannon Damage = 80
Cannon Knockback Amt = 200
Cannon Spell Circle Color = 255, 40, 40, 160
Cannon Spell Insignia Color = 72, 66, 80, 255
# Degrees/sec. Positive is CW, Negative is CCW.
Cannon Spell Circle Rotation Spd = -30
# Degrees/sec. Positive is CW, Negative is CCW.
Cannon Spell Insignia Rotation Spd = 50
}
}

@ -1820,7 +1820,7 @@ Monsters
CollisionDmg = 50
MoveSpd = 50%
Size = 600%
Size = 400%
XP = 0

@ -146,6 +146,7 @@ Images
GFX_InkBullet = inkbullet.png
GFX_InkBubbleExplode = inkbubble_explode.png
GFX_Ink = ink.png
GFX_Cannonball = cannonball.png
GFX_Thief_Sheet = nico-thief.png
GFX_Trapper_Sheet = nico-trapper.png

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.11.0" orientation="orthogonal" renderorder="right-down" width="30" height="20" tilewidth="24" tileheight="24" infinite="1" nextlayerid="3" nextobjectid="45">
<map version="1.10" tiledversion="1.10.2" orientation="orthogonal" renderorder="right-down" width="30" height="20" tilewidth="24" tileheight="24" infinite="1" nextlayerid="3" nextobjectid="46">
<tileset firstgid="1" source="Monsters.tsx"/>
<layer id="1" name="Tile Layer 1" width="30" height="20">
<data encoding="csv"/>
@ -39,5 +39,6 @@
<object id="42" template="Monsters/Giant Crab.tx" type="Monster" x="-108" y="582"/>
<object id="43" template="Monsters/Octopus Arm.tx" type="Monster" x="-48" y="744"/>
<object id="44" template="Monsters/Giant Octopus.tx" type="Monster" x="120" y="744"/>
<object id="45" template="Monsters/Ghost of Pirate Captain.tx" type="Monster" x="-306" y="732"/>
</objectgroup>
</map>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<template>
<tileset firstgid="1" source="../Monsters.tsx"/>
<object name="Ghost of Pirate Captain" type="Monster" gid="33" width="192" height="192"/>
</template>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Loading…
Cancel
Save