Push to master all the current WIP stuff in 0.9.11b:

- Reduce number of collectibles (some might come back in the future).
 - Merge both DLC weaponsets into one, removing redundant weapons.
 - Readjust prices of some items.
 - Initial work on collectibles (currently Frispy Corn is done).
 - Added bigfont for main menu, based on Source Han Sans.
 - Reduced default HUD margin to 10.
 - Added blob shadows.
 - Added precise crosshair drawing.
 - Tweaked decals, imported more stuff from UT.
 - Swapped the Ynykron impact decal for something better.
 - Fixes to slope alignment code.
 - Implemented headpats for MBF Helper Dogs and Cacodemons.
 - Implemented partial HDoom support, with love and headpats.
 - Fix various string functions breaking on unicode.
 - Added cracktro-style text scroll to Titlemap.
 - Fixed handling of healthbars for friendly monsters.
 - Workaround for maps that use the old author name hack (" - by: " separator).
 - Fixed Silver Bullet not autoswitching on first pickup.
 - Fixed misalignment of Silver Bullet zoomed aim.
 - Silver Bullet is unchambered on first pickup, consistent with Candygun.
 - Adjusted collision sizes of all items across the board.
 - Implemented "Use To Pickup" to work around any issues introduced by the previous change.
 - Swapped CHANF_LOOPING for CHANF_LOOP in many cases, this was a typo.
 - Tweaked Biospark arc lengths, for balance and higher performance.
 - Fix misaligned fire offsets of some weapons (most noticeable on Wallbuster).
 - Prettified the loading disclaimers for BD and HDoom.
 - Add pickup flash to all items.
 - Add custom key models for Doom and Heretic.
 - Fix blown kisses giving you "need key" messages.
 - Fix worn armor and embiggeners not being removed on scripted inventory resets.
 - Remove all references to the no longer planned Radio.
 - Workaround for gzdoom devbuild quirk where MenuSound changed its argument type.
 - Added timezone to fake clock.
 - Fix some times and dates in said clock.
 - SWWM blood now also hits ceilings.
 - Added default properties to DLC ammo and weapon stubs.
 - Lore entries for collectibles and dlc weapons (incomplete).
 - Massive amount of typo fixes across the board.
This commit is contained in:
Mari the Deer 2020-10-20 11:37:14 +02:00
commit eb2ee7b29f
42558 changed files with 4995 additions and 1976 deletions

View file

