swwmgz_m/zscript/swwm_player_fx.zsc

353 lines
9.2 KiB
Text

// player effects
// simple object for moving a dropped item towards the player
Class SWWMMagItem play
{
SWWMMagItem next;
Inventory item;
Demolitionist target;
bool Tick()
{
if ( !target || (target.Health <= 0) ) return true;
if ( !item || item.Owner || !item.bSPECIAL || item.bINVISIBLE || !SWWMUtility.SphereIntersect(target,item.pos,800) || !target.CheckSight(item,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) return true;
Class<Inventory> cls = item.GetClass();
if ( item is 'Ammo' ) cls = Ammo(item).GetParentAmmo();
else if ( item is 'MaGammo' ) cls = MagAmmo(item).GetParentMagAmmo();
let oi = target.FindInventory(cls);
if ( !item.bALWAYSPICKUP && oi && (oi.Amount >= oi.MaxAmount) ) return true;
if ( (item is 'SWWMWeapon') && SWWMWeapon(item).HasSwapWeapon(target) && swwm_swapweapons ) return true;
if ( (item is 'SWWMDualWeaponGiver') && SWWMDualWeaponGiver(item).HasSwapWeapon(target) && swwm_swapweapons ) return true;
Vector3 dirto = level.Vec3Diff(item.pos,target.Vec3Offset(0,0,target.height/2));
double dist = dirto.length();
if ( SWWMUtility.BoxIntersect(item,target) )
{
item.Touch(target);
return false;
}
dirto /= dist;
double fact = clamp(dist/800.,0.,1.)**.5;
item.vel *= .75;
item.vel += dirto*SWWMUtility.Lerp(8.,1.,fact);
item.A_SoundVolume(CHAN_AMBEXTRA,1.-.8*fact);
item.A_SoundPitch(CHAN_AMBEXTRA,SWWMUtility.Lerp(2.,.5,fact));
return false;
}
override void OnDestroy()
{
if ( !item ) return;
if ( item.bSPECIAL )
item.bNOGRAVITY = item.default.bNOGRAVITY;
item.A_StopSound(CHAN_AMBEXTRA);
}
}
Class DashTrail : SWWMNonInteractiveActor
{
Mixin SWWMMinimalMovingWaterTick;
Default
{
RenderStyle "Add";
Scale .3;
+MASTERNOSEE;
+FORCEXYBILLBOARD;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
SetState(FindState("Spawn")+Random[ExploS](0,7));
if ( waterlevel > 0 ) return;
let t = Spawn("DashTrail2",level.Vec3Offset(pos,vel*.3));
t.master = master;
t.vel = vel*1.2;
let s = Spawn("SWWMSmoke",level.Vec3Offset(pos,vel*1.6));
s.vel = vel*.8;
s.SetShade(Color(1,1,1)*Random[ExploS](64,128));
s.special1 = Random[ExploS](2,4);
s.scale *= 1.4;
s.alpha *= .3;
}
States
{
Spawn:
JFLB ABCDEFGH 1 Bright
{
A_FadeOut(.2);
A_SetScale(scale.x*.95);
}
Loop;
}
}
Class DashTrail2 : SWWMNonInteractiveActor
{
Mixin SWWMMinimalMovingWaterTick;
Default
{
RenderStyle "Add";
Scale .2;
Alpha .4;
+MASTERNOSEE;
+FORCEXYBILLBOARD;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
SetState(FindState("Spawn")+Random[ExploS](0,7));
}
States
{
Spawn:
JFLR ABCDEFGH 1 Bright
{
A_FadeOut(.02);
A_SetScale(scale.x*1.04);
if ( waterlevel > 0 )
{
let b = Spawn("SWWMBubble",pos);
b.vel = vel;
b.scale *= scale.x;
Destroy();
}
}
Loop;
}
}
Class DemolitionistRadiusShockwaveTail : SWWMNonInteractiveActor
{
Mixin SWWMMinimalMovingTick;
Default
{
RenderStyle "Add";
}
States
{
Spawn:
XZW1 A 1
{
pitch = min(85,(pitch+2)*1.05);
A_FadeOut(.02);
A_SetScale(scale.x*1.08,scale.y);
vel *= .98;
}
Wait;
}
}
Class DemolitionistRadiusShockwave : Actor
{
Actor lasthit;
Default
{
RenderStyle "Add";
Speed 15;
DamageFunction int(200*alpha);
DamageType "GroundPound";
Radius 16;
Height 8;
Alpha .4;
XScale .65;
YScale 3.;
PROJECTILE;
+DONTSPLASH;
+STEPMISSILE;
+NOEXPLODEFLOOR;
+FLATSPRITE;
+RIPPER;
+BLOODLESSIMPACT;
-NOGRAVITY;
+NOFRICTION;
}
override int DoSpecialDamage( Actor target, int damage, Name damagetype )
{
if ( target == lasthit ) return 0;
lasthit = target;
if ( damage <= 0 ) return damage;
if ( (target.mass < LARGE_MASS) && !target.bDONTTHRUST )
{
target.vel.xy += vel.xy.unit()*(30000./max(50,target.mass))*alpha;
if ( (target.pos.z <= floorz) || !target.TestMobjZ() )
target.vel.z += (8000./max(50,target.mass))*alpha;
}
return damage;
}
States
{
Spawn:
XZW1 A 1
{
SetZ(floorz);
pitch = min(85,(pitch+2)*1.05);
if ( !Random[ExploS](0,3) )
{
let p = Spawn("InvisibleSplasher",Vec3Offset(0,0,2));
p.target = target;
}
let s = Spawn("DemolitionistRadiusShockwaveTail",pos);
s.vel = vel*.35;
s.scale = scale;
s.alpha = alpha*.4;
s.angle = angle;
s.pitch = pitch;
s.roll = roll;
A_FadeOut(.015);
A_SetScale(scale.x*1.08,scale.y);
vel *= .98;
}
Wait;
Death:
XZW1 A 1
{
SetZ(floorz);
A_FadeOut(.05);
A_SetScale(scale.x*1.1,scale.y*.97);
}
Wait;
}
}
Class DemolitionistShockwave : SWWMNonInteractiveActor
{
Default
{
+NODAMAGETHRUST;
+FORCERADIUSDMG;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_QuakeEx(7,7,7,30,0,300+min(special1,50)*4,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,falloff:200,rollIntensity:1.5);
if ( target.player != players[consoleplayer] )
{
A_StartSound("demolitionist/hardland",CHAN_FOOTSTEP,CHANF_OVERLAP,attenuation:.3);
A_StartSound("demolitionist/hardland",CHAN_FOOTSTEP,CHANF_OVERLAP,attenuation:.2,pitch:.7);
A_StartSound("demolitionist/hardland",CHAN_FOOTSTEP,CHANF_OVERLAP,attenuation:.1,pitch:.4);
}
SWWMUtility.DoExplosion(self,40+min(special1,120),100000+min(special1*2000,150000),100+min(special1*2,130),80,DE_BLAST|DE_EXTRAZTHRUST|DE_NONEXPLOSIVE,'GroundPound',target);
for ( int i=0; i<360; i+=5 )
{
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[ExploS](0,360),FRandom[ExploS](-90,90))*FRandom[ExploS](1,3);
let s = Spawn("SWWMSmoke",Vec3Angle(4,i,8));
s.vel = pvel+SWWMUtility.AngleToVector3(i,7.);
s.SetShade(Color(1,1,1)*Random[ExploS](64,224));
s.special1 = Random[ExploS](1,4);
s.scale *= 1.5;
s.alpha *= .4;
}
if ( pos.z > floorz+16 ) return;
for ( int i=0; i<360; i+=5 )
{
let r = Spawn("DemolitionistRadiusShockwave",Vec3Angle(5,i));
r.target = target;
r.angle = i;
r.vel.xy = AngleToVector(i,r.speed+min(special1*.15,30));
r.alpha *= .1+min(special1*.03,.9);
}
int numpt = Random[ExploS](10,20);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[ExploS](0,360),FRandom[ExploS](-90,90))*FRandom[ExploS](2,12);
let s = Spawn("SWWMChip",pos);
s.vel = pvel;
}
let raging = RagekitPower(target.FindInventory("RagekitPower"));
if ( raging || swwm_omnibust )
{
// bust the floor if we can
let tempme = new("LineTracer"); // gross hack to pass needed data
int dmg = 40+min(special1,120);
if ( raging ) dmg *= 8;
F3DFloor ff;
for ( int i=0; i<FloorSector.Get3DFloorCount(); i++ )
{
if ( !(FloorSector.Get3DFloor(i).top.ZAtPoint(pos.xy) ~== floorz) ) continue;
ff = FloorSector.Get3DFloor(i);
break;
}
if ( ff ) tempme.Results.ffloor = ff;
tempme.Results.HitSector = FloorSector;
tempme.Results.HitType = TRACE_HitFloor;
BusterWall.Bust(tempme.Results,dmg,target,(0,0,-1),pos.z);
if ( raging )
{
let ps = Spawn("BigPunchSplash",pos);
ps.damagetype = 'GroundPound';
ps.target = target;
ps.special1 = dmg;
raging.DoHitFX();
}
}
}
States
{
Spawn:
TNT1 A 140;
Stop;
}
}
// not an actual light, just handles the attach/detach
Class DemolitionistSelfLight : Thinker
{
bool oldactive;
bool oldglow;
Actor target;
transient CVar tagcolor;
int oldcolor;
double oldheight;
override void Tick()
{
if ( !target || !target.player || (target.player.mo != target) || !(target is 'Demolitionist') || (Demolitionist(target).selflight != self) )
{
Destroy();
return;
}
if ( !tagcolor ) tagcolor = CVar.GetCVar('swwm_tagcolor',target.player);
static const Color litecolor[] =
{
Color(255, 24, 48, 8), // Green
Color(255, 16, 24, 56), // Blue
Color(255, 16, 48, 56), // Cyan
Color(255, 24, 48, 24), // Dragonfly
Color(255, 56, 32, 16), // Gold
Color(255, 48, 16, 56), // Magenta
Color(255, 56, 24, 16), // Orange
Color(255, 56, 32, 32), // Peach
Color(255, 56, 16, 40), // Pink
Color(255, 48, 24, 56), // Purple
Color(255, 48, 16, 8), // Red
Color(255, 32, 16, 56), // Violet
Color(255, 48, 48, 48), // White
Color(255, 56, 56, 16), // Yellow
Color(255, 16, 16, 16), // Black
Color(255, 32, 16, 16) // Rust
};
int idx = tagcolor.GetInt();
if ( (idx < 0) || (idx >= litecolor.Size()) ) idx = 0;
bool curactive = !(target.bINVISIBLE || (target.alpha <= double.epsilon));
// setting the pitch to a value outside [-90,90] makes it auto-update to the actor's own pitch
// this is undocumented and it's very great and nice and fine that such a thing had to be found out purely by chance
// how very wonderful /s
double curheight = target.player?(target.player.viewz-target.pos.z):(target.height*.93);
if ( curactive && (!oldactive || (idx != oldcolor) || (curheight != oldheight)) )
{
target.A_AttachLight('DemoSelfLight',DynamicLight.PointLight,Color(255,112,144,176),200,0,DynamicLight.LF_DONTLIGHTSELF|DynamicLight.LF_ATTENUATE|DynamicLight.LF_SPOT,(5,0,curheight),0,15,60,180);
target.A_AttachLight('DemoSelfLight2',DynamicLight.PointLight,litecolor[idx],80,0,DynamicLight.LF_DONTLIGHTSELF|DynamicLight.LF_ATTENUATE,(0,0,target.height/2));
}
else if ( !curactive && oldactive )
{
target.A_AttachLight('DemoSelfLight',DynamicLight.PointLight,0,0,0);
target.A_AttachLight('DemoSelfLight2',DynamicLight.PointLight,0,0,0);
}
oldactive = curactive;
oldcolor = idx;
oldheight = curheight;
}
}