Add option to only allow one emergency reboot per map (enforced on nightmare difficulties).

Make Elemental Coating shader less eye-straining.
Leave "ashen remains" when a target is erased by the Ynykron.
Fix crushers not breaking if player isn't taking damage.
This commit is contained in:
Mari the Deer 2021-03-21 00:51:52 +01:00
commit ea7775119d
10 changed files with 128 additions and 51 deletions

View file

@ -22,6 +22,7 @@ Class Demolitionist : PlayerPawn
SWWMStats mystats;
int cairtime;
bool hasteleported;
bool hasrevived;
int lastmpain;
@ -1328,6 +1329,41 @@ Class Demolitionist : PlayerPawn
}
}
}
private void CheckBreakCrusher()
{
double gaph = (ceilingz-floorz);
if ( gaph > height*.6 ) return;
// the smaller the gap, the more likely the crusher will snap
if ( Random[Demolitionist](0,3) && (FRandom[Demolitionist](0,gaph/height) > .1) ) return;
double diffh = 8.+(default.height-gaph); // how much the crusher will have to "snap" after breaking
let ceil = ceilingsector;
let flor = floorsector;
let ceilse = ceil.ceilingdata;
let florse = flor.floordata;
if ( ceilse && florse )
{
// snap both planes
let q = Spawn("BustedQuake",(ceil.centerspot.x,ceil.centerspot.y,ceil.ceilingplane.ZAtPoint(ceil.centerspot)));
q.special1 = 6;
q = Spawn("BustedQuake",(flor.centerspot.x,flor.centerspot.y,flor.floorplane.ZAtPoint(flor.centerspot)));
q.special1 = 6;
SWWMCrusherBroken.Create(flor,ceil,diffh/2.);
}
else if ( ceilse )
{
// snap ceiling
let q = Spawn("BustedQuake",(ceil.centerspot.x,ceil.centerspot.y,ceil.ceilingplane.ZAtPoint(ceil.centerspot)));
q.special1 = 10;
SWWMCrusherBroken.Create(null,ceil,diffh);
}
else if ( florse )
{
// snap floor
let q = Spawn("BustedQuake",(flor.centerspot.x,flor.centerspot.y,flor.floorplane.ZAtPoint(flor.centerspot)));
q.special1 = 10;
SWWMCrusherBroken.Create(flor,null,diffh);
}
}
override int DamageMobj( Actor inflictor, Actor source, int damage, Name mod, int flags, double angle )
{
// we still have to ENSURE ENTIRELY that this gets nullified (TELEFRAG_DAMAGE overrides damage factors somehow)
@ -1338,6 +1374,9 @@ Class Demolitionist : PlayerPawn
let hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
if ( hnd ) hnd.tookdamage[PlayerNumber()] = true;
}
// check if we can break any active crushers
if ( (mod == 'Crush') && !inflictor && !source )
CheckBreakCrusher();
// no damage whatsoever
if ( scriptedinvul )
return 0;
@ -1832,8 +1871,9 @@ Class Demolitionist : PlayerPawn
else if ( (player.cmd.buttons&BT_ATTACK) && (deadtimer > 120) && swwm_revive )
{
// reboot (if possible)
if ( !FindInventory("ReviveCooldown") )
if ( !FindInventory("ReviveCooldown") && (((swwm_revivecooldown >= 0) && (G_SkillPropertyInt(SKILLP_ACSReturn) < 4)) || !hasrevived) )
{
hasrevived = true;
player.Resurrect();
player.damagecount = 0;
player.bonuscount = 0;
@ -1857,7 +1897,7 @@ Class Demolitionist : PlayerPawn
SWWMHandler.DoFlash(self,Color(255,128,192,255),30);
SWWMScoreObj.Spawn(default.health,Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Height/2),ST_Health);
if ( special1 > 2 ) special1 = 0;
if ( swwm_revivecooldown > 0 )
if ( (swwm_revivecooldown > 0) && (G_SkillPropertyInt(SKILLP_ACSReturn) < 4) )
GiveInventory("ReviveCooldown",1);
}
else if ( level.maptime > revivefail )
@ -2429,6 +2469,7 @@ Class Demolitionist : PlayerPawn
dashfuel = default.dashfuel;
last_boost = 0;
last_kick = 0;
hasrevived = false;
// cancel dash/boost
A_StopSound(CHAN_JETPACK);
fuelcooldown = 0.;

View file

