More Quadravol progress (fire at charge level 1 functional).

This commit is contained in:
Mari the Deer 2022-08-19 00:59:11 +02:00
commit 99eb2d8861
18 changed files with 568 additions and 46 deletions

View file

@ -272,7 +272,7 @@ One mighty relic of the beginnings of **UnSX**. This beefy handcannon spews pote
**Secondary fire:** Pumps more rounds into the gun, for extra potency *(up to 5x)*. Do note that the shot not only will become stronger, but also more unstable.
**Tertiary fire:** Switch the weapon stance, from two-handing to single-handing. You know, so you can give it a full-on spin like in the action movies.
**Tertiary fire:** Switch the weapon stance, from two-handing to one-handing. You know, so you can give it a full-on spin like in the action movies.
**Reload:** Loads more rounds in reserve.

View file

@ -251,6 +251,60 @@ decalgroup ShockMarkBig
ShockMarkBig5 1
}
decal ShockMarkHuge1
{
pic shockmrk
shade "00 00 00"
randomflipx
randomflipy
x-scale 3.0
y-scale 3.0
}
decal ShockMarkHuge2
{
pic shockmk2
shade "00 00 00"
randomflipx
randomflipy
x-scale 3.0
y-scale 3.0
}
decal ShockMarkHuge3
{
pic shockmk3
shade "00 00 00"
randomflipx
randomflipy
x-scale 3.0
y-scale 3.0
}
decal ShockMarkHuge4
{
pic shockmk4
shade "00 00 00"
randomflipx
randomflipy
x-scale 3.0
y-scale 3.0
}
decal ShockMarkHuge5
{
pic shockmk5
shade "00 00 00"
randomflipx
randomflipy
x-scale 3.0
y-scale 3.0
}
decalgroup ShockMarkHuge
{
ShockMarkHuge1 1
ShockMarkHuge2 1
ShockMarkHuge3 1
ShockMarkHuge4 1
ShockMarkHuge5 1
}
decal BigBlast
{
pic bigblast

View file

@ -3,3 +3,14 @@ HardwareShader Texture "models/QuadLED.png"
Shader "shaders/glsl/BrightCanvas.fp"
Texture "scrtex" "QUADRLED"
}
PointLight QUADP1LIGHT
{
Color 1.0 0.5 0.1
Size 250
Attenuate 1
}
Object QuadProj
{
Frame "QFBL" { light "QUADP1LIGHT" }
}

View file

@ -1089,7 +1089,7 @@ SWWM_INTERTIP181 = "Unlike the rapidly thrown quick grenades, the Explodium Gun'
SWWM_INTERTIP182 = "The Sheen HMG sets the air on fire along each bullet's path, just from the sheer pressure of the cartridge used.";
SWWM_INTERTIP183 = "The rare golden shells allow you to cause extreme destruction in a large radius. Just be careful not to stand too close.";
SWWM_INTERTIP184 = "Be careful with your lead balls. They might ricochet back into your face and hurt real bad.";
SWWM_INTERTIP185 = "Once a target is set ablaze by the Quadravol's fireballs, the flames will rapidly spread to nearby targets as well.";
SWWM_INTERTIP185 = "Once you're set ablaze by the Quadravol, the quickest solution is to shake those flames off. Shame that your enemies aren't smart enough to know that.";
SWWM_INTERTIP186 = "Somehow, the Quadravol can be used underwater. One has to wonder what those fireballs are made of.";
SWWM_INTERTIP187 = "The Ray-Khom's alternate fire is lethal in contact with water. Do apply some common sense with this information.";
SWWM_INTERTIP188 = "The Rafan-Kos can prepare a delicious cyberdemon roast in a matter of seconds.";

View file

@ -972,7 +972,7 @@ SWWM_INTERTIP181 = "A diferencia de las granadas rápidas, el fuego secundario d
SWWM_INTERTIP182 = "La Ametralladora Sheen incendia el aire al paso de cada bala, solo con la altísima presión de la munición que usa.";
SWWM_INTERTIP183 = "Los poco comunes cartuchos dorados te permiten causar destrucción extrema en un radio amplio. Eso sí, ten cuidado de no estar demasiado cerca.";
SWWM_INTERTIP184 = "Ten cuidado con tus bolas de plomo. Podrían rebotar y darte en la cara y eso duele mucho.";
SWWM_INTERTIP185 = "Una vez un objetivo ha sido incendiado por las bolas de fuego de la Quadravol, las llamas se propagarán rápidamente a otros objetivos cercanos también.";
SWWM_INTERTIP185 = "Una vez incendiado por la Quadravol, la solución más rápida es sacudirse fuera las llamas. Una pena que tus enemigos no sean tan listos como para saber eso.";
SWWM_INTERTIP186 = "De alguna forma, la Quadravol puede usarse bajo el agua. Uno solo puede preguntarse de qué están hechas esas bolas de fuego.";
SWWM_INTERTIP187 = "El fuego alternativo de la Ray-Khom es letal en contacto con el agua. Intenta aplicar el sentido común con esta información.";
SWWM_INTERTIP188 = "La Rafan-Kos puede preparar un delicioso asado de ciberdemonio en cuestión de segundos.";

