More Mortal Rifle progress. Precision Shot partially implemented.

This commit is contained in:
Mari the Deer 2022-09-13 21:25:06 +02:00
commit 639999de8b
13 changed files with 640 additions and 19 deletions

View file

@ -1,3 +1,3 @@
[default]
SWWM_MODVER="\cyDEMOLITIONIST \cw1.3pre r446 \cu(Tue 13 Sep 18:12:15 CEST 2022)\c-";
SWWM_SHORTVER="\cw1.3pre r446 \cu(2022-09-13 18:12:15)\c-";
SWWM_MODVER="\cyDEMOLITIONIST \cw1.3pre r447 \cu(Tue 13 Sep 21:25:06 CEST 2022)\c-";
SWWM_SHORTVER="\cw1.3pre r447 \cu(2022-09-13 21:25:06)\c-";

View file

@ -1,3 +1,60 @@
Model "MisterCasing"
{
Path "models"
Model 0 "MortalCasing_d.3d"
Skin 0 "MortalRound_Used.png"
Scale 0.03 0.03 0.03
AngleOffset 90
USEACTORPITCH
USEACTORROLL
FrameIndex XZW1 A 0 0
ZOffset 0.35
FrameIndex XZW1 B 0 0
PitchOffset 90
FrameIndex XZW1 C 0 0
PitchOffset 180
FrameIndex XZW1 D 0 0
PitchOffset 270
FrameIndex XZW1 E 0 0
}
Model "MisterGCasing"
{
Path "models"
Model 0 "MortalGrenadeCasing_d.3d"
Skin 0 "MortalGrenade_Used.png"
Scale 0.03 0.03 0.03
AngleOffset 90
USEACTORPITCH
USEACTORROLL
FrameIndex XZW1 A 0 0
ZOffset 1.1
FrameIndex XZW1 B 0 0
}
Model "MisterMag"
{
Path "models"
Model 0 "MortalMag_d.3d"
Scale 0.03 0.03 0.03
AngleOffset 90
USEACTORPITCH
USEACTORROLL
Skin 0 "MortalMag_Empty.png"
FrameIndex XZW1 A 0 0
ZOffset 0.8
PitchOffset 90
FrameIndex XZW1 B 0 0
PitchOffset -90
FrameIndex XZW1 C 0 0
}
Model "MisterRifle"
{
Path "models"
@ -16,6 +73,38 @@ Model "MisterRifle"
FrameIndex XZW1 A 0 0
}
Model "MisterRifle"
{
Path "models/extra"
Model 2 "Flat_d.3d"
Scale 0.15 0.15 0.15
Offset 15 -90 -15
RollOffset 90
AngleOffset 90
Skin 2 "MRMuz0.png"
FrameIndex XZW0 A 2 0
Skin 2 "MRMuz1.png"
FrameIndex XZW0 B 2 0
Skin 2 "MRMuz2.png"
FrameIndex XZW0 C 2 0
Skin 2 "MRMuz3.png"
FrameIndex XZW0 D 2 0
Scale 0.1 0.1 0.1
Offset 15 -80 -26
Skin 2 "MRMuz0.png"
FrameIndex XZW0 E 2 0
Skin 2 "MRMuz1.png"
FrameIndex XZW0 F 2 0
Skin 2 "MRMuz2.png"
FrameIndex XZW0 G 2 0
Skin 2 "MRMuz3.png"
FrameIndex XZW0 H 2 0
}
Model "MisterRifle"
{
Path "models"

BIN
models/extra/MuzTest.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
palettes/Cyanblu.pal Normal file

Binary file not shown.

View file

@ -1,14 +1,157 @@
// Plutoni Inc. Mortal Rifle (from UnSX 2)
// Slot 9, spawns shared with Candygun
// like the silver bullet tracer except there's no penetration factor
// just a maximum possible travel distance (which is mainly used for probing through walls)
Class MisterRailTracer : LineTracer
{
Actor ignoreme;
Array<HitListEntry> hitlist;
Array<Line> shootthroughlist;
Array<WaterHit> waterhitlist;
double RealMaxDist;
bool pastwall, fullstop;
Array<WallPenetrate> WallPenetrateList;
Vector3 exitpoint;
transient Array<F3DFloor> ffloors; // needs to be done like this because HAHA SCOPE
override ETraceStatus TraceCallback()
{
// liquid splashes
if ( Results.CrossedWater )
{
let hl = new("WaterHit");
hl.sect = Results.CrossedWater;
hl.hitpos = Results.CrossedWaterPos;
WaterHitList.Push(hl);
}
else if ( Results.Crossed3DWater )
{
let hl = new("WaterHit");
hl.sect = Results.Crossed3DWater;
hl.hitpos = Results.Crossed3DWaterPos;
WaterHitList.Push(hl);
}
if ( Results.HitType == TRACE_HitActor )
{
if ( Results.HitActor == ignoreme ) return TRACE_Skip;
if ( Results.HitActor.bSHOOTABLE )
{
let ent = new("HitListEntry");
ent.hitactor = Results.HitActor;
ent.hitlocation = Results.HitPos;
ent.x = Results.HitVector;
ent.pastwall = pastwall;
hitlist.Push(ent);
return TRACE_Skip;
}
return TRACE_Skip;
}
else if ( Results.HitType == TRACE_HasHitSky )
{
fullstop = true;
return TRACE_Stop;
}
else if ( Results.HitType != TRACE_HitNone )
{
if ( Results.HitType == TRACE_HitWall )
{
ShootThroughList.Push(Results.HitLine);
if ( (Results.Tier == TIER_Middle) && Results.HitLine.sidedef[1] && !(Results.HitLine.Flags&(Line.ML_BlockHitscan|Line.ML_BlockEverything)) )
return TRACE_Skip;
}
int maxstep = int(RealMaxDist-Results.Distance);
for ( int i=1; i<=maxstep; i++ )
{
Vector3 ofs = Results.HitPos+Results.HitVector*i;
if ( level.IsPointInLevel(ofs) )
{
// double-check if we're piercing through a 3D floor (yes this is a thing that happens, oh boy)
Sector s = level.PointInSector(ofs.xy);
bool stop3d = false;
for ( int j=0; j<ffloors.Size(); j++ )
{
if ( ffloors[j].target != s ) continue;
double minz = ffloors[j].bottom.ZAtPoint(ofs.xy);
double maxz = ffloors[j].top.ZAtPoint(ofs.xy);
if ( (ofs.z < minz) || (ofs.z > maxz) ) continue;
stop3d = true;
break;
}
if ( stop3d ) continue;
let wp = new("WallPenetrate");
wp.hittype = Results.HitType;
wp.hitline = Results.HitLine;
wp.hitside = Results.Side;
wp.hittier = Results.Tier;
wp.hitsector = Results.HitSector;
wp.hitffloor = Results.ffloor;
wp.hitpos = Results.HitPos;
wp.hitdir = Results.HitVector;
wp.bustdir = Results.HitVector;
if ( Results.HitType == TRACE_HitWall )
{
wp.hitnormal = (-Results.HitLine.delta.y,Results.HitLine.delta.x,0).unit();
if ( !Results.Side ) wp.hitnormal *= -1;
ShootThroughList.Push(Results.HitLine);
}
else if ( Results.HitType == TRACE_HitCeiling )
wp.hitnormal = Results.HitSector.ceilingplane.Normal;
else if ( Results.HitType == TRACE_HitFloor )
wp.hitnormal = Results.HitSector.floorplane.Normal;
wp.pastwall = pastwall;
WallPenetrateList.Push(wp);
pastwall = true;
// trace backwards to find exit surface
let at = new("AuxiliarySilverBulletTracer");
at.Trace(ofs,level.PointInSector(ofs.xy),-Results.HitVector,2.,0);
let wp2 = new("WallPenetrate");
wp2.hittype = at.Results.HitType;
wp2.hitline = at.Results.HitLine;
wp2.hitside = at.Results.Side;
wp2.hittier = at.Results.Tier;
wp2.hitsector = at.Results.HitSector;
wp2.hitffloor = at.Results.ffloor;
wp2.hitside = at.Results.Side;
wp2.hitpos = at.Results.HitPos;
wp2.hitdir = at.Results.HitVector;
wp2.bustdir = -at.Results.HitVector;
if ( at.Results.HitType == TRACE_HitWall )
{
wp2.hitnormal = (-at.Results.HitLine.delta.y,at.Results.HitLine.delta.x,0).unit();
if ( !at.Results.Side ) wp2.hitnormal *= -1;
if ( at.Results.HitLine.sidedef[1] )
ShootThroughList.Push(at.Results.HitLine);
}
else if ( at.Results.HitType == TRACE_HitCeiling )
wp2.hitnormal = at.Results.HitSector.ceilingplane.Normal;
else if ( at.Results.HitType == TRACE_HitFloor )
wp2.hitnormal = at.Results.HitSector.floorplane.Normal;
else wp2.hitnormal = wp2.hitdir;
wp2.pastwall = pastwall;
WallPenetrateList.Push(wp2);
fullstop = false;
exitpoint = ofs;
return TRACE_Stop;
}
}
fullstop = true;
return TRACE_Stop;
}
return TRACE_Skip;
}
}
Class MisterRifle : SWWMWeapon
{
int clipcount;
bool chambered, fired;
bool gchambered, gfired;
bool boltlock, initialized;
bool waschambered, wasfired;
bool wasgchambered, wasgfired;
bool waschambered;
bool wasgchambered;
int prefirecnt;
int firemode;
ui int lastfiremode;
@ -19,6 +162,8 @@ Class MisterRifle : SWWMWeapon
Property ClipCount : clipcount;
transient MisterRailTracer mrt; // I pity the fool
override void AttachToOwner( Actor other )
{
if ( !initialized )
@ -55,6 +200,11 @@ Class MisterRifle : SWWMWeapon
lastfiremode = firemode+1;
}
override Vector3 GetTraceOffset()
{
return (10,2.8,-2.4);
}
override bool ReportHUDAmmo()
{
return (chambered&&!fired)||(clipcount>0)||(Ammo1.Amount>0)||(gchambered&&!gfired)||(Ammo2.Amount>0);
@ -141,8 +291,7 @@ Class MisterRifle : SWWMWeapon
if ( bCasing )
{
invoker.waschambered = invoker.chambered;
invoker.wasfired = invoker.fired;
A_ChangeModel("",1,"","",10,"models",invoker.wasfired?"MortalRound_Used.png":"MortalRound.png",CMDL_USESURFACESKIN,-1);
A_ChangeModel("",1,"","",10,"models","MortalRound_Used.png",CMDL_USESURFACESKIN,-1);
}
invoker.chambered = invoker.fired = false;
A_AmmoAlert();
@ -164,8 +313,17 @@ Class MisterRifle : SWWMWeapon
action void A_DropCasing()
{
// TODO
A_ChangeModel("",1,"","",10,"models","",CMDL_USESURFACESKIN,-1);
if ( !invoker.waschambered ) return;
// brass it up (though it's not made of brass)
Vector3 x, y, z;
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),2*x+3*y-18*z);
let c = Spawn("MisterCasing",origin);
c.angle = angle;
c.pitch = pitch;
c.vel = x*FRandom[Junk](-.25,.25)+y*FRandom[Junk](-.25,.25)-(0,0,FRandom[Junk](4.,6.));
c.vel += vel*.5;
}
action void A_FireSelect()
@ -200,7 +358,16 @@ Class MisterRifle : SWWMWeapon
{
// ensure mag is invisible to avoid weird interpolation to hand
A_ChangeModel("",1,"","",7,"models","",CMDL_USESURFACESKIN,-1);
// TODO drop physical empty mag if enabled
if ( swwm_nomagdrop ) return;
// drop it
Vector3 x, y, z;
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),6*x+3*y-18*z);
let c = Spawn("MisterMag",origin);
c.angle = angle;
c.pitch = pitch;
c.vel = x*FRandom[Junk](-.2,.2)+y*FRandom[Junk](-.2,.2)-(0,0,FRandom[Junk](2.,4.));
c.vel += vel*.5;
}
action void A_MagGrab()
@ -248,29 +415,121 @@ Class MisterRifle : SWWMWeapon
// this one is handled separately
if ( invoker.firemode >= 3 ) return ResolveState("FireOverpressure");
A_PlayerFire();
invoker.fired = true; // TODO, mark this round as fired (will do the rest later)
A_SWWMFlash();
invoker.fired = true;
if ( invoker.firemode == 2 )
{
// stream shot
// individual sub-shots handled in the state sequence, not here
A_StartSound("mister/firestream",CHAN_WEAPON,CHANF_OVERLAP);
SWWMHandler.DoFlash(self,Color(32,64,224,255),2);
A_AlertMonsters(swwm_uncapalert?0:4000);
A_MisterFireStream(true);
return ResolveState("FireStream");
}
SWWMHandler.DoFlash(self,Color(48,64,224,255),3);
Vector3 x, y, z;
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x+2.8*y-2.4*z);
if ( invoker.firemode == 1 )
{
// cluster shot
A_StartSound("mister/firescatter",CHAN_WEAPON,CHANF_OVERLAP);
SWWMUtility.DoKnockback(self,-x,15000.);
A_QuakeEx(6,6,6,8,0,10,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,rollIntensity:1.3);
A_BumpFOV(.92);
A_AlertMonsters(swwm_uncapalert?0:8000);
return ResolveState("FireCluster");
}
// precision shot
A_StartSound("mister/firesemi",CHAN_WEAPON,CHANF_OVERLAP);
SWWMUtility.DoKnockback(self,-x,9000.);
A_QuakeEx(5,5,5,6,0,10,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,rollIntensity:.8);
A_BumpFOV(.95);
A_AlertMonsters(swwm_uncapalert?0:6000);
for ( int i=0; i<6; i++ )
{
let s = Spawn("SWWMSmoke",origin);
s.scale *= .4;
s.alpha *= .1;
s.speed *= .5;
s.vel += vel*.5+x*FRandom[Mister](1.,2.);
s.SetShade(Color(0,3,4)*Random[ExploS](48,63));
}
Vector3 dir;
dir = swwm_CoordUtil.GetAxes(BulletSlope(),angle,roll);
FLineTraceData d;
LineTrace(atan2(dir.y,dir.x),10000,asin(-dir.z),TRF_ABSPOSITION|TRF_NOSKY,origin.z,origin.x,origin.y,d);
SWWMBulletTrail.DoTrail(self,origin,dir,10000,2);
if ( d.HitType == TRACE_HitActor )
{
int dmg = 48;
// might as well apply explosion on top
if ( dmg >= d.HitActor.Health ) dmg += 200;
SWWMUtility.DoKnockback(d.HitActor,d.HitDir,20000);
let p = SWWMPuff.Setup(d.HitLocation,d.HitDir,invoker,self,d.HitActor);
dmg = d.HitActor.DamageMobj(p,self,dmg,'Mortal',DMG_THRUSTLESS|DMG_FOILINVUL|DMG_INFLICTOR_IS_PUFF);
if ( d.HitActor.bNOBLOOD || d.HitActor.bDORMANT )
{
let p = Spawn("SWWMBulletImpact",d.HitLocation);
p.angle = atan2(d.HitDir.y,d.HitDir.x)+180;
p.pitch = asin(d.HitDir.z);
}
else
{
d.HitActor.TraceBleed(dmg,self);
d.HitActor.SpawnBlood(d.HitLocation,atan2(d.HitDir.y,d.HitDir.x)+180,dmg);
}
let b = Spawn("MisterBulletImpact",d.HitLocation-d.HitDir*4.);
b.angle = atan2(d.HitDir.y,d.HitDir.x)+180;
b.pitch = asin(d.HitDir.z);
b.target = self;
}
else if ( d.HitType != TRACE_HitNone )
{
Vector3 hitnormal = -d.HitDir;
if ( d.HitType == TRACE_HitFloor )
{
if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.top.Normal;
else hitnormal = d.HitSector.floorplane.Normal;
}
else if ( d.HitType == TRACE_HitCeiling )
{
if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.bottom.Normal;
else hitnormal = d.HitSector.ceilingplane.Normal;
}
else if ( d.HitType == TRACE_HitWall )
{
hitnormal = (-d.HitLine.delta.y,d.HitLine.delta.x,0).unit();
if ( !d.LineSide ) hitnormal *= -1;
}
let p = Spawn("SWWMBulletImpact",d.HitLocation+hitnormal*0.01);
p.angle = atan2(hitnormal.y,hitnormal.x);
p.pitch = asin(-hitnormal.z);
if ( d.HitLine ) d.HitLine.RemoteActivate(self,d.LineSide,SPAC_Impact,d.HitLocation);
let b = Spawn("MisterBulletImpact",d.HitLocation+hitnormal*4.);
b.angle = atan2(hitnormal.y,hitnormal.x);
b.pitch = asin(-hitnormal.z);
b.target = self;
if ( swwm_omnibust ) BusterWall.BustLinetrace(d,2150,self,d.HitDir,d.HitLocation.z);
}
return ResolveState(null);
}
action void A_MisterFireStream()
action void A_MisterFireStream( bool bFromMain = false )
{
// TODO
A_PlayerFire();
if ( !bFromMain )
{
A_PlayerFire();
SWWMHandler.DoFlash(self,Color(32,64,224,255),2);
A_SWWMFlash("FastFlash");
}
Vector3 x, y, z;
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x+2.8*y-2.4*z);
SWWMUtility.DoKnockback(self,-x,5000.);
A_QuakeEx(3,3,3,5,0,10,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,rollIntensity:.4);
A_BumpFOV(.97);
}
action void A_MisterStartRail()
@ -281,18 +540,34 @@ Class MisterRifle : SWWMWeapon
action void A_MisterFireRail()
{
// TODO, just mark round as fired for now
A_PlayerFire();
Vector3 x, y, z;
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x+2.8*y-2.4*z);
SWWMHandler.DoFlash(self,Color(64,64,224,255),9);
A_SWWMFlash();
invoker.fired = true;
A_StartSound("mister/fireover",CHAN_WEAPON,CHANF_OVERLAP);
SWWMUtility.DoKnockback(self,-x,90000.);
A_QuakeEx(8,8,8,12,0,10,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,rollIntensity:2.);
A_BumpFOV(.85);
A_AlertMonsters(swwm_uncapalert?0:12000);
}
action void A_MisterFireGrenade()
{
// TODO, just mark round as fired for now
A_PlayerFire();
Vector3 x, y, z;
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x+2.8*y-4.*z);
SWWMHandler.DoFlash(self,Color(64,64,224,255),3);
A_SWWMFlash("AltFlash");
invoker.gfired = true;
A_StartSound("mister/grenade",CHAN_WEAPON,CHANF_OVERLAP);
SWWMUtility.DoKnockback(self,-x,12000.);
A_QuakeEx(4,4,4,5,0,10,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,rollIntensity:.6);
A_BumpFOV(.96);
A_AlertMonsters(swwm_uncapalert?0:5000);
}
action void A_GrenadeOpen()
@ -300,7 +575,6 @@ Class MisterRifle : SWWMWeapon
A_PlayerReload();
A_StartSound("mister/grenadeopen");
invoker.wasgchambered = invoker.gchambered;
invoker.wasgfired = invoker.gfired;
// theoretically, this is an either-or situation
// either there's no grenade in the chamber whatsoever
// or there's the casing of a fired grenade
@ -310,7 +584,7 @@ Class MisterRifle : SWWMWeapon
A_ChangeModel("",1,"","",8,"models","",CMDL_USESURFACESKIN,-1);
A_ChangeModel("",1,"","",9,"models","",CMDL_USESURFACESKIN,-1);
}
else // invoker.wasgfired
else
{
// show only a fired cartridge
A_ChangeModel("",1,"","",8,"models","MortalGrenade_Used.png",CMDL_USESURFACESKIN,-1);
@ -321,9 +595,18 @@ Class MisterRifle : SWWMWeapon
action void A_GrenadeDrop()
{
// TODO
A_ChangeModel("",1,"","",8,"models","",CMDL_USESURFACESKIN,-1);
A_ChangeModel("",1,"","",9,"models","",CMDL_USESURFACESKIN,-1);
if ( !invoker.wasgchambered ) return;
// droppage
Vector3 x, y, z;
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),8*x+3*y-18*z);
let c = Spawn("MisterGCasing",origin);
c.angle = angle;
c.pitch = pitch;
c.vel = x*FRandom[Junk](-.2,.2)+y*FRandom[Junk](-.2,.2)-(0,0,FRandom[Junk](2.,4.));
c.vel += vel*.5;
}
action void A_GrenadeGrab()
@ -706,6 +989,31 @@ Class MisterRifle : SWWMWeapon
XZWB JKLMNOPQRST 1;
XZWB T -1 A_FullLower();
Stop;
Flash:
XZW0 A 2 Bright
{
let psp = player.FindPSprite(PSP_FLASH);
psp.frame = Random[GunFlash](0,3);
let l = Spawn("MisterWeaponLight",pos);
l.target = self;
}
Stop;
FastFlash:
XZW0 A 2 Bright
{
let psp = player.FindPSprite(PSP_FLASH);
psp.frame = Random[GunFlash](0,3);
}
Stop;
AltFlash:
XZW0 E 2 Bright
{
let psp = player.FindPSprite(PSP_FLASH);
psp.frame = Random[GunFlash](4,7);
let l = Spawn("MisterWeaponLight",pos);
l.target = self;
}
Stop;
Spawn:
XZW1 A -1;
Stop;

