Stunner implemented.

Small tweaks.
This commit is contained in:
Marisa the Magician 2019-09-22 15:20:52 +02:00
commit c0ad22d9e6
8 changed files with 327 additions and 7 deletions

View file

@ -167,8 +167,6 @@ Any targets unlucky enough to stand in its way will be pushed away.
Secondary fire: "Inverts the polarity" of the charge, which results in the Secondary fire: "Inverts the polarity" of the charge, which results in the
complete opposite effect, causing targets to instead be pulled towards you. complete opposite effect, causing targets to instead be pulled towards you.
The secondary fire can be useful to pick up items that are way out of reach.
Since the charge rod rapidly extends on shoot, both fire modes additionally Since the charge rod rapidly extends on shoot, both fire modes additionally
deal considerable melee damage to anything that's too close. deal considerable melee damage to anything that's too close.

View file

@ -35,6 +35,7 @@ Doom Tournament (currently the devel branch is required).
- Protomag (slot 2) (replaces pistol) - Protomag (slot 2) (replaces pistol)
- Dual Protomags - Dual Protomags
- Quadshot (slot 3) (replaces shotguns) - Quadshot (slot 3) (replaces shotguns)
- Stunner (slot 4) (replaces chainsaw)
- Fireblaster (slot 5) (replaces rocket launcher) - Fireblaster (slot 5) (replaces rocket launcher)
- Peacemaker (slot 8) (rare spawn in backpacks) - Peacemaker (slot 8) (rare spawn in backpacks)
- Demolisher (slot 9) (replaces bfg9000) - Demolisher (slot 9) (replaces bfg9000)
@ -71,7 +72,6 @@ Doom Tournament (currently the devel branch is required).
## In progress ## In progress
- Stunner (slot 4) (replaces chainsaw)
- Flamethrower (slot 6) (replaces plasma rifle) - Flamethrower (slot 6) (replaces plasma rifle)
- Impaler (slot 7) (replaces plasma rifle) - Impaler (slot 7) (replaces plasma rifle)

View file