View file

@ -1,3 +1,3 @@
[default]
SWWM_MODVER="\cyDEMOLITIONIST \cw1.3pre r343 \cu(Thu 18 Aug 19:00:27 CEST 2022)\c-";
SWWM_SHORTVER="\cw1.3pre r343 \cu(2022-08-18 19:00:27)\c-";
SWWM_MODVER="\cyDEMOLITIONIST \cw1.3pre r344 \cu(Fri 19 Aug 00:59:11 CEST 2022)\c-";
SWWM_SHORTVER="\cw1.3pre r344 \cu(2022-08-19 00:59:11)\c-";

View file

@ -57,6 +57,37 @@ Model "Quadravol"
FrameIndex XZWZ O 2 107
}
Model "Quadravol"
{
Path "models/extra"
Model 3 "Flat_d.3d"
Scale 0.1 0.1 0.1
Offset 12 -60 -10
RollOffset 90
AngleOffset 90
Skin 3 "QuadMuz0.png"
FrameIndex XZW0 A 3 0
Skin 3 "QuadMuz1.png"
FrameIndex XZW0 B 3 0
Skin 3 "QuadMuz2.png"
FrameIndex XZW0 C 3 0
Skin 3 "QuadMuz3.png"
FrameIndex XZW0 D 3 0
Skin 3 "QuadMuz4.png"
FrameIndex XZW0 E 3 0
Skin 3 "QuadMuz5.png"
FrameIndex XZW0 F 3 0
Skin 3 "QuadMuz6.png"
FrameIndex XZW0 G 3 0
Skin 3 "QuadMuz7.png"
FrameIndex XZW0 H 3 0
Skin 3 "QuadMuz8.png"
FrameIndex XZW0 I 3 0
Skin 3 "QuadMuz9.png"
FrameIndex XZW0 J 3 0
}
Model "Quadravol"
{
Path "models"

View file

@ -99,10 +99,12 @@ quadshot/hit1 sounds/dlc1/quadshot/quad_hit1.ogg
quadshot/hit2 sounds/dlc1/quadshot/quad_hit2.ogg
quadshot/hit3 sounds/dlc1/quadshot/quad_hit3.ogg
$random quadshot/hit { quadshot/hit1 quadshot/hit2 quadshot/hit3 }
$limit quadshot/hit 16
quadshot/twohit1 sounds/dlc1/quadshot/quad_explo1.ogg
quadshot/twohit2 sounds/dlc1/quadshot/quad_explo2.ogg
quadshot/twohit3 sounds/dlc1/quadshot/quad_explo3.ogg
$random quadshot/twohit { quadshot/twohit1 quadshot/twohit2 quadshot/twohit3 }
$limit quadshot/twohit 8
quadshot/extrahit sounds/dlc1/quadshot/quad_xexpl.ogg
quadshot/pointblank sounds/dlc1/quadshot/quad_xxexpl.ogg
quadshot/fly sounds/dlc1/quadshot/quad_fly.ogg

View file

@ -94,7 +94,7 @@ extend Class Quadravol
if ( chambered ) Screen.DrawTexture(BulletTex[charged],false,bx-14,by-10,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
Screen.DrawText(ChargeFont,Font.CR_UNTRANSLATED,bx-14,by-20,String.Format("%d",chargelevel),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
// PLACEHOLDER
String str = "THIS WEAPON IS NOT YET FUNCTIONAL";
String str = "THIS WEAPON IS NOT YET FULLY IMPLEMENTED";
Screen.DrawText(NewSmallFont,Font.CR_RED,(Screen.GetWidth()-NewSmallFont.StringWidth(str)*CleanXFac_1)/2,Screen.GetHeight()-(swwm_hudmargin*hs+NewSmallFont.GetHeight()*CleanYFac_1),str,DTA_CleanNoMove_1,true);
}
}

View file

@ -76,6 +76,11 @@ Class Quadravol : SWWMWeapon
else origin.A_StartSound(UpSound,CHAN_WEAPON,CHANF_OVERLAP);
}
override Vector3 GetTraceOffset()
{
return (10,3,-2.5);
}
action State A_QuadFire()
{
static const String BaseNum[] = {"one","two","three","four","five"};
@ -83,10 +88,62 @@ Class Quadravol : SWWMWeapon
int idx = clamp(invoker.chargelevel-1,0,4);
A_StartSound("quadshot/fire"..BaseNum[idx],CHAN_WEAPON,CHANF_OVERLAP);
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+3*y-2.5*z);
bool pointblank = false;
int rings = 1;
Vector3 dir;
for ( double i=0; i<.25; i+=.05 )
{
for ( int j=0; j<360; j+=(360/rings) )
{
dir = SWWMUtility.ConeSpread(x,y,z,j,i);
pointblank |= LineTrace(atan2(dir.y,dir.x),60,asin(-dir.z),TRF_ABSPOSITION|TRF_NOSKY,origin.z,origin.x,origin.y);
}
rings += 3;
}
Vector3 x2, y2, z2;
[x2, y2, z2] = swwm_CoordUtil.GetAxes(BulletSlope(),angle,roll);
double a, s;
Actor p;
switch ( idx )
{
case 0:
A_Log("\cg// TODO - Fire Level 1\c-");
A_QuakeEx(3,3,3,15,0,10,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,rollIntensity:.4);
A_BumpFOV(.98);
A_SWWMFlash();
SWWMHandler.DoFlash(self,Color(64,255,192,64),5);
A_AlertMonsters(swwm_uncapalert?0:2000);
SWWMUtility.DoKnockback(self,-x,1500.);
p = Spawn("QuadProj",origin);
p.target = self;
p.angle = atan2(x2.y,x2.x);
p.pitch = asin(-x2.z);
p.vel = x2*p.speed;
if ( pointblank )
{
p.tracer = self;
p.special1 = 50;
p.special2 = 40000;
p.ExplodeMissile(null,null);
self.DamageMobj(invoker,self,40,'Fire',DMG_EXPLOSION);
}
for ( int i=0; i<4; i++ )
{
let s = Spawn("SWWMSmoke",origin);
s.special1 = 1;
s.scale *= 1.3;
s.alpha *= .2;
s.vel += vel*.5+x*FRandom[Quadravol](5.,15.)+y*FRandom[Quadravol](-.5,.5)+z*FRandom[Quadravol](-.5,.5);
}
for ( int i=0; i<10; i++ )
{
let s = Spawn("SWWMSpark",origin);
s.scale *= .3;
s.alpha *= .4;
s.vel += vel*.5+x*FRandom[Quadravol](4.,8.)+y*FRandom[Quadravol](-1.,1.)+z*FRandom[Quadravol](-1.,1.);
}
break;
case 1:
A_Log("\cg// TODO - Fire Level 2\c-");
@ -271,12 +328,13 @@ Class Quadravol : SWWMWeapon
}
FireOne:
XZW2 A 1;
XZW3 OPQR 2;
XZW3 STUV 3;
XZW3 OPQR 1;
XZW3 STUV 2;
Goto Ready;
FireTwo:
XZW2 A 1;
XZW3 WXYZ 2;
XZW3 WX 1;
XZW3 YZ 2;
XZW4 ABCD 3;
Goto Ready;
FireThree:
@ -287,13 +345,15 @@ Class Quadravol : SWWMWeapon
FireFour:
XZW2 A 1;
XZW4 MNOP 2;
XZW4 QRST 3;
XZW4 QR 3;
XZW4 ST 4;
Goto Ready;
FireFive:
XZW2 A 1;
XZW4 UVWX 2;
XZW4 YZ 3;
XZW5 AB 3;
XZW4 UV 2;
XZW4 WX 3;
XZW4 YZ 4;
XZW5 AB 5;
Goto Ready;
AltFire:
XZW2 A 2 A_PlayerCheckGun();
@ -367,6 +427,15 @@ Class Quadravol : SWWMWeapon
XZW2 BCDEFGHIJKLMNOPQR 1;
XZW2 R -1 A_FullLower();
Stop;
Flash:
XZW0 A 2 Bright
{
let psp = player.GetPSprite(PSP_FLASH);
psp.frame = Random[GunFlash](0,9);
let l = Spawn("SWWMWeaponLight",pos);
l.target = self;
}
Stop;
// TODO one-handed states
}
}