View file

@ -1 +1,217 @@
// Mortal Rifle projectiles and effects
Class MisterWeaponLight : SWWMWeaponLight
{
Default
{
args 64,224,255,150;
}
}
Class MisterCasing : SWWMCasing
{
Default
{
BounceSound "mister/casing";
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
heat = 0;
}
States
{
Death:
XZW1 BCDE -1
{
bINTERPOLATEANGLES = false;
pitch = roll = 0;
angle = FRandom[Junk](0,360);
frame = RandomPick[Junk](1,4);
}
Stop;
}
}
Class MisterGCasing : SWWMCasing
{
Default
{
Mass 8;
BounceFactor 0.5;
WallBounceFactor 0.5;
BounceSound "mister/gcasing";
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
heat = 0;
}
}
Class MisterMag : SWWMCasing
{
Default
{
Mass 10;
BounceFactor 0.4;
WallBounceFactor 0.4;
BounceSound "explodium/mag";
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
heat = 0;
}
States
{
Death:
XZW1 BC -1
{
bINTERPOLATEANGLES = false;
pitch = roll = 0;
angle = FRandom[Junk](0,360);
frame = RandomPick[Junk](1,2);
}
Stop;
}
}
Class MisterExLight : PaletteLight
{
Default
{
Tag "Cyanblu";
ReactionTime 30;
Args 0,0,0,200;
}
}
Class MisterBulletImpactPop : Actor
{
Default
{
RenderStyle "Add";
Scale 6.;
Radius .1;
Height 0.;
+NOGRAVITY;
+NOBLOCKMAP;
+NODAMAGETHRUST;
+FORCERADIUSDMG;
+FORCEXYBILLBOARD;
+ROLLSPRITE;
+ROLLCENTER;
+NOTELEPORT;
+NOINTERACTION;
}
override void Tick()
{
if ( isFrozen() ) return;
A_SetScale(scale.x*.9,scale.y*.9);
A_FadeOut(.15);
if ( !CheckNoDelay() || (tics == -1) ) return;
if ( tics > 0 ) tics--;
while ( !tics )
{
if ( !SetState(CurState.NextState) )
return;
}
}
States
{
Spawn:
BLPF C 5 NoDelay Bright
{
Scale *= FRandom[ExploS](0.6,1.8);
Scale.x *= RandomPick[ExploS](-1,1);
Scale.y *= RandomPick[ExploS](-1,1);
roll = FRandom[Explos](0,360);
}
Stop;
}
}
Class MisterBulletImpact : Actor
{
Default
{
Obituary "$O_MORTALRIFLE";
DamageType "Mortal";
RenderStyle "Add";
Radius .1;
Height 0.;
Scale 1.5;
+NOGRAVITY;
+NOBLOCKMAP;
+NODAMAGETHRUST;
+FORCERADIUSDMG;
+FORCEXYBILLBOARD;
+NOTELEPORT;
+FOILINVUL;
+NOINTERACTION;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_AlertMonsters(swwm_uncapalert?0:4000);
SWWMUtility.DoExplosion(self,200,20000,100,40,DE_EXTRAZTHRUST);
A_QuakeEx(6,6,6,10,0,400,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,falloff:150,rollintensity:.6);
A_StartSound("mister/hitsemi",CHAN_VOICE,attenuation:.3);
A_StartSound("mister/hitsemi",CHAN_WEAPON,attenuation:.2);
A_SprayDecal("RocketBlast",-172);
Scale *= FRandom[ExploS](0.8,1.1);
Scale.x *= RandomPick[ExploS](-1,1);
Scale.y *= RandomPick[ExploS](-1,1);
int numpt = Random[ExploS](20,30);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[ExploS](0,360),FRandom[ExploS](-90,90))*FRandom[ExploS](1,8);
let s = Spawn("SWWMSmoke",pos);
s.vel = pvel;
s.SetShade(Color(0,3,4)*Random[ExploS](48,63));
s.special1 = Random[ExploS](1,3);
s.scale *= 3.5;
s.alpha *= .4;
}
numpt = Random[ExploS](8,12);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[ExploS](0,360),FRandom[ExploS](-90,90))*FRandom[ExploS](8,12);
let s = Spawn("SWWMSpark",pos);
s.vel = pvel;
}
numpt = Random[ExploS](6,16);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[ExploS](0,360),FRandom[ExploS](-90,90))*FRandom[ExploS](4,16);
let s = Spawn("SWWMChip",pos);
s.vel = pvel;
}
Spawn("MisterExLight",pos);
Spawn("MisterBulletImpactPop",pos);
}
override void Tick()
{
if ( isFrozen() ) return;
A_SetScale(scale.x*1.02,scale.y*1.02);
if ( !CheckNoDelay() || (tics == -1) ) return;
if ( tics > 0 ) tics--;
while ( !tics )
{
if ( !SetState(CurState.NextState) )
return;
}
}
States
{
Spawn:
XEX7 ACEGIKMOQSUWY[] 1 Bright
{
if ( special1 && (special1 < 10) ) SWWMUtility.DoExplosion(self,200-special1*20,20000+special1*1000,100+special1*5,40+special1*2,DE_EXTRAZTHRUST);
special1++;
}
Stop;
}
}

