Remove global 50% damage reduction for players (a bit too cheap).

Add 50% crusher damage reduction + chance to break crushers.
Don't spawn gibs when using 'kill monsters'.
Allow player to "fake pick up" unsupported vanilla armor, so specials and item counters can still work.
This commit is contained in:
Mari the Deer 2021-02-18 20:53:28 +01:00
commit 0e12ca15c8
6 changed files with 151 additions and 10 deletions

View file

@ -1486,8 +1486,8 @@ Class SWWMHandler : EventHandler
// gibbing
private void DoGibThing( WorldEvent e )
{
// no gib if it was erased
if ( e.DamageType == 'Ynykron' ) return;
// no gib if it was erased or used the kill monsters cheat
if ( (e.DamageType == 'Ynykron') || (e.DamageType == 'Massacre') ) return;
int gibhealth = e.Thing.GetGibHealth();
bool gotgibbed = (!e.Thing.bDONTGIB && ((e.Inflictor && e.Inflictor.bEXTREMEDEATH) || (e.DamageSource && e.DamageSource.bEXTREMEDEATH) || (e.DamageType == 'Extreme') || (e.Thing.Health < gibhealth)) && (!e.Inflictor || !e.Inflictor.bNOEXTREMEDEATH) && (!e.DamageSource || !e.DamageSource.bNOEXTREMEDEATH));
bool forcegibbed = false;

View file

@ -89,7 +89,6 @@ Class Demolitionist : PlayerPawn
DamageFactor "Poison", 0.;
DamageFactor "PoisonCloud", 0.;
DamageFactor "Falling", 0.;
DamageFactor "Crush", .25;
Demolitionist.DashFuel 240.;
+NOBLOOD;
+DONTGIB;
@ -2634,15 +2633,56 @@ Class AlmasteelPlating : Inventory
{
if ( inflictor && (inflictor is 'CorrodeDebuff') ) dbf = Inventory(inflictor);
if ( (damage <= 0) || (flags&(DMG_FORCED|DMG_NO_ARMOR)) ) return;
// 50% reduction for normal damage, 80% reduction for explosions
if ( flags&DMG_EXPLOSION ) newdamage = max(1,damage/5);
else newdamage = max(1,damage/2);
newdamage = damage;
// 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);
}
}
}
override bool HandlePickup( Inventory item )
{
// disallow vanilla armors
if ( (item is 'BasicArmor') || (item is 'BasicArmorBonus') || (item is 'BasicArmorPickup') || (item is 'HexenArmor') )
{
item.bPickupGood = true; // but act as if we picked them up
return true;
}
return false;
}
override void AttachToOwner( Actor other )

View file

@ -1205,3 +1205,105 @@ Class SWWMDamageAccumulator : Thinker
return 0;
}
}
// prevents floors/ceilings from ever moving again, as they're "broken crushers"
Class SWWMCrusherBroken : Thinker
{
Sector fsec, csec;
double diffh;
int fphase, cphase;
int ftics, ctics;
static void Create( Sector f, Sector c, double diffh )
{
if ( !f && !c ) return;
let ti = ThinkerIterator.Create("SWWMCrusherBroken",STAT_USER);
SWWMCrusherBroken cb;
while ( cb = SWWMCrusherBroken(ti.Next()) )
{
if ( (cb.fsec == f) && (cb.csec == c) )
return; // we already have this
if ( cb.fsec && (cb.fsec == f) )
{
cb.Destroy(); // we override this one
continue;
}
if ( cb.csec && (cb.csec == c) )
{
cb.Destroy(); // we override this one
continue;
}
}
cb = new("SWWMCrusherBroken");
cb.fsec = f;
cb.csec = c;
cb.ChangeStatNum(STAT_USER);
cb.diffh = diffh;
if ( f && f.floordata ) f.floordata.Destroy();
if ( c && c.ceilingdata ) c.ceilingdata.Destroy();
}
override void Tick()
{
if ( fsec )
{
if ( cphase <= 0 )
{
if ( level.CreateFloor(fsec,Floor.floorLowerByValue,null,16.,diffh*.4) )
{
ftics = int(diffh*.4/16.)+40;
fphase = 1;
}
}
else if ( fphase == 1 )
{
ftics--;
if ( (ftics <= 0) && level.CreateFloor(fsec,Floor.floorLowerByValue,null,1.,diffh*.6) )
{
ftics = int(diffh*.6)+8;
fphase = 2;
}
}
else if ( fphase == 2 )
{
ftics--;
if ( ftics <= 0 ) fphase = 3;
}
else if ( (fphase >= 3) && fsec.floordata )
{
fsec.floordata.Destroy();
fsec.StopSoundSequence(CHAN_WEAPON);
}
}
if ( csec )
{
if ( cphase <= 0 )
{
if ( level.CreateCeiling(csec,Ceiling.ceilRaiseByValue,null,16.,16.,diffh*.4) )
{
ctics = int(diffh*.4/16.)+40;
cphase = 1;
}
}
else if ( cphase == 1 )
{
ctics--;
if ( (ctics <= 0) && level.CreateCeiling(csec,Ceiling.ceilRaiseByValue,null,1.,1.,diffh*.6) )
{
ctics = int(diffh*.6)+10;
cphase = 2;
}
}
else if ( cphase == 2 )
{
ctics--;
if ( ctics <= 0 ) cphase = 3;
}
else if ( (cphase >= 3) && csec.ceilingdata )
{
csec.ceilingdata.Destroy();
csec.StopSoundSequence(CHAN_VOICE);
}
}
}
}