@ -71,43 +71,7 @@ Class AlmasteelPlating : Inventory
// 80% reduction for explosions
if ( flags&DMG_EXPLOSION ) newdamage = newdamage/5;
// 50% reduction for crushing
if ( damageType == 'Crush' )
{
newdamage = newdamage/2;
// additionally, check if we can break any active crushers
double gaph = (Owner.ceilingz-Owner.floorz);
if ( gaph > Owner.height*.6 ) return;
// the smaller the gap, the more likely the crusher will snap
if ( Random[Demolitionist](0,3) && (FRandom[Demolitionist](0,gaph/Owner.height) > .1) ) return;
double diffh = 8.+(Owner.default.height-gaph); // how much the crusher will have to "snap" after breaking
let ceil = Owner.ceilingsector;
let flor = Owner.floorsector;
let ceilse = ceil.ceilingdata;
let florse = flor.floordata;
if ( ceilse && florse )
{
// snap both planes
let q = Spawn("BustedQuake",(ceil.centerspot.x,ceil.centerspot.y,ceil.ceilingplane.ZAtPoint(ceil.centerspot)));
q.special1 = 6;
q = Spawn("BustedQuake",(flor.centerspot.x,flor.centerspot.y,flor.floorplane.ZAtPoint(flor.centerspot)));
q.special1 = 6;
SWWMCrusherBroken.Create(flor,ceil,diffh/2.);
}
else if ( ceilse )
{
// snap ceiling
let q = Spawn("BustedQuake",(ceil.centerspot.x,ceil.centerspot.y,ceil.ceilingplane.ZAtPoint(ceil.centerspot)));
q.special1 = 10;
SWWMCrusherBroken.Create(null,ceil,diffh);
}
else if ( florse )
{
// snap floor
let q = Spawn("BustedQuake",(flor.centerspot.x,flor.centerspot.y,flor.floorplane.ZAtPoint(flor.centerspot)));
q.special1 = 10;
SWWMCrusherBroken.Create(flor,null,diffh);
}
}
if ( damageType == 'Crush' ) newdamage = newdamage/2;
}
override bool HandlePickup( Inventory item )
{
@ -142,7 +106,7 @@ Class ReviveCooldown : Powerup
Default
{
Inventory.Icon "graphics/HUD/Icons/I_Revive.png";
Powerup.Duration -30;
Powerup.Duration -60;
}
override void Tick()
@ -156,7 +120,7 @@ Class ReviveCooldown : Powerup
{
Super.InitEffect();
// adjust the duration
EffectTics = max(0,swwm_revivecooldown)*GameTicRate;
EffectTics = clamp(swwm_revivecooldown*60,0,300)*GameTicRate;
}
override void EndEffect()
{

View file

@ -1,5 +1,47 @@
// Ynykron projectiles and effects
// there was an enemy here, but it's gone now
Class AshenRemains : Actor
{
override void Tick()
{
double fz = CurSector.floorplane.ZAtPoint(pos.xy);
if ( fz != pos.z ) SetOrigin((pos.x,pos.y,fz),true);
if ( isFrozen() ) return;
special1++;
if ( special1 > 350 ) A_FadeOut(0.01);
}
override void PostBeginPlay()
{
if ( (waterlevel > 0) || GetFloorTerrain().isliquid )
{
Destroy();
return;
}
double fz = CurSector.floorplane.ZAtPoint(pos.xy);
SetZ(fz);
prev.z = fz;
SWWMUtility.SetToSlope(self,FRandom[Ynykron](0,360));
}
default
{
RenderStyle "Shaded";
StencilColor "000000";
Radius .1;
Height 0.;
+NOBLOCKMAP;
+NOINTERACTION;
+DONTSPLASH;
+NOTELEPORT;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
// cheap way to let players know they just got fucking erased from existence
Class PlayerGone : PlayerChunk
{
@ -360,7 +402,15 @@ Class YnykronImpact : Actor
{
// voodoo dolls just get erased (how convenient)
// otherwise instantly vaporize the fucker
if ( tracer.player && (tracer.player.mo != tracer) ) tracer.Destroy();
if ( tracer.player && (tracer.player.mo != tracer) )
{
if ( tracer.pos.z < (tracer.floorz+64) )
{
let r = Spawn("AshenRemains",tracer.pos);
r.scale *= tracer.radius/16.;
}
tracer.Destroy();
}
else if ( tracer.CountInv("GrilledCheeseSandwich") > 0 )
{
// force use the sandwich
@ -382,6 +432,11 @@ Class YnykronImpact : Actor
tracer.A_ChangeLinkFlags(true); // remove from blockmap, should guarantee archviles not raising this
IDontFeelSoGood.DeletThis(tracer); // ensures corpse is deleted too
}
if ( tracer.pos.z < (tracer.floorz+64) )
{
let r = Spawn("AshenRemains",tracer.pos);
r.scale *= tracer.radius/16.;
}
}
}
if ( YnykronShot(master) )