View file

@ -13,6 +13,321 @@ Class QuadravolCasing : SWWMCasing
}
}
Class QuadExplLight : PaletteLight
{
Default
{
Tag "QuadExpl";
Args 0,0,0,150;
ReactionTime 20;
}
}
Class QuadFlare : Actor
{
bool bBig;
Default
{
RenderStyle "Add";
Radius .1;
Height 0.;
Alpha .5;
+NOGRAVITY;
+NOBLOCKMAP;
+DONTSPLASH;
+NOTELEPORT;
+FORCEXYBILLBOARD;
+NOINTERACTION;
}
override void Tick()
{
if ( isFrozen() ) return;
if ( !master || !master.bMISSILE )
{
if ( !bBig )
{
bBig = true;
Scale *= 3.;
}
Scale *= .97;
A_FadeOut(.03);
return;
}
SetOrigin(master.pos,true);
}
States
{
Spawn:
QFLR A -1 Bright;
Stop;
}
}
Class QuadTrail : Actor
{
Default
{
RenderStyle "Add";
Radius .1;
Height 0.;
Alpha .5;
Scale 1.5;
+NOBLOCKMAP;
+NOGRAVITY;
+NOTELEPORT;
+FORCEXYBILLBOARD;
+ROLLSPRITE;
+ROLLCENTER;
+DONTSPLASH;
+NOINTERACTION;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
Scale.x *= RandomPick[ExploS](-1,1);
Scale.y *= RandomPick[ExploS](-1,1);
roll = FRandom[ExploS](0,360);
SetState(SpawnState+Random[ExploS](0,19));
}
action void A_Flame()
{
vel *= .9;
A_SetScale(scale.x*.96);
A_FadeOut(.05);
}
override void Tick()
{
if ( isFrozen() ) return;
SetOrigin(level.Vec3Offset(pos,vel),true);
if ( !CheckNoDelay() || (tics == -1) ) return;
if ( tics > 0 ) tics--;
while ( !tics )
{
if ( !SetState(CurState.NextState) )
return;
}
}
States
{
Spawn:
XFLM ABCDEFGHIJKLMNOPQRST 1 Bright A_Flame();
Loop;
}
}
Class QuadEmber : Actor
{
Vector3 freq, amp, ph;
Default
{
RenderStyle "Add";
Radius .1;
Height 0;
Scale .3;
+NOBLOCKMAP;
+NOGRAVITY;
+DONTSPLASH;
+FORCEXYBILLBOARD;
+NOTELEPORT;
+NOINTERACTION;
}
override void PostBeginPlay()
{
Scale *= FRandom[ExploS](.5,1.5);
double ang = FRandom[ExploS](0,360),
pt = FRandom[ExploS](-90,90);
vel = SWWMUtility.Vec3FromAngles(ang,pt)*FRandom[ExploS](4.,8.);
freq = (FRandom[ExploS](.5,3.),FRandom[ExploS](.5,3.),FRandom[ExploS](.5,3.));
amp = (FRandom[ExploS](.5,2.),FRandom[ExploS](.5,2.),FRandom[ExploS](.5,2.));
ph = (FRandom[ExploS](0.,360.),FRandom[ExploS](0.,360.),FRandom[ExploS](0.,360.));
specialf1 = FRandom[ExploS](.98,.99);
specialf2 = FRandom[ExploS](.98,.99);
}
override void Tick()
{
prev = pos;
if ( isFrozen() ) return;
if ( !InStateSequence(CurState,FindState("Death")) )
{
vel *= .95;
vel += .2*(sin(ph.x)*amp.x,sin(ph.y)*amp.y,sin(ph.z)*amp.z);
vel.z -= .05*clamp(2.-amp.length(),0.,2.);
ph.x += freq.x*(360./GameTicRate);
ph.y += freq.y*(360./GameTicRate);
ph.z += freq.z*(360./GameTicRate);
freq *= specialf1;
amp *= specialf2;
Vector3 newpos = level.Vec3Offset(pos,vel);
if ( !level.IsPointInLevel(newpos) )
{
vel *= 0;
SetStateLabel("Death");
return;
}
SetOrigin(newpos,true);
UpdateWaterLevel();
if ( waterlevel > 0 )
{
vel *= 0;
SetStateLabel("Death");
return;
}
A_FadeOut(FRandom[ExploS](.002,.005));
}
else A_FadeOut(FRandom[ExploS](.02,.05));
frame = clamp(int(round(4-alpha*4)),0,4);
if ( tics > 0 ) tics--;
while ( !tics )
{
if ( !SetState(CurState.NextState) )
return;
}
}
States
{
Spawn:
QEMB # -1 Bright;
Stop;
Death:
QEMB # -1 Bright;
Stop;
}
}
Class QuadProj : Actor
{
double drift, accelrate, maxspeed;
Property Drift: drift;
Property AccelRate: accelrate;
Property MaxSpeed: maxspeed;
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_StartSound("quadshot/fly",CHAN_BODY,CHANF_LOOP);
let t = Spawn("QuadFlare",pos);
t.master = self;
t.scale = scale*2.;
}
// acceleration, drift and speed limit
void A_QuadMove()
{
A_QuadTrail();
Vector3 x, y, z;
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
double a = FRandom[Quadravol](0.,360.), s = FRandom[Quadravol](0.,drift);
vel += x*(accelrate/GameTicRate);
vel += SWWMUtility.CircleOffset(y,z,a,s);
double magvel = vel.length();
Vector3 dir = (magvel<=0.)?x:(vel/magvel);
if ( magvel > maxspeed ) magvel = maxspeed;
vel = dir*magvel;
speed = magvel;
}
virtual void A_QuadTrail()
{
let s = Spawn("QuadTrail",pos);
s.scale *= .6;
s.vel = vel*.2;
s = Spawn("SWWMHalfSmoke",pos);
s.vel = (FRandom[Quadravol](-.4,.4),FRandom[Quadravol](-.4,.4),FRandom[Quadravol](-.4,.4));
s.vel += vel*.3;
s.alpha *= .4;
int numpt = Random[Quadravol](5,15);
for ( int i=0; i<numpt; i++ )
{
s = Spawn("QuadEmber",pos);
s.vel += vel*.3;
}
}
virtual void A_QuadExplode()
{
A_StopSound(CHAN_BODY);
Scale *= 2.;
A_SprayDecal("ShockMarkBig",50);
Vector3 x = SWWMUtility.Vec3FromAngles(angle,pitch);
if ( master && ((master.pos.z <= master.floorz) || !master.TestMobjZ()) )
{
Vector3 rel = level.Vec3Diff(master.pos,pos);
double hdiff = 1.-2.*clamp((rel.z-4.)/master.height,0.,.5);
SWWMUtility.DoKnockback(master,x+(0,0,hdiff*.5),200000);
}
if ( tracer ) SWWMUtility.DoKnockback(tracer,-x+(0,0,.1),500000);
SWWMUtility.DoExplosion(self,0,80000+special2,240,80,DE_BLAST|DE_EXTRAZTHRUST);
SWWMUtility.DoExplosion(self,100+special1,0,240,0,DE_QUADRAVOL|DE_NOSPLASH,ignoreme:tracer);
SWWMUtility.DoExplosion(self,150+special1,0,200,80,DE_HOWL|DE_NOSPLASH,ignoreme:tracer);
A_StartSound("quadshot/hit",CHAN_WEAPON,attenuation:.8);
A_StartSound("quadshot/hit",CHAN_VOICE,attenuation:.6);
A_AlertMonsters(swwm_uncapalert?0:1500);
Spawn("QuadExplLight",pos);
int numpt = Random[Quadravol](12,18);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Quadravol](-1,1),FRandom[Quadravol](-1,1),FRandom[Quadravol](-1,1)).unit()*FRandom[Quadravol](2,8);
let s = Spawn("SWWMSmoke",pos);
s.vel = pvel;
s.special1 = Random[Quadravol](2,3);
s.scale *= 4.;
s.alpha *= .3;
}
numpt = Random[Quadravol](10,15);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Quadravol](-1,1),FRandom[Quadravol](-1,1),FRandom[Quadravol](-1,1)).unit()*FRandom[Quadravol](4,16);
let s = Spawn("SWWMSpark",pos);
s.vel = pvel;
}
numpt = Random[Quadravol](4,8);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Quadravol](-1,1),FRandom[Quadravol](-1,1),FRandom[Quadravol](-1,1)).unit()*FRandom[Quadravol](6,12);
let s = Spawn("SWWMChip",pos);
s.vel = pvel;
s.scale *= FRandom[Quadravol](0.9,1.8);
}
if ( swwm_omnibust ) BusterWall.ProjectileBust(self,150,SWWMUtility.Vec3FromAngles(angle,pitch));
}
Default
{
Obituary "$O_QUADRAVOL";
DamageType "Fire";
Scale .5;
Radius 6;
Height 6;
Speed 60;
QuadProj.Drift .15;
QuadProj.AccelRate 30;
QuadProj.MaxSpeed 120;
PROJECTILE;
+FORCEXYBILLBOARD;
+EXPLODEONWATER;
+FORCERADIUSDMG;
+NODAMAGETHRUST;
+HITMASTER;
RenderStyle "Add";
}
States
{
Spawn:
QFBL ABCDEFGHIJ 1 Bright A_QuadMove();
Loop;
Death:
TNT1 A 0 A_QuadExplode();
XEX0 ABCDEFGHIJKLMNOPQRS 1 Bright A_SetScale(scale.x*1.05);
Stop;
}
}
Class OnFireLight : PointLightFlickerRandomAttenuated
{
OnFire of;
@ -29,7 +344,7 @@ Class OnFireLight : PointLightFlickerRandomAttenuated
Args[0] = clamp(of.Amount*4,0,255);
Args[1] = clamp(of.Amount*2,0,160);
Args[2] = clamp(of.Amount/2,0,24);
Args[3] = int(max(of.victim.radius,of.victim.height)*2.+20+clamp(of.amount/5,0,80));
Args[3] = int(max(of.victim.radius,of.victim.height)*2.5+40+clamp(of.amount/4,0,120));
Args[4] = args[3]+8;
SetOrigin(of.Victim.Vec3Offset(0,0,of.Victim.Height/2),true);
}
@ -54,6 +369,7 @@ Class OnFire : Thinker
if ( lite ) lite.Destroy();
amount -= int(victim.waterlevel**2);
}
if ( victim is 'Demolitionist' ) amount = min(amount-2,200); // Demo's body puts out fire faster
if ( victim.Health <= 0 ) amount = min(amount,100);
if ( !(level.maptime%3) )
amount--;
@ -72,7 +388,13 @@ Class OnFire : Thinker
{
int flg = DMG_THRUSTLESS;
if ( victim is 'Centaur' ) flg |= DMG_FOILINVUL; // you're on fire, that shield is worthless
victim.DamageMobj(instigator.FindInventory("Quadravol"),instigator,clamp(int(amount*.1),1,20),'Fire',flg);
Actor inflictor = instigator;
if ( instigator )
{
let q = instigator.FindInventory("Quadravol");
if ( q ) inflictor = q;
}
victim.DamageMobj(inflictor,instigator,clamp(int(amount*.15),1,50),'Fire',flg);
if ( victim.bISMONSTER && !Random[FlameT](0,3) )
victim.Howl();
}
@ -95,16 +417,17 @@ Class OnFire : Thinker
if ( amount > 0 )
{
let c = victim.Spawn("OnFireTrail",pos);
c.scale *= max(.3,mult*.5);
c.scale *= max(.35,mult*.6);
c.vel = victim.vel*.5+SWWMUtility.Vec3FromAngles(ang,pt)*FRandom[FlameT](.5,2.)*c.scale.x;
}
if ( Random[FlameT](0,2) ) continue;
let s = victim.Spawn("SWWMHalfSmoke",pos);
s.scale *= max(1.,1.6*mult);
s.alpha *= min(amount+30,100)*.02;
s.scale *= max(.5,mult*.75);
s.alpha *= min(amount+30,100)*.005;
s.vel = victim.vel*.5+SWWMUtility.Vec3FromAngles(ang,pt)*FRandom[FlameT](.2,.6)*s.scale.x;
}
// spread to nearby actors
let bt = BlockThingsIterator.Create(victim);
// this is too expensive, it has to go
/*let bt = BlockThingsIterator.Create(victim);
while ( bt.Next() )
{
let t = bt.Thing;
@ -123,7 +446,15 @@ Class OnFire : Thinker
}
else Apply(t,instigator,amt);
}
bt.Destroy();
bt.Destroy();*/
// damage nearby actors instead
Actor inflictor = instigator;
if ( instigator )
{
let q = instigator.FindInventory("Quadravol");
if ( q ) inflictor = q;
}
SWWMUtility.DoExplosion(victim,clamp(int(amount*.15),1,50),0,victim.radius+40+amount/5,0,DE_NOBLEED|DE_NOSPLASH|DE_HOWL,'Fire',instigator,DMG_THRUSTLESS,instigator,inflictor);
}
static OnFire Apply( Actor victim, Actor instigator, int amount )
@ -176,7 +507,7 @@ Class OnFireTrail : Actor
Scale.x *= RandomPick[ExploS](-1,1);
Scale.y *= RandomPick[ExploS](-1,1);
roll = FRandom[ExploS](0,360);
SetState(SpawnState+Random[ExploS](0,19));
SetState(SpawnState+Random[ExploS](0,39));
}
action void A_Flame()
{
@ -186,18 +517,19 @@ Class OnFireTrail : Actor
else
{
vel *= .98;
vel.z += .1+.4*abs(scale.x);
vel.z += .1+.2*abs(scale.x);
}
if ( !Random[FlameT](0,int(40*(default.alpha-alpha))) )
{
let s = Spawn("SWWMHalfSmoke",pos);
s.vel = (FRandom[FlameT](-.2,.2),FRandom[FlameT](-.2,.2),FRandom[FlameT](-.2,.2));
s.vel += vel*.3;
s.alpha *= alpha*4;
s.scale *= .5+abs(scale.x)*(.5+special1/6.);
s.alpha *= alpha*.5;
s.scale *= .5+abs(scale.x*2)*(.5+special1/6.);
s.special1 = 1;
}
A_SetScale(scale.x*.98);
A_FadeOut(.005);
A_SetScale(scale.x*.98,scale.y*.98);
A_FadeOut(.01);
}
override void Tick()
{
@ -212,14 +544,18 @@ Class OnFireTrail : Actor
return;
}
}
override bool CanCollideWith( Actor Other, bool passive )
{
return false;
}
Default
{
RenderStyle "Add";
Speed 2;
Radius 4;
Radius 2;
Height 4;
Alpha .15;
Scale .3;
Alpha .3;
Scale .6;
+NOBLOCKMAP;
+NOGRAVITY;
+NOTELEPORT;
@ -228,11 +564,12 @@ Class OnFireTrail : Actor
+ROLLCENTER;
+DONTSPLASH;
+NOINTERACTION;
+MBFBOUNCER;
}
States
{
Spawn:
XFLM ABCDEFGHIJKLMNOPQRST 1 Bright A_Flame();
XFLM AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTT 1 Bright A_Flame();
Loop;
}
}