View file

@ -85,6 +85,7 @@ Class SWWMCasing : Actor abstract
Death:
XZW1 B -1
{
bINTERPOLATEANGLES = false;
pitch = roll = 0;
angle = FRandom[Junk](0,360);
}

View file

@ -701,6 +701,7 @@ Class EvisceratorCasing : SWWMCasing
Death:
XZW1 BC -1
{
bINTERPOLATEANGLES = false;
pitch = roll = 0;
angle = FRandom[Junk](0,360);
frame = RandomPick[Junk](1,2);

View file

@ -1945,6 +1945,7 @@ Class SparksterMag : SWWMCasing
Death:
XZW1 BC -1
{
bINTERPOLATEANGLES = false;
pitch = 0;
angle = FRandom[Junk](0,360);
roll = 0;

View file

@ -21,6 +21,7 @@ Class ExplodiumMag : SWWMCasing
Death:
XZW1 BC -1
{
bINTERPOLATEANGLES = false;
pitch = roll = 0;
angle = FRandom[Junk](0,360);
frame = RandomPick[Junk](1,2);

View file

@ -14,6 +14,9 @@ Class CandyGun : SWWMWeapon
// re-edit to allow picking up spares in coop
override bool HandlePickup( Inventory item )
{
// can't hold both weapons at once
if ( swwm_swapweapons && IsSwapWeapon(item) )
return true;
if ( (item.GetClass() == GetClass()) && !item.ShouldStay() )
{
bool ammoget, spareget;

View file

@ -254,7 +254,7 @@ Class CandyPop : Actor
States
{
Spawn:
BLPF B 3 NoDelay
BLPF B 3 NoDelay Bright
{
SWWMUtility.DoExplosion(self,500,60000,180,60);
Scale *= FRandom[ExploS](0.6,1.8);
@ -319,7 +319,7 @@ Class TinyCandyPop : CandyPop
States
{
Spawn:
BLPF B 3 NoDelay
BLPF B 3 NoDelay Bright
{
SWWMUtility.DoExplosion(self,200,32000,60,20);
Scale *= FRandom[ExploS](0.6,1.8);

View file

@ -28,6 +28,7 @@ Class SilverBulletMag : SWWMCasing
Death:
XZW1 BC -1
{
bINTERPOLATEANGLES = false;
pitch = roll = 0;
angle = FRandom[Junk](0,360);
frame = RandomPick[Junk](1,2);