swwmgz_m/zscript/weapons/swwm_deathlydeathcannon.zsc
Marisa the Magician c770276bd7 Various changes related to items:
- All items now have vanilla hitbox sizes for compatibility.
 - Removed extended hitboxes (no longer needed).
 - Blob shadows are now exclusive to players (and eventually monsters).
 - Glows and sparkles are no longer toggleable.
 - Glows and sparkles have fixed size/radius.
 - Item sparkles are now handled by the glows, rather than the player.
2022-10-28 16:49:14 +02:00

563 lines
15 KiB
Text

// Ynykron Artifact (from UnSX Series, featured in SWWM Platinum as a secret weapon)
// Slot 0, replaces BFG9000, Firemace, Wraithverge (arc)
Class Ynykron : SWWMWeapon
{
transient ui SmoothDynamicValueInterpolator ChargeInter;
enum EChargeState
{
CS_IDLE,
CS_CHARGING,
CS_READY,
CS_DISCHARGING,
CS_POSTFIRE
};
int chargestate;
double chargelevel;
bool inverted, invertreload;
ui int lastmode;
double ventalpha, ventfade;
int ventcooldown;
int clipcount;
Property ClipCount : clipcount;
override void HudTick()
{
Super.HudTick();
if ( !ChargeInter ) ChargeInter = SmoothDynamicValueInterpolator.Create(chargelevel*10,.5);
ChargeInter.Update(chargelevel*10);
if ( lastmode && (lastmode != inverted+1) && (Owner.player == players[consoleplayer]) )
{
let bar = SWWMStatusBar(statusbar);
if ( bar )
{
bar.ntagstr = StringTable.Localize(inverted?"$SWWM_YNYKRONBACKWARD":"$SWWM_YNYKRONFORWARD");
bar.ntagtic = level.totaltime;
bar.ntagcol = nametagcolor;
}
}
lastmode = inverted+1;
}
override bool ReportHUDAmmo()
{
if ( clipcount > 0 ) return true;
return Super.ReportHUDAmmo();
}
override bool CheckAmmo( int firemode, bool autoswitch, bool requireammo, int ammocount )
{
if ( sv_infiniteammo || Owner.FindInventory('PowerInfiniteAmmo',true) ) return true;
if ( (fireMode == PrimaryFire) || (fireMode == AltFire) )
{
if ( (clipcount > 0) || (Ammo1.Amount > 0) ) return true;
if ( autoswitch ) PlayerPawn(Owner).PickNewWeapon(null);
return false;
}
return Super.CheckAmmo(firemode,autoswitch,requireammo,ammocount);
}
override void Travelled()
{
if ( Owner.player && (Owner.player.Readyweapon == self) )
{
Owner.A_StartSound("ynykron/idle",CHAN_WEAPONEXTRA,CHANF_LOOP,.3,4.);
if ( chargestate > CS_IDLE )
Owner.A_StartSound("ynykron/ready",CHAN_WEAPONEXTRA2,CHANF_LOOP,(.025*chargelevel)**3.,2.);
}
}
override Vector3 GetTraceOffset( int index )
{
return (15.,4.,-1.);
}
action void A_YnykronFire()
{
A_SWWMFlash();
A_StopSound(CHAN_WEAPONEXTRA2);
A_StartSound(invoker.inverted?"ynykron/altfire":"ynykron/fire",CHAN_WEAPON,CHANF_OVERLAP,1.,.2);
// global alert
int ns = level.Sectors.Size();
for ( int i=0; i<ns; i++ )
{
Sector s = level.Sectors[i];
for ( Actor a=s.thinglist; a; a=a.snext )
a.LastHeard = self;
}
A_QuakeEx(9,9,9,4,0,1,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,rollIntensity:2.5);
A_BumpFOV(.7);
A_PlayerFire();
SWWMHandler.DoFlash(self,Color(120,255,255,255),30);
A_Overlay(PSP_WEAPON+1,"FireSmoke");
A_OverlayFlags(PSP_WEAPON+1,PSPF_RENDERSTYLE|PSPF_ALPHA|PSPF_FORCESTYLE|PSPF_FORCEALPHA,true);
A_OverlayRenderStyle(PSP_WEAPON+1,STYLE_Add);
A_OverlayAlpha(PSP_WEAPON+1,0.);
invoker.chargestate = CS_POSTFIRE;
invoker.clipcount = 0;
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-z);
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");
}
action void A_Backblast()
{
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-z);
int numpt = Random[Ynykron](10,20);
for ( int i=0; i<numpt; i++ )
{
let s = Spawn("SWWMSmoke",origin);
s.scale *= 3.;
s.alpha *= .4*invoker.specialf1;
s.special1 = Random[Ynykron](2,8);
s.vel += x*FRandom[Ynykron](-40.,-4.)*invoker.specialf1+y*FRandom[Ynykron](-1.,1.)+z*FRandom[Ynykron](-1.,1.);
}
invoker.specialf1 -= .2;
}
override void DoEffect()
{
Super.DoEffect();
if ( !Owner || !Owner.player ) return;
if ( chargestate == CS_IDLE ) chargelevel = 0.;
else if ( chargestate == CS_CHARGING )
{
chargelevel = min(chargelevel*0.997+.2,40.);
if ( chargelevel >= 40. )
{
if ( Owner.player == players[consoleplayer] )
Console.Printf(StringTable.Localize("$SWWM_YNYKRONREADY"));
chargestate = CS_READY;
}
if ( Owner.player.ReadyWeapon == self )
Owner.A_SoundVolume(CHAN_WEAPONEXTRA2,(.025*chargelevel)**3.);
}
if ( Owner.player.ReadyWeapon != self ) return;
let pspm = Owner.player.FindPSprite(PSP_WEAPON);
if ( pspm )
{
double shiver = (chargelevel*.025)**2.;
pspm.x = FRandom[Shivers](-1.,1.)*shiver;
pspm.y = 32+FRandom[Shivers](-1.,1.)*shiver;
}
let psp = Owner.player.FindPSprite(PSP_WEAPON+1);
if ( !psp ) return;
ventalpha = clamp(ventalpha+ventfade,0.,1.);
psp.alpha = ventalpha;
if ( chargestate >= CS_DISCHARGING )
{
if ( chargestate == CS_POSTFIRE ) chargelevel = max(chargelevel*1.024-1.,0.);
else chargelevel = max(chargelevel*1.005-.24,0.);
if ( chargelevel <= 0. ) chargestate = CS_IDLE;
if ( Owner.player.ReadyWeapon == self )
Owner.A_SoundVolume(CHAN_WEAPONEXTRA2,(.025*chargelevel)**3.);
}
}
override bool PickupForAmmoSWWM( SWWMWeapon ownedWeapon )
{
// add the loaded box
if ( !AmmoGive1 && clipcount ) AmmoGive1++;
return Super.PickupForAmmoSWWM(ownedWeapon);
}
override void MarkPrecacheSounds()
{
Super.MarkPrecacheSounds();
MarkSound("ynykron/select");
MarkSound("ynykron/deselect");
MarkSound("ynykron/idle");
MarkSound("ynykron/ready");
MarkSound("ynykron/latch");
MarkSound("ynykron/ventopen");
MarkSound("ynykron/ventclose");
MarkSound("ynykron/puff");
MarkSound("ynykron/puffing");
MarkSound("ynykron/puffend");
MarkSound("ynykron/meleestart");
MarkSound("ynykron/meleeend");
MarkSound("ynykron/checkout");
MarkSound("ynykron/fire");
MarkSound("ynykron/altfire");
MarkSound("ynykron/magout");
MarkSound("ynykron/magin");
MarkSound("ynykron/beam");
MarkSound("ynykron/hit1");
MarkSound("ynykron/hit2");
MarkSound("ynykron/hit3");
MarkSound("ynykron/altbeam");
MarkSound("ynykron/vortex");
MarkSound("ynykron/vortexarc1");
MarkSound("ynykron/vortexarc2");
MarkSound("ynykron/vortexarc3");
MarkSound("ynykron/vortexflash1");
MarkSound("ynykron/vortexflash2");
MarkSound("ynykron/vortexend");
MarkSound("ynykron/wind");
}
Default
{
Tag "$T_YNYKRON";
Inventory.PickupMessage "$T_YNYKRON";
Inventory.PickupSound "misc/w_pkup_vip";
Obituary "$O_YNYKRON";
SWWMWeapon.Tooltip "$TT_YNYKRON";
SWWMWeapon.GetLine "getynykron";
Weapon.SlotNumber 0;
Weapon.SelectionOrder 9000;
Weapon.UpSound "ynykron/select";
Stamina -5000000;
Weapon.AmmoType1 "YnykronAmmo";
Weapon.AmmoGive1 1;
SWWMWeapon.DropAmmoType "SWWMCellAmmoBig";
+SWWMWEAPON.NOFIRSTGIVE;
Ynykron.ClipCount 1;
+WEAPON.BFG;
+WEAPON.EXPLOSIVE;
}
States
{
Spawn:
XZW1 A -1;
Stop;
Select:
XZW2 L 2
{
invoker.ventcooldown = Random[Ynykron](6,15);
A_StartSound("ynykron/idle",CHAN_WEAPONEXTRA,CHANF_LOOP,.3,4.);
if ( invoker.chargelevel > 0. )
A_StartSound("ynykron/ready",CHAN_WEAPONEXTRA2,CHANF_LOOP,(.025*invoker.chargelevel)**3.,2.);
A_FullRaise();
}
XZW2 MNOPQRSTUVWXYZ 2;
XZW3 A 2;
Goto Ready;
Ready:
XZW2 A 1
{
if ( invoker.chargestate == CS_DISCHARGING )
return ResolveState("Discharge");
int flg = WRF_ALLOWZOOM|WRF_ALLOWUSER1;
if ( (invoker.chargestate > CS_IDLE) || ((invoker.clipcount <= 0) && ((invoker.Ammo1.Amount > 0) || sv_infiniteammo || FindInventory('PowerInfiniteAmmo',true))) )
flg |= WRF_ALLOWRELOAD;
if ( (invoker.chargestate > CS_IDLE) || ((invoker.clipcount <= 0) && (invoker.Ammo1.Amount <= 0) && !sv_infiniteammo && !FindInventory('PowerInfiniteAmmo',true)) )
flg |= WRF_NOSECONDARY;
if ( invoker.chargestate == CS_CHARGING )
flg |= WRF_NOPRIMARY;
A_WeaponReady(flg);
if ( invoker.chargelevel >= 20. )
{
invoker.ventcooldown--;
if ( invoker.ventcooldown <= 0 )
return ResolveState("ReadyVent");
}
if ( player.cmd.buttons&BT_ATTACK )
invoker.CheckAmmo(EitherFire,true);
return ResolveState(null);
}
Wait;
ReadyVent:
XZW2 A 1
{
invoker.ventcooldown = Random[Ynykron](10,15)*5+2*(40-int(invoker.chargelevel));
A_Overlay(PSP_WEAPON+1,"ReadyVentSmoke");
A_OverlayFlags(PSP_WEAPON+1,PSPF_RENDERSTYLE|PSPF_ALPHA|PSPF_FORCESTYLE|PSPF_FORCEALPHA,true);
A_OverlayRenderStyle(PSP_WEAPON+1,STYLE_Add);
A_OverlayAlpha(PSP_WEAPON+1,0.);
A_WeaponReady(WRF_NOFIRE|WRF_NOSWITCH);
A_StartSound("ynykron/ventopen",CHAN_WEAPON,CHANF_OVERLAP);
}
XZWA ABCDEF 2 A_WeaponReady(WRF_NOFIRE|WRF_NOSWITCH);
XZWA G 2
{
A_WeaponReady(WRF_NOFIRE|WRF_NOSWITCH);
A_StartSound("ynykron/ventclose",CHAN_WEAPON,CHANF_OVERLAP);
}
XZWA HI 2 A_WeaponReady(WRF_NOFIRE|WRF_NOSWITCH);
Goto Ready;
ReadyVentSmoke:
XZWB D 1
{
invoker.ventfade = .3;
A_StartSound("ynykron/puff",CHAN_WEAPON,CHANF_OVERLAP);
}
XZWB EF 2;
XZWB G 2
{
invoker.ventfade = -.1;
}
XZWB HIJKLM 2;
Stop;
Fire:
XZW2 A 1
{
if ( (invoker.clipcount <= 0) && ((invoker.Ammo1.Amount > 0) || sv_infiniteammo || FindInventory('PowerInfiniteAmmo',true)) )
return ResolveState("Reload");
if ( invoker.chargestate == CS_IDLE )
return ResolveState("Charge");
A_YnykronFire();
A_StartSound("ynykron/ventopen",CHAN_WEAPON,CHANF_OVERLAP);
return ResolveState(null);
}
XZW3 JK 2;
XZW3 LMNOPQR 3;
Goto Discharging;
FireBlast:
TNT1 AAAAA 1 A_Backblast();
Stop;
FireSmoke:
XZWA J 1
{
invoker.ventfade = .3;
A_StartSound("ynykron/puffing",CHAN_WEAPONEXTRA3,CHANF_LOOP);
}
XZWA KL 2;
XZWA MNOPQRS 3;
Goto DischargingSmoke;
AltFire:
XZW2 A 2
{
if ( (invoker.clipcount <= 0) && ((invoker.Ammo1.Amount > 0) || sv_infiniteammo || FindInventory('PowerInfiniteAmmo',true)) )
{
invoker.invertreload = true;
return ResolveState("Reload");
}
A_StartSound("ynykron/meleestart",CHAN_WEAPON,CHANF_OVERLAP);
return A_JumpIf(invoker.inverted,"TakeInverted");
}
TakeNormal:
XZW2 A 2;
XZW3 STU 2;
XZW3 V 2
{
A_StartSound("ynykron/magout",CHAN_WEAPON,CHANF_OVERLAP);
A_PlayerReload();
}
XZW3 WXYZ 2;
XZW4 A 2;
XZW4 B 2 A_StopSound(CHAN_WEAPONEXTRA);
XZW4 CDEFGHIJKLMNO 2;
XZW4 P 0
{
invoker.inverted = true;
}
Goto PutInverted;
TakeInverted:
XZW5 P 2;
XZW5 QRS 2;
XZW5 T 2
{
A_StartSound("ynykron/magout",CHAN_WEAPON,CHANF_OVERLAP);
A_PlayerReload();
}
XZW5 UVWXY 2;
XZW5 Z 2 A_StopSound(CHAN_WEAPONEXTRA);
XZW6 ABCDEFGHIJKLM 2;
XZW6 N 0
{
invoker.inverted = false;
}
Goto PutNormal;
PutNormal:
XZW4 PQRS 2;
XZW4 T 2 A_StartSound("ynykron/magin",CHAN_WEAPON,CHANF_OVERLAP);
XZW4 UVWXYZ 2;
XZW5 A 2 A_StartSound("ynykron/meleeend",CHAN_WEAPON,CHANF_OVERLAP);
XZW5 B 2 A_StartSound("ynykron/idle",CHAN_WEAPONEXTRA,CHANF_LOOP,.3,4.);
XZW5 CDEFGHIJK 2;
XZW5 L 4;
Goto Ready;
PutInverted:
XZW6 NOPQ 2;
XZW6 R 2 A_StartSound("ynykron/magin",CHAN_WEAPON,CHANF_OVERLAP);
XZW6 STUVWX 2;
XZW6 Y 2 A_StartSound("ynykron/meleeend",CHAN_WEAPON,CHANF_OVERLAP);
XZW6 Z 2 A_StartSound("ynykron/idle",CHAN_WEAPONEXTRA,CHANF_LOOP,.3,4.);
XZW7 ABCDEFGHI 2;
XZW7 J 4;
XZW5 P 0;
Goto Ready;
Discharge:
XZW2 A 2;
XZW7 NO 2;
XZW7 P 2 A_StartSound("ynykron/latch",CHAN_WEAPON,CHANF_OVERLAP);
XZW7 Q 2
{
invoker.chargestate = CS_DISCHARGING;
A_Overlay(PSP_WEAPON+1,"DischargeSmoke");
A_OverlayFlags(PSP_WEAPON+1,PSPF_RENDERSTYLE|PSPF_ALPHA|PSPF_FORCESTYLE|PSPF_FORCEALPHA,true);
A_OverlayRenderStyle(PSP_WEAPON+1,STYLE_Add);
A_OverlayAlpha(PSP_WEAPON+1,0.);
A_WeaponReady(WRF_NOFIRE|WRF_NOSWITCH);
A_StartSound("ynykron/ventopen",CHAN_WEAPON,CHANF_OVERLAP);
}
XZW7 RSTUV 2 A_WeaponReady(WRF_NOFIRE|WRF_NOSWITCH);
Discharging:
XZW7 W 2
{
A_WeaponReady(WRF_NOFIRE|WRF_NOSWITCH);
return A_JumpIf(invoker.chargestate==CS_IDLE,1);
}
Wait;
XZW7 W 3 A_WeaponReady(WRF_NOFIRE|WRF_NOSWITCH);
XZW7 X 2
{
A_WeaponReady(WRF_NOFIRE|WRF_NOSWITCH);
A_StartSound("ynykron/ventclose",CHAN_WEAPON,CHANF_OVERLAP);
}
XZW7 YZ 2 A_WeaponReady(WRF_NOFIRE|WRF_NOSWITCH);
Goto Ready;
DischargeSmoke:
XZWA T 2
{
invoker.ventfade = .3;
A_StartSound("ynykron/puffing",CHAN_WEAPONEXTRA3,CHANF_LOOP);
}
XZWA UVWXY 2;
DischargingSmoke:
XZWA Z 2 A_JumpIf(invoker.chargestate==CS_IDLE,1);
Wait;
XZWA Z 3
{
invoker.ventfade = -.1;
A_SoundVolume(CHAN_WEAPONEXTRA3,.8);
A_StartSound("ynykron/puffend",CHAN_WEAPON,CHANF_OVERLAP);
}
XZWB A 2 A_SoundVolume(CHAN_WEAPONEXTRA3,.6);
XZWB B 2 A_SoundVolume(CHAN_WEAPONEXTRA3,.4);
XZWB C 2 A_SoundVolume(CHAN_WEAPONEXTRA3,.2);
XZWB D 2 A_StopSound(CHAN_WEAPONEXTRA3);
Stop;
Charge:
XZW2 A 2;
XZW3 BC 2;
XZW3 D 2 A_StartSound("ynykron/latch",CHAN_WEAPON,CHANF_OVERLAP);
XZW3 EFGHI 2;
XZW2 A 0
{
invoker.chargestate = CS_CHARGING;
invoker.ventcooldown = Random[Ynykron](6,15);
A_StartSound("ynykron/ready",CHAN_WEAPONEXTRA2,CHANF_LOOP,.01,2.);
}
Goto Ready;
Reload:
XZW2 A 2
{
if ( invoker.chargestate>CS_IDLE ) return ResolveState("Discharge");
if ( invoker.inverted ) return ResolveState("UnloadInverted");
A_StartSound("ynykron/meleestart",CHAN_WEAPON,CHANF_OVERLAP);
return ResolveState(null);
}
UnloadNormal:
XZW2 A 2;
XZW3 STU 2;
XZW3 V 2 A_StartSound("ynykron/magout",CHAN_WEAPON,CHANF_OVERLAP);
XZW3 WXYZ 2;
XZW4 A 2;
XZW4 B 2 A_StopSound(CHAN_WEAPONEXTRA);
XZW4 CDEFGHIJKLMNO 2;
XZW4 P 0
{
if ( !sv_infiniteammo && !FindInventory('PowerInfiniteAmmo',true) )
invoker.Ammo1.Amount = max(invoker.Ammo1.Amount-1,0);
invoker.clipcount = 1;
invoker.inverted = false;
// no mag is dropped, depleted crystals are hazardous and should be disposed of properly
if ( invoker.invertreload )
{
invoker.invertreload = false;
invoker.inverted = true;
return ResolveState("PutInverted");
}
return ResolveState(null);
}
Goto PutNormal;
UnloadInverted:
XZW5 P 2;
XZW5 QRS 2;
XZW5 T 2 A_StartSound("ynykron/magout",CHAN_WEAPON,CHANF_OVERLAP);
XZW5 UVWXY 2;
XZW5 Z 2 A_StopSound(CHAN_WEAPONEXTRA);
XZW6 ABCDEFGHIJKLM 2;
XZW6 N 0
{
if ( !sv_infiniteammo && !FindInventory('PowerInfiniteAmmo',true) )
invoker.Ammo1.Amount = max(invoker.Ammo1.Amount-1,0);
invoker.clipcount = 1;
invoker.inverted = false;
// no mag is dropped, depleted crystals are hazardous and should be disposed of properly
if ( invoker.invertreload )
{
invoker.invertreload = false;
invoker.inverted = true;
return ResolveState("PutInverted");
}
return ResolveState(null);
}
Goto PutNormal;
Zoom:
XZW2 A 2
{
invoker.ventcooldown = Random[Ynykron](6,15);
A_StartSound("ynykron/checkout",CHAN_WEAPON,CHANF_OVERLAP);
A_PlayerCheckGun();
}
XZW8 ABCDEFGHIJKLMNOPQRSTUVW 2;
XZW8 X 4; // smoothen more
Goto Ready;
User1:
XZW2 A 2
{
invoker.ventcooldown = Random[Ynykron](6,15);
A_StartSound("ynykron/meleestart",CHAN_WEAPON,CHANF_OVERLAP);
A_StartSound("demolitionist/wswing",CHAN_WEAPON,CHANF_OVERLAP);
A_PlayerMelee();
}
XZW8 YZ 2;
XZW9 AB 2;
XZW9 C 1 A_Parry(9);
XZW9 DE 1;
XZW9 F 1 A_Melee(100,"demolitionist/whitl",1.5,1.6,1.7,MELEE_Wider);
XZW9 GHIJK 1;
XZW9 LMNO 2;
XZW9 P 2 A_StartSound("ynykron/meleeend",CHAN_WEAPON,CHANF_OVERLAP);
XZW9 QRSTUVWXYZ 2;
Goto Ready;
Deselect:
XZW2 A 2 A_StartSound("ynykron/deselect",CHAN_WEAPON,CHANF_OVERLAP);
XZW2 BCDEFGHIJK 2;
XZW2 L -1
{
A_StopSound(CHAN_WEAPONEXTRA);
A_StopSound(CHAN_WEAPONEXTRA2);
A_FullLower();
}
Stop;
Flash:
XZWZ A 2 Bright
{
let l = Spawn("SWWMWeaponLight",pos);
l.args[0] = 255;
l.args[1] = 255;
l.args[2] = 255;
l.args[3] = 500;
l.target = self;
}
Stop;
}
}