View file

@ -311,7 +311,12 @@ Class DemolitionistMenu : GenericMenu
override void Ticker()
{
Super.Ticker();
if ( ((gamestate != GS_LEVEL) || (players[consoleplayer].Health <= 0) || isclosing) && (animtimer <= 0.) )
if ( (players[consoleplayer].Health <= 0) && !isclosing )
{
MenuSound("menu/democlose");
isclosing = true;
}
if ( (gamestate != GS_LEVEL) || (isclosing && (animtimer <= 0.)) )
{
// ded (or force close)
DoClose();

View file

@ -173,6 +173,7 @@ Class SWWMStats : SWWMStaticThinker
else if ( (inflictor is 'EvisceratorChunk') || (inflictor is 'EvisceratorProj') ) which = 'Eviscerator';
else if ( inflictor is 'SheenTrail' ) which = 'HeavyMahSheenGun';
else if ( (inflictor is 'HellblazerMissile') || (inflictor is 'HellblazerRavagerArm') || (inflictor is 'HellblazerWarheadArm') ) which = 'Hellblazer';
else if ( (inflictor is 'QuadProj') || ((inflictor is 'Demolitionist') && (DamageType == 'Fire')) ) which = 'Quadravol'; // second one is a hack for fire effects
else if ( (inflictor is 'BigBiospark') || (inflictor is 'BiosparkBall') || (inflictor is 'BiosparkBeamImpact') || (inflictor is 'BiosparkComboImpact') || (inflictor is 'BiosparkComboImpactSub') || (inflictor is 'BiosparkBeam') || (inflictor is 'BiosparkArc') || (inflictor is 'BiosparkCore') ) which = 'Sparkster';
else if ( (inflictor is 'SilverAirRip') || (inflictor is 'SilverAirRip2') || (inflictor is 'SilverImpact') || (inflictor is 'FatChodeImpact') || (inflictor is 'FatChodeExplosionArm') ) which = 'SilverBullet';
else if ( (inflictor is 'CandyBeam') || (inflictor is 'CandyPop') || (inflictor is 'CandyMagArm') || (inflictor is 'CandyGunProj') || (inflictor is 'CandyMagProj') || (inflictor is 'CandyBulletImpact') ) which = 'CandyGun';

View file

@ -12,7 +12,8 @@ enum EDoExplosionFlags
DE_COUNTENEMIES = 128, // only count hits for hostiles
DE_COUNTSTEALTH = 256, // only count hits for inactive monsters
DE_COUNTFHKILLS = 512, // only count kills for enemies that were at full health
DE_NOHURTFRIEND = 1024 // splash damage will not affect allies
DE_NOHURTFRIEND = 1024, // splash damage will not affect allies
DE_QUADRAVOL = 2048 // splash burn from a Quadravol projectile, so it'll ignite enemies instead of dealing damage
};
enum EExitType
@ -1185,7 +1186,7 @@ Class SWWMUtility
// complete spherical and more accurate replacement of A_Explode
// 100% free of the buggery GZDoom's own splash damage has
// returns the number of shootables hit/killed
static play int, int DoExplosion( Actor Source, double Damage, double MomentumTransfer, double ExplosionRadius, double FullDamageRadius = 0., int flags = 0, Name DamageType = '', Actor ignoreme = null, int dmgflags = 0 )
static play int, int DoExplosion( Actor Source, double Damage, double MomentumTransfer, double ExplosionRadius, double FullDamageRadius = 0., int flags = 0, Name DamageType = '', Actor ignoreme = null, int dmgflags = 0, Actor realsource = null, Actor realinflictor = null )
{
// debug, display radius sphere
if ( swwm_debugblast )
@ -1202,7 +1203,7 @@ Class SWWMUtility
}
if ( !(flags&DE_NOSPLASH) ) Source.CheckSplash(ExplosionRadius);
double brange = 1./(ExplosionRadius-FullDamageRadius);
Actor Instigator = (flags&DE_NOTMISSILE)?Source:Source.target;
Actor Instigator = realsource?realsource:(flags&DE_NOTMISSILE)?Source:Source.target;
BlockThingsIterator bi = BlockThingsIterator.Create(Source,ExplosionRadius);
int nhit = 0, nkill = 0;
bool haskilled = false;
@ -1262,10 +1263,15 @@ Class SWWMUtility
bool hostile = (Instigator&&a.IsHostile(Instigator)&&(a.bISMONSTER||a.player));
if ( (!(flags&DE_COUNTENEMIES) || hostile) && (!(flags&DE_COUNTSTEALTH) || inactive) ) nhit++;
int dmg = int(Damage*damagescale);
if ( flags&DE_QUADRAVOL )
{
OnFire.Apply(a,Instigator,dmg); // ignite
continue;
}
if ( dmg <= 0 ) continue; // no harm
int oldhp = a.Health;
int basehp = a.GetSpawnHealth();
int ndmg = a.DamageMobj(Source,Instigator,dmg,(DamageType=='')?Source.DamageType:DamageType,DMG_EXPLOSION|dmgflags,atan2(-dir.y,-dir.x));
int ndmg = a.DamageMobj(realinflictor?realinflictor:Source,Instigator,dmg,(DamageType=='')?Source.DamageType:DamageType,DMG_EXPLOSION|dmgflags,atan2(-dir.y,-dir.x));
if ( a && !(flags&DE_NOBLEED) ) a.TraceBleed((ndmg>0)?ndmg:dmg,Source);
if ( (flags&DE_HOWL) && a && (a.Health > 0) && a.bISMONSTER && !Random[DoBlast](0,3) ) a.Howl();
if ( hostile && (!a || (a.Health <= 0)) ) haskilled = true;
@ -1347,10 +1353,15 @@ Class SWWMUtility
bool hostile = (Instigator&&a.IsHostile(Instigator)&&(a.bISMONSTER||a.player));
if ( (!(flags&DE_COUNTENEMIES) || hostile) && (!(flags&DE_COUNTSTEALTH) || inactive) ) nhit++;
int dmg = int(Damage*damagescale);
if ( flags&DE_QUADRAVOL )
{
OnFire.Apply(a,Instigator,dmg); // ignite
continue;
}
if ( dmg <= 0 ) continue; // no harm
int oldhp = a.Health;
int basehp = a.GetSpawnHealth();
int ndmg = a.DamageMobj(Source,Instigator,dmg,(DamageType=='')?Source.DamageType:DamageType,DMG_EXPLOSION|dmgflags,atan2(-dir.y,-dir.x));
int ndmg = a.DamageMobj(realinflictor?realinflictor:Source,Instigator,dmg,(DamageType=='')?Source.DamageType:DamageType,DMG_EXPLOSION|dmgflags,atan2(-dir.y,-dir.x));
if ( a && !(flags&DE_NOBLEED) ) a.TraceBleed((ndmg>0)?ndmg:dmg,Source);
if ( (flags&DE_HOWL) && a && (a.Health > 0) && a.bISMONSTER && !Random[DoBlast](0,3) ) a.Howl();
if ( hostile && (!a || (a.Health <= 0)) ) haskilled = true;
@ -1424,6 +1435,7 @@ Class SWWMUtility
if ( a is 'EvisceratorChunk' ) return true;
if ( a is 'EvisceratorProj' ) return true;
if ( a is 'HellblazerMissile' ) return true;
if ( a is 'QuadProj' ) return true;
if ( a is 'BigBiospark' ) return true;
if ( a is 'BiosparkBall' ) return true;
if ( a is 'BiosparkCore' ) return true;

View file

@ -369,7 +369,7 @@ Class HellblazerMissile : Actor
s.scale *= FRandom[Hellblazer](0.9,1.8);
}
Spawn("HellblazerRing",pos);
if ( swwm_omnibust ) BusterWall.ProjectileBust(self,250,SWWMUtility.Vec3FromAngles(angle,pitch));
if ( swwm_omnibust ) BusterWall.ProjectileBust(self,320,SWWMUtility.Vec3FromAngles(angle,pitch));
}
void A_SubExpl( double xscale = 1. )
@ -479,7 +479,7 @@ Class HellblazerCrackshot : HellblazerMissile
c.ReactionTime += Random[Hellblazer](-10,10);
HellblazerClusterMini(c).A_Steer(tracer);
}
if ( swwm_omnibust ) BusterWall.ProjectileBust(self,200,SWWMUtility.Vec3FromAngles(angle,pitch));
if ( swwm_omnibust ) BusterWall.ProjectileBust(self,250,SWWMUtility.Vec3FromAngles(angle,pitch));
}
States

