More Mortal Rifle progress. Precision Shot partially implemented.
This commit is contained in:
parent
a8cbcca2da
commit
639999de8b
13 changed files with 640 additions and 19 deletions
|
|
@ -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-";
|
||||
|
|
|
|||
|
|
@ -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
BIN
models/extra/MuzTest.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
BIN
palettes/Cyanblu.pal
Normal file
BIN
palettes/Cyanblu.pal
Normal file
Binary file not shown.
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ Class SWWMCasing : Actor abstract
|
|||
Death:
|
||||
XZW1 B -1
|
||||
{
|
||||
bINTERPOLATEANGLES = false;
|
||||
pitch = roll = 0;
|
||||
angle = FRandom[Junk](0,360);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -1945,6 +1945,7 @@ Class SparksterMag : SWWMCasing
|
|||
Death:
|
||||
XZW1 BC -1
|
||||
{
|
||||
bINTERPOLATEANGLES = false;
|
||||
pitch = 0;
|
||||
angle = FRandom[Junk](0,360);
|
||||
roll = 0;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue