Add Pct-based pillar respawning attack for Stone Golem. Add "Breaking Stone Pillar" versions that will automatically shake and crumble. Release Build 9951.
This commit is contained in:
parent
3560ddc31e
commit
784aa022e2
@ -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
|
||||
}
|
||||
|
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user