@ -3,4 +3,32 @@
Class BlackfireIgniter : SWWMWeapon
{
int clipcount;
bool hasaux;
int auxclipcount;
Property ClipCount : clipcount;
Default
{
Tag "$T_BLACKFIRE";
Inventory.PickupMessage "$T_BLACKFIRE";
Obituary "$O_BLACKFIRE";
Inventory.Icon "graphics/HUD/Icons/W_Blackfire.png";
Weapon.SlotNumber 7;
Weapon.SlotPriority 2.;
Weapon.SelectionOrder 550;
Weapon.AmmoType1 "DarkCanister";
Weapon.AmmoGive1 1;
SWWMWeapon.DropAmmoType "DarkCanister";
BlackfireIgniter.ClipCount 100;
Stamina 220000;
+SWWMWEAPON.NOFIRSTGIVE;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}

View file

@ -2,52 +2,291 @@
Class SMW05Ammo : Ammo
{
Mixin SWWMShellAmmo;
Mixin SWWMAmmo;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Default
{
Tag "$T_SMW05BULLET";
Stamina 300;
Inventory.Icon "graphics/HUD/Icons/A_SMW05Ammo.png";
Inventory.Amount 1;
Inventory.MaxAmount 120;
Ammo.BackpackAmount 6;
Ammo.DropAmount 6;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class SMW05SmallAmmo : SMW05Ammo
{
Default
{
Inventory.Amount 6;
}
}
Class SMW05BigAmmo : SMW05Ammo
{
Default
{
Inventory.Amount 30;
}
}
Class SheenAmmo : Ammo
{
Mixin SWWMShellAmmo;
Mixin SWWMAmmo;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Default
{
Tag "$T_SHEENBULLET";
Stamina 400;
Inventory.Icon "graphics/HUD/Icons/A_SheenAmmo.png";
Inventory.Amount 1;
Inventory.MaxAmount 600;
Ammo.BackpackAmount 50;
Ammo.DropAmount 100;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class SheenSmallAmmo: SheenAmmo
{
Default
{
Inventory.Amount 50;
}
}
Class SheenBigAmmo : SheenAmmo
{
Default
{
Inventory.Amount 200;
}
}
Class QuadravolAmmo : Ammo
{
Mixin SWWMAmmo;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Default
{
Tag "$T_QUADAMMO";
Inventory.PickupMessage "$T_QUADAMMO";
Stamina 10000;
Inventory.Icon "graphics/HUD/Icons/A_QuadAmmo.png";
Inventory.Amount 1;
Inventory.MaxAmount 6;
Ammo.BackpackAmount 1;
Ammo.DropAmount 1;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class QuadravolPack : QuadravolAmmo
Class QuadravolAmmoBundleSpawn : Actor
{
override void PostBeginPlay()
{
if ( bCOUNTSECRET ) level.total_secrets--;
int bnd = Random[Bundle](2,3);
for ( int i=0; i<3; i++ )
{
let a = Spawn("QuadravolAmmo",Vec3Angle(6,i*(360/bnd)));
a.special = special;
a.angle = i*(360/bnd);
a.FloatBobPhase = FloatBobPhase;
for ( int j=0; j<5; j++ ) a.args[j] = args[j];
if ( bCOUNTSECRET )
{
a.bCOUNTSECRET = true;
level.total_secrets++;
}
}
Destroy();
}
}
Class DarkCanister : Ammo
{
Mixin SWWMAmmo;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Default
{
Tag "$T_DARKAMMO";
Inventory.PickupMessage "$T_DARKAMMO";
Stamina 20000;
Inventory.Icon "graphics/HUD/Icons/A_DarkAmmo.png";
Inventory.Amount 1;
Inventory.MaxAmount 5;
Ammo.BackpackAmount 1;
Ammo.DropAmount 1;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class EMPCore : Ammo
{
Mixin SWWMAmmo;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Default
{
Tag "$T_EMPCORE";
Inventory.PickupMessage "$T_EMPCORE";
Stamina 60000;
Inventory.Icon "graphics/HUD/Icons/A_EMPCore.png";
Inventory.Amount 1;
Inventory.MaxAmount 10;
Ammo.BackpackAmount 0;
Ammo.DropAmount 1;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class EMPCoreBundleSpawn : Actor
{
override void PostBeginPlay()
{
if ( bCOUNTSECRET ) level.total_secrets--;
int bnd = Random[Bundle](2,3);
for ( int i=0; i<3; i++ )
{
let a = Spawn("EMPCore",Vec3Angle(6,i*(360/bnd)));
a.special = special;
a.angle = i*(360/bnd);
a.FloatBobPhase = FloatBobPhase;
for ( int j=0; j<5; j++ ) a.args[j] = args[j];
if ( bCOUNTSECRET )
{
a.bCOUNTSECRET = true;
level.total_secrets++;
}
}
Destroy();
}
}
Class RayBolt : MagAmmo
{
Default
{
Tag "$T_RAYBOLT";
Inventory.PickupMessage "$T_RAYBOLT";
Inventory.Icon "graphics/HUD/Icons/A_RayBolt.png";
MagAmmo.ParentAmmo "RayAmmo";
MagAmmo.ClipSize 20;
Inventory.MaxAmount 40;
Inventory.InterHubAmount 40;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class RayAmmo : Ammo
{
Mixin SWWMAmmo;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Default
{
Tag "$T_RAYAMMO";
Inventory.PickupMessage "$T_RAYAMMO";
Stamina 150000;
Inventory.Icon "graphics/HUD/Icons/A_RayAmmo.png";
Inventory.Amount 1;
Inventory.MaxAmount 4;
Ammo.BackpackAmount 0;
Ammo.DropAmount 1;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class RayBattery : Ammo
{
Mixin SWWMAmmo;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Default
{
Tag "$T_RAYBATTERY";
Inventory.PickupMessage "$T_RAYBATTERY";
Stamina 320000;
Inventory.Icon "graphics/HUD/Icons/A_RayBattery.png";
Inventory.Amount 1;
Inventory.MaxAmount 2;
Inventory.PickupFlash "SWWMPickupFlash";
Ammo.BackpackAmount 0;
Ammo.DropAmount 1;
+INVENTORY.IGNORESKILL;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}

View file

@ -3,4 +3,22 @@
Class ItamexHammer : SWWMWeapon
{
Default
{
Tag "$T_HAMMER";
Inventory.PickupMessage "$I_HAMMER";
Obituary "$O_HAMMER";
Inventory.Icon "graphics/HUD/Icons/W_ItamexHammer.png";
Weapon.SlotNumber 1;
Weapon.SlotPriority 3.;
Weapon.SelectionOrder 1200;
Stamina 9000;
+WEAPON.MELEEWEAPON;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}

View file

@ -3,4 +3,25 @@
Class HeavyMahSheenGun : SWWMWeapon
{
Default
{
Tag "$T_SHEENHMG";
Inventory.PickupMessage "$I_SHEENHMG";
Obituary "$O_SHEENHMG";
Inventory.Icon "graphics/HUD/Icons/W_SheenHMG.png";
Weapon.SlotNumber 5;
Weapon.SlotPriority 2.;
Weapon.SelectionOrder 100;
Weapon.AmmoType1 "SheenAmmo";
Weapon.AmmoGive1 200;
SWWMWeapon.DropAmmoType "SheenAmmo";
Stamina 100000;
+SWWMWEAPON.NOFIRSTGIVE;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}

View file

@ -3,4 +3,32 @@
Class Quadravol : SWWMWeapon
{
int clipcount;
int extracharge;
Property ClipCount : clipcount;
Default
{
Tag "$T_QUADRAVOL";
Inventory.PickupMessage "$I_QUADRAVOL";
Obituary "$O_QUADRAVOL";
Inventory.Icon "graphics/HUD/Icons/W_Quadravol.png";
Weapon.SlotNumber 6;
Weapon.SlotPriority 2.;
Weapon.SelectionOrder 650;
Weapon.AmmoType1 "QuadAmmo";
Weapon.AmmoGive1 1;
SWWMWeapon.DropAmmoType "QuadAmmo";
Quadravol.ClipCount 10;
Stamina 80000;
+SWWMWEAPON.NOFIRSTGIVE;
+WEAPON.EXPLOSIVE;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}

View file

@ -3,4 +3,29 @@
Class PuntzerBeta : SWWMWeapon
{
int bullets[6];
int rotation;
bool initialized;
Default
{
Tag "$T_PUNTZERBETA";
Inventory.PickupMessage "$I_PUNTZERBETA";
Obituary "$O_PUNTZERBETA";
Inventory.Icon "graphics/HUD/Icons/W_PuntzerBeta.png";
Weapon.SlotNumber 3;
Weapon.SlotPriority 2.;
Weapon.SelectionOrder 450;
Weapon.AmmoType1 "SMW05Ammo";
Weapon.AmmoGive1 6;
SWWMWeapon.DropAmmoType "SMW05Ammo";
Stamina 10000;
+SWWMWEAPON.NOFIRSTGIVE;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}

View file

@ -3,4 +3,31 @@
Class PuntzerGamma : SWWMWeapon
{
int ClipCount;
bool chambered;
Property ClipCount : ClipCount;
Default
{
Tag "$T_PUNTZERGAMMA";
Inventory.PickupMessage "$I_PUNTZERGAMMA";
Obituary "$O_PUNTZERGAMMA";
Inventory.Icon "graphics/HUD/Icons/W_PuntzerGamma.png";
Weapon.SlotNumber 4;
Weapon.SlotPriority 2.;
Weapon.SelectionOrder 200;
PuntzerGamma.ClipCount 30;
Weapon.AmmoType1 "SMW05Ammo";
Weapon.AmmoGive1 30;
SWWMWeapon.DropAmmoType "SMW05Ammo";
Stamina 30000;
+SWWMWEAPON.NOFIRSTGIVE;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}

View file

@ -3,4 +3,38 @@
Class RayKhom : SWWMWeapon
{
int clipcount, clipcount2;
bool chambered;
Property ClipCount : clipcount;
Property ClipCount2 : clipcount2;
Default
{
Tag "$T_RAYKHOM";
Inventory.PickupMessage "$T_RAYKHOM";
Obituary "$O_RAYKHOM";
Inventory.Icon "graphics/HUD/Icons/W_RayKhom.png";
Weapon.SlotNumber 9;
Weapon.SlotPriority 2.;
Weapon.SelectionOrder 750;
Weapon.AmmoType1 "RayAmmo";
Weapon.AmmoGive1 1;
Weapon.AmmoType2 "RayBattery";
Weapon.AmmoGive2 0;
SWWMWeapon.DropAmmoType "RayAmmo";
RayKhom.ClipCount 20;
RayKhom.ClipCount2 500;
Stamina 1600000;
+SWWMWEAPON.NOFIRSTGIVE;
+WEAPON.PRIMARY_USES_BOTH;
+WEAPON.EXPLOSIVE;
+WEAPON.BFG;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}

View file

@ -3,4 +3,34 @@
Class EMPCarbine : SWWMWeapon
{
int clipcount;
bool chambered;
bool initialized;
Property ClipCount : clipcount;
Default
{
Tag "$T_EMPCARBINE";
Inventory.PickupMessage "$I_EMPCARBINE";
Obituary "$O_EMPCARBINE";
Inventory.Icon "graphics/HUD/Icons/W_EMPCarbine.png";
Weapon.SlotNumber 8;
Weapon.SlotPriority 2.;
Weapon.SelectionOrder 850;
Weapon.AmmoType1 "EMPCore";
Weapon.AmmoGive1 1;
SWWMWeapon.DropAmmoType "EMPCore";
EMPCarbine.ClipCount 4;
Stamina 500000;
+SWWMWEAPON.NOFIRSTGIVE;
+WEAPON.EXPLOSIVE;
+WEAPON.ALT_AMMO_OPTIONAL;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}

View file

@ -164,6 +164,7 @@ Mixin Class SWWMAmmo
default
{
+INVENTORY.IGNORESKILL;
Inventory.PickupFlash "SWWMPickupFlash";
}
}
@ -171,6 +172,7 @@ Mixin Class SWWMAmmo
Class MagAmmo : Inventory abstract
{
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Class<Ammo> ParentAmmo;
Ammo pamo;
@ -185,6 +187,7 @@ Class MagAmmo : Inventory abstract
+INVENTORY.KEEPDEPLETED;
Inventory.PickupSound "misc/bullet_pkup";
Inventory.Amount 1;
Inventory.PickupFlash "SWWMPickupFlash";
}
private Inventory DoDrop( Class<Inventory> type )
@ -333,6 +336,7 @@ Class RedShell : Ammo
Mixin SWWMShellAmmo;
Mixin SWWMAmmo;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Default
{
@ -345,6 +349,8 @@ Class RedShell : Ammo
Ammo.DropAmount 3;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 4;
Height 20;
}
States
{
@ -358,6 +364,8 @@ Class RedShell2 : RedShell
Default
{
Inventory.Amount 2;
Radius 6;
Height 20;
}
}
Class RedShell4 : RedShell
@ -365,6 +373,8 @@ Class RedShell4 : RedShell
Default
{
Inventory.Amount 4;
Radius 6;
Height 20;
}
}
Class RedShell8 : RedShell
@ -372,6 +382,8 @@ Class RedShell8 : RedShell
Default
{
Inventory.Amount 8;
Radius 8;
Height 20;
}
}
Class RedShell12 : RedShell
@ -379,6 +391,8 @@ Class RedShell12 : RedShell
Default
{
Inventory.Amount 12;
Radius 10;
Height 20;
}
}
Class RedShell16 : RedShell
@ -386,6 +400,8 @@ Class RedShell16 : RedShell
Default
{
Inventory.Amount 16;
Radius 10;
Height 20;
}
}
@ -394,6 +410,7 @@ Class GreenShell : Ammo
Mixin SWWMShellAmmo;
Mixin SWWMAmmo;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Default
{
@ -406,6 +423,8 @@ Class GreenShell : Ammo
Ammo.DropAmount 2;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 4;
Height 20;
}
States
{
@ -419,6 +438,8 @@ Class GreenShell2 : GreenShell
Default
{
Inventory.Amount 2;
Radius 6;
Height 20;
}
}
Class GreenShell4 : GreenShell
@ -426,6 +447,8 @@ Class GreenShell4 : GreenShell
Default
{
Inventory.Amount 4;
Radius 6;
Height 20;
}
}
Class GreenShell8 : GreenShell
@ -433,6 +456,8 @@ Class GreenShell8 : GreenShell
Default
{
Inventory.Amount 8;
Radius 8;
Height 20;
}
}
Class GreenShell12 : GreenShell
@ -440,6 +465,8 @@ Class GreenShell12 : GreenShell
Default
{
Inventory.Amount 12;
Radius 10;
Height 20;
}
}
@ -448,6 +475,7 @@ Class WhiteShell : Ammo
Mixin SWWMShellAmmo;
Mixin SWWMAmmo;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Default
{
@ -460,6 +488,8 @@ Class WhiteShell : Ammo
Ammo.DropAmount 1;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 4;
Height 20;
}
States
{
@ -473,6 +503,8 @@ Class WhiteShell2 : WhiteShell
Default
{
Inventory.Amount 2;
Radius 6;
Height 20;
}
}
Class WhiteShell4 : WhiteShell
@ -480,6 +512,8 @@ Class WhiteShell4 : WhiteShell
Default
{
Inventory.Amount 4;
Radius 6;
Height 20;
}
}
Class WhiteShell8 : WhiteShell
@ -487,6 +521,8 @@ Class WhiteShell8 : WhiteShell
Default
{
Inventory.Amount 8;
Radius 8;
Height 20;
}
}
@ -495,6 +531,7 @@ Class BlueShell : Ammo
Mixin SWWMShellAmmo;
Mixin SWWMAmmo;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Default
{
@ -507,6 +544,8 @@ Class BlueShell : Ammo
Ammo.DropAmount 2;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 4;
Height 20;
}
States
{
@ -520,6 +559,8 @@ Class BlueShell2 : BlueShell
Default
{
Inventory.Amount 2;
Radius 6;
Height 20;
}
}
Class BlueShell4 : BlueShell
@ -527,6 +568,8 @@ Class BlueShell4 : BlueShell
Default
{
Inventory.Amount 4;
Radius 6;
Height 20;
}
}
Class BlueShell8 : BlueShell
@ -534,6 +577,8 @@ Class BlueShell8 : BlueShell
Default
{
Inventory.Amount 8;
Radius 8;
Height 20;
}
}
@ -542,6 +587,7 @@ Class BlackShell : Ammo
Mixin SWWMShellAmmo;
Mixin SWWMAmmo;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Default
{
@ -554,6 +600,8 @@ Class BlackShell : Ammo
Ammo.DropAmount 1;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 4;
Height 20;
}
States
{
@ -567,6 +615,8 @@ Class BlackShell2 : BlackShell
Default
{
Inventory.Amount 2;
Radius 6;
Height 20;
}
}
Class BlackShell4 : BlackShell
@ -574,6 +624,8 @@ Class BlackShell4 : BlackShell
Default
{
Inventory.Amount 4;
Radius 6;
Height 20;
}
}
@ -582,6 +634,7 @@ Class PurpleShell : Ammo
Mixin SWWMShellAmmo;
Mixin SWWMAmmo;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Default
{
@ -594,6 +647,8 @@ Class PurpleShell : Ammo
Ammo.DropAmount 2;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 4;
Height 20;
}
States
{
@ -607,6 +662,8 @@ Class PurpleShell2 : PurpleShell
Default
{
Inventory.Amount 2;
Radius 6;
Height 20;
}
}
Class PurpleShell4 : PurpleShell
@ -614,6 +671,8 @@ Class PurpleShell4 : PurpleShell
Default
{
Inventory.Amount 4;
Radius 6;
Height 20;
}
}
@ -656,6 +715,7 @@ Class GoldShell : Ammo
Mixin SWWMShellAmmo;
Mixin SWWMAmmo;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
action void A_GoldShellTrail()
{
@ -673,7 +733,10 @@ Class GoldShell : Ammo
Ammo.BackpackAmount 0;
Ammo.DropAmount 1;
+FLOATBOB;
+DONTGIB; // don't crush these, they're valuable
FloatBobStrength 0.25;
Radius 4;
Height 20;
}
States
{
@ -691,6 +754,7 @@ Class EvisceratorShell : Ammo
{
Mixin SWWMAmmo;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Default
{
@ -704,6 +768,8 @@ Class EvisceratorShell : Ammo
Ammo.DropAmount 2;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 8;
Height 22;
}
override void ModifyDropAmount( int dropamount )
{
@ -724,6 +790,8 @@ Class EvisceratorSixPack : EvisceratorShell
{
Inventory.PickupMessage "$I_EVISHELLPAK";
Inventory.Amount 6;
Radius 20;
Height 24;
}
}
@ -757,6 +825,7 @@ Class HellblazerMissiles : Ammo
{
Mixin SWWMAmmo;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Default
{
@ -770,6 +839,8 @@ Class HellblazerMissiles : Ammo
Ammo.DropAmount 1;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 6;
Height 22;
}
override void ModifyDropAmount( int dropamount )
{
@ -789,6 +860,8 @@ Class HellblazerMissileMag : HellblazerMissiles
{
Inventory.PickupMessage "$T_HELLMISSILEMAG";
Inventory.Amount 6;
Radius 12;
Height 26;
}
}
Class HellblazerMissileTrioSpawn : Actor
@ -817,6 +890,7 @@ Class HellblazerCrackshots : Ammo
{
Mixin SWWMAmmo;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Default
{
@ -830,6 +904,8 @@ Class HellblazerCrackshots : Ammo
Ammo.DropAmount 1;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 6;
Height 22;
}
override void ModifyDropAmount( int dropamount )
{
@ -849,6 +925,8 @@ Class HellblazerCrackshotMag : HellblazerCrackshots
{
Inventory.PickupMessage "$T_HELLCLUSTERMAG";
Inventory.Amount 3;
Radius 12;
Height 26;
}
}
@ -856,6 +934,7 @@ Class HellblazerRavagers : Ammo
{
Mixin SWWMAmmo;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Default
{
@ -869,6 +948,8 @@ Class HellblazerRavagers : Ammo
Ammo.DropAmount 1;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 6;
Height 22;
}
override void ModifyDropAmount( int dropamount )
{
@ -888,6 +969,8 @@ Class HellblazerRavagerMag : HellblazerRavagers
{
Inventory.PickupMessage "$T_HELLBURNINATORMAG";
Inventory.Amount 3;
Radius 12;
Height 26;
}
}
@ -895,6 +978,7 @@ Class HellblazerWarheads : Ammo
{
Mixin SWWMAmmo;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Default
{
@ -908,6 +992,8 @@ Class HellblazerWarheads : Ammo
Ammo.DropAmount 1;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 6;
Height 22;
}
override void ModifyDropAmount( int dropamount )
{
@ -927,6 +1013,8 @@ Class HellblazerWarheadMag : HellblazerWarheads
{
Inventory.PickupMessage "$T_HELLNUKEMAG";
Inventory.Amount 2;
Radius 12;
Height 26;
}
}
@ -936,7 +1024,9 @@ Class HellblazerWarheadMag : HellblazerWarheads
Class SparkUnit : Ammo
{
Mixin SWWMAmmo;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Default
{
@ -950,6 +1040,8 @@ Class SparkUnit : Ammo
Ammo.DropAmount 1;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 6;
Height 22;
}
States
{
@ -965,7 +1057,9 @@ Class SparkUnit : Ammo
Class SilverBulletAmmo : Ammo
{
Mixin SWWMAmmo;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Default
{
@ -979,6 +1073,8 @@ Class SilverBulletAmmo : Ammo
Ammo.DropAmount 1;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 10;
Height 26;
}
States
{
@ -990,7 +1086,9 @@ Class SilverBulletAmmo : Ammo
Class SilverBulletAmmo2 : Ammo
{
Mixin SWWMAmmo;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Default
{
@ -1004,6 +1102,8 @@ Class SilverBulletAmmo2 : Ammo
Ammo.DropAmount 1;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 10;
Height 26;
}
States
{
@ -1015,8 +1115,6 @@ Class SilverBulletAmmo2 : Ammo
Class SilverBullets : MagAmmo
{
Mixin SWWMOverlapPickupSound;
Default
{
Tag "$T_XSBBULLET";
@ -1028,6 +1126,8 @@ Class SilverBullets : MagAmmo
Inventory.InterHubAmount 15;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 4;
Height 22;
}
States
{
@ -1038,8 +1138,6 @@ Class SilverBullets : MagAmmo
}
Class SilverBullets2 : MagAmmo
{
Mixin SWWMOverlapPickupSound;
Default
{
Tag "$T_FCBBULLET";
@ -1051,6 +1149,8 @@ Class SilverBullets2 : MagAmmo
Inventory.InterHubAmount 10;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 4;
Height 22;
}
States
{
@ -1111,7 +1211,9 @@ Class SilverBullets2BundleSpawn : Actor
Class CandyGunAmmo : Ammo
{
Mixin SWWMAmmo;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Default
{
@ -1125,6 +1227,8 @@ Class CandyGunAmmo : Ammo
Ammo.DropAmount 1;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 6;
Height 24;
}
States
{
@ -1136,8 +1240,6 @@ Class CandyGunAmmo : Ammo
Class CandyGunBullets : MagAmmo
{
Mixin SWWMOverlapPickupSound;
Default
{
Tag "$T_CANDYBULLET";
@ -1149,6 +1251,8 @@ Class CandyGunBullets : MagAmmo
Inventory.InterHubAmount 27;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 2;
Height 20;
}
States
{
@ -1199,7 +1303,9 @@ Class CandyGunSpares : Ammo
Class YnykronAmmo : Ammo
{
Mixin SWWMAmmo;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Default
{
@ -1213,6 +1319,8 @@ Class YnykronAmmo : Ammo
Ammo.DropAmount 1;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 8;
Height 24;
}
States
{
@ -1229,6 +1337,7 @@ Class YnykronAmmo : Ammo
Class AmmoFabricator : Inventory abstract
{
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
int budget, pertype, maxunitprice;
@ -1363,7 +1472,10 @@ Class AmmoFabricator : Inventory abstract
Inventory.UseSound "fabricator/use";
Inventory.MaxAmount 32;
Inventory.InterHubAmount 32;
Inventory.PickupFlash "SWWMPickupFlash";
FloatBobStrength 0.25;
Radius 10;
Height 24;
}
States
{
@ -1440,6 +1552,8 @@ Class FabricatorTier4 : AmmoFabricator
Class HammerspaceEmbiggener : Inventory
{
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
bool cheatedin;
override void SetGiveAmount( Actor receiver, int amount, bool givecheat )
@ -1526,7 +1640,7 @@ Class HammerspaceEmbiggener : Inventory
for ( Inventory i=Owner.Inv; i; i=i.Inv )
{
if ( !(i is 'Ammo') ) continue;
i.MaxAmount = int(i.Default.MaxAmount*(1+self.Amount/2.));
i.MaxAmount = int(i.default.MaxAmount*(1+Amount/2.));
if ( Ammo(i).BackpackMaxAmount > 0 )
i.MaxAmount = min(i.MaxAmount,Ammo(i).BackpackMaxAmount);
int amount = Ammo(i).BackpackAmount;
@ -1536,10 +1650,17 @@ Class HammerspaceEmbiggener : Inventory
i.Amount = i.MaxAmount;
}
}
// new ammo suddenly added? upgrade it (this shouldn't happen unless fucky scripting has been involved)
if ( (item is 'Ammo') && !Owner.FindInventory(Ammo(item).GetParentAmmo()) )
{
item.MaxAmount = int(item.default.MaxAmount*(1+Amount/2.));
if ( Ammo(item).BackpackMaxAmount > 0 )
item.MaxAmount = min(item.MaxAmount,Ammo(item).BackpackMaxAmount);
}
return res;
}
override void DetachFromOwner()
override void DepleteOrDestroy()
{
// reset upgrade
for ( Inventory i=Owner.Inv; i; i=i.Inv )
@ -1549,6 +1670,7 @@ Class HammerspaceEmbiggener : Inventory
if ( i.Amount > i.MaxAmount )
i.Amount = i.MaxAmount;
}
Super.DepleteOrDestroy();
}
Default
@ -1557,12 +1679,15 @@ Class HammerspaceEmbiggener : Inventory
Inventory.PickupMessage "$T_EMBIGGENER";
Inventory.MaxAmount 16;
Inventory.InterHubAmount 16;
Inventory.PickupFlash "SWWMPickupFlash";
+INVENTORY.UNDROPPABLE;
+INVENTORY.UNTOSSABLE;
+INVENTORY.ALWAYSPICKUP;
+COUNTITEM;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 8;
Height 24;
}
States
{

View file

@ -37,6 +37,8 @@ Class ArmorNuggetItem : SWWMSpareArmor
SWWMSpareArmor.GiveArmor "ArmorNugget";
+INVENTORY.ALWAYSPICKUP;
+COUNTITEM;
Radius 6;
Height 20;
}
States
{
@ -88,6 +90,8 @@ Class BlastSuitItem : SWWMSpareArmor
Inventory.PickupMessage "$T_BLASTSUIT";
Inventory.UseSound "armor/blastsuit";
SWWMSpareArmor.GiveArmor "BlastSuit";
Radius 12;
Height 30;
}
States
{
@ -136,6 +140,8 @@ Class WarArmorItem : SWWMSpareArmor
Inventory.PickupMessage "$T_WARARMOR";
Inventory.UseSound "armor/wararmor";
SWWMSpareArmor.GiveArmor "WarArmor";
Radius 16;
Height 32;
}
States
{

View file

@ -247,7 +247,7 @@ Class HellblazerMissile : Actor
Super.PostBeginPlay();
if ( bNOGRAVITY )
{
A_StartSound("hellblazer/fly",CHAN_BODY,CHANF_LOOPING,1.,2.);
A_StartSound("hellblazer/fly",CHAN_BODY,CHANF_LOOP,1.,2.);
let t = Spawn("HellblazerFlare",pos);
t.master = self;
}
@ -294,7 +294,7 @@ Class HellblazerMissile : Actor
bForceXYBillboard = true;
bRollSprite = false;
A_SetRenderStyle(1.0,STYLE_Add);
A_SprayDecal("BigScorch",50);
A_SprayDecal("BigRocketBlast",50);
A_SetScale(4.5);
SWWMUtility.DoExplosion(self,350,320000,200,90);
A_NoGravity();
@ -391,7 +391,7 @@ Class HellblazerCrackshot : HellblazerMissile
bForceXYBillboard = true;
bRollSprite = false;
A_SetRenderStyle(1.0,STYLE_Add);
A_SprayDecal("BigScorch",50);
A_SprayDecal("BigRocketBlast",50);
A_SetScale(6.);
SWWMUtility.DoExplosion(self,300,320000,250,100);
A_NoGravity();
@ -461,7 +461,7 @@ Class HellblazerRavager : HellblazerMissile
bForceXYBillboard = true;
bRollSprite = false;
A_SetRenderStyle(1.0,STYLE_Add);
A_SprayDecal("HugeScorch",50);
A_SprayDecal("HugeRocketBlast",50);
A_SetScale(8.);
SWWMUtility.DoExplosion(self,400,320000,300,120);
A_NoGravity();
@ -540,7 +540,7 @@ Class HellblazerWarhead : HellblazerMissile
bForceXYBillboard = true;
bRollSprite = false;
A_SetRenderStyle(1.0,STYLE_Add);
A_SprayDecal("WumboScorch",150);
A_SprayDecal("WumboRocketBlast",150);
A_SetScale(7.);
SWWMUtility.DoExplosion(self,2000,600000,400,200);
A_NoGravity();
@ -831,7 +831,7 @@ Class HellblazerClusterMini : HellblazerMissile2
bForceXYBillboard = true;
bRollSprite = false;
A_SetRenderStyle(1.0,STYLE_Add);
A_SprayDecal("BigScorch",50);
A_SprayDecal("BigRocketBlast",50);
A_SetScale(2.5);
SWWMUtility.DoExplosion(self,80,200000,150,60);
A_NoGravity();
@ -1311,6 +1311,11 @@ Class Hellblazer : SWWMWeapon
}
}
override Vector3 GetTraceOffset()
{
return (10.,3.5,-5.);
}
action void A_HellblazerFire( int type = 0, bool bAlt = false )
{
static const Class<Ammo> types[] = {"HellblazerMissiles","HellblazerCrackshots","HellblazerRavagers","HellblazerWarheads"};
@ -1332,7 +1337,7 @@ Class Hellblazer : SWWMWeapon
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
SWWMUtility.DoKnockback(self,-x,bAlt?22000.:32000.);
[x2, y2, z2] = swwm_CoordUtil.GetAxes(BulletSlope(),angle,roll);
origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x+3*y-5*z);
origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x+3.5*y-5*z);
a = FRandom[Hellblazer](0,360);
s = FRandom[Hellblazer](0,bAlt?.02:.005);
dir = (x2+y2*cos(a)*s+z2*sin(a)*s).unit();
@ -1553,6 +1558,8 @@ Class Hellblazer : SWWMWeapon
Hellblazer.ClipCount 6;
+SWWMWEAPON.NOFIRSTGIVE;
+WEAPON.EXPLOSIVE;
Radius 24;
Height 32;
}
States
{

View file

@ -118,9 +118,10 @@ Class mkBloodSpray : Actor
Class mkBloodDrop : Actor
{
bool killme;
bool dead;
bool dead, onceiling;
mkBloodDrop prevblod, nextblod;
Sector tracksector;
F3DFloor trackffloor;
int trackplane;
Default
@ -152,8 +153,16 @@ Class mkBloodDrop : Actor
if ( tracksector )
{
double trackz;
if ( trackplane ) trackz = tracksector.ceilingplane.ZAtPoint(pos.xy);
else trackz = tracksector.floorplane.ZAtPoint(pos.xy);
if ( trackffloor )
{
if ( trackplane ) trackz = trackffloor.bottom.ZAtPoint(pos.xy)-.1;
else trackz = trackffloor.top.ZAtPoint(pos.xy);
}
else
{
if ( trackplane ) trackz = tracksector.ceilingplane.ZAtPoint(pos.xy)-.1;
else trackz = tracksector.floorplane.ZAtPoint(pos.xy);
}
if ( trackz != pos.z )
{
SetZ(trackz);
@ -165,6 +174,17 @@ Class mkBloodDrop : Actor
scale *= 1.005;
A_FadeOut(.01);
}
if ( onceiling && (special2 < 200) && (scale.x > .2) )
{
if ( special1-- ) return;
special2 += 10;
special1 = Random[Blood](20,30)+special2;
let d = Spawn("mkBloodDrop",Vec3Offset(0,0,-2));
d.master = self;
d.SetShade(fillcolor);
d.CopyBloodColor(self);
d.scale = Scale*FRandom[Blood](.4,.6);
}
return; // we don't need to update states when we're dead
}
else
@ -215,6 +235,16 @@ Class mkBloodDrop : Actor
SetZ(floorz);
HitFloor();
A_StartSound("misc/blooddrop",volume:.1);
if ( master )
{
// assume we dropped onto the previous spot
if ( master.tracer )
{
Destroy();
return;
}
master.tracer = self;
}
dead = true;
SWWMUtility.SetToSlope(self,FRandom[Blood](0,360));
tracksector = FloorSector;
@ -227,25 +257,37 @@ Class mkBloodDrop : Actor
ff = FloorSector.Get3DFloor(i);
break;
}
if ( ff )
{
tracksector = ff.model;
trackplane = 1;
}
if ( ff ) trackffloor = ff;
frame = Random[Blood](5,8);
return;
}
if ( pos.z+height > ceilingz )
{
if ( ceilingpic == skyflatnum )
if ( (ceilingpic == skyflatnum) || master )
{
Destroy();
return;
}
// hit the ceiling
// TODO stick to it and drop more blood
SetZ(ceilingz-.1);
A_StartSound("misc/blooddrop",volume:.1);
Destroy();
dead = true;
onceiling = true;
SWWMUtility.SetToSlope(self,FRandom[Blood](0,360),true);
tracksector = CeilingSector;
trackplane = 1;
F3DFloor ff;
for ( int i=0; i<CeilingSector.Get3DFloorCount(); i++ )
{
if ( !(CeilingSector.Get3DFloor(i).flags&F3DFloor.FF_SOLID) ) continue;
if ( !(CeilingSector.Get3DFloor(i).bottom.ZAtPoint(pos.xy) ~== ceilingz) ) continue;
ff = CeilingSector.Get3DFloor(i);
break;
}
if ( ff ) trackffloor = ff;
frame = Random[Blood](5,8);
special1 = Random[Blood](15,25);
special2 = 0;
return;
}
CheckPortalTransition();

View file

@ -223,13 +223,6 @@ Class WallbusterReloadMenu : GenericMenu
return Super.MenuEvent(mkey,fromcontroller);
}
override bool MouseEvent( int type, int mx, int my )
{
bool res = Super.MouseEvent(type,mx,my);
// TODO mouse input?
return res;
}
override bool OnUiEvent( UIEvent ev )
{
int y;
@ -390,7 +383,7 @@ Class CBTHandler : StaticEventHandler
}
cbtvol = min(.6,cbtvol+.1);
if ( (cbtme.GetInt() >= 1) && !cbt.IsActorPlayingSound(CHAN_AMBEXTRA+1) )
cbt.A_StartSound("wallbuster/olddays",CHAN_AMBEXTRA+1,CHANF_UI|CHANF_LOOPING,cbtvol,0.);
cbt.A_StartSound("wallbuster/olddays",CHAN_AMBEXTRA+1,CHANF_UI|CHANF_LOOP,cbtvol,0.);
else if ( (cbtme.GetInt() < 1) && cbt.IsActorPlayingSound(CHAN_AMBEXTRA+1) )
cbt.A_StopSound(CHAN_AMBEXTRA+1);
if ( (cbtme.GetInt() >= 2) && !cbt.IsActorPlayingSound(CHAN_AMBEXTRA+2) )
@ -399,7 +392,7 @@ Class CBTHandler : StaticEventHandler
if ( cbt.IsActorPlayingSound(CHAN_AMBEXTRA+1) )
{
cbt.A_StopSound(CHAN_AMBEXTRA+1);
cbt.A_StartSound("wallbuster/olddays",CHAN_AMBEXTRA+1,CHANF_UI|CHANF_LOOPING,cbtvol,0.);
cbt.A_StartSound("wallbuster/olddays",CHAN_AMBEXTRA+1,CHANF_UI|CHANF_LOOP,cbtvol,0.);
}
cbt.A_StartSound("wallbuster/cbt",CHAN_AMBEXTRA+2,CHANF_UI,cbtvol,0.);
}
@ -633,7 +626,7 @@ Class BusterWall : Thinker
static bool Bust( TraceResults d, int accdamage, Actor instigator, Vector3 x, double hitz )
{
// we can't blow up 3D floors (yet)
// we can't blow up 3D floors
if ( d.ffloor ) return false;
Sector hs = d.HitSector;
int hp;
@ -641,7 +634,7 @@ Class BusterWall : Thinker
{
// no busting the goat
if ( IsIOSWall(d.HitLine) ) return false;
// onesided wall? no bust (TODO: bust polyobjects)
// onesided wall? no bust
if ( !d.HitLine.sidedef[1] ) return false;
// sector is opposite of side hit
hs = d.HitLine.sidedef[!d.Side].sector;
@ -1113,6 +1106,10 @@ Class Wallbuster : SWWMWeapon
p.special1 = max(0,(bc-5)/4);
}
}
override Vector3 GetTraceOffset()
{
return (10.,3.5,-1.8);
}
action void A_FireShells( int num = 1 )
{
static const Class<Ammo> types[] = {"RedShell","GreenShell","BlueShell","PurpleShell"};
@ -1214,7 +1211,7 @@ Class Wallbuster : SWWMWeapon
l.target = self;
}
// third pass, actually fire them
Vector3 base = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x+8*y-10*z);
Vector3 base = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x+3.5*y-6*z);
SpreadgunTracer st;
SpreadSlugTracer sst;
for ( int i=0; i<num; i++ )
@ -1239,10 +1236,10 @@ Class Wallbuster : SWWMWeapon
break;
}
invoker.fired[idx] = true;
double t1 = int(i%5)*72+90;
double t2 = int(i/5)*72+90;
Vector2 b = (cos(t1),sin(t1))*2;
b.y += 8;
double t1 = 90-int(i%5)*72;
double t2 = 360-int(i/5)*72;
Vector2 b = (cos(t1),sin(t1))*1.2;
b.y += 3.;
Vector2 n = (b.x*cos(t2)-b.y*sin(t2),b.x*sin(t2)+b.y*cos(t2));
origin = level.Vec3Offset(base,n.x*y+n.y*z);
invoker.curobt = types[which];
@ -1575,6 +1572,8 @@ Class Wallbuster : SWWMWeapon
SWWMWeapon.DropAmmoType "Shell";
Stamina 35000;
+SWWMWEAPON.NOFIRSTGIVE;
Radius 30;
Height 36;
}
States
{

View file

@ -132,7 +132,7 @@ Class SWWMDroppedKeen : Actor
}
// imitates UE1 light type LT_TexturePaletteOnce/LT_TexturePaletteLoop
Class PaletteLight : DynamicLight
Class PaletteLight : PointLight
{
Color pal[256];
bool IsLooping;
@ -140,7 +140,6 @@ Class PaletteLight : DynamicLight
Default
{
Tag "Explosion";
DynamicLight.Type "Point";
Args 0,0,0,80;
ReactionTime 15;
}
@ -213,7 +212,7 @@ Class SWWMSmoke : Actor
{
double ang, pt;
scale *= FRandom[Puff](.5,1.5);
alpha *= FRandom[Puff](.5,1.5);
alpha = min(1.,alpha*FRandom[Puff](.5,1.5));
ang = FRandom[Puff](0,360);
pt = FRandom[Puff](-90,90);
vel += (cos(pt)*cos(ang),cos(pt)*sin(ang),-sin(pt))*FRandom[Puff](.2,.8);
@ -962,6 +961,7 @@ Class SWWMItemFog : Actor
+ROLLSPRITE;
+ROLLCENTER;
+NOINTERACTION;
+FORCEXYBILLBOARD;
}
States
{
@ -1094,6 +1094,47 @@ Class SWWMTeleportFog : Actor
}
}
Class SWWMPickupFlash : Actor
{
Default
{
RenderStyle "Add";
+NOGRAVITY;
+NOBLOCKMAP;
+DONTSPLASH;
+ROLLSPRITE;
+ROLLCENTER;
+NOINTERACTION;
+FORCEXYBILLBOARD;
}
States
{
Spawn:
BLPF A 1 Bright NoDelay
{
// offset up
SetOrigin(Vec3Offset(0,0,16),false);
roll = FRandom[ExploS](0,360);
scale *= FRandom[ExploS](0.9,1.1);
scale.x *= RandomPick[ExploS](-1,1);
scale.y *= RandomPick[ExploS](-1,1);
int numpt = Random[ExploS](8,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](.3,8);
let s = Spawn("SWWMSmallSmoke",pos);
s.vel = pvel;
s.SetShade(Color(3,2,1)*Random[ExploS](64,85));
s.A_SetRenderStyle(s.alpha,STYLE_AddShaded);
s.scale *= 3.;
s.alpha *= .5;
}
}
BLPF A 1 Bright A_FadeOut(.2);
Wait;
}
}
// Bullet trails from DT
Class WaterHit
{
@ -1193,6 +1234,67 @@ Class SWWMBulletTrail : LineTracer
}
}
// Blob shadows
Class SWWMShadow : Actor
{
Sector oldfloor;
static void Track( Actor other )
{
let s = SWWMShadow(Spawn("SWWMShadow",other.pos));
s.target = other;
s.Update(true);
}
private void Update( bool nointerpolate = false )
{
double curz = target.CurSector.NextLowestFloorAt(target.pos.x,target.pos.y,target.pos.z);
SetOrigin((target.pos.x,target.pos.y,curz),true);
if ( nointerpolate )
prev = pos;
else if ( oldfloor != target.CurSector )
prev.z = pos.z; // prevent interpolation of steep height changes
oldfloor = target.CurSector;
// update scale / alpha
if ( (target is 'Inventory') && (Inventory(target).Owner || !target.bSPECIAL) || target.bKILLED || target.bINVISIBLE || (target.sprite == target.GetSpriteIndex('TNT1')) )
alpha = 0.;
else
{
alpha = 1.-min(1.,.006*abs(target.pos.z-pos.z));
alpha *= target.alpha;
double bscale = (target.radius/16.)*(1.-min(1.,.003*abs(target.pos.z-pos.z)));
A_SetScale(bscale);
}
// update slope alignment
SWWMUtility.SetToSlope(self,0);
}
override void Tick()
{
if ( !target )
{
Destroy();
return;
}
Update();
}
default
{
RenderStyle "Shaded";
StencilColor "000000";
Radius .1;
Height 0.;
+NOBLOCKMAP;
+NOINTERACTION;
+DONTSPLASH;
+NOTELEPORT;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
// Elastic recoil from DT (unused)
Enum ESwingMode
{

View file

@ -408,7 +408,7 @@ Class EvisceratorProj : Actor
{
bForceXYBillboard = true;
A_SetRenderStyle(1.0,STYLE_Add);
A_SprayDecal("BigScorch",50);
A_SprayDecal("BigRocketBlast",50);
A_NoGravity();
A_SetScale(3.5);
SWWMUtility.DoExplosion(self,150,120000,200,80);
@ -671,6 +671,11 @@ Class Eviscerator : SWWMWeapon
}
}
override Vector3 GetTraceOffset()
{
return (10.,4.,-5.);
}
action void A_EvisceratorFire()
{
let weap = Weapon(invoker);
@ -689,7 +694,7 @@ Class Eviscerator : SWWMWeapon
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
SWWMUtility.DoKnockback(self,-x,25000.);
[x2, y2, z2] = swwm_CoordUtil.GetAxes(BulletSlope(),angle,roll);
origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x+3*y-5*z);
origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x+4*y-5*z);
for ( int i=0; i<40; i++ )
{
a = FRandom[Eviscerator](0,360);
@ -704,7 +709,7 @@ Class Eviscerator : SWWMWeapon
for ( int i=0; i<4; i++ )
{
let s = Spawn("SWWMViewSmoke",origin);
SWWMViewSmoke(s).ofs = (10,3,-5);
SWWMViewSmoke(s).ofs = (10,4,-5);
s.target = self;
s.SetShade(Color(1,1,1)*Random[Eviscerator](160,255));
s.alpha *= .2;
@ -818,6 +823,8 @@ Class Eviscerator : SWWMWeapon
Weapon.AmmoGive1 4;
SWWMWeapon.DropAmmoType "EvisceratorShell";
+WEAPON.EXPLOSIVE;
Radius 20;
Height 32;
}
States
{

View file

@ -367,7 +367,7 @@ Class YnykronImpact : Actor
{
// poof away manually
tracer.bINVISIBLE = true;
tracer.A_ChangeLinkFlags(false); // remove from blockmap, should guarantee archviles not raising this
tracer.A_ChangeLinkFlags(true); // remove from blockmap, should guarantee archviles not raising this
IDontFeelSoGood.DeletThis(tracer); // ensures corpse is deleted too
}
}
@ -2050,7 +2050,7 @@ Class YnykronSingularityExplosion : Actor
if ( !Random[ExploS](0,5) )
A_StartSound("ynykron/impact",CHAN_VOICE);
SWWMUtility.DoExplosion(self,10000,5000,400,200);
A_SprayDecal("WumboScorch",-172);
A_SprayDecal("WumboRocketBlast",-172);
Scale *= FRandom[ExploS](0.8,1.1);
Scale.x *= RandomPick[ExploS](-1,1);
Scale.y *= RandomPick[ExploS](-1,1);
@ -2735,6 +2735,7 @@ Class Ynykron : SWWMWeapon
}
override void HudTick()
{
Super.HudTick();
if ( !ChargeInter ) ChargeInter = DynamicValueInterpolator.Create(int(chargelevel*10),.5,1,400);
ChargeInter.Update(int(chargelevel*10));
}
@ -2757,12 +2758,17 @@ Class Ynykron : SWWMWeapon
Super.Travelled();
if ( Owner.player && (Owner.player.Readyweapon == self) )
{
Owner.A_StartSound("ynykron/idle",CHAN_WEAPONEXTRA,CHANF_LOOPING,.3,4.);
Owner.A_StartSound("ynykron/idle",CHAN_WEAPONEXTRA,CHANF_LOOP,.3,4.);
if ( chargestate > CS_IDLE )
Owner.A_StartSound("ynykron/ready",CHAN_WEAPONEXTRA2,CHANF_LOOPING,(.025*chargelevel)**3.,2.);
Owner.A_StartSound("ynykron/ready",CHAN_WEAPONEXTRA2,CHANF_LOOP,(.025*chargelevel)**3.,2.);
}
}
override Vector3 GetTraceOffset()
{
return (15.,4.,-1.);
}
action void A_YnykronFire()
{
A_SWWMFlash();
@ -2793,7 +2799,7 @@ Class Ynykron : SWWMWeapon
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);
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);
@ -2808,7 +2814,7 @@ 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);
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++ )
{
@ -2876,6 +2882,8 @@ Class Ynykron : SWWMWeapon
Ynykron.ClipCount 1;
+WEAPON.BFG;
+WEAPON.EXPLOSIVE;
Radius 32;
Height 36;
}
States
{
@ -2886,9 +2894,9 @@ Class Ynykron : SWWMWeapon
XZW2 L 2
{
invoker.ventcooldown = Random[Ynykron](6,15);
A_StartSound("ynykron/idle",CHAN_WEAPONEXTRA,CHANF_LOOPING,.3,4.);
A_StartSound("ynykron/idle",CHAN_WEAPONEXTRA,CHANF_LOOP,.3,4.);
if ( invoker.chargelevel > 0. )
A_StartSound("ynykron/ready",CHAN_WEAPONEXTRA2,CHANF_LOOPING,(.025*invoker.chargelevel)**3.,2.);
A_StartSound("ynykron/ready",CHAN_WEAPONEXTRA2,CHANF_LOOP,(.025*invoker.chargelevel)**3.,2.);
A_FullRaise();
}
XZW2 MNOPQRSTUVWXYZ 2;
@ -3066,7 +3074,7 @@ Class Ynykron : SWWMWeapon
XZWA T 2
{
invoker.ventfade = .3;
A_StartSound("ynykron/puffing",CHAN_WEAPONEXTRA3,CHANF_LOOPING);
A_StartSound("ynykron/puffing",CHAN_WEAPONEXTRA3,CHANF_LOOP);
}
XZWA UVWXY 2;
XZWA Z 2 A_JumpIf(invoker.chargestate==CS_IDLE,1);
@ -3091,7 +3099,7 @@ Class Ynykron : SWWMWeapon
{
invoker.chargestate = CS_CHARGING;
invoker.ventcooldown = Random[Ynykron](6,15);
A_StartSound("ynykron/ready",CHAN_WEAPONEXTRA2,CHANF_LOOPING,.01,2.);
A_StartSound("ynykron/ready",CHAN_WEAPONEXTRA2,CHANF_LOOP,.01,2.);
}
Goto Ready;
Reload:

View file

@ -21,7 +21,7 @@ Class AirBullet : FastProjectile
}
override void PostBeginPlay()
{
A_StartSound("deepimpact/bullet",CHAN_BODY,CHANF_LOOPING,1.,1.5);
A_StartSound("deepimpact/bullet",CHAN_BODY,CHANF_LOOP,1.,1.5);
}
override int DoSpecialDamage( Actor target, int damage, Name damagetype )
{
@ -236,6 +236,7 @@ Class DeepImpact : SWWMWeapon
override void HudTick()
{
Super.HudTick();
if ( !ChargeInter ) ChargeInter = DynamicValueInterpolator.Create(clipcount,.5,1,25);
ChargeInter.Update(clipcount);
}
@ -264,6 +265,11 @@ Class DeepImpact : SWWMWeapon
}
}
override Vector3 GetTraceOffset()
{
return (10.,2.,-3.);
}
action void A_DryFire()
{
let weap = Weapon(invoker);

View file

@ -1,11 +1,14 @@
// collectable items that may drop sometimes
// collectible items that may drop sometimes
Class SWWMCollectable : Inventory abstract
Class SWWMCollectible : Inventory abstract
{
int avail;
Mixin SWWMUseToPickup;
int avail, gesture;
bool propagated;
Property Availability : avail;
Property PickupGesture : gesture;
// minimum gametype requirements
enum EAvailability
@ -21,12 +24,15 @@ Class SWWMCollectable : Inventory abstract
Inventory.PickupSound "menu/buyinv";
Inventory.Amount 1;
Inventory.MaxAmount 1;
SWWMCollectable.Availability AVAIL_All;
Inventory.PickupFlash "SWWMPickupFlash";
SWWMCollectible.Availability AVAIL_All;
+INVENTORY.UNTOSSABLE;
+INVENTORY.UNDROPPABLE;
+INVENTORY.UNCLEARABLE;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 10;
Height 24;
}
override void PostBeginPlay()
{
@ -64,11 +70,15 @@ Class SWWMCollectable : Inventory abstract
{
if ( !playeringame[i] || !players[i].mo || (i == other.PlayerNumber()) )
continue;
let c = SWWMCollectable(Spawn(GetClass(),pos));
let c = SWWMCollectible(Spawn(GetClass(),pos));
c.propagated = true;
if ( !c.CallTryPickup(players[i].mo) )
c.Destroy();
}
// pickup gesture (has to be -100 or under, which is the range reserved for these)
if ( !other.player || !CVar.GetCVar('swwm_collectanim',other.player).GetBool() || (gesture > -100) )
return;
SWWMGesture.SetGesture(PlayerPawn(other),gesture);
}
States
{
@ -79,66 +89,96 @@ Class SWWMCollectable : Inventory abstract
}
// April Fools 2020
Class FroggyChair : SWWMCollectable
Class FroggyChair : Actor
{
int cdown;
bool carried;
Default
{
Tag "$T_FROGGY";
Inventory.PickupMessage "$T_FROGGY";
Stamina 1440;
Radius 12;
Height 16;
+SOLID;
+SHOOTABLE;
+NODAMAGE;
+NOBLOOD;
+INTERPOLATEANGLES;
}
override void AttachToOwner( Actor other )
private void BeginCarry( Actor carrier )
{
Super.AttachToOwner(other);
if ( !propagated )
cdown = 150;
if ( !carrier ) return;
carrier.A_StartSound("demolitionist/handsup",CHAN_ITEM,CHANF_OVERLAP);
A_SetRenderStyle(.5,STYLE_Translucent);
A_SetSize(32,32); // easier to deselect
carried = true;
bSOLID = false;
bSHOOTABLE = false;
bNOGRAVITY = true;
vel *= 0;
master = carrier;
}
override void DoEffect()
private void EndCarry()
{
Super.DoEffect();
if ( cdown <= 0 ) return;
if ( Owner && Owner.CheckLocalView() )
if ( master ) master.A_StartSound("demolitionist/handsdown",CHAN_ITEM,CHANF_OVERLAP);
A_SetRenderStyle(1.,STYLE_Normal);
A_SetSize(default.radius,default.height);
carried = false;
bSOLID = true;
bSHOOTABLE = true;
bNOGRAVITY = false;
master = null;
}
override void Tick()
{
if ( cdown < 80 )
{
if ( cdown == 140 )
cdown++;
if ( cdown == 10 )
Console.MidPrint(newsmallfont,"$D_FROGGY1");
else if ( cdown == 70 )
else if ( cdown == 80 )
Console.MidPrint(newsmallfont,"$D_FROGGY2");
}
cdown--;
if ( carried )
{
if ( !master || (master.Health <= 0) ) EndCarry();
else
{
Vector3 tomove = master.Vec2OffsetZ(cos(master.angle)*40.,sin(master.angle)*40.,master.player.viewz-32.);
Vector3 dirto = level.Vec3Diff(pos,tomove);
SetOrigin(level.Vec3Offset(pos,dirto*.3),true);
double magvel = dirto.length();
dirto /= magvel;
vel = dirto*min(20,magvel);
double angleto = deltaangle(angle,AngleTo(master));
A_SetAngle(angle+angleto*.3,SPF_INTERPOLATE);
}
return;
}
Super.Tick();
if ( pos.z <= floorz ) vel.xy *= .9; // fast friction
}
override bool Used( Actor user )
{
if ( carried )
{
if ( user != master ) return false;
if ( TestMobjLocation() && level.IsPointInLevel(pos) )
EndCarry();
}
else BeginCarry(user);
return true;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
// The other collectables, which will be implemented eventually
Class MMiaSRVol1 : SWWMCollectable
{
Default
{
Tag "$T_SEXROBOT1";
Inventory.PickupMessage "$T_SEXROBOT1";
Stamina 2000;
}
}
Class MMiaSRVol2 : SWWMCollectable
{
Default
{
Tag "$T_SEXROBOT2";
Inventory.PickupMessage "$T_SEXROBOT2";
Stamina 2000;
}
}
Class MMiaSRVol3 : SWWMCollectable
{
Default
{
Tag "$T_SEXROBOT3";
Inventory.PickupMessage "$T_SEXROBOT3";
Stamina 2000;
}
}
Class MothPlushy : SWWMCollectable
// The collectibles
Class MothPlushy : SWWMCollectible
{
int cdown;
@ -168,16 +208,7 @@ Class MothPlushy : SWWMCollectable
cdown--;
}
}
Class BRCDebutLP : SWWMCollectable
{
Default
{
Tag "$T_BLACKRATS";
Inventory.PickupMessage "$T_BLACKRATS";
Stamina 6000;
}
}
Class AkariProject : SWWMCollectable
Class AkariProject : SWWMCollectible
{
Default
{
@ -186,16 +217,7 @@ Class AkariProject : SWWMCollectable
Stamina 3000;
}
}
Class CatCatcherPoster : SWWMCollectable
{
Default
{
Tag "$T_CATCATCHER";
Inventory.PickupMessage "$T_CATCATCHER";
Stamina 1500;
}
}
Class LoveSignalsCD : SWWMCollectable
Class LoveSignalsCD : SWWMCollectible
{
Default
{
@ -204,7 +226,7 @@ Class LoveSignalsCD : SWWMCollectable
Stamina 4000;
}
}
Class NutatcoBar : SWWMCollectable
Class NutatcoBar : SWWMCollectible
{
Default
{
@ -213,16 +235,7 @@ Class NutatcoBar : SWWMCollectable
Stamina 200;
}
}
Class HegeCactus : SWWMCollectable
{
Default
{
Tag "$T_HEGE";
Inventory.PickupMessage "$T_HEGE";
Stamina 8000;
}
}
Class FrispyCorn : SWWMCollectable
Class FrispyCorn : SWWMCollectible
{
Default
{
@ -231,47 +244,38 @@ Class FrispyCorn : SWWMCollectable
Stamina 500;
}
}
Class LithiumVol1 : SWWMCollectable
{
Default
{
Tag "$T_LITHIUM";
Inventory.PickupMessage "$T_LITHIUM";
Stamina 3500;
}
}
// Heretic
Class DemoPlush : SWWMCollectable
Class DemoPlush : SWWMCollectible
{
Default
{
Tag "$T_DEMOPLUSH";
Inventory.PickupMessage "$T_DEMOPLUSH";
SWWMCollectable.Availability AVAIL_Heretic;
SWWMCollectible.Availability AVAIL_Heretic;
Stamina 6400;
}
}
Class TomeOfPower : SWWMCollectable
Class TomeOfPower : SWWMCollectible
{
Default
{
Tag "$T_TOMEPOWER";
Inventory.PickupMessage "$T_TOMEPOWER";
SWWMCollectable.Availability AVAIL_Heretic;
SWWMCollectible.Availability AVAIL_Heretic;
Stamina 16000;
}
}
Class QuartzFlask : SWWMCollectable
Class QuartzFlask : SWWMCollectible
{
Default
{
Tag "$T_YEFLASK";
Inventory.PickupMessage "$T_YEFLASK";
SWWMCollectable.Availability AVAIL_Heretic;
SWWMCollectible.Availability AVAIL_Heretic;
Stamina 4000;
}
}
Class SayaBean : SWWMCollectable
Class SayaBean : SWWMCollectible
{
int cdown;
@ -279,7 +283,7 @@ Class SayaBean : SWWMCollectable
{
Tag "$T_SAYABEAN";
Inventory.PickupMessage "$T_SAYABEAN";
SWWMCollectable.Availability AVAIL_Heretic;
SWWMCollectible.Availability AVAIL_Heretic;
Stamina 12000;
}
override void AttachToOwner( Actor other )
@ -301,150 +305,63 @@ Class SayaBean : SWWMCollectable
}
}
// Hexen
Class KirinCummies : SWWMCollectable
Class KirinCummies : SWWMCollectible
{
Default
{
Tag "$T_PEACH";
Inventory.PickupMessage "$T_PEACH";
SWWMCollectable.Availability AVAIL_Hexen;
SWWMCollectible.Availability AVAIL_Hexen;
Stamina 400;
}
}
Class MilkBreads : SWWMCollectable
Class MilkBreads : SWWMCollectible
{
Default
{
Tag "$T_MILKBREAD";
Inventory.PickupMessage "$T_MILKBREAD";
SWWMCollectable.Availability AVAIL_Hexen;
SWWMCollectible.Availability AVAIL_Hexen;
Stamina 900;
}
}
Class EyeObelisk : SWWMCollectable
{
int cdown;
Default
{
Tag "$T_OBELISK";
Inventory.PickupMessage "$T_OBELISK";
SWWMCollectable.Availability AVAIL_Hexen;
Stamina 24000;
}
override void PostBeginPlay()
{
if ( InStateSequence(CurState,FindState("Spawn")) )
A_StartSound("obelisk/idle",CHAN_BODY,CHANF_LOOPING);
}
override void AttachToOwner( Actor other )
{
Super.AttachToOwner(other);
if ( propagated ) return;
// nauseatingly fast trip through images of the future
if ( other.player != players[consoleplayer] ) return;
let hnd = EyeObeliskFlash(StaticEventHandler.Find("EyeObeliskFlash"));
if ( hnd ) hnd.doit = true;
}
}
Class KirinManga : SWWMCollectable
Class KirinManga : SWWMCollectible
{
Default
{
Tag "$T_KIRINMANGA";
Inventory.PickupMessage "$T_KIRINMANGA";
SWWMCollectable.Availability AVAIL_Hexen;
SWWMCollectible.Availability AVAIL_Hexen;
Stamina 1600;
}
}
Class EyeObeliskFlash : StaticEventHandler
Class KirinPlush : SWWMCollectible
{
bool doit;
int cd;
ui bool doit_ui;
ui int timeme;
ui TextureID ftex[29];
int cdown;
override void UiTick()
Default
{
if ( !doit && !doit_ui )
{
timeme = 0;
return;
}
if ( timeme == 0 )
{
// do not trigger if the user doesn't want this
if ( CVar.GetCVar('swwm_noscare',players[consoleplayer]).GetBool() )
return;
doit_ui = true;
for ( int i=0; i<29; i++ )
ftex[i] = TexMan.CheckForTexture(String.Format("graphics/obelisk/O_SIGHT%d.png",i),TexMan.Type_Any);
S_StartSound("obelisk/sight",CHAN_VOICE,CHANF_UI|CHANF_NOPAUSE,1.,0.);
}
if ( timeme == 210 ) Console.MidPrint(newsmallfont,"$D_OBELISK");
if ( timeme == 240 ) doit_ui = false;
timeme++;
Tag "$T_KIRINPLUSH";
Inventory.PickupMessage "$T_KIRINPLUSH";
SWWMCollectible.Availability AVAIL_Hexen;
Stamina 20000;
}
override void WorldTick()
override void AttachToOwner( Actor other )
{
if ( !doit ) return;
cd++;
if ( cd < 1 ) return;
cd = 0;
doit = false;
Super.AttachToOwner(other);
if ( !propagated )
cdown = 70;
}
override void RenderOverlay( RenderEvent e )
override void DoEffect()
{
if ( !doit_ui ) return;
double secs = (timeme+e.FracTic)/Thinker.TICRATE;
PlayerInfo p = players[consoleplayer];
if ( secs < .25 ) Screen.Dim("White",(secs*4.)**2.,0,0,Screen.GetWidth(),Screen.GetHeight());
else if ( secs < 2.25 )
Super.DoEffect();
if ( cdown <= 0 ) return;
if ( Owner && Owner.CheckLocalView() )
{
Shader.SetEnabled(p,"ObPass0",true);
Shader.SetEnabled(p,"ObPass1",true);
Shader.SetEnabled(p,"ObPass2",true);
Shader.SetEnabled(p,"ObPass3",true);
Shader.SetUniform1f(p,"ObPass0","Timer",(timeme+e.FracTic)/Thinker.TICRATE);
Shader.SetUniform1f(p,"ObPass1","Timer",(timeme+e.FracTic)/Thinker.TICRATE);
Shader.SetUniform1f(p,"ObPass2","Timer",(timeme+e.FracTic)/Thinker.TICRATE);
Shader.SetUniform1f(p,"ObPass3","Timer",(timeme+e.FracTic)/Thinker.TICRATE);
secs -= .25;
Screen.Dim("Black",1.,0,0,Screen.GetWidth(),Screen.GetHeight());
// flash images:
// 0. mirror man (thievery at the forsaken manor redux)
// 1. viridescent lord (hexmas)
// 2. nightmare lord (spooktober)
// 3. dreadful lady (strife 25th anniversary project)
// 4. shinnovre (unsx 6)
// 5. hiikya (the hiikyan war)
// 6. rebirth of azadeku (project abyss dlc1: forgotten times)
// 7. heart of assimilation (project abyss dlc2: the void lords)
// 8. sage of blue (project abyss dlc3: assault on blue tower)
// 9. ser (project convergence)
int whichimg = clamp(int((10.*secs)/2.),0,9);
if ( !ftex[whichimg] ) return;
double ar = Screen.GetAspectRatio();
Vector2 tsize = TexMan.GetScaledSize(ftex[whichimg]);
double sar = tsize.x/tsize.y;
Vector2 vsize;
if ( sar > ar ) vsize = (tsize.x,tsize.x/ar);
else if ( sar < ar ) vsize = (tsize.y*ar,tsize.y);
else vsize = tsize;
vsize *= .75;
Screen.DrawTexture(ftex[whichimg],false,(vsize.x-tsize.x)/2,(vsize.y-tsize.y)/2,DTA_VirtualWidthF,vsize.x,DTA_VirtualHeightF,vsize.y,DTA_KeepRatio,true);
}
else if ( secs < 6.25 )
{
Shader.SetEnabled(p,"ObPass0",false);
Shader.SetEnabled(p,"ObPass1",false);
Shader.SetEnabled(p,"ObPass2",false);
Shader.SetEnabled(p,"ObPass3",false);
secs -= 2.25;
Screen.Dim("White",(1.-secs*.25)**1.5,0,0,Screen.GetWidth(),Screen.GetHeight());
if ( cdown == 35 )
A_StartSound("kirin/giggle",CHAN_ITEMEXTRA,CHANF_OVERLAP|CHANF_UI,1.,0.);
}
cdown--;
}
}
@ -572,23 +489,14 @@ Class ChanceboxSpawner : Actor
{
override void PostBeginPlay()
{
int numcol = 0;
for ( int i=0; i<AllActorClasses.Size(); i++ )
{
let c = (Class<SWWMCollectable>)(AllActorClasses[i]);
if ( !c || (c == 'SWWMCollectable') ) continue;
let def = GetDefaultByType(c);
// check that we can collect it in this IWAD
if ( !(gameinfo.gametype&def.avail) ) continue;
numcol++;
}
let ti = ThinkerIterator.Create("SWWMCollectable");
while ( ti.Next() ) numcol--;
int numbox = 0;
let ti = ThinkerIterator.Create("ChanceboxSpawner");
while ( ti.Next() ) numbox++;
ti = ThinkerIterator.Create("Chancebox");
while ( ti.Next() ) numcol--;
if ( numcol <= 0 )
while ( ti.Next() ) numbox++;
if ( numbox > 3 )
{
// can't spawn a box, everything's been collected
// there's three boxes in the map already (plus ourselves)
Destroy();
return;
}
@ -606,49 +514,276 @@ Class ChanceboxSpawner : Actor
b.HandleSpawnFlags();
b.bCOUNTSECRET = spawnflags&MTF_SECRET;
b.ChangeTid(tid);
Destroy();
}
Default
{
Radius 12;
Height 20;
}
}
// Collectable box (recycling of discarded "chance box" item)
Class BoxSpawnSpot
{
Vector3 pos;
double angle;
}
Class CBoxLight : SpotLightAttenuated
{
Default
{
Args 112,64,224,100;
DynamicLight.SpotInnerAngle 20;
DynamicLight.SpotOuterAngle 80;
+INTERPOLATEANGLES;
}
override void Tick()
{
Super.Tick();
if ( !target || target.InStateSequence(target.CurState,target.FindState("BlowUp")) )
{
Destroy();
return;
}
Vector2 ofs = ((special1<2)?8:-8,(special1%2)?12:-12);
double ang = (special1<2)?0:180;
angle = target.angle+ang;
SetOrigin(target.Vec3Offset(ofs.x*cos(target.angle)-ofs.y*sin(target.angle),ofs.y*cos(target.angle)+ofs.x*sin(target.angle),10),true);
}
}
// Collectible box (recycling of discarded "chance box" item)
Class Chancebox : Actor
{
bool dud;
static void SpawnChanceboxes()
{
// TODO the whole damn deal of finding secret sectors and whatnot
// this will be huge, and get called from the event handler on first level load
// find all secret sectors, find potential spawn spots within them
// after that, spawn up to 3 boxes total within them
int tboxes = 0;
for ( int i=0; i<level.Sectors.Size(); i++ )
{
if ( !(level.Sectors[i].flags&Sector.SECF_SECRET) ) continue;
Sector s = level.Sectors[i];
// find any spots in the sector that are within it and have no linedefs or blocking actors within a 32 unit box
// start from the center, expand in rings
Vector2 origin = s.centerspot;
double maxradius = 0;
for ( int j=0; j<s.lines.Size(); j++ )
{
Line l = s.lines[j];
double v1len = (l.v1.p-origin).length(),
v2len = (l.v2.p-origin).length();
if ( v1len > maxradius ) maxradius = v1len;
if ( v2len > maxradius ) maxradius = v2len;
}
int rings = 1;
bool spawned = false;
Array<BoxSpawnSpot> spots;
spots.Clear();
for ( double j=0.; j<maxradius; j+=16. )
{
for ( double k=0.; k<360.; k+=(360./rings) )
{
// check spot
Vector3 testpos = (origin.x+j*cos(k),origin.y+j*sin(k),0);
testpos.z = s.floorplane.ZAtPoint(testpos.xy);
if ( (level.PointInSector(testpos.xy) != s) || !level.IsPointInLevel(testpos) ) continue;
bool blocked = false;
BlockLinesIterator bl = BlockLinesIterator.CreateFromPos(testpos,32,32,s);
double tbox[4];
// top, bottom, left, right
tbox[0] = testpos.y+32;
tbox[1] = testpos.y-32;
tbox[2] = testpos.x-32;
tbox[3] = testpos.x+32;
while ( bl.Next() )
{
Line l = bl.CurLine;
if ( !l ) continue;
if ( tbox[2] > l.bbox[3] ) continue;
if ( tbox[3] < l.bbox[2] ) continue;
if ( tbox[0] < l.bbox[1] ) continue;
if ( tbox[1] > l.bbox[0] ) continue;
if ( SWWMUtility.BoxOnLineSide(tbox[0],tbox[1],tbox[2],tbox[3],l) != -1 ) continue;
blocked = true;
break;
}
if ( blocked ) continue;
BlockThingsIterator bt = BlockThingsIterator.CreateFromPos(testpos.x,testpos.y,testpos.z,32,256,false);
while ( bt.Next() )
{
if ( !bt.Thing ) continue;
if ( abs(bt.Thing.pos.x-testpos.x) > 32+bt.Thing.Radius ) continue;
if ( abs(bt.Thing.pos.y-testpos.y) > 32+bt.Thing.Radius ) continue;
blocked = true;
break;
}
if ( blocked ) continue;
let sp = new("BoxSpawnSpot");
sp.pos = testpos;
sp.angle = k+180;
spots.Push(sp);
}
rings += 3;
}
if ( spots.Size() < 10 ) continue;
int ws = Random[Chancebox](0,spots.Size()-1);
let c = Spawn("ChanceboxSpawner",spots[ws].pos);
c.angle = spots[ws].angle;
tboxes++;
if ( tboxes >= 3 ) break; // already spawned 3 boxes in one map (which is a lot)
}
}
action void A_DropSomething()
{
Array<Class <SWWMCollectable> > candidates;
Array<Class <SWWMCollectible> > candidates;
candidates.Clear();
for ( int i=0; i<AllActorClasses.Size(); i++ )
{
let c = (Class<SWWMCollectable>)(AllActorClasses[i]);
if ( !c || (c == 'SWWMCollectable') ) continue;
let c = (Class<SWWMCollectible>)(AllActorClasses[i]);
if ( !c || (c == 'SWWMCollectible') ) continue;
let def = GetDefaultByType(c);
// check that we can collect it in this IWAD
if ( !(gameinfo.gametype&def.avail) ) continue;
candidates.Push(c);
}
let ti = ThinkerIterator.Create("SWWMCollectable");
SWWMCollectable c;
while ( c = SWWMCollectable(ti.Next()) )
let ti = ThinkerIterator.Create("SWWMCollectible");
SWWMCollectible c;
while ( c = SWWMCollectible(ti.Next()) )
{
int f = candidates.Find(c.GetClass());
if ( f < candidates.Size() )
candidates.Delete(f);
}
if ( candidates.Size() <= 0 )
if ( (candidates.Size() <= 0) || invoker.dud )
{
// no candidates? just burst into treats
for ( int i=0; i<=30; i++ )
if ( Random[Chancebox](0,1) )
{
let a = Spawn((i==0)?"RefresherItem":(i%3)?"HealthNuggetItem":"ArmorNuggetItem",pos);
let a = Spawn(!Random[Chancebox](0,2)?"GoldShell":Random[Chancebox](0,2)?"GrilledCheeseSandwich":"YnykronAmmo",pos);
a.bDROPPED = true;
a.bNOGRAVITY = false;
a.vel.z = FRandom[Chancebox](2,4);
if ( i > 0 ) a.vel.xy = (cos(i*12),sin(i*12))*FRandom[Chancebox](4,12);
}
else if ( !Random[Chancebox](0,2) )
{
for ( int i=0; i<=12; i++ )
{
let a = Spawn((i==0)?"CandyGun":"CandyGunBullets",pos);
a.bDROPPED = true;
a.bNOGRAVITY = false;
a.vel.z = FRandom[Chancebox](2,4);
if ( i > 0 ) a.vel.xy = (cos(i*30),sin(i*30))*FRandom[Chancebox](1,2);
}
}
else if ( !Random[Chancebox](0,2) )
{
for ( int i=0; i<3; i++ )
{
let a = Spawn("SilverBullets2",pos);
a.bDROPPED = true;
a.bNOGRAVITY = false;
a.vel.z = FRandom[Chancebox](2,4);
a.vel.xy = (cos(i*120),sin(i*120))*FRandom[Chancebox](1,2);
}
for ( int i=0; i<6; i++ )
{
let a = Spawn("SilverBullets",pos);
a.bDROPPED = true;
a.bNOGRAVITY = false;
a.vel.z = FRandom[Chancebox](2,4);
a.vel.xy = (cos(i*60),sin(i*60))*FRandom[Chancebox](3,4);
}
}
else if ( Random[Chancebox](0,1) )
{
let a = Spawn("HellblazerWarheads",pos);
a.bDROPPED = true;
a.bNOGRAVITY = false;
a.vel.z = FRandom[Chancebox](2,4);
for ( int i=0; i<3; i++ )
{
a = Spawn("HellblazerRavagers",pos);
a.bDROPPED = true;
a.bNOGRAVITY = false;
a.vel.z = FRandom[Chancebox](2,4);
a.vel.xy = (cos(i*120),sin(i*120))*FRandom[Chancebox](1,2);
}
for ( int i=0; i<5; i++ )
{
a = Spawn("HellblazerCrackshots",pos);
a.bDROPPED = true;
a.bNOGRAVITY = false;
a.vel.z = FRandom[Chancebox](2,4);
a.vel.xy = (cos(i*72),sin(i*72))*FRandom[Chancebox](3,4);
}
for ( int i=0; i<8; i++ )
{
a = Spawn("HellblazerMissiles",pos);
a.bDROPPED = true;
a.bNOGRAVITY = false;
a.vel.z = FRandom[Chancebox](2,4);
a.vel.xy = (cos(i*45),sin(i*45))*FRandom[Chancebox](5,6);
}
}
else if ( Random[Chancebox](0,1) )
{
let a = Spawn("BlackShell",pos);
a.bDROPPED = true;
a.bNOGRAVITY = false;
a.vel.z = FRandom[Chancebox](2,4);
for ( int i=0; i<3; i++ )
{
a = Spawn("BlueShell",pos);
a.bDROPPED = true;
a.bNOGRAVITY = false;
a.vel.z = FRandom[Chancebox](2,4);
a.vel.xy = (cos(i*120),sin(i*120))*FRandom[Chancebox](1,2);
}
for ( int i=0; i<8; i++ )
{
a = Spawn((i%2)?"WhiteShell":"PurpleShell",pos);
a.bDROPPED = true;
a.bNOGRAVITY = false;
a.vel.z = FRandom[Chancebox](2,4);
a.vel.xy = (cos(i*72),sin(i*72))*FRandom[Chancebox](3,4);
}
for ( int i=0; i<12; i++ )
{
a = Spawn((i%2)?"RedShell":"GreenShell",pos);
a.bDROPPED = true;
a.bNOGRAVITY = false;
a.vel.z = FRandom[Chancebox](2,4);
a.vel.xy = (cos(i*30),sin(i*30))*FRandom[Chancebox](5,6);
}
}
else if ( Random[Chancebox](0,1) )
{
for ( int i=0; i<100; i++ )
{
let a = Spawn("HealthNuggetItem",pos);
a.bDROPPED = true;
a.bNOGRAVITY = false;
a.vel.z = FRandom[Chancebox](2,8);
a.vel.xy = (cos(i*3.6),sin(i*3.6))*FRandom[Chancebox](1,8);
}
}
else
{
for ( int i=0; i<=15; i++ )
{
let a = Spawn((i==0)?"RefresherItem":(i%3)?"HealthNuggetItem":"ArmorNuggetItem",pos);
a.bDROPPED = true;
a.bNOGRAVITY = false;
a.vel.z = FRandom[Chancebox](2,4);
if ( i > 0 ) a.vel.xy = (cos(i*24),sin(i*24))*FRandom[Chancebox](1,2);
}
}
}
else
@ -687,6 +822,34 @@ Class Chancebox : Actor
override bool Used( Actor user )
{
if ( CurState != FindState("Spawn") ) return false;
if ( !dud )
{
if ( Random[Chancebox](0,2) )
{
int nbox = 0, ndud = 0;
// this one's a dud (unless all the others are)
let ti = ThinkerIterator.Create("Chancebox");
Chancebox c;
while ( c = Chancebox(ti.Next()) )
{
if ( c == self ) continue;
nbox++;
if ( c.dud ) ndud++;
}
if ( ndud < nbox ) dud = true;
}
else
{
// the others are duds
let ti = ThinkerIterator.Create("Chancebox");
Chancebox c;
while ( c = Chancebox(ti.Next()) )
{
if ( c == self ) continue;
c.dud = true; // we found one, the others just drop goodies
}
}
}
if ( bCountSecret )
{
user.GiveSecret();
@ -702,10 +865,31 @@ Class Chancebox : Actor
SetStateLabel("PreActive");
return true;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
for ( int i=0; i<4; i++ )
{
let l = Spawn("CBoxLight",pos);
l.special1 = i;
l.target = self;
}
let ti = ThinkerIterator.Create("Chancebox");
Chancebox c;
while ( c = Chancebox(ti.Next()) )
{
if ( c.dud || (c.CurState == c.FindState("Spawn")) )
continue;
// automatically become a dud if collectible has been found
dud = true;
break;
}
}
Default
{
Radius 16;
Height 32;
Tag "$T_CHANCEBOX";
Radius 12;
Height 20;
+MOVEWITHSECTOR;
+ROLLSPRITE;
+SOLID;
@ -747,16 +931,16 @@ Class Chancebox : Actor
BlowUp:
XZW2 A 1
{
A_SetSize(16,4);
A_SetSize(12,3);
A_QuakeEx(2,2,2,9,0,500,"",QF_RELATIVE|QF_SCALEDOWN,falloff:200,rollIntensity:.2);
A_StartSound("chancebox/explode",CHAN_VOICE);
angle = specialf1;
pitch = roll = 0;
let t = Spawn("ChanceboxTop",Vec3Offset(0,0,32));
let t = Spawn("ChanceboxTop",Vec3Offset(0,0,20));
t.angle = angle;
let s1 = Spawn("ChanceboxSide",level.Vec3Offset(pos,(RotateVector((16,0),angle+90),0)));
let s1 = Spawn("ChanceboxSide",level.Vec3Offset(pos,(RotateVector((12,0),angle+90),0)));
s1.angle = angle+90;
let s2 = Spawn("ChanceboxSide",level.Vec3Offset(pos,(RotateVector((16,0),angle-90),0)));
let s2 = Spawn("ChanceboxSide",level.Vec3Offset(pos,(RotateVector((12,0),angle-90),0)));
s2.angle = angle-90;
A_DropSomething();
}
@ -771,8 +955,8 @@ Class ChanceboxTop : Actor
{
Default
{
Radius 16;
Height 4;
Radius 12;
Height 3;
Species "Chancebox";
PROJECTILE;
+THRUSPECIES;
@ -806,8 +990,8 @@ Class ChanceboxSide : Actor
{
Default
{
Radius 16;
Height 32;
Radius 12;
Height 24;
Species "Chancebox";
PROJECTILE;
+THRUSPECIES;

View file

@ -3,6 +3,9 @@
// preload fonts and stuff
Class SWWMPreloader : StaticEventHandler
{
transient ui Font TewiFont, MPlusFont;
transient ui CVar lang;
override void OnRegister()
{
Font.GetFont('k6x8');
@ -17,7 +20,18 @@ Class SWWMPreloader : StaticEventHandler
Font.GetFont('Tewi');
Font.GetFont('TewiShaded');
Font.GetFont('TewiShadedInverse');
Font.GetFont('SWWMBigFont');
}
// FIXME uncomment this once it's supported
/*override void UiTick()
{
// HACK! Graf, please let us change this in a cleaner way
if ( menuDelegate.GetClass() == 'DoomMenuDelegate' )
{
menuDelegate.Destroy();
menuDelegate = new("SWWMMenuDelegate");
}
}*/
}
// save version holder
@ -545,6 +559,8 @@ Class SWWMHandler : EventHandler
lpos /= xcnt;
SWWMInterest.Spawn(lpos,theline:l);
}
// spawn loot
Chancebox.SpawnChanceboxes();
}
else if ( e.IsSaveGame || e.IsReopen )
{
@ -656,7 +672,7 @@ Class SWWMHandler : EventHandler
}
}
// reset score (optional) if inventory should be cleared
if ( level.removeitems && !e.IsReturn && swwm_resetscore )
if ( swwm_resetscore && level.removeitems && !e.IsReturn )
c.credits = c.hcredits = 0;
}
@ -803,6 +819,8 @@ Class SWWMHandler : EventHandler
// ignore if not targetted or player can't see it
if ( (a.target != players[consoleplayer].mo)
|| !SWWMUtility.InPlayerFOV(players[consoleplayer],a) ) continue;
// [HDoom] ignore cute girls
if ( SWWMHDoomHandler.IsCuteGirl(a.target) ) continue;
// is it already in?
bool addme = true;
for ( int i=0; i<combatactors.Size(); i++ )
@ -923,7 +941,8 @@ Class SWWMHandler : EventHandler
{
if ( (e.Thing.IsFriend(e.DamageSource) || SWWMUtility.IsCivilian(e.DamageSource)) )
lastcombat = AddOneliner("friendhit",1,10);
else if ( (!lastcombat || (gametic > lastcombat+100)) && !Random[DemoLines](0,(e.DamageSource.bBOSS||e.DamageSource.bBOSSDEATH)?2:4) ) lastcombat = AddOneliner("gethit",1,15);
else if ( (!lastcombat || (gametic > lastcombat+100)) && !Random[DemoLines](0,(e.DamageSource.bBOSS||e.DamageSource.bBOSSDEATH)?2:4) && !SWWMHDoomHandler.IsCuteGirl(e.DamageSource) ) // [HDoom] don't shout at the girls
lastcombat = AddOneliner("gethit",1,15);
}
highesttic = gametic;
}
@ -959,7 +978,7 @@ Class SWWMHandler : EventHandler
{
if ( e.Thing.IsFriend(e.DamageSource) || SWWMUtility.IsCivilian(e.Thing) )
lastcombat = AddOneliner("friendkill",1,5);
else if ( (!lastcombat || (gametic > lastcombat+100)) && !Random[DemoLines](0,(e.Thing.bBOSS||e.Thing.bBOSSDEATH)?2:5) )
else if ( (!lastcombat || (gametic > lastcombat+100)) && !Random[DemoLines](0,(e.Thing.bBOSS||e.Thing.bBOSSDEATH)?2:5) && !SWWMHDoomHandler.IsCuteGirl(e.Thing) ) // [HDoom] don't shout at the girls
lastcombat = AddOneliner("scorekill",1,15);
}
}
@ -1076,6 +1095,7 @@ Class SWWMHandler : EventHandler
private void DoKeyTagFix( Actor a )
{
if ( a is 'SWWMKey' ) return; // mod's custom keys are fine
if ( a is 'RedCard' ) a.SetTag("$T_REDCARD");
else if ( a is 'BlueCard' ) a.SetTag("$T_BLUECARD");
else if ( a is 'YellowCard' ) a.SetTag("$T_YELLOWCARD");
@ -1139,7 +1159,19 @@ Class SWWMHandler : EventHandler
e.Thing.A_SetSize(20,40);
e.Thing.bNOBLOOD = true;
}
else if ( (e.Thing is 'MBFHelperDog') || ((e.Thing is 'Cacodemon') && !(e.Thing is 'DeadCacodemon')) )
{
// you can pet the dog, and you can also pet the caco
let hp = Actor.Spawn("HeadpatTracker",e.Thing.pos);
hp.target = e.Thing;
}
if ( !swwm_notrack && (e.Thing.bSHOOTABLE || e.Thing.bISMONSTER) && !(e.Thing is 'LampMoth') && !(e.Thing is 'CompanionLamp') ) SWWMCombatTracker.Spawn(e.Thing);
if ( swwm_shadows && (e.Thing.bSHOOTABLE || e.Thing.bISMONSTER || e.Thing.bCORPSE || (e.Thing is 'Inventory')) )
{
// Uncomment once sprite shadows are added in-engine
//if ( ((e.Thing is 'Demolitionist') || (e.Thing.SpawnState.sprite == e.Thing.GetSpriteIndex('XZW1'))) )
SWWMShadow.Track(e.Thing);
}
}
override void PostUiTick()
@ -1246,8 +1278,6 @@ Class SWWMHandler : EventHandler
{
if ( e.Replacement is 'DSparilHax' )
e.Replacee = 'Sorcerer2';
if ( e.Replacement is 'SWWMHangingKeen' )
e.Replacee = 'CommanderKeen';
}
override void CheckReplacement( ReplaceEvent e )
@ -1262,8 +1292,8 @@ Class SWWMHandler : EventHandler
static const Class<Actor> bluepool[] = {"BlueShell","BlueShell2","BlueShell4"};
static const Class<Actor> blackpool[] = {"BlackShell","BlackShell2"};
if ( e.Replacee is 'ItemFog' ) e.Replacement = 'SWWMItemFog';
if ( e.Replacee is 'TeleportFog' ) e.Replacement = 'SWWMTeleportFog';
if ( (e.Replacee is 'CommanderKeen') && (!e.Replacement || (e.Replacement == 'CommanderKeen')) )
else if ( e.Replacee is 'TeleportFog' ) e.Replacement = 'SWWMTeleportFog';
else if ( (e.Replacee is 'CommanderKeen') && (!e.Replacement || (e.Replacement == 'CommanderKeen')) )
{
let def = GetDefaultByType(e.Replacee);
bool dehackery = false;
@ -1274,6 +1304,25 @@ Class SWWMHandler : EventHandler
}
if ( !dehackery ) e.Replacement = 'SWWMHangingKeen';
}
else if ( e.Replacee is 'RedCard' )
{
if ( level.GetChecksum() ~== "3805A661D5C4523AFF7BF86991071043" )
return; // don't replace red key in Equinox MAP13
e.Replacement = 'SWWMRedCard';
}
else if ( e.Replacee is 'BlueCard' ) e.Replacement = 'SWWMBlueCard';
else if ( e.Replacee is 'YellowCard' ) e.Replacement = 'SWWMYellowCard';
else if ( e.Replacee.GetClassName() == 'KDiZDSilverKey' ) e.Replacement = 'SWWMSilverCardKDiZD';
else if ( e.Replacee.GetClassName() == 'KDiZDGreenKey' ) e.Replacement = 'SWWMGreenCardKDiZD';
else if ( e.Replacee.GetClassName() == 'KDiZDOrangeKey' ) e.Replacement = 'SWWMOrangeCardKDiZD';
else if ( e.Replacee.GetClassName() == 'GreenCard' ) e.Replacement = 'SWWMGreenCard';
else if ( e.Replacee is 'RedSkull' ) e.Replacement = 'SWWMRedSkull';
else if ( e.Replacee is 'BlueSkull' ) e.Replacement = 'SWWMBlueSkull';
else if ( e.Replacee is 'YellowSkull' ) e.Replacement = 'SWWMYellowSkull';
else if ( e.Replacee is 'KeyGreen' ) e.Replacement = 'SWWMKeyGreen';
else if ( e.Replacee is 'KeyBlue' ) e.Replacement = 'SWWMKeyBlue';
else if ( e.Replacee is 'KeyYellow' ) e.Replacement = 'SWWMKeyYellow';
else if ( e.Replacee.GetClassName() == 'KeyRed' ) e.Replacement = 'SWWMKeyRed';
else if ( (e.Replacee is 'Chainsaw') || (e.Replacee is 'Gauntlets') || (e.Replacee is 'FWeapAxe') ) e.Replacement = 'PusherWeapon';
else if ( (e.Replacee is 'Fist') || (e.Replacee is 'Staff') ) e.Replacement = 'DeepImpact';
else if ( (e.Replacee is 'Pistol') || (e.Replacee is 'GoldWand') || (e.Replacee is 'FWeapFist') || (e.Replacee is 'CWeapMace') || (e.Replacee is 'MWeapWand') ) e.Replacement = 'ExplodiumGun';
@ -1502,7 +1551,7 @@ Class SWWMHandler : EventHandler
else if ( (e.Replacee == 'Infrared') || (e.Replacee == 'ArtiTorch') ) e.Replacement = 'SWWMLamp';
else if ( (e.Replacee == 'GreenArmor') || (e.Replacee == 'SilverShield') || (e.Replacee == 'MeshArmor') ) e.Replacement = 'BlastSuitItem';
else if ( (e.Replacee == 'BlueArmor') || (e.Replacee == 'FalconShield') || (e.Replacee == 'EnchantedShield') ) e.Replacement = 'WarArmorItem';
else if ( (e.Replacee == 'ArtiPork') || (e.Replacee == 'ArtiDarkServant') || (e.Replacee == 'ArtiTeleport') || (e.Replacee == 'ArtiTeleportOther') ) e.Replacement = 'SWWMNothing'/*'Chancebox'*/;
else if ( (e.Replacee == 'ArtiPork') || (e.Replacee == 'ArtiDarkServant') || (e.Replacee == 'ArtiTeleport') || (e.Replacee == 'ArtiTeleportOther') ) e.Replacement = 'ChanceboxSpawner';
}
override void NetworkProcess( ConsoleEvent e )
@ -1512,7 +1561,7 @@ Class SWWMHandler : EventHandler
{
if ( (e.player == -1) || !playeringame[e.player] || !players[e.player].mo ) return;
let mo = players[e.player].mo;
if ( (mo.Health <= 0) || !(mo is 'Demolitionist') ) return;
if ( e.Args[0] < 0 ) return; // special gestures can't be manually started
SWWMGesture.SetGesture(mo,e.Args[0]);
}
if ( e.IsManual ) return;
@ -1523,7 +1572,13 @@ Class SWWMHandler : EventHandler
if ( SWWMCredits.Take(players[e.Args[0]],e.Args[1]) )
{
players[e.Args[0]].mo.GiveInventory(item,e.Args[2],true);
if ( item is 'Weapon' ) players[e.Args[0]].mo.A_SelectWeapon((Class<Weapon>)(item));
if ( item is 'Weapon' )
{
// special case, select dual guns if we bought a second one
if ( (item is 'ExplodiumGun') && (players[e.Args[0]].mo.CountInv("ExplodiumGun") > 1) )
players[e.Args[0]].mo.A_SelectWeapon("DualExplodiumGun");
else players[e.Args[0]].mo.A_SelectWeapon((Class<Weapon>)(item));
}
}
}
else if ( e.Name.Left(10) ~== "swwmtrade." )

View file

@ -84,6 +84,8 @@ Class HealthNuggetItem : SWWMHealth
SWWMHealth.GiveHealth "HealthNugget";
+INVENTORY.ALWAYSPICKUP;
+COUNTITEM;
Radius 6;
Height 20;
}
States
{
@ -116,6 +118,8 @@ Class TetraHealthItem : SWWMHealth
Inventory.MaxAmount 15;
Inventory.InterHubAmount 15;
SWWMHealth.GiveHealth "TetraHealth";
Radius 8;
Height 24;
}
States
{
@ -141,6 +145,8 @@ Class CubeHealthItem : SWWMHealth
Inventory.MaxAmount 10;
Inventory.InterHubAmount 10;
SWWMHealth.GiveHealth "CubeHealth";
Radius 8;
Height 24;
}
States
{
@ -181,6 +187,8 @@ Class RefresherItem : SWWMHealth
+COUNTITEM;
+INVENTORY.BIGPOWERUP;
+INVENTORY.ALWAYSPICKUP;
Radius 6;
Height 24;
}
States
{

View file

@ -874,8 +874,11 @@ Class SWWMStatusBar : BaseStatusBar
int xx = int(ss.x-(margin+2));
String str;
int label = showmaplabel.GetInt();
if ( !label || ((level.clusterflags&level.CLUSTER_HUB) && (label == 2)) ) str = level.levelname;
else str = String.Format("%s - %s",level.mapname.MakeUpper(),level.levelname);
String ln = level.levelname;
int iof = ln.IndexOf(" - by: ");
if ( iof != -1 ) ln.Truncate(iof);
if ( !label || ((level.clusterflags&level.CLUSTER_HUB) && (label == 2)) ) str = ln;
else str = String.Format("%s - %s",level.mapname.MakeUpper(),ln);
let fnt = LangFont(mTewiFont);
Screen.DrawText(fnt,Font.CR_FIRE,xx-fnt.StringWidth(str),yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
yy += fnt.GetHeight();

View file

@ -22,6 +22,23 @@ Class SWWMStatScreen : StatusScreen abstract
if ( lang.GetString() ~== "jp" ) return MPlusFont;
return req;
}
override void Start( wbstartstruct wbstartstruct )
{
Super.Start(wbstartstruct);
// support for old author text style
int iof = lnametexts[0].IndexOf(" - by: ");
if ( iof != -1 )
{
authortexts[0] = lnametexts[0].Mid(iof+7);
lnametexts[0].Truncate(iof);
}
iof = lnametexts[1].IndexOf(" - by: ");
if ( iof != -1 )
{
authortexts[1] = lnametexts[1].Mid(iof+7);
lnametexts[1].Truncate(iof);
}
}
override void StartMusic()
{
if ( !origmus ) origmus = CVar.GetCVar('swwm_intermusic',players[consoleplayer]);

View file

@ -20,6 +20,47 @@ Mixin Class SWWMAutoUseFix
}
}
Class CrossLineFinder : LineTracer
{
Array<Line> clines;
Array<int> csides;
override ETraceStatus TraceCallback()
{
if ( (Results.HitType == TRACE_HitWall) && (Results.HitLine.activation&SPAC_Cross) )
{
clines.Push(Results.HitLine);
csides.Push(Results.Side);
}
return TRACE_Skip;
}
}
Mixin Class SWWMUseToPickup
{
// allow pickup by use
override bool Used( Actor user )
{
Vector3 itempos = Vec3Offset(0,0,Height/2),
userpos = user.Vec2OffsetZ(0,0,user.player.viewz);
Touch(user);
// we got picked up
if ( bDestroyed || Owner || !bSPECIAL )
{
Vector3 tracedir = level.Vec3Diff(userpos,itempos);
double dist = tracedir.length();
tracedir /= dist;
let cf = new("CrossLineFinder");
cf.Trace(userpos,level.PointInSector(userpos.xy),tracedir,dist,0);
// trigger all player cross lines found between user and item
for ( int i=0; i<cf.clines.Size(); i++ )
cf.clines[i].Activate(user,cf.csides[i],SPAC_Cross);
return true;
}
return false;
}
}
Mixin Class SWWMOverlapPickupSound
{
// overlap sounds
@ -170,6 +211,7 @@ Class SWWMArmor : Armor abstract
Class SWWMSpareArmor : Inventory abstract
{
Mixin SWWMAutoUseFix;
Mixin SWWMUseToPickup;
Mixin SWWMOverlapPickupSound;
Class<SWWMArmor> giveme;
@ -201,6 +243,7 @@ Class SWWMSpareArmor : Inventory abstract
+INVENTORY.AUTOACTIVATE;
Inventory.MaxAmount 5;
Inventory.InterHubAmount 5;
Inventory.PickupFlash "SWWMPickupFlash";
+FLOATBOB;
FloatBobStrength 0.25;
}
@ -209,6 +252,7 @@ Class SWWMSpareArmor : Inventory abstract
Class SWWMHealth : Inventory abstract
{
Mixin SWWMAutoUseFix;
Mixin SWWMUseToPickup;
Mixin SWWMOverlapPickupSound;
// can't use the Health class for whatever reason
@ -342,6 +386,7 @@ Class SWWMHealth : Inventory abstract
Inventory.MaxAmount 5;
Inventory.InterHubAmount 5;
Inventory.UseSound "misc/health_pkup";
Inventory.PickupFlash "SWWMPickupFlash";
+FLOATBOB;
FloatBobStrength 0.25;
}
@ -896,10 +941,33 @@ Class UseLineTracer : LineTracer
}
}
Class SWWMCrosshairTracer : LineTracer
{
Actor ignoreme;
override ETraceStatus TraceCallback()
{
if ( Results.HitType == TRACE_HitActor )
{
if ( Results.HitActor == ignoreme ) 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;
}
}
// Base class for all SWWM Weapons
Class SWWMWeapon : Weapon abstract
{
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
private int SWeaponFlags;
Actor pfield; // instance of parry field for current melee attack
@ -912,6 +980,21 @@ Class SWWMWeapon : Weapon abstract
FlagDef NoFirstGive : SWeaponFlags, 0; // don't give ammo on first pickup (for weapons with a clip count)
FlagDef HideInMenu : SWeaponFlags, 1; // don't show in inventory menu (usually for sister weapons)
transient CVar phair; // use custom precise crosshair
transient ui CVar ch_img, ch_siz, ch_grow, ch_col, ch_hp, ch_on;
ui SWWMCrosshairTracer ctr;
ui Vector3 cpos;
ui Color ccol;
ui Vector2 lagvpos;
override void DoEffect()
{
Super.DoEffect();
if ( !phair ) phair = CVar.GetCVar('swwm_precisecrosshair',players[consoleplayer]);
// force custom crosshair
if ( phair.GetBool() ) crosshair = 99;
else crosshair = 0;
}
override bool HandlePickup( Inventory item )
{
if ( (GetClass() == item.GetClass()) && !item.ShouldStay() )
@ -995,10 +1078,97 @@ Class SWWMWeapon : Weapon abstract
// HUD-side ticking
virtual ui void HudTick()
{
[cpos, ccol] = TraceForCrosshair();
// avoid jumpy switching
if ( Owner.player.PendingWeapon is 'SWWMWeapon' )
{
SWWMWeapon(Owner.player.PendingWeapon).cpos = cpos;
SWWMWeapon(Owner.player.PendingWeapon).lagvpos = lagvpos;
}
}
// extra drawing, usually scopes
virtual ui void RenderUnderlay( RenderEvent e )
{
// draw custom crosshair
if ( automapactive ) return;
if ( !phair || !phair.GetBool() ) return;
if ( !ch_on ) ch_on = CVar.GetCVar('crosshairon',players[consoleplayer]);
if ( !ch_on.GetBool() ) return;
let sb = SWWMStatusBar(StatusBar);
if ( !sb ) return;
sb.viewport.FromHud();
sb.proj.CacheResolution();
sb.proj.CacheFov(players[consoleplayer].fov);
sb.proj.OrientForRenderUnderlay(e);
sb.proj.BeginProjection();
Vector3 tdir = level.Vec3Diff(e.ViewPos,cpos);
// project
sb.proj.ProjectWorldPos(e.ViewPos+tdir);
Vector2 vpos;
if ( !sb.proj.IsInFront() ) return;
Vector2 npos = sb.proj.ProjectToNormal();
vpos = sb.viewport.SceneToWindow(npos);
if ( lagvpos == (0,0) ) lagvpos = vpos;
else lagvpos = lagvpos*.7+vpos*.3; // this will be fucky depending on the FPS, but oh well
if ( !ch_img ) ch_img = CVar.GetCVar('crosshair',players[consoleplayer]);
int cnum = abs(ch_img.GetInt());
if ( !cnum ) return;
String tn = String.Format("XHAIR%s%d",(Screen.GetWidth()<640)?"S":"B",cnum);
TextureID ctex = TexMan.CheckForTexture(tn,TexMan.Type_MiscPatch);
if ( !ctex.IsValid() ) ctex = TexMan.CheckForTexture(String.Format("XHAIR%s1",(Screen.GetWidth()<640)?"S":"B"),TexMan.Type_MiscPatch);
if ( !ctex.IsValid() ) ctex = TexMan.CheckForTexture("XHAIRS1",TexMan.Type_MiscPatch);
Vector2 ts = TexMan.GetScaledSize(ctex);
if ( !ch_siz ) ch_siz = CVar.GetCVar('crosshairscale',players[consoleplayer]);
double cs = ch_siz.GetFloat();
double sz = 1.;
if ( cs > 0. ) sz = Screen.GetHeight()*cs/200.;
if ( !ch_grow ) ch_grow = CVar.GetCVar('crosshairgrow',players[consoleplayer]);
if ( ch_grow.GetBool() ) sz *= sb.CrosshairSize;
Screen.DrawTexture(ctex,false,int(lagvpos.x),int(lagvpos.y),DTA_DestWidthF,ts.x*sz,DTA_DestHeightF,ts.y*sz,DTA_AlphaChannel,true,DTA_FillColor,ccol);
}
ui Vector3, Color TraceForCrosshair()
{
if ( !ctr ) ctr = new("SWWMCrosshairTracer");
ctr.ignoreme = Owner;
Vector3 x, y, z, ofs;
double s;
[x, y, z] = swwm_CoordUtil.GetAxes(Owner.pitch,Owner.angle,Owner.roll);
ofs = GetTraceOffset();
Vector3 origin = level.Vec3Offset(Owner.Vec2OffsetZ(0,0,Owner.player.viewz),ofs.x*x+ofs.y*y+ofs.z*z);
ctr.Trace(origin,level.PointInSector(origin.xy),x,10000.,0);
if ( !ch_col ) ch_col = CVar.GetCVar('crosshaircolor',players[consoleplayer]);
Color col = ch_col.GetInt();
if ( !ch_hp ) ch_hp = CVar.GetCVar('crosshairhealth',players[consoleplayer]);
if ( ch_hp.GetInt() >= 2 )
{
int hp = Clamp(Owner.Health,0,200);
double sat = (hp<150)?1.:(1.-(health-150)/100.);
Vector3 rgb = SWWMUtility.HSVtoRGB((hp/300.,sat,1.));
col = Color(int(rgb.x*255),int(rgb.y*255),int(rgb.z*255));
}
else if ( ch_hp.GetInt() == 1 )
{
double hp = Clamp(Owner.Health,0,100)/100.;
if ( hp <= 0 ) col = Color(255,0,0);
else if ( hp < .3 ) col = Color(255,int(hp*255/.3),0);
else if ( hp < .85 ) col = Color(int((.6-hp)*255/.3),255,0);
else col = Color(0,255,0);
}
else if ( (ctr.Results.HitType == TRACE_HitActor) && ctr.Results.HitActor.bSHOOTABLE )
{
// show target health, rather than our own
double hp = ctr.Results.HitActor.Health/double(ctr.Results.HitActor.GetSpawnHealth());
if ( hp <= 0 ) col = Color(255,0,0);
else if ( hp < .3 ) col = Color(255,int(hp*255/.3),0);
else if ( hp < .85 ) col = Color(int((.6-hp)*255/.3),255,0);
else col = Color(0,255,0);
}
return ctr.Results.HitPos, col;
}
// where the trace is coming from relative to eyes
virtual clearscope Vector3 GetTraceOffset() const
{
return (0.,0.,0.);
}
// animations
action void A_PlayerFire()
@ -1141,7 +1311,9 @@ Class SWWMWeapon : Weapon abstract
{
if ( ut.uses[i].hitactor )
{
if ( (ut.uses[i].hitactor == self) || (ut.uses[i].hitactor is 'Demolitionist') ) continue;
// punching is not greeting/patting (that'd be weird)
if ( (ut.uses[i].hitactor == self) || (ut.uses[i].hitactor is 'Demolitionist')
|| (ut.uses[i].hitactor is 'HeadpatTracker') ) continue;
if ( ut.uses[i].hitactor.Used(self) ) break;
}
else if ( ut.uses[i].hitline && UseLineTracer.TangibleLine(ut.uses[i]) )
@ -1282,6 +1454,7 @@ Class SWWMWeapon : Weapon abstract
Weapon.YAdjust 0;
Weapon.SlotPriority 1.;
Inventory.RestrictedTo "Demolitionist";
Inventory.PickupFlash "SWWMPickupFlash";
+INVENTORY.IGNORESKILL;
+WEAPON.NOALERT;
+WEAPON.NODEATHINPUT;

View file

@ -125,7 +125,7 @@ Class PusherProjectile : Actor
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_StartSound("pusher/fly",CHAN_BODY,CHANF_LOOPING,1.,2.);
A_StartSound("pusher/fly",CHAN_BODY,CHANF_LOOP,1.,2.);
A_StartSound("pusher/altfire",CHAN_VOICE);
oldvel = vel;
oldangle = angle;
@ -359,6 +359,7 @@ Class PusherWeapon : SWWMWeapon
override void HudTick()
{
Super.HudTick();
if ( !ChargeInter ) ChargeInter = DynamicValueInterpolator.Create(int(chargelevel*100),.5,1,50);
ChargeInter.Update(int(chargelevel*100));
}
@ -368,6 +369,11 @@ Class PusherWeapon : SWWMWeapon
return true;
}
override Vector3 GetTraceOffset()
{
return (10.,2.,-3.5);
}
action void A_PusherDrill()
{
invoker.chargelevel = clamp(invoker.chargelevel+FRandom[Pusher](-.1,.2),.3,1.);
@ -378,7 +384,7 @@ Class PusherWeapon : SWWMWeapon
A_Recoil(-cos(pitch));
Vector3 x, y, z;
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x+2*y-3*z);
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x+2*y-3.5*z);
FLineTraceData d;
LineTrace(angle,60,pitch,TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
if ( d.HitType != TRACE_HitNone )
@ -438,7 +444,7 @@ Class PusherWeapon : SWWMWeapon
for ( int i=0; i<numpt; i++ )
{
let s = Spawn("SWWMViewSmoke",origin);
SWWMViewSmoke(s).ofs = (10,2,-3);
SWWMViewSmoke(s).ofs = (10,2,-3.5);
s.target = self;
s.special1 = 1;
s.scale *= 1.4;
@ -464,7 +470,7 @@ Class PusherWeapon : SWWMWeapon
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+2*y-3*z);
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x+2*y-3.5*z);
FLineTraceData d;
LineTrace(angle,80,pitch,TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
bool gone = false;
@ -537,7 +543,7 @@ Class PusherWeapon : SWWMWeapon
for ( int i=0; i<numpt; i++ )
{
let s = Spawn("SWWMViewSmoke",origin);
SWWMViewSmoke(s).ofs = (10,2,-3);
SWWMViewSmoke(s).ofs = (10,2,-3.5);
s.target = self;
s.special1 = 2;
s.scale *= 1.4;
@ -587,9 +593,11 @@ Class PusherWeapon : SWWMWeapon
Weapon.UpSound "pusher/select";
Weapon.SlotNumber 1;
Weapon.SlotPriority 2.;
Weapon.SelectionOrder 2100;
Weapon.SelectionOrder 1500;
Stamina 10000;
+WEAPON.MELEEWEAPON;
Radius 20;
Height 32;
}
States
@ -611,10 +619,10 @@ Class PusherWeapon : SWWMWeapon
invoker.chargelevel = .2;
invoker.hitcnt = 0;
A_StartSound("pusher/start",CHAN_WEAPON,CHANF_OVERLAP);
A_StartSound("pusher/motor",CHAN_WEAPONEXTRA,CHANF_LOOPING,pitch:1.5);
A_StartSound("pusher/motor",CHAN_WEAPONEXTRA,CHANF_LOOP,pitch:1.5);
}
XZW2 M 2;
XZW2 N 0 A_StartSound("pusher/drill",CHAN_WEAPON,CHANF_LOOPING);
XZW2 N 0 A_StartSound("pusher/drill",CHAN_WEAPON,CHANF_LOOP);
Hold:
XZW2 N 1
{
@ -656,7 +664,7 @@ Class PusherWeapon : SWWMWeapon
XZW2 A 2
{
A_StartSound("pusher/start",CHAN_WEAPON,CHANF_OVERLAP);
A_StartSound("pusher/motor",CHAN_WEAPONEXTRA,CHANF_LOOPING,pitch:1.5);
A_StartSound("pusher/motor",CHAN_WEAPONEXTRA,CHANF_LOOP,pitch:1.5);
A_StartSound("pusher/pullback",CHAN_WEAPON,CHANF_OVERLAP);
}
XZW2 UVW 2;

269
zscript/swwm_keys.zsc Normal file
View file

@ -0,0 +1,269 @@
// Key item replacements, including some for popular map packs
Class SWWMKey : Key abstract
{
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
override void DoEffect()
{
Super.DoEffect();
if ( Icon.IsNull() )
{
// fetch icon from parent (if it exists)
Class<Key> pc = Species;
if ( !pc ) return;
let p = GetDefaultByType(pc);
Icon = p.Icon;
}
}
Default
{
+NOTDMATCH;
+FLOATBOB;
FloatBobStrength 0.25;
}
}
Class SWWMRedCard : SWWMKey
{
Default
{
Tag "$T_REDCARD";
Species "RedCard";
Inventory.PickupMessage "$T_REDCARD";
Radius 10;
Height 25;
}
States
{
Spawn:
XZW1 AB 10;
Loop;
}
}
Class SWWMYellowCard : SWWMKey
{
Default
{
Tag "$T_YELLOWCARD";
Species "YellowCard";
Inventory.PickupMessage "$T_YELLOWCARD";
Radius 10;
Height 25;
}
States
{
Spawn:
XZW1 AB 10;
Loop;
}
}
Class SWWMBlueCard : SWWMKey
{
Default
{
Tag "$T_BLUECARD";
Species "BlueCard";
Inventory.PickupMessage "$T_BLUECARD";
Radius 10;
Height 25;
}
States
{
Spawn:
XZW1 AB 10;
Loop;
}
}
Class SWWMSilverCardKDiZD : SWWMKey
{
Default
{
Tag "$T_SILVERCARD";
Species "BlueSkull";
Inventory.PickupMessage "$T_SILVERCARD";
Radius 10;
Height 25;
}
States
{
Spawn:
XZW1 AB 10;
Loop;
}
}
Class SWWMGreenCardKDiZD : SWWMKey
{
Default
{
Tag "$T_GREENCARD";
Species "YellowSkull";
Inventory.PickupMessage "$T_GREENCARD";
Radius 10;
Height 25;
}
States
{
Spawn:
XZW1 AB 10;
Loop;
}
}
Class SWWMOrangeCardKDiZD : SWWMKey
{
Default
{
Tag "$T_ORANGECARD";
Species "RedSkull";
Inventory.PickupMessage "$T_ORANGECARD";
Radius 10;
Height 25;
}
States
{
Spawn:
XZW1 AB 10;
Loop;
}
}
Class SWWMGreenCard : SWWMKey
{
Default
{
Tag "$T_GREENCARD";
Species "GreenCard";
Inventory.PickupMessage "$T_GREENCARD";
Radius 10;
Height 25;
}
States
{
Spawn:
XZW1 AB 10;
Loop;
}
}
// more Doom key color variants will be implemented as needed
Class SWWMRedSkull : SWWMKey
{
Default
{
Tag "$T_REDSKULL";
Species "RedSkull";
Inventory.PickupMessage "$T_REDSKULL";
Radius 10;
Height 25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class SWWMBlueSkull : SWWMKey
{
Default
{
Tag "$T_BLUESKULL";
Species "BlueSkull";
Inventory.PickupMessage "$T_BLUESKULL";
Radius 10;
Height 25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class SWWMYellowSkull : SWWMKey
{
Default
{
Tag "$T_YELLOWSKULL";
Species "YellowSkull";
Inventory.PickupMessage "$T_YELLOWSKULL";
Radius 10;
Height 25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class SWWMKeyGreen : SWWMKey
{
Default
{
Tag "$T_KEYGREEN";
Species "KeyGreen";
Inventory.PickupMessage "$T_KEYGREEN";
Radius 10;
Height 25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class SWWMKeyBlue : SWWMKey
{
Default
{
Tag "$T_KEYBLUE";
Species "KeyBlue";
Inventory.PickupMessage "$T_KEYBLUE";
Radius 10;
Height 25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class SWWMKeyYellow : SWWMKey
{
Default
{
Tag "$T_KEYYELLOW";
Species "KeyYellow";
Inventory.PickupMessage "$T_KEYYELLOW";
Radius 10;
Height 25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class SWWMKeyRed : SWWMKey
{
Default
{
Tag "$T_KEYRED";
Species "KeyRed";
Inventory.PickupMessage "$T_KEYRED";
Radius 10;
Height 25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}

View file

@ -13,6 +13,7 @@ Class MenuTransaction
bool result, usedup;
}
// FIXME this whole thing needs to be refactored eventually
Class SWWMKnowledgeBaseMenu : GenericMenu
{
enum EDemoTab
@ -23,7 +24,6 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
TAB_KEYS,
TAB_LIBRARY,
TAB_STORE,
TAB_RADIO,
TAB_GAME,
TAB_TRADING,
TAB_CHAT,
@ -83,6 +83,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
int kcode;
// crimey clock stuff
int c_year, c_month, c_day, c_hour, c_minute;
String c_tz;
// mouse stuff
Vector2 curmouse;
bool isrclick;
@ -146,41 +147,55 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
if ( gameinfo.gametype&GAME_Heretic )
{
// March 10th 2171, 17:34 JST
// Epoch: 6351554040
c_year = 2171;
c_month = 3;
c_day = 9;
c_hour = 9;
c_minute = 41;
c_hour = 17;
c_minute = 34;
c_tz = "JST";
}
else if ( gameinfo.gametype&GAME_Hexen )
{
// May 25th 2171, 16:41 JST
// Epoch: 6355438860
c_year = 2171;
c_month = 4;
c_day = 24;
c_hour = 16;
c_minute = 41;
c_tz = "JST";
}
else if ( gameinfo.gametype&GAME_Strife )
{
// September 13th 2173, 11:26 JST
// Epoch: 6425490360
c_year = 2173;
c_month = 7;
c_day = 12;
c_hour = 11;
c_minute = 26;
c_tz = "JST";
}
else // Doom
{
// June 6th 2148, 18:37 EDT
// (June 7th 2148, 07:37 JST)
// Epoch: 5630769420
c_year = 2148;
c_month = 5;
c_day = 5;
c_hour = 12;
c_minute = 27;
c_hour = 18;
c_minute = 37;
c_tz = "EDT";
}
}
// please don't look at this
private String CrimeTime()
{
// we have to do things this way because dates in this mod go beyond 32-bit unix time
static const int days_in_month[] = {31,28,31,30,31,30,31,31,30,31,30,31};
bool leap_year;
int y = c_year, m = c_month, d = c_day, h = c_hour, mn = c_minute;
@ -260,7 +275,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
addtime = 0;
}
}
return String.Format("%04d-%02d-%02d %02d:%02d",y,m+1,d+1,h,mn);
return String.Format("%04d-%02d-%02d %02d:%02d %s",y,m+1,d+1,h,mn,c_tz);
}
override bool MenuEvent( int mkey, bool fromcontroller )
@ -595,7 +610,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
if ( (curtab == TAB_INVENTORY) && (invlist.Size() > 0) && (sel0 < invlist.Size()) )
{
// can't use this
if ( (invlist[sel0] is 'Ammo') || (invlist[sel0] is 'MagAmmo') || (invlist[sel0] is 'SWWMCollectable')
if ( (invlist[sel0] is 'Ammo') || (invlist[sel0] is 'MagAmmo') || (invlist[sel0] is 'SWWMCollectible')
|| (invlist[sel0] is 'HammerspaceEmbiggener') )
return true;
let t = new("MenuTransaction");
@ -751,8 +766,8 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
static const string tabnames[] =
{
"$SWWM_MISSTAB", "$SWWM_STATTAB", "$SWWM_INVTAB", "$SWWM_KEYTAB",
"$SWWM_KBASETAB", "$SWWM_STORETAB", "$SWWM_RADIOTAB", "$SWWM_GAMETAB",
"$SWWM_TRADETAB", "$SWWM_CHATTAB", "$SWWM_SECRETTAB", "$SWWM_HELPTAB"
"$SWWM_KBASETAB", "$SWWM_STORETAB", "$SWWM_GAMETAB", "$SWWM_TRADETAB",
"$SWWM_CHATTAB", "$SWWM_SECRETTAB", "$SWWM_HELPTAB"
};
xx = 0;
int maxtab = multiplayer?TAB_CHAT:TAB_GAME;
@ -957,7 +972,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
{
if ( !invlist[i] ) continue;
str = invlist[i].GetTag();
if ( invlist[i] is 'SWWMCollectable' )
if ( invlist[i] is 'SWWMCollectible' )
str.AppendFormat(" (¥%d)",invlist[i].default.Stamina);
len = fnt.StringWidth(str);
if ( len > longest ) longest = len;
@ -1365,7 +1380,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
{
if ( !invlist[i] ) continue;
str = invlist[i].GetTag();
if ( invlist[i] is 'SWWMCollectable' )
if ( invlist[i] is 'SWWMCollectible' )
str.AppendFormat(" (¥%d)",invlist[i].default.Stamina);
len = fnt.StringWidth(str);
if ( len > longest ) longest = len;
@ -1837,7 +1852,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
qsort_lore(a,p+1,h);
}
private bool CmpCollectable( Inventory a, Inventory b )
private bool CmpCollectible( Inventory a, Inventory b )
{
if ( a.Stamina == b.Stamina )
{
@ -1848,13 +1863,13 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
return a.default.Stamina < b.default.Stamina;
}
private int partition_collectable( Array<Inventory> a, int l, int h )
private int partition_collectible( Array<Inventory> a, int l, int h )
{
Inventory pv = a[h];
int i = (l-1);
for ( int j=l; j<=(h-1); j++ )
{
if ( CmpCollectable(pv,a[j]) )
if ( CmpCollectible(pv,a[j]) )
{
i++;
Inventory tmp = a[j];
@ -1867,12 +1882,12 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
a[i+1] = tmp;
return i+1;
}
private void qsort_collectable( Array<Inventory> a, int l, int h )
private void qsort_collectible( Array<Inventory> a, int l, int h )
{
if ( l >= h ) return;
int p = partition_collectable(a,l,h);
qsort_collectable(a,l,p-1);
qsort_collectable(a,p+1,h);
int p = partition_collectible(a,l,h);
qsort_collectible(a,l,p-1);
qsort_collectible(a,p+1,h);
}
override void Ticker()
@ -1908,7 +1923,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
// alphabetically sorted inventory
for ( Inventory inv=players[consoleplayer].mo.Inv; inv; inv=inv.Inv )
{
if ( (inv.Amount <= 0) || !inv.SpawnState.ValidateSpriteFrame() || (inv is 'Key') || (inv is 'BasicArmor') || (inv is 'HexenArmor') || (inv is 'Powerup') || (inv is 'SWWMArmor') || (!(inv is 'Ammo') && !(inv is 'Weapon') && !inv.bINVBAR) && !(inv is 'HammerspaceEmbiggener') && !(inv is 'SWWMCollectable') && !(inv is 'MagAmmo') || (inv is 'SWWMCollectable') ) continue;
if ( (inv.Amount <= 0) || !inv.SpawnState.ValidateSpriteFrame() || (inv is 'Key') || (inv is 'BasicArmor') || (inv is 'HexenArmor') || (inv is 'Powerup') || (inv is 'SWWMArmor') || (!(inv is 'Ammo') && !(inv is 'Weapon') && !inv.bINVBAR) && !(inv is 'HammerspaceEmbiggener') && !(inv is 'SWWMCollectible') && !(inv is 'MagAmmo') || (inv is 'SWWMCollectible') ) continue;
// no hidden weapons
if ( (inv is 'SWWMWeapon') && SWWMWeapon(inv).bHIDEINMENU ) continue;
String tag = inv.GetTag();
@ -1944,14 +1959,14 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
let k = Key(players[consoleplayer].mo.FindInventory(Key.GetKeyType(i)));
if ( k ) invlist.Push(k);
}
// collectables, sorted by name
// collectibles, sorted by name
Array<Inventory> cols;
for ( Inventory inv=players[consoleplayer].mo.Inv; inv; inv=inv.Inv )
{
if ( inv is 'SWWMCollectable' )
if ( inv is 'SWWMCollectible' )
cols.Push(inv);
}
qsort_collectable(cols,0,cols.Size()-1);
qsort_collectible(cols,0,cols.Size()-1);
invlist.Append(cols);
// crop selection
if ( sel0 >= invlist.Size() ) sel0 = max(0,invlist.Size()-1);
@ -1965,8 +1980,8 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
{
let type = (Class<Inventory>)(AllActorClasses[i]);
if ( !type ) continue;
// no collectables
if ( type is 'SWWMCollectable' ) continue;
// no collectibles
if ( type is 'SWWMCollectible' ) continue;
// skip maxed items
let cur = players[consoleplayer].mo.FindInventory(type);
if ( cur && (cur.Amount >= cur.MaxAmount) ) continue;
@ -2091,7 +2106,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
// alphabetically sorted inventory
for ( Inventory inv=players[consoleplayer].mo.Inv; inv; inv=inv.Inv )
{
if ( (inv.Amount <= 0) || !inv.SpawnState.ValidateSpriteFrame() || (inv is 'Key') || (inv is 'BasicArmor') || (inv is 'HexenArmor') || (inv is 'Powerup') || (inv is 'SWWMArmor') || (!(inv is 'Ammo') && !(inv is 'Weapon') && !inv.bINVBAR) && !(inv is 'HammerspaceEmbiggener') && !(inv is 'SWWMCollectable') && !(inv is 'MagAmmo') ) continue;
if ( (inv.Amount <= 0) || !inv.SpawnState.ValidateSpriteFrame() || (inv is 'Key') || (inv is 'BasicArmor') || (inv is 'HexenArmor') || (inv is 'Powerup') || (inv is 'SWWMArmor') || (!(inv is 'Ammo') && !(inv is 'Weapon') && !inv.bINVBAR) && !(inv is 'HammerspaceEmbiggener') && !(inv is 'SWWMCollectible') && !(inv is 'MagAmmo') ) continue;
// no hidden weapons
if ( (inv is 'SWWMWeapon') && SWWMWeapon(inv).bHIDEINMENU ) continue;
String tag = inv.GetTag();
@ -2212,9 +2227,19 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
if ( w )
{
// play if actually switching
if ( hnd.checklist[j].result ) MenuSound(GetDefaultByType(w).UpSound);
if ( hnd.checklist[j].result )
{
// gz 4.5pre workaround (expects a Name now)
String snd = GetDefaultByType(w).UpSound;
MenuSound(snd);
}
}
else
{
// gz 4.5pre workaround (expects a Name now)
String snd = GetDefaultByType(hnd.checklist[j].used).UseSound;
MenuSound(snd);
}
else MenuSound(GetDefaultByType(hnd.checklist[j].used).UseSound);
}
}
else
@ -2390,8 +2415,8 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
static const string tabnames[] =
{
"$SWWM_MISSTAB", "$SWWM_STATTAB", "$SWWM_INVTAB", "$SWWM_KEYTAB",
"$SWWM_KBASETAB", "$SWWM_STORETAB", "$SWWM_RADIOTAB", "$SWWM_GAMETAB",
"$SWWM_TRADETAB", "$SWWM_CHATTAB", "$SWWM_SECRETTAB", "$SWWM_HELPTAB"
"$SWWM_KBASETAB", "$SWWM_STORETAB", "$SWWM_GAMETAB", "$SWWM_TRADETAB",
"$SWWM_CHATTAB", "$SWWM_SECRETTAB", "$SWWM_HELPTAB"
};
static const string ltabnames[] =
{
@ -2403,7 +2428,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
};
int maxtab = multiplayer?TAB_CHAT:TAB_GAME;
int mx = maxtab;
if ( (curtab > TAB_CHAT) ) mx++;
if ( curtab > TAB_CHAT ) mx++;
for ( int i=0; i<=mx; i++ )
{
str = StringTable.Localize(tabnames[(i>maxtab)?curtab:i]);
@ -2656,7 +2681,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
else if ( (invlist[i] is 'Health') || (invlist[i] is 'HealthPickup') || (invlist[i] is 'SWWMHealth') ) clscol = Font.CR_RED;
else if ( (invlist[i] is 'Armor') || (invlist[i] is 'SWWMSpareArmor') ) clscol = Font.CR_GREEN;
else if ( invlist[i] is 'PuzzleItem' ) clscol = Font.CR_LIGHTBLUE;
else if ( invlist[i] is 'SWWMCollectable' ) clscol = Font.CR_FIRE;
else if ( invlist[i] is 'SWWMCollectible' ) clscol = Font.CR_FIRE;
Screen.DrawText(fnt,clscol,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,(i!=sel0)?Color(96,0,0,0):Color(0,0,0,0));
yy += 16;
if ( yy >= 370 )
@ -2692,7 +2717,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
{
if ( !invlist[i] ) continue;
str = invlist[i].GetTag();
if ( invlist[i] is 'SWWMCollectable' )
if ( invlist[i] is 'SWWMCollectible' )
str.AppendFormat(" (¥%d)",invlist[i].default.Stamina);
len = fnt.StringWidth(str);
if ( len > longest ) longest = len;
@ -2704,9 +2729,9 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
{
if ( !invlist[i] ) continue;
str = invlist[i].GetTag();
if ( invlist[i] is 'SWWMCollectable' )
if ( invlist[i] is 'SWWMCollectible' )
str.AppendFormat(" \cj(\cg¥\cf%d\cj)\c-",invlist[i].default.Stamina);
Screen.DrawText(fnt,(invlist[i] is 'SWWMCollectable')?Font.CR_PURPLE:Font.CR_UNTRANSLATED,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,(i!=sel0)?Color(96,0,0,0):Color(0,0,0,0));
Screen.DrawText(fnt,(invlist[i] is 'SWWMCollectible')?Font.CR_PURPLE:Font.CR_UNTRANSLATED,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,(i!=sel0)?Color(96,0,0,0):Color(0,0,0,0));
yy += 16;
if ( yy >= 370 )
{
@ -2883,11 +2908,6 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
Screen.DrawTexture(WindowSeparatorH,false,origin.x,origin.y+377,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
}
}
else if ( curtab == TAB_RADIO )
{
str = StringTable.Localize("$SWWM_COMINGSOON");
Screen.DrawText(fnt,Font.CR_FIRE,(ss.x-fnt.StringWidth(str))/2.,(ss.y-fnt.GetHeight())/2.,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
}
else if ( curtab == TAB_GAME )
{
str = StringTable.Localize("$SWWM_COMINGSOON");

View file

@ -182,6 +182,7 @@ Class SWWMOptionMenu : OptionMenu
}
}
// main menu w/ version info
Class SWWMMainMenu : ListMenu
{
transient Font TewiFont;
@ -200,3 +201,272 @@ Class SWWMMainMenu : ListMenu
Screen.DrawText(TewiFont,Font.CR_GOLD,(xx+4)*CleanXFac_1,(yy+2)*CleanYFac_1,str,DTA_CleanNoMove_1,true);
}
}
// scaled SWWM GZ logo
class ListMenuItemSWWMLogo : ListMenuItem
{
TextureID mTexture;
void Init( ListMenuDescriptor desc, TextureID patch )
{
Super.Init(desc.mXpos,desc.mYpos);
mTexture = patch;
}
// the old way
override void Drawer( bool selected )
{
if ( !mTexture.Exists() )
return;
Vector2 vs = TexMan.GetScaledSize(mTexture);
double x = (320-vs.x)/2;
Screen.DrawTexture(mTexture,false,x,-48,DTA_Clean,true);
}
// FIXME The 4.5+ way - swap out for this once it's done
/*override void Draw( bool selected, ListMenuDescriptor desc )
{
if ( !mTexture.Exists() )
return;
int w = desc?desc.DisplayWidth():ListMenuDescriptor.CleanScale;
int h = desc?desc.DisplayHeight():-1;
Vector2 vs = TexMan.GetScaledSize(mTexture);
double x;
if ( w == ListMenuDescriptor.CleanScale )
{
x = (320-vs.x)/2;
Screen.DrawTexture(mTexture,false,x,-48,DTA_Clean,true);
}
else
{
x = (w-vs.x)/2;
Screen.DrawTexture(mTexture,false,x,-48,DTA_VirtualWidth,w,DTA_VirtualHeight,h,DTA_FullscreenScale,FSMode_ScaleToFit43);
}
}*/
}
// message box that enforces newsmallfont and changes text color to match menus
Class SWWMMessageBox : MessageBoxMenu
{
override void Init( Menu parent, String message, int messagemode, bool playsound, Name cmd, voidptr native_handler )
{
Super.Init(parent,message,messagemode,playsound,cmd,native_handler);
textFont = arrowFont = newsmallfont;
destWidth = CleanWidth;
destHeight = CleanHeight;
selector = "▶";
int mr1 = 170+textFont.StringWidth(Stringtable.Localize("$TXT_YES"));
int mr2 = 170+textFont.StringWidth(Stringtable.Localize("$TXT_NO"));
mMouseRight = max(mr1,mr2);
mMessage = textFont.BreakLines(Stringtable.Localize(message), 300);
}
override void Drawer()
{
int fontheight = textFont.GetHeight();
int y = 100;
int c = mMessage.Count();
y -= c*fontHeight/2;
for ( int i=0; i<c; i++ )
{
Screen.DrawText(textFont,OptionMenuSettings.mFontColorValue,160-mMessage.StringWidth(i)/2,y, mMessage.StringAt(i),DTA_Clean,true);
y += fontheight;
}
if ( mMessageMode != 0 ) return;
y += fontheight;
mMouseY = y;
Screen.DrawText(textFont,messageSelection==0?OptionMenuSettings.mFontColorSelection:OptionMenuSettings.mFontColor,160,y,Stringtable.Localize("$TXT_YES"),DTA_Clean,true);
Screen.DrawText(textFont,messageSelection==1?OptionMenuSettings.mFontColorSelection:OptionMenuSettings.mFontColor,160,y+fontheight+1,Stringtable.Localize("$TXT_NO"),DTA_Clean,true);
if ( messageSelection < 0 ) return;
if ( (MenuTime()%8) < 6 )
Screen.DrawText(arrowFont,OptionMenuSettings.mFontColorSelection,(150-160)*CleanXfac+Screen.GetWidth()/2,(y+(fontheight+1)*messageSelection-100+fontheight/2-5)*CleanYfac+Screen.GetHeight()/2,selector,DTA_CellX,8*CleanXfac,DTA_CellY,8*CleanYfac);
}
// FIXME the 4.5+ way - swap out for this once it's done
/*override void Init( Menu parent, String message, int messagemode, bool playsound, Name cmd, voidptr native_handler )
{
Super.Init(parent,message,messagemode,playsound,cmd,native_handler);
textFont = arrowFont = newsmallfont;
destWidth = CleanWidth;
destHeight = CleanHeight;
selector = "▸";
int mr1 = destWidth/2+10+textFont.StringWidth(Stringtable.Localize("$TXT_YES"));
int mr2 = destWidth/2+10+textFont.StringWidth(Stringtable.Localize("$TXT_NO"));
mMouseRight = max(mr1,mr2);
mMessage = textFont.BreakLines(Stringtable.Localize(message),int(300/NotifyFontScale));
}
override void Drawer()
{
let fontheight = textFont.GetHeight()*NotifyFontScale;
double y = destHeight/2;
int c = mMessage.Count();
y -= c*fontHeight/2;
for ( int i=0; i<c; i++ )
{
Screen.DrawText(textFont,OptionMenuSettings.mFontColorValue,destWidth/2-mMessage.StringWidth(i)*NotifyFontScale/2,y,mMessage.StringAt(i),DTA_VirtualWidth,destWidth, DTA_VirtualHeight,destHeight,DTA_KeepRatio,true,DTA_ScaleX,NotifyFontScale,DTA_ScaleY,NotifyFontScale);
y += fontheight;
}
if ( mMessageMode != 0 ) return;
y += fontheight;
mMouseY = int(y);
Screen.DrawText(textFont,messageSelection==0?OptionMenuSettings.mFontColorSelection:OptionMenuSettings.mFontColor,destWidth/2,y,Stringtable.Localize("$TXT_YES"), DTA_VirtualWidth,destWidth,DTA_VirtualHeight,destHeight,DTA_KeepRatio,true,DTA_ScaleX,NotifyFontScale,DTA_ScaleY,NotifyFontScale);
Screen.DrawText(textFont,messageSelection==1?OptionMenuSettings.mFontColorSelection:OptionMenuSettings.mFontColor,destWidth/2,y+fontheight, Stringtable.Localize("$TXT_NO"),DTA_VirtualWidth,destWidth,DTA_VirtualHeight,destHeight,DTA_KeepRatio,true,DTA_ScaleX,NotifyFontScale,DTA_ScaleY,NotifyFontScale);
if ( messageSelection < 0 ) return;
if ( (MenuTime()%8) < 6 )
Screen.DrawText(arrowFont,OptionMenuSettings.mFontColorSelection,destWidth/2-11,y+fontheight*messageSelection,selector,DTA_VirtualWidth,destWidth, DTA_VirtualHeight,destHeight,DTA_KeepRatio,true);
}*/
}
// main menu item with wiggly text when selected and Demo face selectors on both sides
class ListMenuItemSWWMTextItemM : ListMenuItemSelectable
{
String mText;
Font mFont;
void Init( ListMenuDescriptor desc, String text, String hotkey, Name child, int param = 0 )
{
Super.Init(desc.mXpos,desc.mYpos,desc.mLinespacing,child,param);
mText = text;
mFont = desc.mFont;
mHotkey = hotkey.GetNextCodePoint(0);
}
override int GetWidth()
{
return max(1,mFont.StringWidth(StringTable.Localize(mText)));
}
override void Drawer( bool selected )
{
String text = StringTable.Localize(mText);
// centered
double x = (320-mFont.StringWidth(text))/2;
double y = mYPos-12; // text needs to be offset up for some reason, otherwise doesn't match mouse selection bounds
if ( selected )
{
double xx = x;
int tlen = text.CodePointCount();
for ( int i=0, pos=0; i<tlen; i++ )
{
int ch;
[ch, pos] = text.GetNextCodePoint(pos);
double yy = y+4*sin(32*i+8*Menu.MenuTime());
Screen.DrawChar(mFont,Font.CR_SAPPHIRE,xx,yy,ch,DTA_Clean,true);
xx += mFont.GetCharWidth(ch)-2; // account for menu font kerning
}
}
else Screen.DrawText(mFont,Font.CR_WHITE,x,y,text,DTA_Clean,true);
}
override void DrawSelector( double xofs, double yofs, TextureID tex )
{
if ( tex.isNull() ) return;
double x = (320-GetWidth())/2;
Screen.DrawTexture(tex,true,x+xofs,mYpos+yofs,DTA_Clean,true,DTA_CenterOffset,true);
x = (320+GetWidth())/2;
Screen.DrawTexture(tex,true,x-xofs,mYpos+yofs,DTA_Clean,true,DTA_CenterOffset,true);
}
// FIXME The 4.5+ way - swap out for this once it's done
/*override void Draw( bool selected, ListMenuDescriptor desc )
{
int w = desc?desc.DisplayWidth():ListMenuDescriptor.CleanScale;
int h = desc?desc.DisplayHeight():-1;
String text = StringTable.Localize(mText);
double x;
// centered
if ( w == ListMenuDescriptor.CleanScale ) x = (320-mFont.StringWidth(text))/2;
else x = (w-mFont.StringWidth(text))/2;
double y = mYPos-12; // text needs to be offset up for some reason, otherwise doesn't match mouse selection bounds
if ( selected )
{
double xx = x;
int tlen = text.CodePointCount();
if ( w == ListMenuDescriptor.CleanScale )
{
for ( int i=0, pos=0; i<tlen; i++ )
{
int ch;
[ch, pos] = text.GetNextCodePoint(pos);
double yy = y+4*sin(32*i+8*Menu.MenuTime());
Screen.DrawChar(mFont,Font.CR_SAPPHIRE,xx,yy,ch,DTA_Clean,true);
xx += mFont.GetCharWidth(ch)-2; // account for menu font kerning
}
}
else
{
for ( int i=0, pos=0; i<tlen; i++ )
{
int ch;
[ch, pos] = text.GetNextCodePoint(pos);
double yy = y+4*sin(32*i+8*Menu.MenuTime());
Screen.DrawChar(mFont,Font.CR_SAPPHIRE,xx,yy,ch,DTA_VirtualWidth,w,DTA_VirtualHeight,h,DTA_FullscreenScale,FSMode_ScaleToFit43);
xx += mFont.GetCharWidth(ch)-2; // account for menu font kerning
}
}
}
else
{
if ( w == ListMenuDescriptor.CleanScale )
Screen.DrawText(mFont,Font.CR_WHITE,x,y,text,DTA_Clean,true);
else
Screen.DrawText(mFont,Font.CR_WHITE,x,y,text,DTA_VirtualWidth,w,DTA_VirtualHeight,h,DTA_FullscreenScale,FSMode_ScaleToFit43);
}
}
override void DrawSelector( double xofs, double yofs, TextureID tex, ListMenuDescriptor desc )
{
if ( tex.isNull() ) return;
int w = desc?desc.DisplayWidth():ListMenuDescriptor.CleanScale;
int h = desc?desc.DisplayHeight():-1;
if ( w == ListMenuDescriptor.CleanScale )
{
double x = (320-GetWidth())/2;
Screen.DrawTexture(tex,true,x+xofs,mYpos+yofs,DTA_Clean,true,DTA_CenterOffset,true,DTA_Rotate,15.*sin(8*Menu.MenuTime()));
x = (320+GetWidth())/2;
Screen.DrawTexture(tex,true,x-xofs,mYpos+yofs,DTA_Clean,true,DTA_CenterOffset,true,DTA_Rotate,-15.*sin(8*Menu.MenuTime()));
}
else
{
double x = (w-GetWidth())/2;
Screen.DrawTexture(tex,true,x+xofs,mYpos+yofs,DTA_VirtualWidth,w,DTA_VirtualHeight,h,DTA_FullscreenScale,FSMode_ScaleToFit43,DTA_CenterOffset,true,DTA_Rotate,15.*sin(8*Menu.MenuTime()));
x = (w+GetWidth())/2;
Screen.DrawTexture(tex,true,x-xofs,mYpos+yofs,DTA_VirtualWidth,w,DTA_VirtualHeight,h,DTA_FullscreenScale,FSMode_ScaleToFit43,DTA_CenterOffset,true,DTA_Rotate,-15.*sin(8*Menu.MenuTime()));
}
}*/
}
// FIXME uncomment this once it's supported
/*Class SWWMMenuDelegate : DoomMenuDelegate
{
transient CVar lang;
transient Font TewiFont, MPlusFont, SWWMBigFont;
override int DrawCaption( String title, Font fnt, int y, bool drawit )
{
// forcibly use our bigfont here
// somehow it doesn't get overriden when using PickFont()
// most likely because of pointer poopery
// could we get a function for fetching a font's name, graf?
if ( !SWWMBigFont ) SWWMBigFont = Font.GetFont('SWWMBigFont');
return Super.DrawCaption(title,SWWMBigFont,y,drawit);
}
// this doesn't seem to always work?
override Font PickFont( Font fnt )
{
if ( !lang ) lang = CVar.GetCVar('language',players[consoleplayer]);
if ( !TewiFont ) TewiFont = Font.GetFont('TewiShaded');
if ( !MPlusFont ) MPlusFont = Font.GetFont('MPlusShaded');
if ( !SWWMBigFont ) SWWMBigFont = Font.GetFont('SWWMBigFont');
if ( (fnt == SmallFont) || (fnt == SmallFont2) || (fnt == AlternativeSmallFont) || (fnt == NewSmallFont) || !fnt )
{
if ( lang.GetString() ~== "jp" ) return MPlusFont;
return TewiFont;
}
if ( (fnt == BigFont) || (fnt == AlternativeBigFont) || (fnt == OriginalBigFont) || (fnt == IntermissionFont) ) return SWWMBigFont;
return fnt;
}
}*/

View file

@ -59,6 +59,7 @@ Class Demolitionist : PlayerPawn
int itemsense_cnt;
int healcooldown, healtimer, oldhealth;
bool scriptedinvul;
Property DashFuel : dashfuel;
@ -274,12 +275,12 @@ Class Demolitionist : PlayerPawn
}
if ( !giveall ) return;
}
if ( (giveall == ALL_YESYES) || (name ~== "collectables") )
if ( (giveall == ALL_YESYES) || (name ~== "collectibles") )
{
for ( int i=0; i<AllActorClasses.Size(); i++ )
{
let type = (class<SWWMCollectable>)(AllActorClasses[i]);
if ( !type || (type == 'SWWMCollectable') ) continue;
let type = (class<SWWMCollectible>)(AllActorClasses[i]);
if ( !type || (type == 'SWWMCollectible') ) continue;
let def = GetDefaultByType(type);
// check that we can collect it in this IWAD
if ( !(gameinfo.gametype&def.avail) ) continue;
@ -320,11 +321,17 @@ Class Demolitionist : PlayerPawn
override void ClearInventory()
{
Super.ClearInventory();
// reset score (optional)
if ( swwm_resetscore )
// remove some specific "undroppable" items
Actor last = self;
while ( last.inv )
{
let creds = SWWMCredits.Find(player);
if ( creds ) creds.credits = creds.hcredits = 0;
let i = last.inv;
if ( (i is 'SWWMArmor') || (i is 'HammerspaceEmbiggener') )
{
i.DepleteOrDestroy();
if ( !i.bDestroyed ) last = i;
}
else last = i;
}
}
override void PostBeginPlay()
@ -451,7 +458,7 @@ Class Demolitionist : PlayerPawn
A_StopSound(CHAN_AMBEXTRA);
if ( curunder > UNDER_NONE )
{
A_StartSound(undersnd[curunder],CHAN_AMBEXTRA,CHANF_LOOPING|CHANF_UI);
A_StartSound(undersnd[curunder],CHAN_AMBEXTRA,CHANF_LOOP|CHANF_UI);
if ( !restore && (players[consoleplayer].Camera == self) )
A_StartSound(entersnd[curunder],CHAN_FOOTSTEP,CHANF_OVERLAP|CHANF_UI);
}
@ -977,6 +984,9 @@ Class Demolitionist : PlayerPawn
}
override int DamageMobj( Actor inflictor, Actor source, int damage, Name mod, int flags, double angle )
{
// no damage whatsoever
if ( scriptedinvul )
return 0;
// completely nullify non-lethal fall damage
if ( (mod == 'Falling') && (damage < TELEFRAG_DAMAGE) )
damage = 0;
@ -1836,6 +1846,8 @@ Class Demolitionist : PlayerPawn
{
if ( !player ) return false;
bool rslt = max(abs(player.cmd.forwardmove),abs(player.cmd.sidemove))>6400;
// FIXME easier method - uncomment on new GZDoom release
// bool rslt = player.cmd.buttons&BT_RUN;
if ( notfast ) rslt = !rslt;
return rslt;
}
@ -1903,8 +1915,8 @@ Class Demolitionist : PlayerPawn
// we need the crouch button state to be preserved for other functions
if ( wascrouching ) player.cmd.buttons |= BT_CROUCH;
}
/* // requires PR #1169
override void Travelled()
// FIXME requires PR #1169 - uncomment on next GZDoom release
/*override void Travelled()
{
// reinitialize
dashfuel = default.dashfuel;
@ -1924,10 +1936,9 @@ Class Demolitionist : PlayerPawn
player.PendingWeapon = SWWMGesture(player.ReadyWeapon).formerweapon;
player.SetPSprite(PSP_WEAPON,player.ReadyWeapon.ResolveState("Deselect"));
}
}
*/
/* // requires PR #1173
override bool PreTeleport( Vector3 destpos, double destangle, int flags )
}*/
// FIXME requires PR #1173 - uncomment on next GZDoom release
/*override bool PreTeleport( Vector3 destpos, double destangle, int flags )
{
// store old pos
pretelepos = pos;
@ -1957,8 +1968,7 @@ Class Demolitionist : PlayerPawn
let l = SWWMLamp(FindInventory("SWWMLamp"));
if ( l && l.thelamp )
CompanionLamp(l.thelamp).justteleport = true;
}
*/
}*/
States
{
Spawn:
@ -2096,6 +2106,40 @@ Class Demolitionist : PlayerPawn
#### # 3;
XZWD EFGHIJKLMNOPQRSTUVW 3;
Goto Spawn+1;
Headpat:
#### # 3;
XZWH ST 3;
XZWH UVW 2;
XZWH XYZ 1;
XZWI A 1;
XZWI BCDE 2;
XZWI FGH 1;
XZWH XYZ 1;
XZWI A 1;
XZWI BCDE 2;
XZWI FGH 1;
XZWI IJK 2;
XZWI LMNO 3;
Goto Spawn+1;
Ragepat:
#### # 3;
XZWH ST 2;
XZWH UVW 1;
XZWH XZ 1;
XZWI BCDE 1;
XZWI FH 1;
XZWH XZ 1;
XZWI BCDE 1;
XZWI FH 1;
XZWH XZ 1;
XZWI BCDE 1;
XZWI FH 1;
XZWH XZ 1;
XZWI BCDE 1;
XZWI FH 1;
XZWI IJK 1;
XZWI LMNO 2;
Goto Spawn+1;
Missile:
// attacking
#### # 2;
@ -2767,6 +2811,11 @@ Class LoveHeart : Actor
if ( target is 'MBFHelperDog' )
{
// befriend good doggo
if ( target.bCOUNTKILL )
{
target.bCOUNTKILL = false;
level.total_monsters--;
}
target.bFRIENDLY = true;
if ( deathmatch )
target.SetFriendPlayer(self.target.player);
@ -2789,7 +2838,14 @@ Class LoveHeart : Actor
bNOEXTREMEDEATH = false;
}
else if ( target is 'SWWMHangingKeen' )
damage = max(target.Health,damage); // rescued by love :3
else if ( SWWMHDoomHandler.IsCuteGirl(target) )
{
// no cute demon girl can resist demo's charm
damage = max(target.Health,damage);
bEXTREMEDEATH = false;
bNOEXTREMEDEATH = true;
}
return damage;
}
@ -2845,7 +2901,9 @@ Class LoveHeart : Actor
if ( BlockingLine )
{
int s = SWWMUtility.PointOnLineSide(pos.xy,BlockingLine);
BlockingLine.RemoteActivate(target,s,SPAC_Use,pos);
int locknum = SWWMUtility.GetLineLock(BlockingLine);
if ( !locknum || (target && target.CheckKeys(locknum,false,true)) )
BlockingLine.RemoteActivate(target,s,SPAC_Use,pos);
}
if ( swwm_omnibust )
{
@ -2899,6 +2957,81 @@ Class LoveHeart : Actor
}
}
Class HeadpatTracker : Actor
{
State patstate; // state the target will jump to on headpat
// if null, will simply resume current state
State deathstate; // if the actor enters this state, we can't headpat no more
int oldtargettics; // previous tics left in target's pre-pat state
bool patting; // currently in pat
Actor patter; // who's patting
double hdoomheightfix; // certain hdoom monsters kneel down, so their heads are lower than expected
double hdoomangfix; // fix for imp in a chair
bool lethalpat; // ending headpat immediately drops enemy health to 0
default
{
+NOGRAVITY;
+NOTELEPORT;
+DONTSPLASH;
}
override void Tick()
{
if ( !target || (target.Health <= 0) || (deathstate && target.InStateSequence(target.CurState,deathstate)) )
{
Destroy();
return;
}
if ( patting )
{
// keep bolted in here
target.vel *= 0;
patter.vel *= 0;
patter.player.vel *= 0;
target.SetOrigin(pos,true);
// keep aim
double delta = deltaangle(target.angle,target.AngleTo(patter));
if ( abs(delta) < 1. ) target.angle = target.AngleTo(patter);
else target.angle += .3*delta;
delta = deltaangle(patter.angle,patter.AngleTo(target)+hdoomangfix);
if ( abs(delta) < 1. ) patter.A_SetAngle(patter.AngleTo(target)+hdoomangfix,SPF_INTERPOLATE);
else patter.A_SetAngle(patter.angle+.3*delta,SPF_INTERPOLATE);
double hfact = 1.2-hdoomheightfix;
delta = deltaangle(patter.pitch,SWWMUtility.PitchTo(patter,target,hfact));
if ( abs(delta) < 1. ) patter.A_SetPitch(SWWMUtility.PitchTo(patter,target,hfact),SPF_INTERPOLATE);
else patter.A_SetPitch(patter.pitch+.3*delta,SPF_INTERPOLATE);
return;
}
A_SetSize(target.radius+8,target.height+8);
SetOrigin(target.pos,false);
}
override bool Used( Actor user )
{
if ( !target ) return false;
if ( patting ) return false; // already on it
if ( user.player.crouchdir == -1 ) return false; // need to be standing up
if ( !user.player.onground ) return false; // need to be on solid ground
// check use range
Vector3 diff = level.Vec3Diff(user.pos,target.pos);
if ( (diff.z < -target.height*.5) || (diff.z > user.height*.5) ) return false;
if ( user is 'Demolitionist' )
{
patter = user;
let g = SWWMGesture.SetGesture(Demolitionist(patter),-2);
if ( !g ) return false; // can't headpat at the moment
patting = true;
g.pats = self;
oldtargettics = target.tics;
target.tics = -1;
patter.player.cheats |= CF_TOTALLYFROZEN;
Demolitionist(patter).scriptedinvul = true;
target.bDORMANT = true;
return true;
}
return false;
}
}
Class HHitList
{
Actor a;
@ -2911,7 +3044,9 @@ Class SWWMGesture : SWWMWeapon
Weapon formerweapon;
int whichgesture, nextgesture;
bool deaded, queued;
Array<int> squeue;
int gonect;
HeadpatTracker pats; // for headpat gesture, our current tracker
// these should prevent autoswitch when out of ammo
override bool ReportHUDAmmo()
@ -2923,21 +3058,25 @@ Class SWWMGesture : SWWMWeapon
return false;
}
static void SetGesture( PlayerPawn mo, int which = 0 )
static SWWMGesture SetGesture( PlayerPawn mo, int which = 0 )
{
if ( mo.player.PendingWeapon is 'SWWMGesture' ) return; // already initiating a gesture
if ( (mo.player.ReadyWeapon is 'SWWMGesture') )
if ( !mo || !(mo is 'Demolitionist') ) return null; // only Demo
if ( mo.Health <= 0 ) return null; // dead
if ( mo.player.cheats&CF_TOTALLYFROZEN ) return null; // frozen today
if ( mo.player.PendingWeapon is 'SWWMGesture' ) return null; // already initiating a gesture
if ( mo.player.ReadyWeapon is 'SWWMGesture' )
{
// already gesturing
// just queue another one
// (ignore grenade, that one uses special refire handling)
if ( which != -1 )
let g = SWWMGesture(mo.player.ReadyWeapon);
if ( which <= -100 ) g.squeue.Push(which); // collectable gestures have a dedicated array
if ( which <= -1 ) return null; // special gestures can't be queued
else
{
let g = SWWMGesture(mo.player.ReadyWeapon);
g.nextgesture = which;
g.queued = true;
}
return;
return null;
}
SWWMGesture w = SWWMGesture(mo.FindInventory("SWWMGesture"));
if ( !w )
@ -2949,6 +3088,7 @@ Class SWWMGesture : SWWMWeapon
else w.formerweapon = mo.player.ReadyWeapon;
w.whichgesture = which;
mo.player.PendingWeapon = w;
return w;
}
action void A_CallPlayerGesture( statelabel st, statelabel cst )
@ -2962,6 +3102,13 @@ Class SWWMGesture : SWWMWeapon
action void A_FinishGesture()
{
if ( invoker.squeue.Size() > 0 )
{
invoker.whichgesture = invoker.squeue[0];
invoker.squeue.Delete(0); // push back
player.SetPSprite(PSP_WEAPON,ResolveState("Ready"));
return;
}
if ( invoker.queued )
{
invoker.whichgesture = invoker.nextgesture;
@ -2973,6 +3120,75 @@ Class SWWMGesture : SWWMWeapon
player.SetPSprite(PSP_WEAPON,ResolveState("Deselect"));
}
action void A_Headpat()
{
A_StartSound("demolitionist/petting",CHAN_WEAPON,CHANF_OVERLAP,.4);
let pt = invoker.pats;
if ( !pt ) return;
int numpt = Random[ExploS](6,9);
Vector3 dir = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
Vector3 patpos = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz-4),dir*30.);
for ( int i=0; i<numpt; i++ )
{
let s = Spawn("LoveHeartSparkle",patpos);
s.angle = FRandom[ExploS](0,360);
s.pitch = FRandom[ExploS](-90,90);
}
if ( pt.target && pt.target.bSHOOTABLE )
{
int healamt = 10;
let raging = RagekitPower(FindInventory("RagekitPower"));
if ( raging )
{
healamt *= 8;
raging.DoHitFX();
}
if ( pt.target.GiveBody(healamt,pt.target.GetSpawnHealth()) )
{
SWWMScoreObj.Spawn(healamt,pt.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+target.Height/2),Font.CR_BLUE);
SWWMHandler.DoFlash(pt.target,Color(32,224,128,255),10);
}
}
}
action void A_HeadpatEnd()
{
player.cheats &= ~CF_TOTALLYFROZEN;
Demolitionist(player.mo).scriptedinvul = false;
let pt = invoker.pats;
if ( !pt ) return;
pt.patting = false;
let t = pt.target;
if ( t )
{
if ( pt.patstate ) t.SetState(pt.patstate);
else t.tics = pt.oldtargettics;
t.bDORMANT = false;
if ( t.bISMONSTER )
{
if ( pt.lethalpat )
{
t.DamageMobj(invoker,self,t.Health,'Love',DMG_FORCED|DMG_THRUSTLESS);
pt.Destroy();
return;
}
// befriend
if ( t.bCOUNTKILL )
{
t.bCOUNTKILL = false;
level.total_monsters--;
}
t.bFRIENDLY = true;
if ( deathmatch )
t.SetFriendPlayer(player);
// cancel any attacks
if ( t.InStateSequence(t.CurState,t.FindState("Missile"))
|| t.InStateSequence(t.CurState,t.FindState("Melee")) )
t.SetState(t.FindState("See"));
}
}
}
action void A_ThrowMag()
{
let weap = Weapon(invoker);
@ -3058,6 +3274,7 @@ Class SWWMGesture : SWWMWeapon
Default
{
+WEAPON.CHEATNOTWEAPON;
+WEAPON.NO_AUTO_SWITCH;
+WEAPON.WIMPY_WEAPON;
+SWWMWEAPON.HIDEINMENU;
+INVENTORY.UNDROPPABLE;
@ -3079,6 +3296,8 @@ Class SWWMGesture : SWWMWeapon
{
switch ( invoker.whichgesture )
{
case -2:
return ResolveState("Headpat");
case -1:
return ResolveState("QuickGrenade");
case 1:
@ -3094,6 +3313,57 @@ Class SWWMGesture : SWWMWeapon
Fire:
TNT1 A 1;
Goto Ready;
Headpat:
TNT1 A 0 A_JumpIf(CountInv("RagekitPower"),"Ragepat");
TNT1 A 3 A_CallPlayerGesture("Headpat","Headpat");
XZW4 NO 3;
XZW4 P 2 A_StartSound("demolitionist/handsup",CHAN_WEAPON,CHANF_OVERLAP);
XZW4 QR 2;
XZW4 STUV 1;
XZW4 W 2;
XZW4 X 2 A_Headpat();
XZW4 YZ 2;
XZW5 ABC 1;
XZW4 STUV 1;
XZW4 W 2;
XZW4 X 2 A_Headpat();
XZW4 YZ 2;
XZW5 ABC 1;
XZW5 DE 2;
XZW5 F 2 A_StartSound("demolitionist/handsdown",CHAN_WEAPON,CHANF_OVERLAP);
XZW5 GHIJ 3;
TNT1 A 4 A_HeadpatEnd();
TNT1 A -1 A_FinishGesture();
Ragepat:
TNT1 A 3 A_CallPlayerGesture("Ragepat","Ragepat");
XZW4 NO 2;
XZW4 P 1 A_StartSound("demolitionist/handsup",CHAN_WEAPON,CHANF_OVERLAP);
XZW4 QR 1;
XZW4 SU 1;
XZW4 W 1;
XZW4 X 1 A_Headpat();
XZW4 YZ 1;
XZW5 AC 1;
XZW4 SU 1;
XZW4 W 1;
XZW4 X 1 A_Headpat();
XZW4 YZ 1;
XZW5 AC 1;
XZW4 SU 1;
XZW4 W 1;
XZW4 X 1 A_Headpat();
XZW4 YZ 1;
XZW5 AC 1;
XZW4 SU 1;
XZW4 W 1;
XZW4 X 1 A_Headpat();
XZW4 YZ 1;
XZW5 AC 1;
XZW5 DE 1;
XZW5 F 1 A_StartSound("demolitionist/handsdown",CHAN_WEAPON,CHANF_OVERLAP);
XZW5 GHIJ 2;
TNT1 A 4 A_HeadpatEnd();
TNT1 A -1 A_FinishGesture();
QuickGrenade:
TNT1 A 3;
XZW3 S 3 A_StartSound("demolitionist/handsup",CHAN_WEAPON,CHANF_OVERLAP);

View file

@ -17,6 +17,7 @@ Class GrilledCheeseSandwich : Inventory
{
Mixin SWWMAutoUseFix;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
// for falling off cliffs and others
// last 5 seconds of safe positions
@ -186,6 +187,7 @@ Class GrilledCheeseSandwich : Inventory
Inventory.PickupMessage "$T_SANDWICH";
Inventory.MaxAmount 5;
Inventory.InterHubAmount 5;
Inventory.PickupFlash "SWWMPickupFlash";
+INVENTORY.ALWAYSPICKUP;
+INVENTORY.AUTOACTIVATE;
+INVENTORY.INVBAR;
@ -193,6 +195,8 @@ Class GrilledCheeseSandwich : Inventory
+INVENTORY.BIGPOWERUP;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 12;
Height 24;
}
States
@ -233,8 +237,8 @@ Class GhostSnd : Actor
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_StartSound("powerup/ghostact",CHAN_VOICE,CHANF_LOOPING,.1,1.5);
A_StartSound("powerup/ghostact",CHAN_7,CHANF_LOOPING,.4,ATTN_NONE);
A_StartSound("powerup/ghostact",CHAN_VOICE,CHANF_LOOP,.1,1.5);
A_StartSound("powerup/ghostact",CHAN_7,CHANF_LOOP,.4,ATTN_NONE);
}
override void OnDestroy()
{
@ -332,6 +336,7 @@ Class GhostArtifact : Inventory
{
Mixin SWWMAutoUseFix;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Default
{
@ -343,6 +348,7 @@ Class GhostArtifact : Inventory
Inventory.PickupMessage "$T_GHOSTARTI";
Inventory.MaxAmount 5;
Inventory.InterHubAmount 5;
Inventory.PickupFlash "SWWMPickupFlash";
+INVENTORY.ALWAYSPICKUP;
+INVENTORY.AUTOACTIVATE;
+INVENTORY.INVBAR;
@ -350,6 +356,8 @@ Class GhostArtifact : Inventory
+INVENTORY.BIGPOWERUP;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 12;
Height 24;
}
override bool Use( bool pickup )
@ -409,8 +417,8 @@ Class GravSnd : Actor
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_StartSound("powerup/gravityact",CHAN_VOICE,CHANF_LOOPING,.2,1.5);
A_StartSound("powerup/gravityact",CHAN_7,CHANF_LOOPING,.7,ATTN_NONE);
A_StartSound("powerup/gravityact",CHAN_VOICE,CHANF_LOOP,.2,1.5);
A_StartSound("powerup/gravityact",CHAN_7,CHANF_LOOP,.7,ATTN_NONE);
}
override void OnDestroy()
{
@ -478,6 +486,7 @@ Class GravitySuppressor : Inventory
{
Mixin SWWMAutoUseFix;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
override bool Use( bool pickup )
{
@ -507,6 +516,7 @@ Class GravitySuppressor : Inventory
Inventory.PickupMessage "$T_GRAVITYS";
Inventory.MaxAmount 5;
Inventory.InterHubAmount 5;
Inventory.PickupFlash "SWWMPickupFlash";
+INVENTORY.ALWAYSPICKUP;
+INVENTORY.AUTOACTIVATE;
+INVENTORY.INVBAR;
@ -514,6 +524,8 @@ Class GravitySuppressor : Inventory
+INVENTORY.BIGPOWERUP;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 12;
Height 28;
}
States
{
@ -574,8 +586,8 @@ Class InvinciSnd : Actor
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_StartSound("powerup/invinciballact",CHAN_VOICE,CHANF_LOOPING,.4,1.5);
A_StartSound("powerup/invinciballact",CHAN_7,CHANF_LOOPING,.8,ATTN_NONE);
A_StartSound("powerup/invinciballact",CHAN_VOICE,CHANF_LOOP,.4,1.5);
A_StartSound("powerup/invinciballact",CHAN_7,CHANF_LOOP,.8,ATTN_NONE);
}
override void OnDestroy()
{
@ -691,6 +703,7 @@ Class FuckingInvinciball : Inventory
{
Mixin SWWMAutoUseFix;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
override Inventory CreateCopy( Actor other )
{
@ -732,6 +745,7 @@ Class FuckingInvinciball : Inventory
Inventory.PickupMessage "$T_INVINCIBALL";
Inventory.MaxAmount 5;
Inventory.InterHubAmount 5;
Inventory.PickupFlash "SWWMPickupFlash";
+INVENTORY.ALWAYSPICKUP;
+INVENTORY.AUTOACTIVATE;
+INVENTORY.INVBAR;
@ -739,6 +753,8 @@ Class FuckingInvinciball : Inventory
+INVENTORY.BIGPOWERUP;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 10;
Height 28;
}
States
{
@ -800,8 +816,8 @@ Class RageSnd : Actor
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_StartSound("powerup/ragekitact",CHAN_VOICE,CHANF_LOOPING,.4,1.5);
A_StartSound("powerup/ragekitact",CHAN_7,CHANF_LOOPING,.5,ATTN_NONE);
A_StartSound("powerup/ragekitact",CHAN_VOICE,CHANF_LOOP,.4,1.5);
A_StartSound("powerup/ragekitact",CHAN_7,CHANF_LOOP,.5,ATTN_NONE);
}
override void OnDestroy()
{
@ -951,6 +967,7 @@ Class Ragekit : Inventory
{
Mixin SWWMAutoUseFix;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
override bool Use( bool pickup )
{
@ -958,6 +975,12 @@ Class Ragekit : Inventory
if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA);
if ( Owner.GiveBody(100,100) )
SWWMScoreObj.Spawn(100,Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),Font.CR_BLUE);
if ( !(Owner is 'Demolitionist') )
{
SWWMHandler.DoFlash(Owner,Color(64,255,0,0),30);
Owner.A_QuakeEx(8,8,8,20,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:1.);
return true;
}
let r = RagekitPower(Owner.FindInventory("RagekitPower"));
if ( r )
{
@ -988,6 +1011,7 @@ Class Ragekit : Inventory
Inventory.PickupMessage "$T_RAGEKIT";
Inventory.MaxAmount 5;
Inventory.InterHubAmount 5;
Inventory.PickupFlash "SWWMPickupFlash";
+INVENTORY.ALWAYSPICKUP;
+INVENTORY.AUTOACTIVATE;
+INVENTORY.INVBAR;
@ -995,6 +1019,8 @@ Class Ragekit : Inventory
+INVENTORY.BIGPOWERUP;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 12;
Height 24;
}
States
{
@ -1007,6 +1033,7 @@ Class Ragekit : Inventory
Class Omnisight : Inventory
{
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
override bool Use( bool pickup )
{
@ -1026,6 +1053,7 @@ Class Omnisight : Inventory
Inventory.MaxAmount 1;
Inventory.InterHubAmount 0;
Inventory.RestrictedTo "Demolitionist";
Inventory.PickupFlash "SWWMPickupFlash";
+INVENTORY.ALWAYSPICKUP;
+INVENTORY.AUTOACTIVATE;
+COUNTITEM;
@ -1034,6 +1062,8 @@ Class Omnisight : Inventory
+INVENTORY.UNTOSSABLE;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 6;
Height 24;
}
States
{
@ -1082,7 +1112,7 @@ Class LampMoth : Actor
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_StartSound("moth/fly",CHAN_BODY,CHANF_LOOPING,.02,4.,FRandom[Moth](.8,1.2));
A_StartSound("moth/fly",CHAN_BODY,CHANF_LOOP,.02,4.,FRandom[Moth](.8,1.2));
if ( master && master.player ) SetFriendPlayer(master.player);
else bFRIENDLY = false;
}
@ -1577,6 +1607,7 @@ Class CompanionLamp : Actor
Class SWWMLamp : Inventory
{
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
bool bActive;
TextureID OnIcon;
@ -1683,6 +1714,7 @@ Class SWWMLamp : Inventory
Inventory.Amount 1;
Inventory.MaxAmount 5;
Inventory.InterHubAmount 5;
Inventory.PickupFlash "SWWMPickupFlash";
+INVENTORY.ALWAYSPICKUP;
+INVENTORY.AUTOACTIVATE;
+INVENTORY.INVBAR;
@ -1692,6 +1724,8 @@ Class SWWMLamp : Inventory
FloatBobStrength 0.25;
SWWMLamp.Charge 100;
Stamina 70000;
Radius 8;
Height 28;
}
States
{
@ -1751,8 +1785,8 @@ Class BarrierSnd : Actor
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_StartSound("powerup/barrieract",CHAN_VOICE,CHANF_LOOPING,.06,1.5);
A_StartSound("powerup/barrieract",CHAN_7,CHANF_LOOPING,.1,ATTN_NONE);
A_StartSound("powerup/barrieract",CHAN_VOICE,CHANF_LOOP,.06,1.5);
A_StartSound("powerup/barrieract",CHAN_7,CHANF_LOOP,.1,ATTN_NONE);
}
override void OnDestroy()
{
@ -1812,6 +1846,7 @@ Class EBarrier : Inventory
{
Mixin SWWMAutoUseFix;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
override bool Use( bool pickup )
{
@ -1841,6 +1876,7 @@ Class EBarrier : Inventory
Inventory.PickupMessage "$T_BARRIER";
Inventory.MaxAmount 5;
Inventory.InterHubAmount 5;
Inventory.PickupFlash "SWWMPickupFlash";
+INVENTORY.ALWAYSPICKUP;
+INVENTORY.AUTOACTIVATE;
+INVENTORY.INVBAR;
@ -1848,6 +1884,8 @@ Class EBarrier : Inventory
+INVENTORY.BIGPOWERUP;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 6;
Height 28;
}
States
{

View file

@ -1,45 +0,0 @@
// TODO code for the in-game radio
Class Playlist
{
Array<String> trk; // track titles
String name; // playlist name
String fmt; // format string for track files
}
Class SWWMRadioHandler : EventHandler
{
Array<Playlist> lists;
ui int curlist, curtrack;
transient ui CVar shuffle, active;
ui Array<Int> shuffledorder; // current playlist track indices, shuffled
ui String oldmus;
override void OnRegister()
{
// load playlists from swwmradio.txt files
}
ui void NextTrack()
{
// advance the playlist
// if we reach the end, reshuffle if needed
}
ui void SetTrack( int list, int idx )
{
// pick a specific track from the playlist
// reshuffle if needed
}
override void UiTick()
{
if ( !active ) active = CVar.GetCVar('swwm_radio',players[consoleplayer]);
if ( active.GetBool() && (musplaying.name != oldmus) )
{
// advance the playlist
NextTrack();
}
oldmus = musplaying.name;
}
}

View file

@ -1,6 +1,15 @@
// SHAMEFUL DISPLAY
// >loading brutal doom with this
// At this point there's no clearer way to tell people to stop combining
// incompatible mods.
// The BD crowd never listens, never learns, you can't just mix up gameplay
// mods and expect everything to work.
// You also can't expect modders to put in the effort needed to go and add
// compatibility for a mod that wouldn't even make any sense to add
// compatibility for because both replace the same things and are entirely
// different beasts with different styles altogether.
// Just stop. Put that gray matter to use. Do you really think it's worth it?
// Don't do this shit.
Class SWWMBrutalHandler : StaticEventHandler
{
ui int timer;
@ -17,8 +26,16 @@ Class SWWMBrutalHandler : StaticEventHandler
break;
}
SetRandomSeed[bdscreen](Random[bdscreen]()+consoleplayer+MSTime());
if ( detected )
Console.Printf("\cg========\n\cgIf you have BD on your autoload, you really shouldn't.\n\cgIf you manually loaded it with this mod, why would you?\n\cgThey're not compatible and never will be.\n\cg========");
if ( !detected ) return;
Console.Printf(
"\cx┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n"
"\cx┃ \cfIf you have BD on your autoload you really shouldn't. \cx┃\n"
"\cx┃ \cfIf you manually loaded it with this mod, why would you? \cx┃\n"
"\cx┃ \cfThey're not compatible and never will be. \cx┃\n"
"\cx┃ \cfThis mod will now shit the bed once you go in-game, \cx┃\n"
"\cx┃ \cfand trust me, it's better this way. \cx┃\n"
"\cx┃ \cf<See you again, have a nice day> \cx┃\n"
"\cx┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛");
}
override void UiTick()
@ -31,7 +48,7 @@ Class SWWMBrutalHandler : StaticEventHandler
S_StartSound("brutal/ezmodo",CHAN_YOUDONEFUCKEDUP,CHANF_UI|CHANF_NOPAUSE|CHANF_OVERLAP,1,ATTN_NONE);
S_StartSound("brutal/ezmodo",CHAN_YOUDONEFUCKEDUP,CHANF_UI|CHANF_NOPAUSE|CHANF_OVERLAP,1,ATTN_NONE);
}
else if ( timer == 350 ) ThrowAbortException(">Brutal Doom");
else if ( timer == 350 ) ThrowAbortException("This manual abort is for your own safety");
timer++;
}
else timer = 0;
@ -64,6 +81,16 @@ Class SWWMBrutalHandler : StaticEventHandler
}
// HORNY
// Surprisingly, I've put in actual effort into this compatibility thing (even
// if it's just sort of partial).
// Demo-chan has no pp in this body that they can stick into the girls, so all
// they get is the headpats. There's some sort of crazy magic going on here,
// that makes the demon gals fall to their knees instantly. Saya thinks it
// might be a side effect of teaching them the "blow kiss" spell (which has the
// same effect).
// Obviously, all the standard weapons work, and these gals appear to be of the
// masochistic kind. This is generally not very effective compared to the pats
// and smooches, but it's there, if you're willing to hurt them (I wouldn't).
Class SWWMHDoomHandler : StaticEventHandler
{
ui int timer;
@ -79,8 +106,105 @@ Class SWWMHDoomHandler : StaticEventHandler
break;
}
SetRandomSeed[hdscreen](Random[hdscreen]()+consoleplayer+MSTime());
if ( detected )
Console.Printf("\cg========\n\cgHa ha very funny.\n\cgIf you want the Demolitionist to fuck some hot demon girls go commission a porn artist.\n\cg========");
if ( !detected ) return;
Console.Printf(
"\cx┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n"
"\cx┃ \cfOh my, someone appears to be \cgH \ckO \cdR \cvN \chY \ct♥ \cx┃\n"
"\cx┃ \cfWell, all you'll be getting here is the power of headpats. \cx┃\n"
"\cx┃ \cfIf you want Demo-chan to actually fuck some hot demon girls, \cx┃\n"
"\cx┃ \cfjust go commission a porn artist or something, idk. \cx┃\n"
"\cx┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛");
}
static bool IsCuteGirl( Actor a )
{
Class p = a.GetClass();
while ( p.GetParentClass() && (p.GetParentClass() != 'Actor') )
{
p = p.GetParentClass();
if ( p.GetClassName() == 'HDoomMonster' )
return true;
}
return false;
}
static bool IsSexyTime( Actor a )
{
Class p = a.GetClass();
while ( p.GetParentClass() && (p.GetParentClass() != 'Actor') )
{
p = p.GetParentClass();
if ( p.GetClassName() == 'SexActor' )
return true;
}
return false;
}
static bool IsStaticSexyTime( Actor a )
{
Class p = a.GetClass();
while ( p.GetParentClass() && (p.GetParentClass() != 'Actor') )
{
p = p.GetParentClass();
if ( p.GetClassName() == 'StaticSexActor' )
return true;
}
return false;
}
override void WorldThingSpawned( WorldEvent e )
{
// demo can't sex the ladies (not with this body)
// spawn a headpat tracker, we can at least do this much for them
if ( IsSexyTime(e.Thing) )
{
e.Thing.bUSESPECIAL = false;
let hp = Actor.Spawn("HeadpatTracker",e.Thing.pos);
hp.target = e.Thing;
// sweet dreams, demon
HeadpatTracker(hp).patstate = e.Thing.FindState("TooLate");
HeadpatTracker(hp).deathstate = e.Thing.FindState("Finish");
// height fixes
String cname = e.Thing.GetClassName();
if ( cname.Left(12) ~== "Cacodemoness" )
HeadpatTracker(hp).hdoomheightfix = .2;
else if ( cname.Left(12) ~== "ImpEncounter" )
HeadpatTracker(hp).hdoomheightfix = .35;
else if ( cname.Left(8) ~== "Mancubus" )
HeadpatTracker(hp).hdoomheightfix = .1;
else if ( cname.Left(9) ~== "HLostSoul" )
HeadpatTracker(hp).hdoomheightfix = .5;
else if ( cname.Left(10) ~== "ArchViless" )
HeadpatTracker(hp).hdoomheightfix = -.1;
}
else if ( IsStaticSexyTime(e.Thing) )
{
e.Thing.bUSESPECIAL = false;
let hp = Actor.Spawn("HeadpatTracker",e.Thing.pos);
hp.target = e.Thing;
if ( e.Thing.GetClassName() == 'ImpInAChair' )
{
HeadpatTracker(hp).hdoomheightfix = .2;
HeadpatTracker(hp).hdoomangfix = 15;
}
}
else if ( IsCuteGirl(e.Thing) )
{
let hp = Actor.Spawn("HeadpatTracker",e.Thing.pos);
hp.target = e.Thing;
// sweet dreams, demon
HeadpatTracker(hp).lethalpat = true;
String cname = e.Thing.GetClassName();
// height fixes
if ( cname.Left(12) ~== "ImpEncounter" )
HeadpatTracker(hp).hdoomheightfix = .1;
else if ( cname.Left(8) ~== "Mancubus" )
HeadpatTracker(hp).hdoomheightfix = -.1;
else if ( cname.Left(9) ~== "HLostSoul" )
HeadpatTracker(hp).hdoomheightfix = .5;
else if ( cname.Left(10) ~== "ArchViless" )
HeadpatTracker(hp).hdoomheightfix = -.3;
}
}
override void UiTick()
@ -106,7 +230,7 @@ Class SWWMHDoomHandler : StaticEventHandler
override void RenderOverlay( RenderEvent e )
{
if ( !detected || (timer < 50) ) return;
if ( !detected || (timer < 50) || (timer > 150) ) return;
if ( !scr ) scr = TexMan.CheckForTexture("graphics/hdscreen.png",TexMan.Type_Any);
double ar = Screen.GetAspectRatio();
Vector2 tsize = TexMan.GetScaledSize(scr);
@ -118,6 +242,7 @@ Class SWWMHDoomHandler : StaticEventHandler
else if ( sar < ar ) vsize = (tsize.y*ar,tsize.y);
else vsize = tsize;
}
Screen.DrawTexture(scr,false,(vsize.x-tsize.x)/2.,(vsize.y-tsize.y)/2.,DTA_VirtualWidthF,vsize.x,DTA_VirtualHeightF,vsize.y,DTA_KeepRatio,true);
double alph = clamp(2.5-(timer+e.FracTic)/50.,0.,.25)*4.;
Screen.DrawTexture(scr,false,(vsize.x-tsize.x)/2.,(vsize.y-tsize.y)/2.,DTA_VirtualWidthF,vsize.x,DTA_VirtualHeightF,vsize.y,DTA_KeepRatio,true,DTA_Alpha,alph);
}
}

View file

@ -158,7 +158,7 @@ Class SpreadImpact : Actor
Super.PostBeginPlay();
if ( swwm_extraalert ) A_AlertMonsters(200);
A_StartSound("spreadgun/pellet",CHAN_VOICE,CHANF_DEFAULT,.4,4.);
A_SprayDecal("TinyBulletChip",-20);
A_SprayDecal("TinyPock",-20);
int numpt = Random[Spreadgun](2,4)-special1;
Vector3 x = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
for ( int i=0; i<numpt; i++ )
@ -205,7 +205,7 @@ Class SlugImpact : Actor
Super.PostBeginPlay();
if ( swwm_extraalert ) A_AlertMonsters(500);
A_StartSound("spreadgun/slug",CHAN_VOICE,CHANF_DEFAULT,1.,2.);
A_SprayDecal("BulletChip",-20);
A_SprayDecal("Pock",-20);
int numpt = Random[Spreadgun](5,10)-special1;
Vector3 x = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
for ( int i=0; i<numpt; i++ )
@ -1413,7 +1413,7 @@ Class TheBall : Actor
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_StartSound("pusher/fly",CHAN_WEAPON,CHANF_LOOPING,.6,3.,2.);
A_StartSound("pusher/fly",CHAN_WEAPON,CHANF_LOOP,.6,3.,2.);
heat = 1.;
}
override void Tick()
@ -1594,7 +1594,7 @@ Class GoldenImpact : Actor
A_QuakeEx(9,9,9,40,0,5000,"",QF_RELATIVE|QF_SCALEDOWN,falloff:500,rollintensity:1.5);
A_StartSound("spreadgun/goldexpl",CHAN_VOICE,attenuation:.3);
A_StartSound("spreadgun/goldexpl",CHAN_WEAPON,attenuation:.15);
A_SprayDecal("WumboScorch",-172);
A_SprayDecal("WumboRocketBlast",-172);
Scale *= FRandom[ExploS](0.8,1.1);
Scale.x *= RandomPick[ExploS](-1,1);
Scale.y *= RandomPick[ExploS](-1,1);
@ -1730,7 +1730,7 @@ Class GoldenSubImpact : Actor
Super.PostBeginPlay();
SWWMUtility.DoExplosion(self,777,30000,400,300,DE_EXTRAZTHRUST);
A_QuakeEx(7,7,7,20,0,2000,"",QF_RELATIVE|QF_SCALEDOWN,falloff:200,rollintensity:.8);
A_SprayDecal("BigScorch",-172);
A_SprayDecal("BigRocketBlast",-172);
Scale *= FRandom[ExploS](0.8,1.1);
Scale.x *= RandomPick[ExploS](-1,1);
Scale.y *= RandomPick[ExploS](-1,1);
@ -1866,7 +1866,7 @@ Class GoldenSubSubImpact : Actor
Super.PostBeginPlay();
SWWMUtility.DoExplosion(self,77,20000,200,100,DE_EXTRAZTHRUST);
A_QuakeEx(4,4,4,15,0,1000,"",QF_RELATIVE|QF_SCALEDOWN,falloff:100,rollintensity:.4);
A_SprayDecal("Scorch",-172);
A_SprayDecal("RocketBlast",-172);
Scale *= FRandom[ExploS](0.8,1.1);
Scale.x *= RandomPick[ExploS](-1,1);
Scale.y *= RandomPick[ExploS](-1,1);
@ -2142,6 +2142,11 @@ Class Spreadgun : SWWMWeapon
}
}
override Vector3 GetTraceOffset()
{
return (10.,2.,-2.);
}
action void A_FireShell()
{
static const Class<Ammo> types[] = {"RedShell","GreenShell","WhiteShell","BlueShell","BlackShell","PurpleShell","GoldShell"};
@ -2573,6 +2578,8 @@ Class Spreadgun : SWWMWeapon
SWWMWeapon.DropAmmoType "Clip";
Stamina 15000;
+SWWMWEAPON.NOFIRSTGIVE;
Radius 10;
Height 24;
}
States

View file

@ -147,8 +147,8 @@ Class BigBiospark : Actor
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_StartSound("biospark/bigspark",CHAN_VOICE,CHANF_LOOPING|CHANF_OVERLAP,1.,.6);
A_StartSound("biospark/bigspark",CHAN_VOICE,CHANF_LOOPING|CHANF_OVERLAP,1.,.6);
A_StartSound("biospark/bigspark",CHAN_VOICE,CHANF_LOOP|CHANF_OVERLAP,1.,.6);
A_StartSound("biospark/bigspark",CHAN_VOICE,CHANF_LOOP|CHANF_OVERLAP,1.,.6);
let h = Spawn("BigBiosparkHitbox",pos);
h.target = self;
for ( int i=0; i<special1; i++ )
@ -437,7 +437,7 @@ Class BiosparkBall : Actor
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_StartSound("biospark/spark",CHAN_VOICE,CHANF_LOOPING);
A_StartSound("biospark/spark",CHAN_VOICE,CHANF_LOOP);
let h = Spawn("BiosparkHitbox",pos);
h.target = self;
}
@ -472,7 +472,7 @@ Class BiosparkBall : Actor
let s = Spawn(!Random[Sparkster](0,10)?"BiosparkArc":"BiosparkArcSmall",spos);
s.target = target;
s.master = self;
s.ReactionTime += Random[Sparkster](0,5);
s.ReactionTime += Random[Sparkster](0,3);
s.angle = ang;
s.pitch = pt;
}
@ -578,7 +578,7 @@ Class BiosparkBall : Actor
s.target = target;
s.angle = ang;
s.pitch = pt;
s.ReactionTime += Random[Sparkster](0,10);
s.ReactionTime += Random[Sparkster](0,4);
}
Spawn("BiosparkExplLight",pos);
if ( swwm_omnibust ) BusterWall.ProjectileBust(self,30,(cos(angle)*cos(pitch),sin(angle)*cos(pitch),sin(-pitch)));
@ -629,7 +629,7 @@ Class BiosparkBall : Actor
s.target = target;
s.angle = ang;
s.pitch = pt;
s.ReactionTime += Random[Sparkster](0,int(5*factor));
s.ReactionTime += Random[Sparkster](0,int(3*factor));
}
}
States
@ -743,7 +743,7 @@ Class BiosparkBeamImpact : Actor
s.master = self;
s.angle = ang;
s.pitch = pt;
s.ReactionTime += Random[Sparkster](0,10);
s.ReactionTime += Random[Sparkster](0,4);
}
Spawn("BiosparkExplLight",pos);
}
@ -794,7 +794,7 @@ Class BiosparkBeamImpact : Actor
s.master = self;
s.angle = ang;
s.pitch = pt;
s.ReactionTime += Random[Sparkster](0,int(5*factor));
s.ReactionTime += Random[Sparkster](0,int(3*factor));
}
}
override void Tick()
@ -1208,7 +1208,7 @@ Class BiosparkBeam : Actor
a.angle = angle;
a.pitch = pitch;
a.target = target;
a.ReactionTime += Random[Sparkster](0,8);
a.ReactionTime += Random[Sparkster](-2,4);
}
numpt = Random[Sparkster](2,5);
for ( int i=0; i<numpt; i++ )
@ -1218,7 +1218,7 @@ Class BiosparkBeam : Actor
a.pitch = pitch;
a.target = target;
a.master = self;
a.ReactionTime += Random[Sparkster](0,6);
a.ReactionTime += Random[Sparkster](-1,3);
}
numpt = Random[Sparkster](25,50);
for ( int i=0; i<numpt; i++ )
@ -1586,7 +1586,7 @@ Class BiosparkArc : Actor
Obituary "$O_SPARKSTER";
RenderStyle "Add";
DamageFunction 3;
ReactionTime 12;
ReactionTime 10;
Speed 16;
Radius .1;
Height 0;
@ -1613,7 +1613,7 @@ Class BiosparkArcSmall : BiosparkArc
{
Default
{
ReactionTime 9;
ReactionTime 10;
DamageFunction 1;
Speed 8;
}
@ -1840,7 +1840,7 @@ Class BiosparkCore : Actor
s.target = target;
s.angle = ang;
s.pitch = pt;
s.ReactionTime += Random[Sparkster](0,10);
s.ReactionTime += Random[Sparkster](0,5);
}
Spawn("BiosparkExplLight",pos);
}
@ -1985,6 +1985,7 @@ Class Sparkster : SWWMWeapon
override void HudTick()
{
Super.HudTick();
if ( !iclip ) iclip = DynamicValueInterpolator.Create(clipcount*30,.25,1,10);
else iclip.Update(clipcount*30);
}
@ -2002,6 +2003,11 @@ Class Sparkster : SWWMWeapon
return Super.ReportHUDAmmo();
}
override Vector3 GetTraceOffset()
{
return (10.,4.5,-5.);
}
action void A_FireSpark( int mode )
{
int scnt = invoker.clipcount;
@ -2009,7 +2015,7 @@ Class Sparkster : SWWMWeapon
else invoker.clipcount = max(0,invoker.clipcount-1);
Vector3 x, y, z, x2, y2, z2, dir;
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x+5*y-5*z);
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x+4.5*y-5*z);
double a, s;
Actor p;
switch ( mode )
@ -2094,7 +2100,7 @@ Class Sparkster : SWWMWeapon
{
Super.Travelled();
if ( Owner.player && (Owner.player.Readyweapon == self) )
Owner.A_StartSound("biospark/idle",CHAN_WEAPONEXTRA,CHANF_LOOPING,.4,4.);
Owner.A_StartSound("biospark/idle",CHAN_WEAPONEXTRA,CHANF_LOOP,.4,4.);
}
action void A_FailZoom()
@ -2119,6 +2125,8 @@ Class Sparkster : SWWMWeapon
Sparkster.ClipCount 8;
+SWWMWEAPON.NOFIRSTGIVE;
+WEAPON.EXPLOSIVE;
Radius 22;
Height 24;
}
States
{
@ -2129,7 +2137,7 @@ Class Sparkster : SWWMWeapon
XZW2 G 2
{
A_FullRaise();
A_StartSound("biospark/idle",CHAN_WEAPONEXTRA,CHANF_LOOPING,.4,4.);
A_StartSound("biospark/idle",CHAN_WEAPONEXTRA,CHANF_LOOP,.4,4.);
}
XZW2 HIJKLM 2;
Goto Ready;

View file

@ -117,8 +117,8 @@ Class ExplodiumMagProj : Actor
{
Obituary "$O_EXPLODIUM";
DamageType "Explodium";
Radius 6;
Height 6;
Radius 4;
Height 4;
Gravity 0.5;
Speed 30;
PROJECTILE;
@ -148,7 +148,7 @@ Class ExplodiumMagProj : Actor
A_QuakeEx(9,9,9,30,0,400+80*special1,"",QF_RELATIVE|QF_SCALEDOWN,falloff:300,rollintensity:2.);
A_StartSound("explodium/maghit",CHAN_VOICE,attenuation:.35);
A_StartSound("explodium/maghit",CHAN_WEAPON,attenuation:.2);
A_SprayDecal("BigScorch",172);
A_SprayDecal("BigRocketBlast",172);
Scale *= FRandom[ExploS](0.8,1.1);
Scale.x *= RandomPick[ExploS](-1,1);
Scale.y *= RandomPick[ExploS](-1,1);
@ -226,6 +226,8 @@ Class ExplodiumBulletImpact : Actor
Obituary "$O_EXPLODIUM";
DamageType "Explodium";
RenderStyle "Add";
Radius .1;
Height 0.;
Scale 1.2;
+NOGRAVITY;
+NOBLOCKMAP;
@ -243,7 +245,7 @@ Class ExplodiumBulletImpact : Actor
A_QuakeEx(4,4,4,10,0,250,"",QF_RELATIVE|QF_SCALEDOWN,falloff:150,rollintensity:0.2);
A_StartSound("explodium/hit",CHAN_VOICE,attenuation:.6);
A_StartSound("explodium/hit",CHAN_WEAPON,attenuation:.3);
A_SprayDecal("Scorch",-172);
A_SprayDecal("RocketBlast",-172);
Scale *= FRandom[ExploS](0.8,1.1);
Scale.x *= RandomPick[ExploS](-1,1);
Scale.y *= RandomPick[ExploS](-1,1);
@ -312,6 +314,25 @@ Class ExplodiumGun : SWWMWeapon
Screen.DrawText(TewiFont,Font.CR_FIRE,bx-19,by-14,String.Format("%d",max(clipcount,0)),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
}
override void HudTick()
{
[cpos, ccol] = TraceForCrosshair();
let sw = SWWMWeapon(SisterWeapon);
// avoid jumpy switching
if ( (Owner.player.PendingWeapon is 'SWWMWeapon') && (Owner.player.PendingWeapon != sw) )
{
SWWMWeapon(Owner.player.PendingWeapon).cpos = cpos;
SWWMWeapon(Owner.player.PendingWeapon).lagvpos = lagvpos;
}
[sw.cpos, sw.ccol] = sw.TraceForCrosshair();
}
override Vector3 GetTraceOffset()
{
if ( Owner.player.ReadyWeapon == SisterWeapon ) return (10.,3.5,-2.);
return (10.,3.,-2.);
}
override bool HandlePickup( Inventory item )
{
if ( (item.GetClass() == 'ExplodiumGun') && !item.ShouldStay() )
@ -530,6 +551,8 @@ Class ExplodiumGun : SWWMWeapon
Stamina 8000;
ExplodiumGun.ClipCount 7;
+WEAPON.EXPLOSIVE;
Radius 12;
Height 24;
}
States
{
@ -705,6 +728,32 @@ Class DualExplodiumGun : SWWMWeapon
Screen.DrawText(TewiFont,Font.CR_FIRE,bx-43,by-14,String.Format("%d",max(clipcount,0)),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
}
override void RenderUnderlay( RenderEvent e )
{
Super.RenderUnderlay(e);
// draw both crosshairs
SWWMWeapon(SisterWeapon).RenderUnderlay(e);
}
override void HudTick()
{
[cpos, ccol] = TraceForCrosshair();
let sw = SWWMWeapon(SisterWeapon);
// avoid jumpy switching
if ( (Owner.player.PendingWeapon is 'SWWMWeapon') && (Owner.player.PendingWeapon != sw) )
{
SWWMWeapon(Owner.player.PendingWeapon).cpos = sw.cpos;
SWWMWeapon(Owner.player.PendingWeapon).lagvpos = sw.lagvpos;
}
[sw.cpos, sw.ccol] = sw.TraceForCrosshair();
}
override Vector3 GetTraceOffset()
{
if ( Owner.player.ReadyWeapon == SisterWeapon ) return (10.,-3.,-2.);
return (10.,-3.5,-2.);
}
action void A_LeftFlash( StateLabel flashlabel = null )
{
if ( !player || !player.ReadyWeapon )

View file

@ -546,7 +546,7 @@ Class CandyGunProj : Actor
A_QuakeEx(9,9,9,70,0,1500+100*special1,"",QF_RELATIVE|QF_SCALEDOWN,falloff:1200,rollintensity:2.);
A_StartSound("candygun/gunhit",CHAN_VOICE,attenuation:.24);
A_StartSound("candygun/gunhit",CHAN_WEAPON,attenuation:.12);
A_SprayDecal("WumboScorch",172);
A_SprayDecal("WumboRocketBlast",172);
Scale *= FRandom[ExploS](0.8,1.1);
Scale.x *= RandomPick[ExploS](-1,1);
Scale.y *= RandomPick[ExploS](-1,1);
@ -662,7 +662,7 @@ Class CandyMagProj : Actor
A_QuakeEx(9,9,9,30,0,500+80*special1,"",QF_RELATIVE|QF_SCALEDOWN,falloff:500,rollintensity:2.);
A_StartSound("candygun/maghit",CHAN_VOICE,attenuation:.24);
A_StartSound("candygun/maghit",CHAN_WEAPON,attenuation:.12);
A_SprayDecal("HugeScorch",172);
A_SprayDecal("HugeRocketBlast",172);
Scale *= FRandom[ExploS](0.8,1.1);
Scale.x *= RandomPick[ExploS](-1,1);
Scale.y *= RandomPick[ExploS](-1,1);
@ -757,7 +757,7 @@ Class CandyBulletImpact : Actor
A_QuakeEx(6,6,6,15,0,300,"",QF_RELATIVE|QF_SCALEDOWN,falloff:200,rollintensity:0.2);
A_StartSound("candygun/hit",CHAN_VOICE,attenuation:.25);
A_StartSound("candygun/hit",CHAN_WEAPON,attenuation:.5);
A_SprayDecal("BigScorch",-172);
A_SprayDecal("BigRocketBlast",-172);
Scale *= FRandom[ExploS](0.8,1.1);
Scale.x *= RandomPick[ExploS](-1,1);
Scale.y *= RandomPick[ExploS](-1,1);
@ -955,6 +955,11 @@ Class CandyGun : SWWMWeapon
Screen.DrawText(TewiFont,Font.CR_FIRE,bx-37,by-40,String.Format("%d",Ammo2.Amount),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
}
override Vector3 GetTraceOffset()
{
return (10.,3,-2.);
}
action void A_Schutt()
{
let weap = Weapon(invoker);
@ -1160,6 +1165,8 @@ Class CandyGun : SWWMWeapon
+SWWMWEAPON.NOFIRSTGIVE;
+WEAPON.EXPLOSIVE;
+WEAPON.BFG;
Radius 12;
Height 24;
}
States
{

View file

@ -110,7 +110,7 @@ Class SilverImpact : Actor
return;
}
A_StartSound("silverbullet/hit",CHAN_VOICE,CHANF_DEFAULT,1.,.7);
A_SprayDecal("BigBulletChip",-64);
A_SprayDecal("BigPock",-64);
A_SprayDecal("HugeWallCrack",-64);
int numpt = Random[Silverbullet](15,25);
Vector3 x = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
@ -437,9 +437,9 @@ Class FatChodeImpact : Actor
A_AlertMonsters(8000);
A_QuakeEx(7,7,7,50,0,2000,"",QF_RELATIVE|QF_SCALEDOWN,falloff:800,rollIntensity:1.);
A_StartSound("silverbullet/chode",CHAN_VOICE,CHANF_DEFAULT,1.,.35);
A_SprayDecal("BigBulletChip",-64);
A_SprayDecal("BigPock",-64);
A_SprayDecal("HugeWallCrack",-64);
A_SprayDecal("WumboScorch",-64);
A_SprayDecal("WumboRocketBlast",-64);
Scale *= FRandom[ExploS](0.8,1.1);
Scale.x *= RandomPick[ExploS](-1,1);
Scale.y *= RandomPick[ExploS](-1,1);
@ -592,7 +592,7 @@ Class FatChodeExplosionArm : Actor
SWWMUtility.DoExplosion(self,20+reactiontime,8000+1500*reactiontime,80+5*reactiontime,50,DE_THRUWALLS);
if ( level.IsPointInLevel(pos) )
{
A_SprayDecal("HugeScorch",-32);
A_SprayDecal("HugeRocketBlast",-32);
Spawn("FatChodeExplosionTrail",pos);
Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](1,5);
let s = Spawn("SWWMHalfSmoke",pos);
@ -621,7 +621,6 @@ Class SilverBullet : SWWMWeapon
double zoomlevel;
ui TextureID reticle;
transient ui CVar useshaders;
bool initialized;
int rezoom;
bool proneme;
@ -679,6 +678,7 @@ Class SilverBullet : SWWMWeapon
}
override void HudTick()
{
Super.HudTick();
if ( !ZoomInter ) ZoomInter = DynamicValueInterpolator.Create(int(zoomlevel*10),.5,1,20);
ZoomInter.Update(int(zoomlevel*10));
}
@ -701,20 +701,6 @@ Class SilverBullet : SWWMWeapon
}
return Super.CheckAmmo(firemode,autoswitch,requireammo,ammocount);
}
override void AttachToOwner( Actor other )
{
Super.AttachToOwner(other);
if ( !initialized )
{
initialized = true;
// first copy always has a XSB mag with a XSB bullet in the chamber
chambered = true;
fired = false;
fcbchambered = false;
fcbloaded = false;
fcbselected = false;
}
}
override void DetachFromOwner()
{
// force disable zoom
@ -727,7 +713,6 @@ Class SilverBullet : SWWMWeapon
{
Super.DoEffect();
if ( zoomed ) crosshair = 99;
else crosshair = 0;
if ( !Owner || !Owner.player )
{
proneme = false;
@ -755,8 +740,10 @@ Class SilverBullet : SWWMWeapon
Shader.SetEnabled(players[consoleplayer],"SilverScope",true);
if ( !reticle ) reticle = TexMan.CheckForTexture("graphics/SBReticle.png",TexMan.Type_Any);
Screen.DrawTexture(reticle,false,ss.x*.5,ss.y*.5,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_LegacyRenderStyle,STYLE_Stencil,DTA_FillColor,Color(0,0,0));
return;
}
else Shader.SetEnabled(players[consoleplayer],"SilverScope",false);
Super.RenderUnderlay(e);
}
action void ProcessTraceHit( SilverBulletTracer t, Vector3 origin, Vector3 dir )
@ -929,6 +916,11 @@ Class SilverBullet : SWWMWeapon
s.target = self;
}
}
override Vector3 GetTraceOffset()
{
if ( zoomed ) return (0.,0.,0.);
return (10.,1,-1.);
}
action void A_SilverFire()
{
A_SWWMFlash();
@ -943,7 +935,8 @@ Class SilverBullet : SWWMWeapon
SWWMHandler.DoFlash(self,Color(110,255,192,80),8);
Vector3 x, y, z;
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x+1*y-1*z);
Vector3 origin = Vec2OffsetZ(0,0,player.viewz);
if ( !invoker.zoomed ) origin = level.Vec3Offset(origin,10*x+1*y-1*z);
Vector3 x2, y2, z2;
[x2, y2, z2] = swwm_CoordUtil.GetAxes(BulletSlope(),angle,roll);
if ( invoker.fcbchambered )
@ -1119,8 +1112,10 @@ Class SilverBullet : SWWMWeapon
SWWMWeapon.DropAmmoType "SilverBulletAmmo";
SilverBullet.ClipCount 5;
+SWWMWEAPON.NOFIRSTGIVE;
+WEAPON.NO_AUTO_SWITCH;
+WEAPON.ALT_AMMO_OPTIONAL;
+WEAPON.EXPLOSIVE;
Radius 36;
Height 36;
}
States
{

View file

@ -85,6 +85,8 @@ Class SWWMStats : Thinker
let ls = new("LevelStat");
ls.hub = !!(level.clusterflags&level.CLUSTER_HUB);
ls.levelname = level.levelname;
int iof = ls.levelname.IndexOf(" - by: ");
if ( iof != -1 ) ls.levelname.Truncate(iof);
ls.mapname = level.mapname;
ls.kcount = level.killed_monsters;
ls.ktotal = level.total_monsters;
@ -361,11 +363,11 @@ Class SWWMLoreLibrary : Thinker
if ( ref ~== "BlackfireIgniter" ) return true;
if ( ref ~== "EMPCarbine" ) return true;
if ( ref ~== "RayKhom" ) return true;
// check if entry is for a collectable
// check if entry is for a collectible
for ( int i=0; i<AllActorClasses.Size(); i++ )
{
let c = (Class<SWWMCollectable>)(AllActorClasses[i]);
if ( !c || (c == 'SWWMCollectable') ) continue;
let c = (Class<SWWMCollectible>)(AllActorClasses[i]);
if ( !c || (c == 'SWWMCollectible') ) continue;
let def = GetDefaultByType(c);
// skip if we match and it's not for this game
if ( (c.GetClassName() == ref) && !(gameinfo.gametype&def.avail) )
@ -910,12 +912,14 @@ Class SWWMCombatTracker : Thinker
if ( (gameinfo.gametype&GAME_Strife) && (!mytarget.bINCOMBAT && !mytarget.bJUSTATTACKED) || (mytarget is 'Beggar') || (mytarget is 'Peasant') )
straifu = true;
int mxdist = maxdist.GetInt();
// enemies within a set distance that have us as target
if ( !straifu && mytarget.target && (mytarget.target.Health > 0) && (mytarget.target.player == players[consoleplayer]) && ((mxdist <= 0) || (mytarget.Vec3To(mytarget.target).length() < mxdist)) && mytarget.CheckSight(mytarget.target,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) updated = level.maptime+70;
// players (but not voodoo dolls), always visible in sp/coop
if ( !deathmatch && mytarget.player && (mytarget.player.mo == mytarget) ) updated = level.maptime+35;
// friendlies within a set distance
else if ( mytarget.bFRIENDLY && ((mxdist <= 0) || (mytarget.Vec3To(players[consoleplayer].mo).length() < mxdist)) && players[consoleplayer].mo.CheckSight(mytarget,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) updated = level.maptime+35;
// enemies within a set distance that have us as target
else if ( !straifu && mytarget.target && (mytarget.target.Health > 0) && (mytarget.target.player == players[consoleplayer]) && ((mxdist <= 0) || (mytarget.Vec3To(mytarget.target).length() < mxdist)) && mytarget.CheckSight(mytarget.target,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) updated = level.maptime+70;
// any visible enemies within one quarter of the set distance
if ( ((mxdist <= 0) || (mytarget.Vec3To(players[consoleplayer].mo).length() < (mxdist/4))) && players[consoleplayer].mo.CheckSight(mytarget,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) updated = level.maptime;
else if ( ((mxdist <= 0) || (mytarget.Vec3To(players[consoleplayer].mo).length() < (mxdist/4))) && players[consoleplayer].mo.CheckSight(mytarget,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) updated = level.maptime;
}
else if ( (mytarget is 'BossBrain') || (mytarget is 'SWWMHangingKeen') )
{

View file

@ -5,6 +5,10 @@ Class SWWMTitleStuff : EventHandler
transient ui TextureID tex[3];
transient ui Font TewiFont, MPlusFont;
transient ui CVar lang, fuzz;
transient ui Array<String> scrolls;
transient ui int sline;
transient ui double sbase;
transient ui String lastlang;
// returns MPlus if we're playing in Japanese, otherwise returns the requested font
private ui Font LangFont( Font req )
@ -63,5 +67,50 @@ Class SWWMTitleStuff : EventHandler
else vsize = tsize;
alf = clamp(((level.maptime+e.FracTic)/Thinker.TICRATE)-26,0.,2.)*.5;
Screen.DrawTexture(tex[1],false,(vsize.x-tsize.x)/2,(vsize.y-tsize.y)/2,DTA_VirtualWidthF,vsize.x,DTA_VirtualHeightF,vsize.y,DTA_KeepRatio,true,DTA_Alpha,alf);
if ( (level.maptime/Thinker.TICRATE) < 30 ) return;
// scrolls
if ( (scrolls.Size() <= 0 ) || (lastlang != lang.GetString()) )
{
scrolls.Clear();
String sstr = StringTable.Localize("$SWWM_TITLESCROLL");
sstr.Split(scrolls,"\n");
sbase = (level.maptime+e.FracTic)/Thinker.TICRATE;
if ( sline >= scrolls.Size() ) sline = 0;
}
lastlang = lang.GetString();
// estimate scrool length
double llen = fnt.StringWidth(scrolls[sline]);
double soffset = 40*((level.maptime+e.FracTic)/Thinker.TICRATE-sbase);
if ( soffset > llen+320 )
{
sline++;
if ( sline >= scrolls.Size() ) sline = 0;
sbase = (level.maptime+e.FracTic)/Thinker.TICRATE;
soffset = 0;
}
double xx = 320-soffset;
int tlen = scrolls[sline].CodePointCount();
for ( int i=0, pos=0; i<tlen; i++ )
{
int ch;
[ch, pos] = scrolls[sline].GetNextCodePoint(pos);
if ( (xx > -8) && (xx < 320) )
{
for ( double trl = .1; trl < 1.; trl += .04 )
{
double yy = 160+10*sin(15*i+160*(level.maptime+e.FracTic)/Thinker.TICRATE-90.*(1.-trl));
alf = max(0,1.-abs(160-xx)/160.)**.5;
alf *= .2*trl;
double xxofs = 5*sin(15*i+120*(level.maptime+e.FracTic)/Thinker.TICRATE-90.*(1.-trl))-16*(1.-trl);
Screen.DrawChar(fnt,Font.CR_BLUE,xx-xxofs,yy,ch,DTA_VirtualWidth,320,DTA_VirtualHeight,200,DTA_KeepRatio,true,DTA_Alpha,alf,DTA_LegacyRenderStyle,STYLE_Add);
}
double yy = 160+10*sin(15*i+160*(level.maptime+e.FracTic)/Thinker.TICRATE);
alf = max(0,1.-abs(160-xx)/160.)**.5;
double xxofs = 5*sin(15*i+120*(level.maptime+e.FracTic)/Thinker.TICRATE);
Color c = Color(int(127.5+127.5*sin(10*i+80*(level.maptime+e.FracTic)/Thinker.TICRATE)),0,0);
Screen.DrawChar(fnt,Font.CR_SAPPHIRE,xx-xxofs,yy,ch,DTA_VirtualWidth,320,DTA_VirtualHeight,200,DTA_KeepRatio,true,DTA_Alpha,alf);
}
xx += fnt.GetCharWidth(ch);
}
}
}

View file

@ -14,21 +14,59 @@ const FallbackTag = "AWESOME IT'S PENIS"; // used on tag processing, please don'
Class SWWMUtility
{
// thanks zscript
static clearscope double fract( double a )
{
return a-floor(a);
}
// this can probably be simplified, but I'm lazy
static clearscope Vector3 HSVtoRGB( Vector3 hsv )
{
Vector3 p;
p.x = abs(fract(hsv.x+1.)*6.-3.);
p.y = abs(fract(hsv.x+(2./3.))*6.-3.);
p.z = abs(fract(hsv.x+(1./3.))*6.-3.);
Vector3 p2;
p2.x = (1.-hsv.y)+clamp(p.x-1.,0.,1.)*hsv.y;
p2.y = (1.-hsv.y)+clamp(p.y-1.,0.,1.)*hsv.y;
p2.z = (1.-hsv.y)+clamp(p.z-1.,0.,1.)*hsv.y;
return p2*hsv.z;
}
static clearscope void StripColor( out String str )
{
int len = str.CodePointCount();
for ( int i=0; i<len; i++ )
int i = 0;
for ( int i=0, pos=0; i<len; i++ )
{
int remlen = 0;
if ( str.GetNextCodePoint(i) != 0x1C )
int cplen = 0;
int ch, nxt;
[ch, nxt] = str.GetNextCodePoint(pos);
if ( ch != 0x1C )
{
pos = nxt;
continue;
}
remlen++;
if ( str.GetNextCodePoint(i+remlen) == 0x5B )
while ( str.GetNextCodePoint(i+remlen) != 0x5D )
remlen++;
cplen++;
[ch, nxt] = str.GetNextCodePoint(pos+remlen);
if ( ch == 0x5B )
{
int ch2;
do
{
[ch2, nxt] = str.GetNextCodePoint(pos+remlen);
remlen += nxt-(pos+remlen);
cplen++;
}
while ( ch2 != 0x5D );
}
remlen++;
str.Remove(i,remlen);
len -= remlen;
str.Remove(pos,remlen);
len -= cplen;
i--;
}
}
@ -52,13 +90,14 @@ Class SWWMUtility
str.Truncate(0);
workstr.Replace("_"," ");
int len = workstr.CodePointCount();
for ( int i=0; i<len; i++ )
for ( int i=0, pos=0; i<len; i++ )
{
int cp1 = workstr.GetNextCodePoint(i);
int cp1;
[cp1, pos] = workstr.GetNextCodePoint(pos);
str.AppendCharacter(cp1);
if ( i < len-1 )
{
int cp2 = workstr.GetNextCodePoint(i+1);
int cp2 = workstr.GetNextCodePoint(pos);
// this looks awkward, but I have to also account for non-letter characters
// uppercase after lowercase
if ( (String.CharUpper(cp1) != cp1) && (String.CharLower(cp2) != cp2) )
@ -73,6 +112,17 @@ Class SWWMUtility
}
}
static double PitchTo( Actor a, Actor b, double hfact = 1. )
{
if ( !a || !b ) return 0;
Vector3 thispos = a.player?a.Vec2OffsetZ(0,0,a.player.viewz):a.Vec3Offset(0,0,a.missileheight);
Vector3 otherpos = b.Vec3Offset(0,0,b.height*hfact);
Vector3 diff = level.Vec3Diff(thispos,otherpos);
double dist = diff.length();
if ( dist > 0 ) return -asin(diff.z/dist);
return 0;
}
static clearscope int GetLineLock( Line l )
{
int locknum = l.locknumber;
@ -113,6 +163,60 @@ Class SWWMUtility
return (((p.y-l.v1.p.y)*l.delta.x+(l.v1.p.x-p.x)*l.delta.y) > double.epsilon);
}
// haha another one
// copied from BoxOnLineSide()
static clearscope int BoxOnLineSide( double top, double bottom, double left, double right, Line l )
{
if ( !l ) return 0;
int p1, p2;
if ( l.delta.x == 0 )
{
// ST_VERTICAL:
p1 = (right < l.v1.p.x);
p2 = (left < l.v1.p.x);
if ( l.delta.y < 0 )
{
p1 ^= 1;
p2 ^= 1;
}
}
else if ( l.delta.y == 0 )
{
// ST_HORIZONTAL:
p1 = (top > l.v1.p.y);
p2 = (bottom > l.v1.p.y);
if ( l.delta.x < 0 )
{
p1 ^= 1;
p2 ^= 1;
}
}
else if ( (l.delta.x*l.delta.y) >= 0 )
{
// ST_POSITIVE:
p1 = PointOnLineSide((left,top),l);
p2 = PointOnLineSide((right,bottom),l);
}
else
{
// ST_NEGATIVE:
p1 = PointOnLineSide((right,top),l);
p2 = PointOnLineSide((left,bottom),l);
}
return (p1==p2)?p1:-1;
}
// wrapper
static clearscope int ActorOnLineSide( Actor a, Line l )
{
double box[4];
box[0] = a.pos.y+a.radius;
box[1] = a.pos.y-a.radius;
box[2] = a.pos.x-a.radius;
box[3] = a.pos.x+a.radius;
return BoxOnLineSide(box[0],box[1],box[2],box[3],l);
}
// box intersection check, for collision detection
static clearscope bool BoxIntersect( Actor a, Actor b, Vector3 ofs = (0,0,0), int pad = 0 )
{
@ -227,19 +331,35 @@ Class SWWMUtility
}
// Thanks to ZZYZX and Nash
static play void SetToSlope( Actor a, double dang )
static play void SetToSlope( Actor a, double dang, bool ceil = false )
{
vector3 fnormal = a.FloorSector.floorplane.Normal;
Sector sect;
Vector3 fnormal;
if ( ceil )
{
sect = a.CeilingSector;
fnormal = -sect.ceilingplane.Normal;
}
else
{
sect = a.FloorSector;
fnormal = sect.floorplane.Normal;
}
// find closest 3d floor for its normal
F3DFloor ff;
for ( int i=0; i<a.FloorSector.Get3DFloorCount(); i++ )
for ( int i=0; i<sect.Get3DFloorCount(); i++ )
{
if ( !(a.FloorSector.Get3DFloor(i).flags&F3DFloor.FF_SOLID) ) continue;
if ( !(a.FloorSector.Get3DFloor(i).top.ZAtPoint(a.pos.xy) ~== a.floorz) ) continue;
ff = a.FloorSector.Get3DFloor(i);
if ( !(sect.Get3DFloor(i).flags&F3DFloor.FF_SOLID) ) continue;
if ( !ceil && !(sect.Get3DFloor(i).top.ZAtPoint(a.pos.xy) ~== a.floorz) ) continue;
else if ( ceil && !(sect.Get3DFloor(i).top.ZAtPoint(a.pos.xy) ~== a.ceilingz) ) continue;
ff = sect.Get3DFloor(i);
break;
}
if ( ff ) fnormal = -ff.top.Normal;
if ( ff )
{
if ( ceil ) fnormal = ff.bottom.Normal;
else fnormal = -ff.top.Normal;
}
vector2 fnormalp1 = ((fnormal.x != 0) || (fnormal.y != 0))?(fnormal.x,fnormal.y).Unit():(0,0);
vector2 fnormalp2 = ((fnormal.x,fnormal.y).Length(),fnormal.z);
double fang = atan2(fnormalp1.y,fnormalp1.x); // floor angle (not pitch!)
@ -676,7 +796,6 @@ Class SWWMUtility
int ndmg = a.DamageMobj(Source,Instigator,dmg,(DamageType=='')?Source.DamageType:DamageType,DMG_EXPLOSION,atan2(-dir.y,-dir.x));
if ( !(flags&DE_NOBLEED) ) a.TraceBleed((ndmg>0)?ndmg:dmg,Source);
}
// TODO destructible geometry support
}
static play bool InPlayerFOV( PlayerInfo p, Actor a, double maxdist = 0. )