@ -13,6 +13,48 @@ Model "Stunner"
FrameIndex STNP A 1 0 FrameIndex STNP A 1 0
} }
Model "StunTrail"
{
Path "models"
Model 0 "FatRing_d.3d"
Skin 0 "JRingEx2.png"
PitchOffset 90
Scale 0.01 0.05 0.05
DONTCULLBACKFACES
USEACTORPITCH
USEACTORROLL
FrameIndex FATR A 0 11
FrameIndex FATR B 0 12
FrameIndex FATR C 0 13
FrameIndex FATR D 0 14
FrameIndex FATR E 0 15
}
Model "StunProj"
{
Path "models"
Model 0 "FatRing_d.3d"
Skin 0 "JRingEx2.png"
PitchOffset 90
Scale 0.1 0.5 0.5
DONTCULLBACKFACES
USEACTORPITCH
USEACTORROLL
FrameIndex FATR A 0 0
FrameIndex FATR B 0 1
FrameIndex FATR C 0 2
FrameIndex FATR D 0 3
FrameIndex FATR E 0 4
FrameIndex FATR F 0 5
FrameIndex FATR G 0 6
FrameIndex FATR H 0 7
FrameIndex FATR I 0 8
FrameIndex FATR J 0 9
FrameIndex FATR K 0 10
}
Model "Stunner" Model "Stunner"
{ {
Path "models" Path "models"

BIN
models/JRingex2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View file

@ -102,7 +102,7 @@ Class FatRing : Actor
{ {
Super.Tick(); Super.Tick();
if ( isFrozen() ) return; if ( isFrozen() ) return;
A_FadeOut(1/21.,0); A_FadeOut(1/19.,0);
} }
States States
{ {
@ -128,6 +128,7 @@ Class BigBlast : Actor
override void PostBeginPlay() override void PostBeginPlay()
{ {
Super.PostBeginPlay(); Super.PostBeginPlay();
A_AlertMonsters();
A_Explode(50+special1,150); A_Explode(50+special1,150);
A_QuakeEx(4,4,4,10,0,300,"",QF_RELATIVE|QF_SCALEDOWN,falloff:150,rollintensity:0.2); A_QuakeEx(4,4,4,10,0,300,"",QF_RELATIVE|QF_SCALEDOWN,falloff:150,rollintensity:0.2);
A_PlaySound("big/blast",CHAN_VOICE,pitch:FRandom[BigGun](0.8,1.2)); A_PlaySound("big/blast",CHAN_VOICE,pitch:FRandom[BigGun](0.8,1.2));
@ -326,6 +327,7 @@ Class BigGun : UnrealWeapon
l.hitactor.DamageMobj(invoker,self,l.hitdamage,'BigShot',DMG_THRUSTLESS); l.hitactor.DamageMobj(invoker,self,l.hitdamage,'BigShot',DMG_THRUSTLESS);
UTMainHandler.DoKnockback(l.hitactor,l.x,90000.); UTMainHandler.DoKnockback(l.hitactor,l.x,90000.);
let b = Spawn("BigBlast",l.hitlocation-l.x*8.); let b = Spawn("BigBlast",l.hitlocation-l.x*8.);
b.target = self;
b.special1 = l.hitdamage; b.special1 = l.hitdamage;
b.angle = atan2(l.x.y,l.x.x); b.angle = atan2(l.x.y,l.x.x);
b.pitch = asin(-l.x.z); b.pitch = asin(-l.x.z);
@ -349,6 +351,7 @@ Class BigGun : UnrealWeapon
if ( !invoker.t.Results.Side ) hitnormal *= -1; if ( !invoker.t.Results.Side ) hitnormal *= -1;
} }
let b = Spawn("BigBlast",invoker.t.Results.HitPos+hitnormal*8.); let b = Spawn("BigBlast",invoker.t.Results.HitPos+hitnormal*8.);
b.target = self;
b.special1 = int(invoker.t.penetration); b.special1 = int(invoker.t.penetration);
b.angle = atan2(hitnormal.y,hitnormal.x); b.angle = atan2(hitnormal.y,hitnormal.x);
b.pitch = asin(-hitnormal.z); b.pitch = asin(-hitnormal.z);

View file

@ -125,7 +125,7 @@ Class UFireball : Actor
{ {
A_PlaySound("flamegun/exp",CHAN_VOICE,pitch:1.2); A_PlaySound("flamegun/exp",CHAN_VOICE,pitch:1.2);
Spawn("UFireLight",pos); Spawn("UFireLight",pos);
A_Explode(GetMissileDamage(0,0),60,XF_HURTSOURCE); A_Explode(GetMissileDamage(0,0),60);
UTMainHandler.DoBlast(self,60,9000); UTMainHandler.DoBlast(self,60,9000);
} }
A_SprayDecal("SmallRocketBlast"); A_SprayDecal("SmallRocketBlast");
@ -184,7 +184,7 @@ Class UFireball2 : UFireball
action void A_FireballExplo2() action void A_FireballExplo2()
{ {
scale *= 2.; scale *= 2.;
A_Explode(GetMissileDamage(0,0),90,XF_HURTSOURCE); A_Explode(GetMissileDamage(0,0),90);
UTMainHandler.DoBlast(self,90,12000); UTMainHandler.DoBlast(self,90,12000);
Vector3 dir = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch)); Vector3 dir = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
int numpt = Random[ExploS](10,15); int numpt = Random[ExploS](10,15);

View file

@ -68,6 +68,7 @@ Class SMiniShell : FastProjectile
action void A_ShellExplode() action void A_ShellExplode()
{ {
bFORCEXYBILLBOARD = true; bFORCEXYBILLBOARD = true;
A_AlertMonsters();
A_SetRenderStyle(1.0,STYLE_Add); A_SetRenderStyle(1.0,STYLE_Add);
A_NoGravity(); A_NoGravity();
A_Explode(150,50,XF_HURTSOURCE|XF_EXPLICITDAMAGETYPE,damagetype:'exploded'); A_Explode(150,50,XF_HURTSOURCE|XF_EXPLICITDAMAGETYPE,damagetype:'exploded');

View file

@ -24,10 +24,247 @@ Class StunnerAmmo : Ammo
Class StunTrail : Actor Class StunTrail : Actor
{ {
Default
{
RenderStyle "Add";
Radius 0.1;
Height 0;
+NOBLOCKMAP;
+NOGRAVITY;
+DONTSPLASH;
+NOTELEPORT;
+FORCEXYBILLBOARD;
}
override void Tick()
{
Super.Tick();
if ( isFrozen() ) return;
A_FadeOut(1./11.,0);
}
States
{
Spawn:
FATR ABCDE 3 Bright;
Stop;
}
}
Class StunLight : PaletteLight
{
Default
{
Tag "DYellow";
}
}
Class StunTracer : LineTracer
{
Actor owner, ignore;
override ETraceStatus TraceCallback()
{
if ( Results.HitType == TRACE_HitActor )
{
if ( (Results.HitActor == owner) || (Results.HitActor == ignore) ) return TRACE_Skip;
if ( Results.HitActor.bSHOOTABLE ) return TRACE_Stop;
return TRACE_Skip;
}
else if ( (Results.HitType == TRACE_HitWall) && (Results.Tier == TIER_Middle) )
{
if ( !Results.HitLine.sidedef[1] || (Results.HitLine.Flags&(Line.ML_BlockHitscan|Line.ML_BlockEverything)) )
return TRACE_Stop;
return TRACE_Skip;
}
return TRACE_Stop;
}
} }
Class StunProj : Actor Class StunProj : Actor
{ {
StunTracer t;
Vector3 tracedir;
bool moving;
double totaldist;
override void PostBeginPlay()
{
Super.PostBeginPlay();
t = new("StunTracer");
t.owner = target;
t.ignore = self;
moving = true;
}
override void Tick()
{
Super.Tick();
if ( isFrozen() ) return;
if ( !moving )
{
A_FadeOut(1/19.,0);
return;
}
// step trace
tracedir = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
t.Trace(pos,cursector,tracedir,500,0);
totaldist += t.Results.Distance;
// spawn particles
for ( int i=10; i<t.Results.Distance; i+=80 )
Spawn("StunLight",Vec3Offset(tracedir.x*i,tracedir.y*i,tracedir.z*i));
for ( int i=0; i<t.Results.Distance; i+=4 )
{
Vector3 pofs = tracedir*FRandom[Stunner](0,2)+(FRandom[Stunner](-.5,.5),FRandom[Stunner](-.5,.5),FRandom[Stunner](-.5,.5));
let s = Spawn("UTSpark",Vec3Offset(tracedir.x*i+pofs.x,tracedir.y*i+pofs.y,tracedir.z*i+pofs.z));
s.scale *= 0.2;
s.bNOGRAVITY = true;
s.vel = (FRandom[Stunner](-.3,.3),FRandom[Stunner](-.3,.3),FRandom[Stunner](-.3,.3));
}
for ( int i=10; i<t.Results.Distance; i+=20 )
{
let s = Spawn("StunTrail",Vec3Offset(tracedir.x*i,tracedir.y*i,tracedir.z*i));
s.angle = angle;
s.pitch = pitch;
}
if ( totaldist >= 10000.0 )
{
// reposition and explode on air
SetOrigin(t.Results.HitPos-t.Results.HitVector*4,false);
StunExplode();
}
else if ( t.Results.HitType == TRACE_HitNone )
{
// reposition
SetOrigin(t.Results.HitPos+t.Results.HitVector,false);
angle = atan2(t.Results.HitVector.y,t.Results.HitVector.x);
pitch = asin(-t.Results.HitVector.z);
}
else if ( t.Results.HitType == TRACE_HitActor )
{
// reposition and explode on actor
SetOrigin(t.Results.HitPos-t.Results.HitVector*4,false);
StunExplode();
Actor a = t.Results.HitActor;
a.DamageMobj(self,target,max(1,int(1.1*specialf1)),'jolted',DMG_USEANGLE,atan2(t.Results.HitVector.y,t.Results.HitVector.x));
if ( !a.bDONTTHRUST )
{
UTMainHandler.DoKnockback(a,t.Results.HitVector,(bAMBUSH?-22000:26000)*specialf1);
a.vel.z += 2.*specialf1;
}
angle = atan2(t.Results.HitVector.y,t.Results.HitVector.x);
pitch = asin(-t.Results.HitVector.z);
}
else
{
// reposition and explode on wall
SetOrigin(t.Results.HitPos-t.Results.HitVector*4,false);
A_SprayDecal("ShockMark",16);
Vector3 HitNormal = t.Results.HitVector;
if ( t.Results.HitType == TRACE_HitWall )
{
t.Results.HitLine.RemoteActivate(target,t.Results.Side,SPAC_Impact,pos);
// calculate normal
HitNormal = (-t.Results.HitLine.delta.y,t.Results.HitLine.delta.x,0).unit();
if ( t.Results.Side == 0 ) HitNormal *= -1;
}
else if ( t.Results.HitType == TRACE_HitFloor )
{
if ( t.Results.ffloor ) HitNormal = -t.Results.ffloor.top.Normal;
else HitNormal = t.Results.HitSector.floorplane.Normal;
}
else if ( t.Results.HitType == TRACE_HitCeiling )
{
if ( t.Results.ffloor ) HitNormal = -t.Results.ffloor.bottom.Normal;
else HitNormal = t.Results.HitSector.ceilingplane.Normal;
}
StunExplode();
angle = atan2(HitNormal.y,HitNormal.x);
pitch = asin(-HitNormal.z);
}
}
void StunExplode()
{
moving = false;
SetStateLabel("Death");
A_Explode(int(0.6*specialf1),50);
A_QuakeEx(1,1,1,3,0,250,"",QF_RELATIVE|QF_SCALEDOWN,falloff:120,rollintensity:0.2);
A_PlaySound("stun/hit",CHAN_VOICE,pitch:FRandom[Stunner](1.5,1.9)-0.08*specialf1);
UTMainHandler.DoBlast(self,50,(bAMBUSH?-7000:11000)*specialf1);
Vector3 dir = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
int numpt = Random[ExploS](10,15);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](2,6);
let s = Spawn("UTSpark",pos);
s.scale *= 0.2;
s.bNOGRAVITY = true;
s.vel = pvel;
}
}
Default
{
Obituary "$O_STUNNER";
RenderStyle "Add";
DamageType 'jolted';
Radius 0;
Height 0.1;
+NOGRAVITY;
+NOCLIP;
+DONTSPLASH;
+FORCERADIUSDMG;
+NODAMAGETHRUST;
+NOTELEPORT;
+FORCEXYBILLBOARD;
}
States
{
Spawn:
TNT1 A -1;
Stop;
Death:
FATR ABCDEFGHIJK 2 Bright;
Stop;
}
}
Class StunnerImpact : Actor
{
Default
{
Radius 0.1;
Height 0;
+NOGRAVITY;
+NOCLIP;
+DONTSPLASH;
+NOTELEPORT;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_SprayDecal("WallCrack",20);
int numpt = Random[Stunner](10,20);
Vector3 x = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (-x+(FRandom[Stunner](-.8,.8),FRandom[Stunner](-.8,.8),FRandom[Stunner](-.8,.8))).unit()*FRandom[Stunner](0.1,1.2);
let s = Spawn("UTSmoke",pos);
s.vel = pvel;
s.SetShade(Color(1,1,1)*Random[Stunner](128,192));
}
numpt = Random[Stunner](4,10);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Stunner](-1,1),FRandom[Stunner](-1,1),FRandom[Stunner](-1,1)).unit()*FRandom[Stunner](2,8);
let s = Spawn("UTSpark",pos);
s.vel = pvel;
}
numpt = Random[Stunner](4,12);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Stunner](-1,1),FRandom[Stunner](-1,1),FRandom[Stunner](-1,1)).unit()*FRandom[Stunner](2,8);
let s = Spawn("UTChip",pos);
s.vel = pvel;
}
Destroy();
}
} }
Class Stunner : UnrealWeapon Class Stunner : UnrealWeapon
@ -48,10 +285,49 @@ Class Stunner : UnrealWeapon
if ( self is 'UTPlayer' ) if ( self is 'UTPlayer' )
UTPlayer(self).PlayAttacking3(); UTPlayer(self).PlayAttacking3();
StunnerAmmo(weap.Ammo1).rechargephase = 0; StunnerAmmo(weap.Ammo1).rechargephase = 0;
A_PlaySound("stun/fire",CHAN_WEAPON,Dampener.Active(self)?.4:1.); A_PlaySound("stun/fire",CHAN_WEAPON,Dampener.Active(self)?.4:1.,pitch:1.2-invoker.chargesize*0.06);
double mult = Amplifier.GetMult(self,int(invoker.ChargeSize*50)+50); double mult = Amplifier.GetMult(self,int(invoker.ChargeSize*50)+50);
invoker.FireEffect(); invoker.FireEffect();
A_QuakeEx(1+int(0.5*invoker.chargesize),1+int(0.5*invoker.chargesize),1+int(0.5*invoker.chargesize),5+int(1.2*invoker.chargesize),0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.05+0.01*invoker.chargesize);
UTMainHandler.DoSwing(self,(FRandom[Stunner](-0.04,0.04),FRandom[Stunner](-0.9,-0.4)),1+invoker.chargesize*0.3,-0.1,3,SWING_Spring,3,2.5);
A_Overlay(-2,"Null"); A_Overlay(-2,"Null");
Vector3 x, y, z;
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),x*10-z*5);
let p = Spawn("StunProj",origin);
p.angle = angle;
p.pitch = BulletSlope();
p.target = self;
p.specialf1 = invoker.chargesize*mult;
p.bAMBUSH = weap.bAltFire;
FLineTraceData d;
LineTrace(angle,60,BulletSlope(),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
if ( d.HitType == TRACE_HitActor )
{
int dmg = int(5*invoker.chargesize);
if ( d.HitLocation.z >= (d.HitActor.pos.z+d.HitActor.height*0.81) )
dmg = d.HitActor.DamageMobj(invoker,self,dmg*2,'Decapitated',DMG_THRUSTLESS);
else dmg = d.HitActor.DamageMobj(invoker,self,dmg,'impact',DMG_THRUSTLESS);
UTMainHandler.DoKnockback(d.HitActor,x,4000*invoker.chargesize);
if ( d.HitActor.bNOBLOOD )
{
let p = Spawn("StunnerImpact",d.HitLocation-d.HitDir*4);
p.angle = atan2(d.HitDir.y,d.HitDir.x);
p.pitch = asin(-d.HitDir.z);
}
else
{
d.HitActor.TraceBleed(dmg,invoker);
d.HitActor.SpawnBlood(d.HitLocation,atan2(d.HitDir.y,d.HitDir.x)+180,dmg);
}
}
else if ( d.HitType != TRACE_HitNone )
{
let p = Spawn("StunnerImpact",d.HitLocation-d.HitDir*4);
p.angle = atan2(d.HitDir.y,d.HitDir.x);
p.pitch = asin(-d.HitDir.z);
if ( d.HitType == TRACE_HitWall ) d.HitLine.RemoteActivate(self,d.LineSide,SPAC_Impact,d.HitLocation-d.HitDir*4);
}
} }
action void A_BeginCharge() action void A_BeginCharge()
{ {