More Ynykron work. Altfire is almost done.

This commit is contained in:
Mari the Deer 2020-09-11 22:29:49 +02:00
commit 578e9f3ae4
17 changed files with 753 additions and 48 deletions

View file

@ -27,6 +27,11 @@
- Finish writing all those damn side stories.
- Make 'em fancy, maybe add some lil' art to them.
**Funny Fellas:**
- Monster/decoration replacement packs. All of it modelled and tweaked to fit the style and theme of the mod. Expect enhanced enemy behaviour, not gonna keep it "vanilla".
- Porting weapons to Hideous Destructor as a meme.
**Fight for the Front and freedom. Move out!:**
- Oh boy, Strife support time.
@ -34,10 +39,6 @@
- Voice acting? Maybe not, I'd need people to re-voice all Strife NPCs.
- Oh god I have to do dialogue sprites for all characters. Maybe I can get someone else for the job?
**Funny Fellas:**
- Monster/decoration replacement packs. All of it modelled and tweaked to fit the style and theme of the mod. Expect enhanced enemy behaviour, not gonna keep it "vanilla".
- Porting weapons to Hideous Destructor as a meme.
**At this point I'm just making shit up:**

View file

@ -19,17 +19,18 @@ Most of the work here is original, but there are some notable exceptions:
- This mod uses libeye, by KeksDose. Big thanks.
- Title theme, "Traumatic State", by Teque (which a lot of people just know as "the AS-Golgotha music").
- Intermission theme, "Dragony", also by Teque (very comfy music considering the rest of his repertoire).
- Trailer theme, "Gateways Part II", also by Teque, and Cube (pretty cool track tbh).
- The anti-BD feature uses art and music by IOSYS, art was edited into the Doom palette.
- The crash handler uses a sound bit from Umineko and a short clip of the Curb Your Enthusiasm theme.
- Tewi font by lucy (https://github.com/lucy/tewi-font). Modified to add gradients and drop shadow.
- MPlus font by M⁺ FONTS PROJECT (http://mplus-fonts.osdn.jp/mplus-bitmap-fonts). Modified to add gradients and drop shadow.
- Miniwi font by Josuah Demangeon (http://josuah.net). Modified to add gradients and drop shadow.
- k6x8 font by littlelimit (https://littlelimit.net/k6x8.htm). Modified to add gradients and drop shadow.
- Terrain splashes for Doom by MagicWazard.
- Terrain splashes for Doom by MagicWazard (typical Realm667 stuff that we've all used).
- Nashgore footprint texture by Valerie Lavender.
- Slope alignment utility code by ZZYZX & Nash.
- Intermission fanart:
* Substance20 (@S20TBL)
* Captain J (@Jho7835)
* Redead-ITA
* Sgt. Shivers (@Sgt_Shivers_)
- A certain hidden easter egg / meme uses crappified/bassboosted edits of Old Days and the CBT Wikipedia article.

View file

@ -669,7 +669,7 @@ O_SILVERBULLET = "%o could not ignore the girth of %k's bullets.";
O_SILVERBULLET2 = "%o was blasted by %k's girthy bullets.";
O_CANDYGUN = "%k made %o taste the sweetness (and death).";
O_YNYKRON = "%o was instantly removed by %k.";
O_YNYKRONALT = "%o was spaghettified by %k.";
O_YNYKRONALT = "%o was furiously obliterated by %k.";
O_POUND = "%o was very impressed by %k's landing.";
O_DASH = "%o was discombobulated by a very fast moving %k.";
O_JUMP = "%o was stepped on %k.";

View file

@ -622,7 +622,7 @@ O_SILVERBULLET = "%o no pudo ignorar el grosor de las balas de %k.";
O_SILVERBULLET2 = "%o fue reventad@[ao_esp] por las gruesas balas de %k.";
O_CANDYGUN = "%k hizo probar a %o un sabor dulce (de muerte).";
O_YNYKRON = "%o fue borrad@[ao_esp] instantáneamente por %k.";
O_YNYKRONALT = "%o fue espaguetificad@[ao_esp] por %k.";
O_YNYKRONALT = "%o fue aniquilad@[ao_esp] furiosamente por %k.";
O_POUND = "%o se llevó una gran impresión del aterrizaje de %k.";
O_DASH = "%o fue descuajeringad@[ao_esp] a todo gas por %k.";
O_JUMP = "%o fue pisotead@[ao_esp] por %k.";

View file

@ -1,2 +1,2 @@
[default]
SWWM_MODVER="\chSWWM \cwGZ\c- r534 (Fri 11 Sep 16:20:58 CEST 2020)";
SWWM_MODVER="\chSWWM \cwGZ\c- r535 (Fri 11 Sep 22:29:49 CEST 2020)";

View file

@ -143,9 +143,6 @@ OptionMenu "SWWMCreditsMenu"
StaticText "Traumatic State", "White"
StaticText "Dragony", "White"
StaticText " "
StaticText "Nitro", "Gold"
StaticText "Gateways Part II", "White"
StaticText " "
StaticText "$SWWM_CFANART", "Red"
StaticText " "
StaticText "Substance20 (@S20TBL)", "Gold"

View file

@ -150,6 +150,107 @@ Model "YnykronVoidBeam"
Skin 0 "DarkRaysStartEnd.png"
FrameIndex XZW1 D 0 0
}
Model "YnykronVoidBeamTail"
{
Path "models/extra"
Model 0 "BaseBeam_d.3d"
Scale 0.0625 0.05 0.05
Offset 8 0 0
DONTCULLBACKFACES
USEACTORPITCH
USEACTORROLL
// starter
Skin 0 "DarkRaysStart.png"
FrameIndex XZW1 A 0 0
// trailer
Skin 0 "DarkRays.png"
FrameIndex XZW1 B 0 0
// cap
Skin 0 "DarkRaysEnd.png"
FrameIndex XZW1 C 0 0
// early cap
Skin 0 "DarkRaysStartEnd.png"
FrameIndex XZW1 D 0 0
}
Model "YnykronLightningArc"
{
Path "models/extra"
Model 0 "WarpBeam_d.3d"
Scale 0.5 0.8 0.8
Offset 64 0 0
DONTCULLBACKFACES
USEACTORPITCH
USEACTORROLL
Skin 0 "VortexArcS.png"
FrameIndex XZW1 A 0 1
FrameIndex XZW1 B 0 2
FrameIndex XZW1 C 0 3
FrameIndex XZW1 D 0 4
FrameIndex XZW1 E 0 5
FrameIndex XZW1 F 0 6
FrameIndex XZW1 G 0 7
FrameIndex XZW1 H 0 8
FrameIndex XZW1 I 0 9
FrameIndex XZW1 J 0 10
FrameIndex XZW1 K 0 11
FrameIndex XZW1 L 0 12
Skin 0 "VortexArc.png"
FrameIndex XZW2 A 0 1
FrameIndex XZW2 B 0 2
FrameIndex XZW2 C 0 3
FrameIndex XZW2 D 0 4
FrameIndex XZW2 E 0 5
FrameIndex XZW2 F 0 6
FrameIndex XZW2 G 0 7
FrameIndex XZW2 H 0 8
FrameIndex XZW2 I 0 9
FrameIndex XZW2 J 0 10
FrameIndex XZW2 K 0 11
FrameIndex XZW2 L 0 12
}
Model "YnykronLightningArcSub"
{
Path "models/extra"
Model 0 "WarpBeam_d.3d"
Scale 0.125 0.2 0.2
Offset 16 0 0
DONTCULLBACKFACES
USEACTORPITCH
USEACTORROLL
Skin 0 "VortexArcS.png"
FrameIndex XZW1 A 0 1
FrameIndex XZW1 B 0 2
FrameIndex XZW1 C 0 3
FrameIndex XZW1 D 0 4
FrameIndex XZW1 E 0 5
FrameIndex XZW1 F 0 6
FrameIndex XZW1 G 0 7
FrameIndex XZW1 H 0 8
FrameIndex XZW1 I 0 9
FrameIndex XZW1 J 0 10
FrameIndex XZW1 K 0 11
FrameIndex XZW1 L 0 12
Skin 0 "VortexArc.png"
FrameIndex XZW2 A 0 1
FrameIndex XZW2 B 0 2
FrameIndex XZW2 C 0 3
FrameIndex XZW2 D 0 4
FrameIndex XZW2 E 0 5
FrameIndex XZW2 F 0 6
FrameIndex XZW2 G 0 7
FrameIndex XZW2 H 0 8
FrameIndex XZW2 I 0 9
FrameIndex XZW2 J 0 10
FrameIndex XZW2 K 0 11
FrameIndex XZW2 L 0 12
}
Model "YnykronSingularity"
{

Binary file not shown.

View file

@ -814,9 +814,9 @@ ynykron/vortexarc3 sounds/ynykron/mc_vortexarc3.ogg
$random ynykron/vortexarc { ynykron/vortexarc1 ynykron/vortexarc2 ynykron/vortexarc3 }
ynykron/vortexflash1 sounds/ynykron/mc_vortexflash1.ogg
ynykron/vortexflash2 sounds/ynykron/mc_vortexflash2.ogg
ynykron/vortexflash3 sounds/ynykron/mc_vortexflash3.ogg
$random ynykron/vortexflash { ynykron/vortexflash1 ynykron/vortexflash2 ynykron/vortexflash3 }
$random ynykron/vortexflash { ynykron/vortexflash1 ynykron/vortexflash2 }
ynykron/vortexend sounds/ynykron/mc_vortexend.ogg
ynykron/wind sounds/ynykron/mc_vortexwind.ogg
misc/secret sounds/menu/findsecret.ogg
misc/keytry sounds/menu/failuse.ogg

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Before After
Before After

View file

@ -316,6 +316,23 @@ Class YnykronImpact : Actor
qsort_candidates(a,p+1,h);
}
void FlashPlayer( int str, double rad )
{
double vfov = CVar.GetCVar('fov',players[consoleplayer]).GetFloat()*0.5;
double hfov = atan(Screen.GetAspectRatio()*tan(vfov));
let mo = players[consoleplayer].camera;
Vector3 pp;
if ( !CheckSight(mo) ) return;
if ( mo is 'PlayerPawn' ) pp = mo.Vec2OffsetZ(0,0,PlayerPawn(mo).player.viewz);
else pp = mo.Vec3Offset(0,0,mo.CameraHeight);
Vector3 sc = level.SphericalCoords(pp,pos,(mo.angle,mo.pitch));
if ( (abs(sc.x) < hfov) && (abs(sc.y) < vfov) && (sc.z < rad) )
{
str = int(str*(1.-(sc.z/rad)));
SWWMHandler.DoFlash(mo,Color(str,255,255,255),2);
SWWMHandler.DoFlash(mo,Color(str/2,255,255,255),10);
}
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
@ -323,6 +340,7 @@ Class YnykronImpact : Actor
if ( swwm_ynykronalert && (!special2 || swwm_extraalert) ) A_AlertMonsters();
rad = args[0]+300+10*clamp(special1/10,0,15);
A_QuakeEx(4,4,4,50,0,rad*4,"",QF_RELATIVE|QF_SCALEDOWN,falloff:rad*2,rollintensity:.6);
FlashPlayer(60,1200);
if ( tracer )
{
// voodoo dolls just get erased (how convenient)
@ -938,10 +956,28 @@ Class YnykronShot : Actor
+DONTSPLASH;
+NOINTERACTION;
}
void FlashPlayer( int str, double rad )
{
double vfov = CVar.GetCVar('fov',players[consoleplayer]).GetFloat()*0.5;
double hfov = atan(Screen.GetAspectRatio()*tan(vfov));
let mo = players[consoleplayer].camera;
Vector3 pp;
if ( !CheckSight(mo) ) return;
if ( mo is 'PlayerPawn' ) pp = mo.Vec2OffsetZ(0,0,PlayerPawn(mo).player.viewz);
else pp = mo.Vec3Offset(0,0,mo.CameraHeight);
Vector3 sc = level.SphericalCoords(pp,pos,(mo.angle,mo.pitch));
if ( (abs(sc.x) < hfov) && (abs(sc.y) < vfov) && (sc.z < rad) )
{
str = int(str*(1.-(sc.z/rad)));
SWWMHandler.DoFlash(mo,Color(str,255,255,255),3);
SWWMHandler.DoFlash(mo,Color(str/2,255,255,255),30);
}
}
override void PostBeginPlay()
{
A_QuakeEx(6,6,6,150,0,65536,"",QF_RELATIVE|QF_SCALEDOWN,falloff:65536,rollIntensity:1.);
A_StartSound("ynykron/beam",CHAN_VOICE,CHANF_DEFAULT,1.,0.);
FlashPlayer(240,8000);
hitlist.Clear();
beamcount = 0;
blastcount = 0;
@ -1039,6 +1075,35 @@ Class YnykronAltTracer : LineTracer
}
}
Class YnykronHaloTail : Actor
{
Default
{
RenderStyle "Add";
+NOGRAVITY;
+DONTSPLASH;
+NOTELEPORT;
+NOBLOCKMAP;
+NOINTERACTION;
+FORCEXYBILLBOARD;
Radius .1;
Height 0.;
Scale 1.5;
}
override void Tick()
{
if ( isFrozen() ) return;
A_SetScale(scale.x+.5);
A_FadeOut(.2);
}
States
{
Spawn:
MHAL A -1 Bright;
Stop;
}
}
Class YnykronHalo : Actor
{
Default
@ -1064,6 +1129,9 @@ Class YnykronHalo : Actor
}
SetOrigin(target.pos,true);
A_SetScale(1.5*target.scale.x);
A_AttachLight('YNYKRONHALOLIGHT',DynamicLight.PointLight,Color(224,32,255),int(900*scale.x),0,DYNAMICLIGHT.LF_ATTENUATE);
let h = Spawn("YnykronHaloTail",pos);
h.scale = scale;
}
States
{
@ -1094,40 +1162,40 @@ Class GatherDust : Actor
Scale *= FRandom[ExploS](.75,1.5);
Scale.x *= RandomPick[ExploS](-1,1);
Scale.y *= RandomPick[ExploS](-1,1);
SetShade(Color(4,3,5)*Random[ExploS](5,20));
}
void A_Gravitate()
{
if ( target && !target.InStateSequence(target.CurState,target.FindState("Death")) )
{
if ( alpha < .02 ) A_FadeIn(FRandom[ExploS](.0002,.001));
if ( alpha < .08 ) A_FadeIn(FRandom[ExploS](.0002,.004));
Vector3 dirto = level.Vec3Diff(pos,target.pos);
double distto = dirto.length();
if ( distto < (32.*target.scale.x) )
{
// sucked in
target.specialf2 += 1.;
target.specialf2 += FRandom[ExploS](.1,.4);
Destroy();
return;
}
dirto /= distto;
double mxdist = 5000.*target.scale.x;
vel = dirto*16.*(clamp((mxdist-distto)/mxdist,.5,1.)**3.);
vel = dirto*25.*(clamp((mxdist-distto)/mxdist,.5,1.)**4.);
vel += target.vel;
return;
}
vel *= .98;
A_FadeOut(.001);
A_FadeOut(.002);
}
Default
{
RenderStyle "Shaded";
StencilColor "f8 a0 ff";
Radius .1;
Height 0.;
Alpha 0.;
Scale 2.;
Scale 3.;
+NOGRAVITY;
+NOBLOCKMAP;
+DONTSPLASH;
@ -1144,6 +1212,33 @@ Class GatherDust : Actor
}
}
Class YnykronVoidBeamTail : Actor
{
Default
{
RenderStyle "Add";
+NOGRAVITY;
+DONTSPLASH;
+NOTELEPORT;
+NOBLOCKMAP;
+NOINTERACTION;
+FORCEXYBILLBOARD;
Radius .1;
Height 0.;
}
override void Tick()
{
if ( isFrozen() ) return;
A_FadeOut();
}
States
{
Spawn:
XZW1 # -1 Bright;
Stop;
}
}
Class YnykronVoidBeam : Actor
{
Actor basebeam, prevbeam, nextbeam;
@ -1306,6 +1401,12 @@ Class YnykronVoidBeam : Actor
nextbeam.angle += da*.2;
nextbeam.pitch += dp*.2;
}
let h = Spawn("YnykronVoidBeamTail",pos);
h.angle = angle;
h.pitch = pitch;
h.alpha = alpha*2.;
h.scale = scale;
h.frame = frame;
}
override void Tick()
@ -1328,33 +1429,449 @@ Class YnykronVoidBeam : Actor
}
}
Class YnykronLightningImpact : Actor
{
Default
{
Obituary "$O_YNYKRONALT";
DamageType "Electric";
Radius .1;
Height 0;
+FOILINVUL;
+FORCERADIUSDMG;
+NODAMAGETHRUST;
+NOINTERACTION;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
SWWMUtility.DoExplosion(self,400,120000,100,40);
A_QuakeEx(3,3,3,12,0,800,"",QF_RELATIVE|QF_SCALEDOWN,falloff:300,rollIntensity:.4);
A_SprayDecal("ShockMark",-172);
int numpt = Random[ExploS](8,16);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](3,12);
let s = Spawn("SWWMSmoke",pos);
s.vel = pvel;
s.SetShade(Color(1,1,1)*Random[ExploS](64,224));
s.special1 = Random[ExploS](1,4);
s.scale *= 2.;
s.alpha *= .4;
}
numpt = Random[ExploS](5,10);
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,12);
let s = Spawn("SWWMSpark",pos);
s.vel = pvel;
}
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,24);
let s = Spawn("SWWMChip",pos);
s.vel = pvel;
}
Destroy();
}
}
Class YnykronLightningArc : Actor
{
Vector3 nextpos, nextdir;
Vector3 destpos;
action void A_Trace()
{
let t = new("CandyBeamTracer");
t.hitlist.Clear();
Vector3 x, y, z;
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
t.ShootThroughList.Clear();
t.Trace(pos,CurSector,x,speed,TRACE_HitSky);
for ( int i=0; i<t.ShootThroughList.Size(); i++ )
{
t.ShootThroughList[i].Activate(target,0,SPAC_PCross);
if ( t.ShootThroughList[i].special == GlassBreak ) // fuck glass
t.ShootThroughList[i].Activate(target,0,SPAC_Impact);
}
for ( int i=0; i<t.hitlist.Size(); i++ )
{
SWWMUtility.DoKnockback(t.hitlist[i].hitactor,-t.hitlist[i].x,GetMissileDamage(0,0)*1000);
t.hitlist[i].hitactor.DamageMobj(self,target,GetMissileDamage(0,0),'Electric',DMG_THRUSTLESS);
}
Vector3 normal = -t.Results.HitVector, dir = t.Results.HitVector;
if ( t.Results.HitType != TRACE_HitNone )
{
if ( t.Results.HitType != TRACE_HasHitSky )
{
if ( t.Results.HitType == TRACE_HitWall )
{
normal = (-t.Results.HitLine.delta.y,t.Results.HitLine.delta.x,0).unit();
if ( !t.Results.Side ) normal *= -1;
t.Results.HitLine.RemoteActivate(target,t.Results.Side,SPAC_Impact,t.Results.HitPos);
}
else if ( t.Results.HitType == TRACE_HitFloor )
{
if ( t.Results.ffloor ) normal = -t.Results.ffloor.top.Normal;
else normal = t.Results.HitSector.floorplane.Normal;
}
else if ( t.Results.HitType == TRACE_HitCeiling )
{
if ( t.Results.ffloor ) normal = -t.Results.ffloor.bottom.Normal;
else normal = t.Results.HitSector.ceilingplane.Normal;
}
let s = Spawn("YnykronLightningImpact",level.Vec3Offset(t.Results.HitPos,normal*8));
s.target = target;
s.angle = atan2(normal.y,normal.x);
s.pitch = asin(-normal.z);
}
invoker.nextpos = t.Results.HitPos;
bAMBUSH = true;
return;
}
invoker.nextpos = level.Vec3Offset(pos,x*speed);
double a = FRandom[Ynykron](0,360), s = FRandom[Ynykron](0.,.8);
dir = (dir+cos(a)*y*s+sin(a)*z*s).unit();
if ( !special1 )
{
invoker.destpos = level.Vec3Offset(pos,x*10000);
// calculate the closest strike point to home in onto
Vector3 strikepoints[32];
double closest = 10000.;
for ( int i=0; i<32; i++ )
{
a = FRandom[Ynykron](0,360);
s = FRandom[Ynykron](.2,1.);
Vector3 tdir = (dir+cos(a)*y*s+sin(a)*z*s).unit();
FLineTraceData d;
LineTrace(atan2(tdir.y,tdir.x),10000,asin(-tdir.z),TRF_THRUACTORS,data:d);
strikepoints[i] = d.HitLocation;
if ( d.Distance < closest )
{
invoker.destpos = strikepoints[i];
closest = d.Distance;
}
}
}
Vector3 dirto = level.Vec3Diff(invoker.nextpos,invoker.destpos);
double dist = dirto.length();
if ( dist > 10 )
{
dirto /= dist;
dir = (dir+.8*dirto*(clamp(1.-(dist/1500.),0.,1.)**1.5)).unit();
}
invoker.nextdir = dir;
}
action void A_Spread( Sound arcsnd )
{
Vector3 tdir = level.Vec3Diff(pos,invoker.nextpos);
if ( (GetClass() == 'YnykronLightningArc') && !Random[Ynykron](0,3) )
{
for ( int i=0; i<3; i++ )
{
let r = Spawn("YnykronLightningArcSub",level.Vec3Offset(pos,tdir*FRandom[Ynykron](0,1)));
Vector3 x, y, z;
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
double a = FRandom[Ynykron](0,360), s = FRandom[Sparkster](0.,1.);
Vector3 sdir = (x+y*cos(a)*s+z*sin(a)*s).unit();
r.angle = atan2(sdir.y,sdir.x);
r.pitch = asin(-sdir.z);
r.target = target;
r.special1 = 1;
YnykronLightningArc(r).destpos = invoker.destpos;
r.ReactionTime += Random[Ynykron](-3,3);
}
}
if ( ((ReactionTime > 0) && (special1 > ReactionTime)) || bAMBUSH ) return;
let b = Spawn(GetClass(),invoker.nextpos);
b.angle = atan2(invoker.nextdir.y,invoker.nextdir.x);
b.pitch = asin(-invoker.nextdir.z);
b.target = target;
b.special1 = special1+1;
YnykronLightningArc(b).destpos = invoker.destpos;
b.SetState(b.FindState("Trailer"));
if ( arcsnd != "" ) A_StartSound(arcsnd,CHAN_WEAPON);
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
frame = Random[Ynykron](0,11);
}
override void Tick()
{
if ( isFrozen() ) return;
if ( !CheckNoDelay() || (tics == -1) ) return;
if ( tics > 0 ) tics--;
while ( !tics )
{
if ( !SetState(CurState.NextState) )
return;
}
}
Default
{
Obituary "$O_YNYKRONALT";
RenderStyle "Add";
DamageFunction 1000;
Speed 128;
Radius .1;
Height 0;
Alpha 2.;
+NOGRAVITY;
+NOCLIP;
+DONTSPLASH;
+NOTELEPORT;
+FOILINVUL;
+NOINTERACTION;
}
States
{
Spawn:
XZW1 # 0 Bright;
XZW1 # 1 Bright A_Trace();
XZW1 # 1 Bright A_Spread("ynykron/vortexarc");
XZW1 # 1 Bright A_FadeOut();
Wait;
Trailer:
XZW2 # 0 Bright;
XZW2 # 1 Bright A_Trace();
XZW2 # 1 Bright A_Spread("ynykron/vortexarc");
XZW2 # 1 Bright A_FadeOut();
Wait;
}
}
Class YnykronLightningArcSub : YnykronLightningArc
{
Default
{
DamageFunction 250;
Speed 32;
ReactionTime 10;
}
States
{
Spawn:
XZW1 # 0 Bright;
XZW1 # 1 Bright A_Trace();
XZW1 # 1 Bright A_Spread("");
XZW1 # 1 Bright A_FadeOut();
Wait;
Trailer:
XZW2 # 0 Bright;
XZW2 # 1 Bright A_Trace();
XZW2 # 1 Bright A_Spread("");
XZW2 # 1 Bright A_FadeOut();
Wait;
}
}
Class YnykronCloud : Actor
{
Vector3 gx, gy, gz;
double phase;
Vector3 dirto;
double frightening; // lightning flash
Color basecol;
double rollvel;
override void Tick()
{
prev = pos;
if ( isFrozen() ) return;
if ( !CheckNoDelay() || (tics == -1) ) return;
if ( tics > 0 ) tics--;
while ( !tics )
{
if ( !SetState(CurState.NextState) )
return;
}
}
void FlashPlayer( int str, double rad )
{
double vfov = CVar.GetCVar('fov',players[consoleplayer]).GetFloat()*0.5;
double hfov = atan(Screen.GetAspectRatio()*tan(vfov));
let mo = players[consoleplayer].camera;
Vector3 pp;
if ( !CheckSight(mo) ) return;
if ( mo is 'PlayerPawn' ) pp = mo.Vec2OffsetZ(0,0,PlayerPawn(mo).player.viewz);
else pp = mo.Vec3Offset(0,0,mo.CameraHeight);
Vector3 sc = level.SphericalCoords(pp,pos,(mo.angle,mo.pitch));
if ( (abs(sc.x) < hfov) && (abs(sc.y) < vfov) && (sc.z < rad) )
{
str = int(str*(1.-(sc.z/rad)));
SWWMHandler.DoFlash(mo,Color(str,255,255,255),1);
SWWMHandler.DoFlash(mo,Color(str/2,240,224,255),10);
}
}
override void PostBeginPlay()
{
SetState(FindState("Spawn")+Random[ExploS](0,19));
Scale *= FRandom[ExploS](.75,1.5);
Scale.x *= RandomPick[ExploS](-1,1);
Scale.y *= RandomPick[ExploS](-1,1);
if ( master ) Scale *= master.scale.x;
// orbit axes
[gx, gy, gz] = swwm_CoordUtil.GetAxes(FRandom[ExploS](-90,90),FRandom[ExploS](0,360),FRandom[ExploS](-90,90));
specialf1 = FRandom[ExploS](200,400);
scale *= specialf1/200.;
specialf2 = FRandom[ExploS](3.,8.)*RandomPick[ExploS](-1,1);
special2 = Random[ExploS](10,40);
basecol = Color(4,3,5)*Random[ExploS](5,20);
SetShade(basecol);
rollvel = FRandom[ExploS](.5,3.)*RandomPick[ExploS](-1,1);
}
void A_Gravitate()
{
if ( frightening > 0. )
{
alpha = max(frightening,.3);
int str = int(RandomPick[ExploS](255,240,192,254,248,128,160,204)*frightening);
Color litecol = Color(min(255,basecol.r+str),min(255,basecol.g+str),min(255,basecol.b+str));
SetShade(litecol);
frightening *= .96;
if ( frightening < .1 )
{
frightening = 0.;
SetShade(basecol);
}
}
roll += rollvel;
if ( master && !master.InStateSequence(master.CurState,master.FindState("Death")) )
{
if ( special1 == 0 )
{
A_FadeIn(FRandom[ExploS](.001,.002));
if ( alpha > .3 ) special1 = 1;
}
else if ( special1 > 0 )
{
special1++;
if ( special1 >= special2 )
special1 = -1;
}
else if ( special1 == -1 ) A_FadeOut(FRandom[ExploS](.003,.006));
dirto = level.Vec3Diff(pos,master.pos);
double distto = dirto.length();
dirto /= distto;
// orbit
Vector3 orbitdir = (gx*cos(phase)+gy*sin(phase))*(specialf1+32)*master.scale.x;
SetOrigin(level.Vec3Offset(master.pos,orbitdir),true);
phase += FRandom[ExploS](.12,.24)*specialf2*(1.-specialf1/600.);
return;
}
SetOrigin(level.Vec3Offset(pos,-dirto*3.*abs(specialf2)),true);
specialf2 *= .98;
A_FadeOut(.005);
}
Default
{
DamageType 'YnykronAlt';
Obituary "$O_YNYKRONALT";
RenderStyle "Shaded";
Radius .1;
Height 0.;
Alpha 0.;
Scale 3.;
+NOGRAVITY;
+NOBLOCKMAP;
+DONTSPLASH;
+NOTELEPORT;
+NOINTERACTION;
+FORCEXYBILLBOARD;
+ROLLSPRITE;
+NOCLIP;
}
States
{
Spawn:
DUST ABCDEFGHIJKLMNOPQRST 1 A_Gravitate();
Wait;
}
}
Class YnykronLightningLight : PaletteLight
{
Default
{
Tag "WhiteExpl";
ReactionTime 12;
Args 0,0,0,900;
}
}
Class YnykronLightningLight2 : PaletteLight
{
Default
{
Tag "WhiteExpl";
ReactionTime 10;
Args 0,0,0,500;
}
}
Class SimpleMoveTracer : LineTracer
{
override ETraceStatus TraceCallback()
{
if ( Results.HitType == TRACE_HitActor ) return TRACE_Skip;
else if ( (Results.HitType == TRACE_HitWall) && (Results.Tier == TIER_Middle) )
{
if ( !Results.HitLine.sidedef[1] || (Results.HitLine.Flags&Line.ML_BLOCKPROJECTILE) )
return TRACE_Stop;
return TRACE_Skip;
}
return TRACE_Stop;
}
}
Class YnykronSingularity : Actor
{
Actor beamers[16];
const MAXBEAMS = 20;
const MAXCLOUDS = 500;
Actor beamers[MAXBEAMS];
Actor clouds[MAXCLOUDS];
const MION_CONST = 48538.; // miön v-force compression constant (approximate)
const YNON_CONST = .063738; // ÿnon v-force field constant (approximate)
const AXAN_CONST = 29.2761; // axan u-force field constant (approximate)
const YNON_CONST = .043738; // ÿnon v-force field constant (approximate)
const AXAN_CONST = 27.2761; // axan u-force field constant (approximate)
const GOAL_MASS = 26741.; // mass required to compensate Ynykron altfire negative energy release (-2.4×10¹⁵ J, approximately)
double critmass; // actual mass required (cummulative with absorbed vortices)
int litetimer;
transient SimpleMoveTracer mt;
override void PostBeginPlay()
{
let g = Spawn("YnykronHalo",pos);
g.target = self;
A_StartSound("ynykron/vortex",CHAN_BODY,CHANF_LOOP);
A_StartSound("ynykron/vortex",CHAN_BODY,CHANF_LOOP,1.,.6);
A_StartSound("ynykron/wind",CHAN_ITEM,CHANF_LOOP,1.,.0);
A_StartSound("ynykron/hit",CHAN_VOICE,CHANF_OVERLAP,1.,.0);
// initial mass and radius
specialf1 = scale.x;
specialf2 = scale.x*scale.x*MION_CONST;
critmass = GOAL_MASS;
litetimer = level.maptime+Random[Ynykron](180,240);
}
// lightweight tick, we don't need anything else other than states
override void Tick()
{
if ( isFrozen() ) return;
Vector3 newpos = level.Vec3Offset(pos,vel);
Vector3 newpos;
if ( !mt ) mt = new("SimpleMoveTracer");
mt.Trace(pos,CurSector,vel,1.,0);
if ( mt.Results.HitType == TRACE_HitNone ) newpos = level.Vec3Offset(pos,vel);
else newpos = level.Vec3Offset(mt.Results.HitPos,-mt.Results.HitVector);
if ( level.IsPointInLevel(newpos) )
SetOrigin(newpos,true);
if ( !CheckNoDelay() || (tics == -1) ) return;
@ -1375,8 +1892,8 @@ Class YnykronSingularity : Actor
void A_SingularityTick()
{
// gather dust particles (very minor "background" mass gain)
int numpt = int(max(2,16*scale.x));
// gather dust particles (minor "background" mass gain)
int numpt = int(max(4,32*scale.x));
for ( int i=0; i<numpt; i++ )
{
double ang = FRandom[ExploS](0,360);
@ -1404,9 +1921,59 @@ Class YnykronSingularity : Actor
let gd = Spawn("GatherDust",level.Vec3Offset(d.HitLocation,norm*8));
gd.target = self;
}
// TODO storm clouds and lightning
// storm clouds
for ( int i=0; i<MAXCLOUDS; i++ )
{
if ( clouds[i] && (clouds[i].special1 > -1) ) continue;
clouds[i] = Spawn("YnykronCloud",pos);
clouds[i].target = target;
clouds[i].master = self;
}
// check dense cloud formations for lightning
if ( level.maptime > litetimer )
{
int which = Random[Ynykron](0,MAXCLOUDS-1);
if ( clouds[which] )
{
Array<Actor> contacts;
Array<double> dists;
contacts.Clear();
dists.Clear();
for ( int i=0; i<MAXCLOUDS; i++ )
{
if ( !clouds[i] || (i == which) || (clouds[i].Alpha < .1) ) continue;
double dist = clouds[which].Distance3D(clouds[i]);
if ( dist > (200*scale.x) ) continue;
contacts.Push(clouds[i]);
dists.Push(dist);
}
if ( (contacts.Size() > 12) && !Random[Ynykron](0,5) )
{
Spawn("YnykronLightningLight",clouds[which].pos);
Spawn("YnykronLightningLight2",clouds[which].pos);
A_StartSound("ynykron/vortexflash",CHAN_WEAPON,CHANF_OVERLAP,1.,0.,FRandom[Ynykron](.9,1.1));
YnykronCloud(clouds[which]).frightening = 1.;
YnykronCloud(clouds[which]).FlashPlayer(200,3000);
for ( int i=0; i<contacts.Size(); i++ )
YnykronCloud(contacts[i]).frightening = (1.-dists[i]/(200*scale.x))**.5;
litetimer = level.maptime+Random[Ynykron](120,240);
SWWMUtility.DoExplosion(clouds[which],1200,40000,500,150);
// lightning arcs
int numpt = Random[Ynykron](0,3);
Vector3 dirto = level.Vec3Diff(pos,clouds[which].pos);
dirto /= dirto.length();
for ( int i=0; i<numpt; i++ )
{
let l = Spawn("YnykronLightningArc",clouds[which].pos);
l.angle = atan2(dirto.y,dirto.x)+FRandom[Ynykron](-5,5);
l.pitch = asin(-dirto.z)+FRandom[Ynykron](-5,5);
l.target = target;
}
}
}
}
// ol' crazy purple beams from original
for ( int i=0; i<16; i++ )
for ( int i=0; i<MAXBEAMS; i++ )
{
if ( beamers[i] || Random[Ynykron](0,40) ) continue;
beamers[i] = Spawn("YnykronVoidBeam",pos);
@ -1476,6 +2043,13 @@ Class YnykronSingularity : Actor
double grav = (3.*YNON_CONST*specialf2*capmass)/(dist**.5);
// strong gravitational force as per u-field (approximate)
grav += (4.*AXAN_CONST*specialf2*capmass)/(dist**2.);
// account for ground friction
if ( a.pos.z <= a.floorz )
{
double frict, movef;
[frict, movef] = a.GetFriction();
grav *= movef;
}
if ( a.mass < LARGE_MASS )
{
// v-force field compression (very rough approximation)
@ -1517,14 +2091,33 @@ Class YnykronSingularity : Actor
SetStateLabel("Death");
}
void FlashPlayer( int str, double rad )
{
double vfov = CVar.GetCVar('fov',players[consoleplayer]).GetFloat()*0.5;
double hfov = atan(Screen.GetAspectRatio()*tan(vfov));
let mo = players[consoleplayer].camera;
Vector3 pp;
if ( !CheckSight(mo) ) return;
if ( mo is 'PlayerPawn' ) pp = mo.Vec2OffsetZ(0,0,PlayerPawn(mo).player.viewz);
else pp = mo.Vec3Offset(0,0,mo.CameraHeight);
Vector3 sc = level.SphericalCoords(pp,pos,(mo.angle,mo.pitch));
if ( (abs(sc.x) < hfov) && (abs(sc.y) < vfov) && (sc.z < rad) )
{
str = int(str*(1.-(sc.z/rad)));
SWWMHandler.DoFlash(mo,Color(str,255,255,255),3);
SWWMHandler.DoFlash(mo,Color(str/2,240,224,255),30);
}
}
void A_SingularityBlast()
{
Console.Printf("// TODO explosion goes here");
A_StopSound(CHAN_BODY);
A_QuakeEx(8,8,8,80,0,65536,"",QF_RELATIVE|QF_SCALEDOWN,falloff:65536,rollIntensity:1.6);
A_StopAllSounds();
A_StartSound("ynykron/vortexend",CHAN_VOICE,attenuation:0.);
FlashPlayer(250,9000);
vel *= 0;
// kill off and detach any leftover beams
for ( int i=0; i<16; i++ )
for ( int i=0; i<MAXBEAMS; i++ )
{
if ( !beamers[i] ) continue;
YnykronVoidBeam(beamers[i]).maxlife = 0;
@ -1537,11 +2130,11 @@ Class YnykronSingularity : Actor
if ( special1 > 80 )
{
if ( IsActorPlayingSound(CHAN_VOICE) ) return;
for ( int i=0; i<16; i++ ) if ( beamers[i] ) return;
for ( int i=0; i<MAXBEAMS; i++ ) if ( beamers[i] ) return;
Destroy();
return;
}
for ( int i=0; i<16; i++ )
for ( int i=0; i<MAXBEAMS; i++ )
{
if ( beamers[i] )
{
@ -1691,7 +2284,7 @@ Class YnykronAltBeam : Actor
if ( isFrozen() ) return;
A_FadeOut(FRandom[Ynykron](.01,.02));
special2++;
if ( special2 == 2 )
if ( special2 == 1 )
SpreadOut();
if ( !CheckNoDelay() || (tics == -1) ) return;
if ( tics > 0 ) tics--;
@ -1773,10 +2366,28 @@ Class YnykronAltShot : Actor
+DONTSPLASH;
+NOINTERACTION;
}
void FlashPlayer( int str, double rad )
{
double vfov = CVar.GetCVar('fov',players[consoleplayer]).GetFloat()*0.5;
double hfov = atan(Screen.GetAspectRatio()*tan(vfov));
let mo = players[consoleplayer].camera;
Vector3 pp;
if ( !CheckSight(mo) ) return;
if ( mo is 'PlayerPawn' ) pp = mo.Vec2OffsetZ(0,0,PlayerPawn(mo).player.viewz);
else pp = mo.Vec3Offset(0,0,mo.CameraHeight);
Vector3 sc = level.SphericalCoords(pp,pos,(mo.angle,mo.pitch));
if ( (abs(sc.x) < hfov) && (abs(sc.y) < vfov) && (sc.z < rad) )
{
str = int(str*(1.-(sc.z/rad)));
SWWMHandler.DoFlash(mo,Color(str,255,255,255),5);
SWWMHandler.DoFlash(mo,Color(str/2,0,0,0),15);
}
}
override void PostBeginPlay()
{
A_QuakeEx(4,4,4,80,0,65536,"",QF_RELATIVE|QF_SCALEDOWN,falloff:65536,rollIntensity:.8);
A_StartSound("ynykron/altbeam",CHAN_VOICE,CHANF_DEFAULT,1.,0.);
FlashPlayer(240,8000);
let b = Spawn("YnykronAltBeam",pos);
b.target = target;
b.angle = angle;
@ -1890,18 +2501,12 @@ Class Ynykron : SWWMWeapon
Vector3 x, y, z, origin;
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),x*15+y*4);
if ( invoker.inverted )
{
// TODO altfire
Console.Printf("\cgYNYKRON ALTFIRE NOT DONE, FALLBACK TO PRIMARY\c-");
}
//else
{
let s = Spawn("YnykronShot",origin);
s.target = self;
s.angle = angle;
s.pitch = BulletSlope();
}
Actor s;
if ( invoker.inverted ) s = Spawn("YnykronAltShot",origin);
else s = Spawn("YnykronShot",origin);
s.target = self;
s.angle = angle;
s.pitch = BulletSlope();
invoker.specialf1 = 1.;
A_Overlay(PSP_WEAPON+3,"FireBlast");
}

View file

@ -234,7 +234,7 @@ Class CandyPop : Actor
double hfov = atan(Screen.GetAspectRatio()*tan(vfov));
let mo = players[consoleplayer].camera;
Vector3 pp;
if ( !mo.CheckSight(self) ) return;
if ( !CheckSight(mo) ) return;
if ( mo is 'PlayerPawn' ) pp = mo.Vec2OffsetZ(0,0,PlayerPawn(mo).player.viewz);
else pp = mo.Vec3Offset(0,0,mo.CameraHeight);
Vector3 sc = level.SphericalCoords(pp,pos,(mo.angle,mo.pitch));

View file

@ -129,7 +129,7 @@ Class SWWMStats : Thinker
else if ( (inflictor is 'HellblazerRavagerArm') || (inflictor is 'HellblazerWarheadArm') ) which = 'Hellblazer';
else if ( (inflictor is 'BigBiospark') || (inflictor is 'BiosparkBall') || (inflictor is 'BiosparkBeamImpact') || (inflictor is 'BiosparkComboImpact') || (inflictor is 'BiosparkComboImpactSub') || (inflictor is 'BiosparkBeam') || (inflictor is 'BiosparkArc') ) which = 'Sparkster';
else if ( (inflictor is 'CandyBeam') || (inflictor is 'CandyPop') || (inflictor is 'CandyMagArm') || (inflictor is 'CandyGunProj') || (inflictor is 'CandyMagProj') || (inflictor is 'CandyBulletImpact') ) which = 'CandyGun';
else if ( (inflictor is 'YnykronBeam') || (inflictor is 'YnykronImpact') ) which = 'Ynykron';
else if ( (inflictor is 'YnykronBeam') || (inflictor is 'YnykronImpact') || (inflictor is 'YnykronSingularity') || (inflictor is 'YnykronCloud') || (inflictor is 'YnykronVoidBeam') || (inflictor is 'YnykronLightningArc') || (inflictor is 'YnykronLightningImpact') ) which = 'Ynykron';
else if ( (inflictor is 'Demolitionist') || (inflictor is 'DemolitionistShockwave') || (inflictor is 'DemolitionistRadiusShockwave') ) which = 'SWWMWeapon'; // hack to assume Demolitionist as weapon
if ( !which ) return;
for ( int i=0; i<wstats.Size(); i++ )