Add Pct-based pillar respawning attack for Stone Golem. Add "Breaking Stone Pillar" versions that will automatically shake and crumble. Release Build 9951.

mac-build
sigonasr2 7 months ago
parent 717f4551ea
commit 89db31ceea
  1. 29
      Adventures in Lestoria/BreakingPillar.cpp
  2. 5
      Adventures in Lestoria/MonsterAttribute.h
  3. 51
      Adventures in Lestoria/StoneGolem.cpp
  4. 2
      Adventures in Lestoria/Version.h
  5. 26
      Adventures in Lestoria/assets/config/MonsterStrategies.txt
  6. 50
      Adventures in Lestoria/assets/config/Monsters.txt
  7. BIN
      Adventures in Lestoria/assets/gamepack.pak
  8. BIN
      x64/Release/Adventures in Lestoria.exe

@ -43,6 +43,11 @@ All rights reserved.
using A=Attribute;
void Monster::STRATEGY::BREAKING_PILLAR(Monster&m,float fElapsedTime,std::string strategy){
enum Phase{
INITIALIZE,
RUN,
};
if(m.GetHealthRatio()>=ConfigFloat("Break Phase 1 HP % Threshold")/100.f){
m.animation.ModifyDisplaySprite(m.internal_animState,ConfigString("Unbroken Animation Name"));
}else
@ -50,6 +55,30 @@ void Monster::STRATEGY::BREAKING_PILLAR(Monster&m,float fElapsedTime,std::string
m.animation.ModifyDisplaySprite(m.internal_animState,ConfigString("Break Phase 1 Animation Name"));
}else m.animation.ModifyDisplaySprite(m.internal_animState,ConfigString("Break Phase 2 Animation Name"));
switch(m.phase){
case INITIALIZE:{
m.F(A::BREAK_TIME)=ConfigFloat("Break Time");
m.F(A::SHAKE_TIMER)=0.2f;
m.phase=RUN;
}break;
case RUN:{
m.F(A::BREAK_TIME)-=fElapsedTime;
if(m.F(A::BREAK_TIME)<=2.f){
if(m.F(A::BREAK_TIME)<=0.f){
m._DealTrueDamage(m.GetHealth()); //Kill the pillar, making it crumble.
break;
}
m.F(A::SHAKE_TIMER)-=fElapsedTime;
if(m.F(A::SHAKE_TIMER)<=0.f){
m.F(A::SHAKE_TIMER)+=0.2f;
if(m.B(A::SHAKE_DIR))m.SetX(m.GetPos().x-2);
else m.SetX(m.GetPos().x+2);
m.B(A::SHAKE_DIR)=!m.B(A::SHAKE_DIR);
}
}
}break;
}
m.SetStrategyDeathFunction([&](GameEvent&deathEvent,Monster&m,const std::string&strategy){
m.lifetime=0.01f;
m.B(A::MARKED_DEAD)=true;

@ -126,4 +126,9 @@ enum class Attribute{
PLAYED_FLAG,
HEALTH_PCT_PHASE, //Used for tracking the percentage a mechanic was done in Stone Golem Fight.
STAGE_POLYGONS,
NEXT_HEALTH_PCT_PILLAR_PHASE,
BAD_PILLAR_SPAWN_COUNT,
BREAK_TIME,
SHAKE_TIMER,
SHAKE_DIR,
};

@ -55,7 +55,9 @@ void Monster::STRATEGY::STONE_GOLEM(Monster&m,float fElapsedTime,std::string str
enum PhaseName{
INITIALIZE,
SPAWN_PILLAR_PREPARE,
RESPAWN_PILLAR_PREPARE,
SPAWN_PILLAR_CAST,
RESPAWN_PILLAR_CAST,
STANDARD,
STONE_THROW_CAST,
STONE_THROW_FINISH_ANIMATION,
@ -114,7 +116,10 @@ void Monster::STRATEGY::STONE_GOLEM(Monster&m,float fElapsedTime,std::string str
m.F(A::RECOVERY_TIME)=ConfigFloat("Beginning Phase.Pillar Cast Delay Time");
m.I(A::PATTERN_REPEAT_COUNT)=ConfigInt("Beginning Phase.Repeat Count");
m.F(A::HEALTH_PCT_PHASE)=1.f;
m.F(A::NEXT_HEALTH_PCT_PILLAR_PHASE)=ConfigFloat("Pillar Respawns.Start HP Threshold")/100.f;
m.phase=SPAWN_PILLAR_PREPARE;
if(ConfigIntArr("Pillar Respawns.Respawn Count",0)<ConfigIntArr("Pillar Respawns.Respawn Count",1))ERR(std::format("WARNING! {} Stone golem pillars were declared damaged when only {} will spawn. Please make sure the number is the same or equal to the total spawned pillars! (\"Pillar Respawns.Respawn Count\" strategy property)",ConfigIntArr("Pillar Respawns.Respawn Count",1),ConfigIntArr("Pillar Respawns.Respawn Count",0)));
}break;
case SPAWN_PILLAR_PREPARE:{
m.F(A::RECOVERY_TIME)-=fElapsedTime;
@ -127,6 +132,17 @@ void Monster::STRATEGY::STONE_GOLEM(Monster&m,float fElapsedTime,std::string str
m.phase=SPAWN_PILLAR_CAST;
}
}break;
case RESPAWN_PILLAR_PREPARE:{
m.F(A::RECOVERY_TIME)-=fElapsedTime;
if(m.F(A::RECOVERY_TIME)<=0.f){
m.V(A::LOCKON_POS)=game->GetPlayer()->GetPos();
m.SIZET(A::LOOPING_SOUND_ID)=SoundEffect::PlayLoopingSFX("Rock Toss Cast",m.GetPos());
m.PerformAnimation("CAST",m.GetFacingDirectionToTarget(m.V(A::LOCKON_POS)));
game->AddEffect(std::make_unique<SpellCircle>(m.V(A::LOCKON_POS),ConfigFloat("Pillar Respawns.Cast Time"),"range_indicator.png","spell_insignia.png",m.OnUpperLevel(),vf2d{1.f,1.f}*(MONSTER_DATA.at("Stone Golem Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Golem Pillar").GetSizeMult()/12.f)*1.25f,0.3f,vf2d{},ConfigPixel("Pillar Respawns.Spell Circle Color"),util::random(2*PI),util::degToRad(ConfigFloat("Pillar Respawns.Spell Circle Rotation Spd")),false,vf2d{1.f,1.f}*(MONSTER_DATA.at("Stone Golem Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Golem Pillar").GetSizeMult()/12.f)*0.9f,0.3f,vf2d{},ConfigPixel("Pillar Respawns.Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Pillar Respawns.Spell Insignia Rotation Spd"))),true);
m.F(A::CASTING_TIMER)=ConfigFloat("Pillar Respawns.Cast Time");
m.phase=RESPAWN_PILLAR_CAST;
}
}break;
case SPAWN_PILLAR_CAST:{
m.F(A::CASTING_TIMER)-=fElapsedTime;
if(m.F(A::CASTING_TIMER)<=0.f){
@ -144,18 +160,49 @@ void Monster::STRATEGY::STONE_GOLEM(Monster&m,float fElapsedTime,std::string str
}
}
}break;
case RESPAWN_PILLAR_CAST:{
m.F(A::CASTING_TIMER)-=fElapsedTime;
if(m.F(A::CASTING_TIMER)<=0.f){
SoundEffect::StopLoopingSFX(m.SIZET(A::LOOPING_SOUND_ID));
SoundEffect::PlaySFX("Pillar Rise",m.V(A::LOCKON_POS));
if(m.I(A::BAD_PILLAR_SPAWN_COUNT)>0&&
(util::random_range(0,1)<0.5f||m.I(A::PATTERN_REPEAT_COUNT)<=m.I(A::BAD_PILLAR_SPAWN_COUNT))){
Monster&badPillar{game->SpawnMonster(m.V(A::LOCKON_POS),MONSTER_DATA.at("Breaking Stone Golem Pillar"),m.OnUpperLevel())};
badPillar._DealTrueDamage(badPillar.GetMaxHealth()-1U); //Force the health to be 1.
m.I(A::BAD_PILLAR_SPAWN_COUNT)--;
}else game->SpawnMonster(m.V(A::LOCKON_POS),MONSTER_DATA.at("Stone Golem Pillar"),m.OnUpperLevel());
m.I(A::PATTERN_REPEAT_COUNT)--;
game->Hurt(m.V(A::LOCKON_POS),MONSTER_DATA.at("Stone Golem Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Golem Pillar").GetSizeMult(),MONSTER_DATA.at("Stone Golem Pillar").GetAttack(),m.OnUpperLevel(),0.f,HurtType::PLAYER);
if(m.I(A::PATTERN_REPEAT_COUNT)<=0){
m.phase=STANDARD;
}else{
m.PerformIdleAnimation(m.GetFacingDirectionToTarget(game->GetPlayer()->GetPos()));
m.F(A::RECOVERY_TIME)=ConfigFloat("Pillar Respawns.Cast Delay Time");
m.phase=RESPAWN_PILLAR_PREPARE;
}
}
}break;
case STANDARD:{
BEAR(m,fElapsedTime,"Bear");
//Extending the bear script's variables to read the state of it...
const bool SlamHasFinished=m.I(A::ATTACK_COUNT)!=m.I(A::BEAR_STOMP_COUNT);
if(SlamHasFinished){
if(m.F(A::HEALTH_PCT_PHASE)-m.GetHealthRatio()>=0.1f){
m.F(A::HEALTH_PCT_PHASE)-=0.1f;
if(m.F(A::HEALTH_PCT_PHASE)-m.GetHealthRatio()>=ConfigFloat("Shockwave.Repeating Threshold")/100.f){
m.F(A::HEALTH_PCT_PHASE)-=ConfigFloat("Shockwave.Repeating Threshold")/100.f;
m.F(A::CASTING_TIMER)=ConfigFloat("Shockwave.Cast Time");
PrepareSafeAreas();
m.phase=SHOCKWAVE;
break;
}
if(m.F(A::NEXT_HEALTH_PCT_PILLAR_PHASE)>=m.GetHealthRatio()){
m.F(A::NEXT_HEALTH_PCT_PILLAR_PHASE)-=ConfigFloat("Pillar Respawns.Repeating Threshold")/100.f;
m.F(A::RECOVERY_TIME)=ConfigFloat("Pillar Respawns.Cast Delay Time");
m.I(A::PATTERN_REPEAT_COUNT)=ConfigIntArr("Pillar Respawns.Respawn Count",0);
m.I(A::BAD_PILLAR_SPAWN_COUNT)=ConfigIntArr("Pillar Respawns.Respawn Count",1);
m.phase=RESPAWN_PILLAR_PREPARE;
break;
}
const bool StoneThrowRollSucceeds=util::random(100.f)<=ConfigFloat("Standard Attack.Stone Throw Chance");
m.I(A::ATTACK_COUNT)=m.I(A::BEAR_STOMP_COUNT); //Make sure the slams are now reset if necessary.

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 1
#define VERSION_MINOR 2
#define VERSION_PATCH 3
#define VERSION_BUILD 9948
#define VERSION_BUILD 9951
#define stringify(a) stringify_(a)
#define stringify_(a) #a

@ -898,6 +898,25 @@ MonsterStrategy
}
Stone Golem
{
Pillar Respawns
{
Start HP Threshold = 75%
# How much HP Pct separates each triple pillar respawn.
Repeating Threshold = 10%
# How many pillars to spawn each time. Optionally, the second argument indicates how many spawn damaged.
Respawn Count = 3,2 damaged
Cast Time = 2s
Cast Delay Time = 0.5s
Spell Circle Color = 40, 40, 40, 80
Spell Insignia Color = 144, 137, 160, 255
# Degrees/sec. Positive is CW, Negative is CCW.
Spell Circle Rotation Spd = -30
# Degrees/sec. Positive is CW, Negative is CCW.
Spell Insignia Rotation Spd = 50
}
Beginning Phase
{
# Number of pillars to spawn.
@ -933,6 +952,10 @@ MonsterStrategy
}
Shockwave
{
Start HP Threshold = 90%
# How much HP Pct separates each shockwave attack.
Repeating Threshold = 10%
Cast Time = 3s
Damage = 60
Pillar Damage = 1
@ -953,6 +976,9 @@ MonsterStrategy
Break Phase 2 HP % Threshold = 34% or below
Break Phase 2 Animation Name = BREAK2
# How long until the pillar breaks. When <2 seconds remains, it starts visually shaking to indicate it is about to disappear.
Break Time = 999999s
Death Ring Bullet Count = 24
Death Ring Bullet Speed = 140
Death Ring Bullet Damage = 15

@ -1096,6 +1096,56 @@ Monsters
# Death Sound = Slime Dead
# Walk Sound = Slime Walk
# Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity
# DROP[0] = Ring of the Bear,100%,1,1
}
Breaking Stone Golem Pillar
{ # Has three lives and breaks once all three health is lost. Changes sprite based on health.
Health = 3
Attack = 40
CollisionDmg = 0
Immovable = True
Invulnerable = True
MoveSpd = 0%
# The Pillar is supposed to be 350 radius.
Size = 600%
Collision Radius = 7
# If provided, constructs a rectangular collision instance for this enemy.
# Args: Pos X,Pos Y,Width,Height.
# NOTE: Position coordinates are relative.
Rectangle Collision = -4,-4,8,8
XP = 0
Strategy = Breaking Pillar
## Breaking Pillar override
Break Time = 3s
#Size of each animation frame
SheetFrameSize = 24,96
# Setting this to true means every four rows indicates one animation, the ordering of the directions is: NORTH, EAST, SOUTH, WEST
4-Way Spritesheet = False
Animations
{
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# Animations must be defined in the same order as they are in their sprite sheets
# The First Four animations must represent a standing, walking, attack, and death animation. Their names are up to the creator.
NORMAL = 4, 0.4, OneShot
BREAK1 = 4, 0.4, OneShot
BREAK2 = 4, 0.4, OneShot
CRUMBLE = 6, 0.3, OneShot
}
Hurt Sound = Warrior Ground Slam
# Death Sound = Slime Dead
# Walk Sound = Slime Walk
# Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity
# DROP[0] = Ring of the Bear,100%,1,1
}

Loading…
Cancel
Save