View file

@ -524,7 +524,7 @@ Class Eviscerator : SWWMWeapon
XZWB ABC 2;
Goto ReadyExt;
Flash:
XZWZ A 2
XZWZ A 2 Bright
{
let psp = player.GetPSprite(PSP_FLASH);
psp.frame = Random[GunFlash](0,3);
@ -533,7 +533,7 @@ Class Eviscerator : SWWMWeapon
}
Stop;
AltFlash:
XZWZ A 2
XZWZ A 2 Bright
{
let psp = player.GetPSprite(PSP_FLASH);
psp.frame = Random[GunFlash](4,7);

View file

@ -553,7 +553,7 @@ Class ExplodiumGun : SWWMWeapon
XZW2 B -1 A_FullLower();
Stop;
Flash:
XZWZ A 2
XZWZ A 2 Bright
{
let psp = player.GetPSprite(PSP_FLASH);
psp.frame = Random[GunFlash](0,9);
@ -1176,7 +1176,7 @@ Class DualExplodiumGun : SWWMWeapon
XZWB B 2;
Stop;
Flash:
XZWZ A 2
XZWZ A 2 Bright
{
let psp = player.GetPSprite(PSP_FLASH);
psp.frame = Random[GunFlash](0,9);
@ -1185,7 +1185,7 @@ Class DualExplodiumGun : SWWMWeapon
}
Stop;
LeftFlash:
XZWZ K 2
XZWZ K 2 Bright
{
let psp = player.GetPSprite(PSP_FLASH+1);
psp.frame = Random[GunFlash](10,19);

View file

@ -689,7 +689,7 @@ Class CandyGun : SWWMWeapon
XZWE U -1 A_FullLower();
Stop;
Flash:
XZWZ A 2
XZWZ A 2 Bright
{
let psp = player.GetPSprite(PSP_FLASH);
psp.frame = Random[GunFlash](0,9);