The Pusher is gone.
This commit is contained in:
parent
fb4951e5c4
commit
834116c8c7
70 changed files with 77 additions and 1257 deletions
|
|
@ -1,5 +1,5 @@
|
|||
// Itamex Reinforced Combat Hammer (from UnSX 5)
|
||||
// Slot 1, spawns shared with Pusher
|
||||
// Slot 1, spawns shared with Deep Impact
|
||||
|
||||
Class ItamexHammer : SWWMWeapon
|
||||
{
|
||||
|
|
@ -16,7 +16,7 @@ Class ItamexHammer : SWWMWeapon
|
|||
SWWMWeapon.GetLine "getitamexhammer";
|
||||
Inventory.Icon "graphics/HUD/Icons/W_ItamexHammer.png";
|
||||
Weapon.SlotNumber 1;
|
||||
Weapon.SlotPriority 3.;
|
||||
Weapon.SlotPriority 2.;
|
||||
Weapon.SelectionOrder 1200;
|
||||
Stamina 9000;
|
||||
+WEAPON.MELEEWEAPON;
|
||||
|
|
|
|||
|
|
@ -209,8 +209,6 @@ extend Class SWWMHandler
|
|||
if ( (e.Thing is 'Cyberdemon') && (inflictor is 'Rocket') && (buff.tracer == e.Thing) )
|
||||
SWWMUtility.MarkAchievement("cybully",src.player);
|
||||
}
|
||||
if ( (inflictor is 'PusherWeapon') || (inflictor is 'PusherProjectile') )
|
||||
SWWMUtility.AchievementProgressInc("tender",1,src.player);
|
||||
Inventory tk;
|
||||
if ( (tk = e.Thing.FindInventory("DeepImpactOnlyToken")) && (tk.special1 == 1) )
|
||||
SWWMUtility.MarkAchievement("shame",src.player);
|
||||
|
|
|
|||
|
|
@ -210,106 +210,6 @@ extend Class SWWMHandler
|
|||
Console.Printf("%d effects cleared.",n);
|
||||
return;
|
||||
}
|
||||
else if ( e.Name ~== "swwmdebugdumprng" )
|
||||
{
|
||||
if ( multiplayer && (e.player != Net_Arbitrator) )
|
||||
{
|
||||
if ( e.player == consoleplayer )
|
||||
Console.Printf("Only the net arbitrator can call this event.");
|
||||
return;
|
||||
}
|
||||
// dump the values of all mod RNGs (might help someday to track down what desyncs)
|
||||
String msg = String.Format("\cxRNG dump for player %d (\c-%s\cx):\c-",consoleplayer,players[consoleplayer].GetUserName());
|
||||
msg.AppendFormat("\n\n\cfPlay RNG (will cause desyncs if mismatched):\c-\n");
|
||||
msg.AppendFormat("\nBlood: %08x",Random2[Blood]());
|
||||
msg.AppendFormat("\nBoolet: %08x",Random2[Boolet]());
|
||||
msg.AppendFormat("\nBundle: %08x",Random2[Bundle]());
|
||||
msg.AppendFormat("\nCandy: %08x",Random2[Candy]());
|
||||
msg.AppendFormat("\nChancebox: %08x",Random2[Chancebox]());
|
||||
msg.AppendFormat("\nCorrode: %08x",Random2[Corrode]());
|
||||
msg.AppendFormat("\nDemolitionist: %08x",Random2[Demolitionist]());
|
||||
msg.AppendFormat("\nDoBlast: %08x",Random2[DoBlast]());
|
||||
msg.AppendFormat("\nDropChance: %08x",Random2[DropChance]());
|
||||
msg.AppendFormat("\nEviscerator: %08x",Random2[Eviscerator]());
|
||||
msg.AppendFormat("\nExplodium: %08x",Random2[Explodium]());
|
||||
msg.AppendFormat("\nExploS: %08x",Random2[ExploS]());
|
||||
msg.AppendFormat("\nExtraMissiles: %08x",Random2[ExtraMissiles]());
|
||||
msg.AppendFormat("\nFlameT: %08x",Random2[FlameT]());
|
||||
msg.AppendFormat("\nFlicker: %08x",Random2[Flicker]());
|
||||
msg.AppendFormat("\nGesture: %08x",Random2[Gesture]());
|
||||
msg.AppendFormat("\nGibs: %08x",Random2[Gibs]());
|
||||
msg.AppendFormat("\nGoldDrop: %08x",Random2[GoldDrop]());
|
||||
msg.AppendFormat("\nGoldy: %08x",Random2[Goldy]());
|
||||
msg.AppendFormat("\nGunFlash: %08x",Random2[GunFlash]());
|
||||
msg.AppendFormat("\nHellblazer: %08x",Random2[Hellblazer]());
|
||||
msg.AppendFormat("\nImpact: %08x",Random2[Impact]());
|
||||
msg.AppendFormat("\nInvinciball: %08x",Random2[Invinciball]());
|
||||
msg.AppendFormat("\nJunk: %08x",Random2[Junk]());
|
||||
msg.AppendFormat("\nMoth: %08x",Random2[Moth]());
|
||||
msg.AppendFormat("\nMykradvo: %08x",Random2[Mykradvo]());
|
||||
msg.AppendFormat("\nNugget: %08x",Random2[Nugget]());
|
||||
msg.AppendFormat("\nParry: %08x",Random2[Parry]());
|
||||
msg.AppendFormat("\nPonch: %08x",Random2[Ponch]());
|
||||
msg.AppendFormat("\nPuff: %08x",Random2[Puff]());
|
||||
msg.AppendFormat("\nPusher: %08x",Random2[Pusher]());
|
||||
msg.AppendFormat("\nRage: %08x",Random2[Rage]());
|
||||
msg.AppendFormat("\nReplacements: %08x",Random2[Replacements]());
|
||||
msg.AppendFormat("\nShellDrop: %08x",Random2[ShellDrop]());
|
||||
msg.AppendFormat("\nShivers: %08x",Random2[Shivers]());
|
||||
msg.AppendFormat("\nSilverbullet: %08x",Random2[Silverbullet]());
|
||||
msg.AppendFormat("\nSpareShells: %08x",Random2[SpareShells]());
|
||||
msg.AppendFormat("\nSparkster: %08x",Random2[Sparkster]());
|
||||
msg.AppendFormat("\nSpread: %08x",Random2[Spread]());
|
||||
msg.AppendFormat("\nSpreadgun: %08x",Random2[Spreadgun]());
|
||||
msg.AppendFormat("\nWallbuster: %08x",Random2[Wallbuster]());
|
||||
msg.AppendFormat("\nYnykron: %08x",Random2[Ynykron]());
|
||||
msg.AppendFormat("\n\n\cfUI RNG (should not cause desyncs if mismatched):\c-\n");
|
||||
msg.AppendFormat("\nbdscreen: %08x",Random2[bdscreen]());
|
||||
msg.AppendFormat("\nClientSparkles: %08x",Random2[ClientSparkles]());
|
||||
msg.AppendFormat("\nDemoLines: %08x",Random2[DemoLines]());
|
||||
msg.AppendFormat("\nFInTheChat: %08x",Random2[FInTheChat]());
|
||||
msg.AppendFormat("\nFunTags: %08x",Random2[FunTags]());
|
||||
msg.AppendFormat("\nhdscreen: %08x",Random2[hdscreen]());
|
||||
msg.AppendFormat("\nHudStuff: %08x",Random2[HudStuff]());
|
||||
msg.AppendFormat("\nInterArt: %08x",Random2[InterArt]());
|
||||
msg.AppendFormat("\nScoreBits: %08x",Random2[ScoreBits]());
|
||||
msg.AppendFormat("\nTUID: %08x",Random2[TUID]());
|
||||
msg.AppendFormat("\nUIStuff: %08x",Random2[UIStuff]());
|
||||
msg.AppendFormat("\nWallbusterMenu: %08x",Random2[WallbusterMenu]());
|
||||
Console.Printf(msg);
|
||||
return;
|
||||
}
|
||||
else if ( e.Name ~== "swwmdebugdlglines" )
|
||||
{
|
||||
if ( multiplayer && (e.player != Net_Arbitrator) )
|
||||
{
|
||||
if ( e.player == consoleplayer )
|
||||
Console.Printf("Only the net arbitrator can call this event.");
|
||||
return;
|
||||
}
|
||||
// checks that ALL dialogue text fits in 3 lines
|
||||
String alldlg_pack = "SWWM_SAYAPHOBOS1:SWWM_SAYAPHOBOS2:SWWM_SAYAPHOBOS3:SWWM_SAYAPHOBOS4:SWWM_SAYADEIMOS1:SWWM_SAYADEIMOS2:SWWM_SAYADEIMOS3:SWWM_SAYADEIMOS4:SWWM_SAYADIS1:SWWM_SAYADIS2:SWWM_SAYADIS3:SWWM_SAYADIS4:SWWM_SAYATHY1:SWWM_SAYATHY2:SWWM_SAYATHY3:SWWM_SAYATHY4:SWWM_CYTHOSIGIL1:SWWM_CYTHOSIGIL2:SWWM_CYTHOSIGIL3:SWWM_CYTHOSIGIL4:SWWM_SAYADIMPLE1:SWWM_SAYADIMPLE2:SWWM_SAYADIMPLE3:SWWM_SAYADIMPLE4:SWWM_SAYADIMPLE5:SWWM_SAYACIRCLE1:SWWM_SAYACIRCLE2:SWWM_SAYACIRCLE3:SWWM_SAYACIRCLE4:SWWM_SAYACIRCLE5:SWWM_SAYAGOTCHA1:SWWM_SAYAGOTCHA2:SWWM_SAYAGOTCHA3:SWWM_SAYAGOTCHA4:SWWM_SAYAGOTCHA5:SWWM_SAYAGOTCHAEND1:SWWM_SAYAGOTCHAEND2:SWWM_SAYAGOTCHAEND3:SWWM_SAYAGOTCHAEND4:SWWM_SAYAGOTCHAEND5:SWWM_SAYAIOS1:SWWM_SAYAIOS2:SWWM_SAYAIOS3:SWWM_SAYAIOS4:SWWM_SAYAIOS5:SWWM_SAYARAMPANCY1:SWWM_SAYARAMPANCY2:SWWM_SAYARAMPANCY3:SWWM_SAYARAMPANCY4:SWWM_CYTHONERVE1:SWWM_CYTHONERVE2:SWWM_CYTHONERVE3:SWWM_CYTHONERVE4:SWWM_CYTHONERVE5:SWWM_SAYAEVIA1:SWWM_SAYAEVIA2:SWWM_SAYAEVIA3:SWWM_SAYAEVIA4:SWWM_SAYAEVIB1:SWWM_SAYAEVIB2:SWWM_SAYAMAW1:SWWM_SAYAMAW2:SWWM_SAYAMAW3:SWWM_SAYAMAW4:SWWM_SAYAMAW5:SWWM_SAYAMASTERS1:SWWM_SAYAMASTERS2:SWWM_SAYAMASTERS3:SWWM_SAYAMASTERS4:SWWM_SAYAMASTERS5:SWWM_SAYADSPARIL1:SWWM_SAYADSPARIL2:SWWM_SAYADSPARIL3:SWWM_SAYADSPARIL4:SWWM_SAYADSPARIL5:SWWM_SAYAHEADS1:SWWM_SAYAHEADS2:SWWM_SAYAHEADS3:SWWM_SAYAHEADS4:SWWM_SAYAHEADS5:SWWM_SAYAHEADS6:SWWM_SAYABULLS1:SWWM_SAYABULLS2:SWWM_SAYABULLS3:SWWM_SAYABULLS4:SWWM_SAYABULLS5:SWWM_SAYAGREETA1:SWWM_SAYAGREETA2:SWWM_SAYAGREETA3:SWWM_SAYAGREETB1:SWWM_SAYAGREETC1:SWWM_SAYAGREETD1:SWWM_SAYAGREETE1:SWWM_SAYAGREETF1:SWWM_SAYABLOODA1:SWWM_SAYABLOODA2:SWWM_SAYABLOODB1:SWWM_SAYABLOODC1:SWWM_SAYABLOODD1:SWWM_SAYAHYPO1:SWWM_SAYAHYPO2:SWWM_SAYAHYPO3:SWWM_SAYAHYPO4:SWWM_KIRINWORSHIPA1:SWWM_KIRINWORSHIPB1:SWWM_KIRINWORSHIPC1:SWWM_KIRINWORSHIPD1:SWWM_KIRINWORSHIPD2:SWWM_SAYAGAMEA1:SWWM_SAYAGAMEA2:SWWM_SAYAGAMEB1:SWWM_SAYAGAMEC1:SWWM_SAYAMASTERSA1:SWWM_SAYAMASTERSA2:SWWM_SAYAMASTERSB1:SWWM_SAYAMASTERSC1:SWWM_SAYAMASTERSD1:SWWM_SAYAMASTERSE1:SWWM_SAYAMASTERSF1:SWWM_SAYAFIGHTER1:SWWM_SAYAFIGHTER2:SWWM_SAYACLERICA1:SWWM_SAYACLERICA2:SWWM_SAYACLERICB1:SWWM_SAYACLERICC1:SWWM_SAYACLERICC2:SWWM_SAYAMAGE1:SWWM_SAYAMAGE2:SWWM_SAYAMAGE3:SWWM_SAYAMAGE4:SWWM_SAYAKORAXA1:SWWM_SAYAKORAXB1:SWWM_SAYAKORAXC1:SWWM_SAYAKORAXD1:SWWM_SAYAKORAXE1:SWWM_SAYABLIGHTA1:SWWM_SAYABLIGHTB1:SWWM_SAYABLIGHTC1:SWWM_SAYABLIGHTC2:SWWM_SAYACONSTABLEA1:SWWM_SAYACONSTABLEA2:SWWM_SAYACONSTABLEB1:SWWM_SAYACONSTABLEC1:SWWM_SAYACONSTABLED1:SWWM_SAYANAVEA1:SWWM_SAYANAVEA2:SWWM_SAYANAVEB1:SWWM_SAYANAVEC1:SWWM_SAYANAVED1:SWWM_SAYANAVEE1:SWWM_SAYANAVEF1:SWWM_SAYADEATHKINGS1:SWWM_KIRINPUZZLEA1:SWWM_KIRINPUZZLEA2:SWWM_KIRINPUZZLEB1:SWWM_KIRINPUZZLEC1:SWWM_KIRINPUZZLEC2:SWWM_KIRINPUZZLED1:SWWM_KIRINPUZZLED2:SWWM_KIRINPUZZLEE1:SWWM_KIRINPUZZLEE2:SWWM_KIRINPUZZLEF1:SWWM_KIRINPUZZLEF2:SWWM_KIRINPUZZLEF3:SWWM_KIRINPUZZLEG1:SWWM_KIRINPUZZLEH1:SWWM_KIRINPUZZLEI1:SWWM_KIRINPUZZLEI2:SWWM_KIRINPUZZLEJ1:SWWM_KIRINPUZZLEJ2:SWWM_KIRINPUZZLEK1:SWWM_KIRINPUZZLEL1:SWWM_KIRINPUZZLEM1:SWWM_KIRINPUZZLEN1:SWWM_KIRINPUZZLEO1:SWWM_KIRINPUZZLEP1:SWWM_KIRINPUZZLEQ1:SWWM_KIRINPUZZLER1:SWWM_KIRINPUZZLER2:SWWM_KIRINPUZZLER3:SWWM_KIRINPUZZLES1:SWWM_KIRINPUZZLET1:SWWM_KIRINPUZZLEU1:SWWM_ZNVTXT1:SWWM_ZNVTXT2:SWWM_ZNVTXT3:SWWM_ZNVTXT4:SWWM_ZNVTXT5";
|
||||
Array<String> alldlg;
|
||||
alldlg_pack.Split(alldlg,":");
|
||||
let mSmallFont = Font.GetFont('TewiFont');
|
||||
for ( int i=0; i<alldlg.Size(); i++ )
|
||||
{
|
||||
let l = mSmallFont.BreakLines(StringTable.Localize(alldlg[i],false),220);
|
||||
if ( l.Count() > 3 ) Console.Printf("\cg%s exceeds line limit (%d > 3)\c-",alldlg[i],l.Count());
|
||||
else
|
||||
{
|
||||
if ( !e.Args[0] )
|
||||
{
|
||||
l.Destroy();
|
||||
continue;
|
||||
}
|
||||
Console.Printf("\cd%s is within line limit (%d <= 3)\c-",alldlg[i],l.Count());
|
||||
}
|
||||
for ( int j=0; j<l.Count(); j++ ) Console.Printf("> %s",l.StringAt(j));
|
||||
l.Destroy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if ( e.Name ~== "swwmprofilehandler" )
|
||||
{
|
||||
if ( multiplayer && (e.player != Net_Arbitrator) )
|
||||
|
|
|
|||
|
|
@ -163,7 +163,6 @@ Class SWWMStats : SWWMStaticThinker
|
|||
if ( inflictor && inflictor.FindInventory("ParriedBuff") ) which = 'DoomWeapon'; // gross hack
|
||||
// properly credit some projectiles to their respective gun
|
||||
else if ( inflictor is 'AirBullet' ) which = 'DeepImpact';
|
||||
else if ( inflictor is 'PusherProjectile' ) which = 'PusherWeapon';
|
||||
else if ( (inflictor is 'ExplodiumMagArm') || (inflictor is 'ExplodiumMagProj') || (inflictor is 'ExplodiumBulletImpact') ) which = 'ExplodiumGun';
|
||||
else if ( ((inflictor is 'SaltImpact') && !inflictor.Args[0]) || ((inflictor is 'SaltBeam') && !inflictor.Args[1]) || (inflictor is 'CorrodeDebuff') || (inflictor is 'CorrosiveFlechette') || ((inflictor is 'TheBall') && !inflictor.special1) || (inflictor is 'GoldenImpact') || (inflictor is 'GoldenSubImpact') || (inflictor is 'GoldenSubSubImpact') ) which = 'Spreadgun';
|
||||
else if ( ((inflictor is 'SaltImpact') && inflictor.Args[0]) || ((inflictor is 'SaltBeam') && inflictor.Args[1]) || ((inflictor is 'TheBall') && inflictor.special1) ) which = 'Wallbuster';
|
||||
|
|
|
|||
|
|
@ -1368,7 +1368,6 @@ Class SWWMUtility
|
|||
{
|
||||
if ( !a.bMISSILE ) return false;
|
||||
if ( a is 'AirBullet' ) return true;
|
||||
if ( a is 'PusherProjectile' ) return true;
|
||||
if ( a is 'ExplodiumMagProj' ) return true;
|
||||
if ( a is 'CorrosiveFlechette' ) return true;
|
||||
if ( a is 'TheBall' ) return true;
|
||||
|
|
@ -2148,20 +2147,13 @@ Class SWWMUtility
|
|||
return c;
|
||||
}
|
||||
|
||||
// melee weapons + extra slot 2 guns (50% chance)
|
||||
// melee weapon + extra slot 2 guns
|
||||
static Class<Weapon> PickSWWMSlot1()
|
||||
{
|
||||
// so the player can recover it if they decided to drop it in a previous map, or they didn't start with it
|
||||
if ( CheckNeedsItem('DeepImpact') ) return 'DeepImpact';
|
||||
bool hasmelee = (!CheckNeedsItem('PusherWeapon')/*||!CheckNeedsItem('ItamexHammer')*/);
|
||||
bool hasallmelee = (!CheckNeedsItem('PusherWeapon')/*&&!CheckNeedsItem('ItamexHammer')*/);
|
||||
bool gunexists = ItemExists('ExplodiumGun',worldonly:true)/*||ItemExists('PlasmaBlast',worldonly:true)*/;
|
||||
// if the player already has a melee weapon, 50% chance to spawn either slot 2 weapon as long as one doesn't exist in the map already
|
||||
// if the player has ALL melee weapons (somehow), that chance becomes 100%
|
||||
if ( hasmelee && !gunexists && (hasallmelee || Random[Replacements](0,1)) )
|
||||
return PickSWWMSlot2();
|
||||
//return PickPair('PusherWeapon','ItamexHammer');
|
||||
return 'PusherWeapon';
|
||||
//if ( CheckNeedsItem('ItamexHammer') ) return 'ItamexHammer';
|
||||
return PickSWWMSlot2();
|
||||
}
|
||||
// pistol spawn, pretty simple
|
||||
static Class<Weapon> PickSWWMSlot2()
|
||||
|
|
@ -2202,13 +2194,16 @@ Class SWWMUtility
|
|||
// second plasma rifle spawn
|
||||
static Class<Weapon> PickSWWMSlot8()
|
||||
{
|
||||
//return PickPair('SilverBullet','MisterRifle');
|
||||
//return PickPair('SilverBullet','RayKhom');
|
||||
return 'SilverBullet';
|
||||
}
|
||||
// first bfg spawn
|
||||
static Class<Weapon> PickSWWMSlot9()
|
||||
{
|
||||
//return PickPair('CandyGun','RayKhom');
|
||||
// 33% chance to still drop another candy gun if it's not at max capacity
|
||||
//if ( !Random[Replacements](0,2) && ItemExists('CandyGun') && CheckNeedsItem('CandyGunSpares',true) )
|
||||
// return 'CandyGun';
|
||||
//return PickPair('CandyGun','MisterRifle');
|
||||
return 'CandyGun';
|
||||
}
|
||||
// second bfg spawn (each weapon can only exist once)
|
||||
|
|
@ -2230,7 +2225,7 @@ Class SWWMUtility
|
|||
static Class<Weapon> PickDoomSlot6()
|
||||
{
|
||||
bool hasslot7 = (!CheckNeedsItem('Sparkster')/*||!CheckNeedsItem('ModernSparkster')*/);
|
||||
bool hasslot8 = (!CheckNeedsItem('SilverBullet')/*||!CheckNeedsItem('MortalRifle')*/);
|
||||
bool hasslot8 = (!CheckNeedsItem('SilverBullet')/*||!CheckNeedsItem('RayKhom')*/);
|
||||
// if the player already has a slot 7 weapon...
|
||||
if ( hasslot7 )
|
||||
{
|
||||
|
|
@ -2246,7 +2241,7 @@ Class SWWMUtility
|
|||
// either bfg spawn
|
||||
static Class<Weapon> PickDoomSlot7()
|
||||
{
|
||||
bool hasslot9 = (!CheckNeedsItem('CandyGun')/*||!CheckNeedsItem('RayKhom')*/);
|
||||
bool hasslot9 = (!CheckNeedsItem('CandyGun')/*||!CheckNeedsItem('MisterRifle')*/);
|
||||
bool hasslot0 = (!CheckNeedsItem('Ynykron')/*||!CheckNeedsItem('RafanKos')*/);
|
||||
let rep = PickSWWMSlot0(false);
|
||||
// if the player already has a slot 9 weapon (and a slot 0 weapon can still spawn)...
|
||||
|
|
|
|||
|
|
@ -257,8 +257,8 @@ Class BigPunchImpact : Actor
|
|||
override void PostBeginPlay()
|
||||
{
|
||||
Super.PostBeginPlay();
|
||||
A_QuakeEx(8,8,8,18,0,600,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,falloff:200,rollIntensity:.9);
|
||||
A_StartSound("pusher/althit",CHAN_VOICE,CHANF_DEFAULT,bAMBUSH?.6:1.);
|
||||
A_QuakeEx(8,8,8,18,0,600,"",QF_RELATIVE|QF_SCALEDOWN,falloff:200,rollIntensity:.9);
|
||||
A_StartSound("demolitionist/xpunch",CHAN_VOICE,CHANF_DEFAULT,bAMBUSH?.6:1.);
|
||||
A_SprayDecal("BigWallCrack",-20);
|
||||
int numpt = Random[Ponch](9,16);
|
||||
if ( bAMBUSH ) numpt /= 3;
|
||||
|
|
|
|||
|
|
@ -457,8 +457,8 @@ extend Class SWWMWeapon
|
|||
A_QuakeEx(quakin/2,quakin/2,quakin/2,3,0,1,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,rollIntensity:0.06*quakin);
|
||||
if ( raging && !(flags&MELEE_ForceSound) )
|
||||
{
|
||||
if ( blooded ) A_StartSound("pusher/altmeat",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
if ( bloodless ) A_StartSound("pusher/althit",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
if ( blooded ) A_StartSound("demolitionist/xpunchf",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
if ( bloodless ) A_StartSound("demolitionist/xpunch",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
}
|
||||
else if ( hitsound == "" )
|
||||
{
|
||||
|
|
@ -546,7 +546,7 @@ extend Class SWWMWeapon
|
|||
int quakin = raging?4:1;
|
||||
A_QuakeEx(quakin,quakin,quakin,3,0,1,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,rollIntensity:0.12*quakin);
|
||||
A_BumpFOV(.98);
|
||||
A_StartSound((raging&&!(flags&MELEE_ForceSound))?"pusher/althit":(hitsound!="")?hitsound:"demolitionist/punch",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
A_StartSound((raging&&!(flags&MELEE_ForceSound))?"demolitionist/xpunch":(hitsound!="")?hitsound:"demolitionist/punch",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
A_AlertMonsters(swwm_uncapalert?0:100);
|
||||
if ( raging ) raging.DoHitFX();
|
||||
if ( (flags&MELEE_ForceBust) || swwm_omnibust ) BusterWall.BustLinetrace(d,raging?(dmg*8):dmg,self,d.HitDir,d.HitLocation.z);
|
||||
|
|
|
|||
|
|
@ -1,399 +0,0 @@
|
|||
// Tach-Engine Technologies Microfusion Rotary Hammer aka "Pusher" (planned for unreleased Zanaveth Ultra Suite 2)
|
||||
// Slot 1, replaces Chainsaw, Gauntlets, Timon's Axe
|
||||
|
||||
Class PusherWeapon : SWWMWeapon
|
||||
{
|
||||
double chargelevel, vibe;
|
||||
int hitcnt;
|
||||
|
||||
transient ui DynamicValueInterpolator ChargeInter;
|
||||
|
||||
override void HudTick()
|
||||
{
|
||||
Super.HudTick();
|
||||
if ( !ChargeInter ) ChargeInter = DynamicValueInterpolator.Create(int(chargelevel*100),.5,1,50);
|
||||
ChargeInter.Update(int(chargelevel*100));
|
||||
}
|
||||
|
||||
override bool ReportHUDAmmo()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
override Vector3 GetTraceOffset()
|
||||
{
|
||||
return (10.,2.,-3.5);
|
||||
}
|
||||
|
||||
action void A_PusherDrill()
|
||||
{
|
||||
invoker.chargelevel = clamp(invoker.chargelevel+FRandom[Pusher](-.04,.08),.3,1.);
|
||||
A_QuakeEx(1,1,1,3,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:.5);
|
||||
A_WeaponOffset(FRandom[Pusher](-1,1)*2,32+FRandom[Pusher](-1,1)*2);
|
||||
A_BumpFOV(1.01);
|
||||
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.5*z);
|
||||
FLineTraceData d;
|
||||
LineTrace(angle,60,pitch,TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
|
||||
SWWMBulletTrail.DoTrail(self,origin,x,60,0);
|
||||
if ( d.HitType != TRACE_HitNone )
|
||||
{
|
||||
A_QuakeEx(2,2,2,7,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:.8);
|
||||
A_AlertMonsters(swwm_uncapalert?0:1200);
|
||||
int dmg = int(4+invoker.chargelevel*8);
|
||||
if ( invoker.chargelevel > .4 ) invoker.chargelevel -= FRandom[Pusher](.01,.03);
|
||||
if ( d.HitType == TRACE_HitActor )
|
||||
{
|
||||
double diff = deltaangle(self.angle,AngleTo(d.HitActor));
|
||||
self.angle += clamp(diff,-5.,5.);
|
||||
SWWMUtility.DoKnockback(d.HitActor,d.HitDir,8500);
|
||||
d.HitActor.A_QuakeEx(3,3,3,10,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:1.1);
|
||||
let p = SWWMPuff.Setup(d.HitLocation,d.HitDir,invoker,self,d.HitActor);
|
||||
dmg = d.HitActor.DamageMobj(p,self,dmg,'Tenderize',DMG_THRUSTLESS|DMG_INFLICTOR_IS_PUFF);
|
||||
if ( d.HitActor.bNOBLOOD || d.HitActor.bDORMANT || d.HitActor.bINVULNERABLE )
|
||||
{
|
||||
let p = Spawn("PusherImpact",d.HitLocation-d.HitDir*4);
|
||||
p.angle = atan2(-d.HitDir.y,-d.HitDir.x);
|
||||
p.pitch = asin(d.HitDir.z);
|
||||
}
|
||||
else
|
||||
{
|
||||
d.HitActor.TraceBleed(dmg,invoker);
|
||||
d.HitActor.SpawnBlood(d.HitLocation,atan2(d.HitDir.y,d.HitDir.x)+180,dmg);
|
||||
d.HitActor.A_StartSound("pusher/meat",CHAN_DAMAGE,CHANF_OVERLAP);
|
||||
}
|
||||
// move towards target (unless we're standing on it)
|
||||
if ( !(self is 'Demolitionist') || (Demolitionist(self).oldencroached != d.HitActor) )
|
||||
bJUSTATTACKED = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector3 HitNormal = -d.HitDir;
|
||||
if ( d.HitType == TRACE_HitFloor )
|
||||
{
|
||||
if ( d.Hit3DFloor ) HitNormal = -d.Hit3DFloor.top.Normal;
|
||||
else HitNormal = d.HitSector.floorplane.Normal;
|
||||
}
|
||||
else if ( d.HitType == TRACE_HitCeiling )
|
||||
{
|
||||
if ( d.Hit3DFloor ) HitNormal = -d.Hit3DFloor.bottom.Normal;
|
||||
else HitNormal = d.HitSector.ceilingplane.Normal;
|
||||
}
|
||||
else if ( d.HitType == TRACE_HitWall )
|
||||
{
|
||||
HitNormal = (-d.HitLine.delta.y,d.HitLine.delta.x,0).unit();
|
||||
if ( !d.LineSide ) HitNormal *= -1;
|
||||
d.HitLine.RemoteActivate(self,d.LineSide,SPAC_Impact,d.HitLocation+HitNormal*4);
|
||||
}
|
||||
let p = Spawn("PusherImpact",d.HitLocation+HitNormal*4);
|
||||
p.angle = atan2(HitNormal.y,HitNormal.x);
|
||||
p.pitch = asin(-HitNormal.z);
|
||||
if ( d.HitType == TRACE_HitFloor ) p.CheckSplash(40);
|
||||
if ( waterlevel > 2 ) SWWMUtility.DoKnockback(self,-x,30000);
|
||||
}
|
||||
if ( swwm_omnibust ) BusterWall.BustLinetrace(d,dmg,self,d.HitDir,d.HitLocation.z);
|
||||
}
|
||||
else if ( waterlevel > 2 ) SWWMUtility.DoKnockback(self,-x,50000);
|
||||
if ( swwm_extraalert || !(invoker.hitcnt%20) ) A_AlertMonsters(swwm_uncapalert?0:500);
|
||||
invoker.hitcnt++;
|
||||
}
|
||||
|
||||
action void A_PusherAlt()
|
||||
{
|
||||
A_StopSound(CHAN_WEAPON);
|
||||
if ( IsActorPlayingSound(CHAN_WEAPONEXTRA,"pusher/motor") )
|
||||
A_StartSound("pusher/motorend",CHAN_WEAPONEXTRA,CHANF_DEFAULT,pitch:1.5);
|
||||
A_StartSound("pusher/stop",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
A_StartSound("pusher/altfire",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
A_BumpFOV(1.+invoker.chargelevel*.2);
|
||||
A_Recoil(-(2.+4.*invoker.chargelevel)*cos(pitch));
|
||||
A_QuakeEx(2+int(invoker.chargelevel*2),2+int(invoker.chargelevel*2),2+int(invoker.chargelevel*2),3+int(invoker.chargelevel*6),0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:.3+invoker.chargelevel*.7);
|
||||
A_WeaponOffset(0,32);
|
||||
A_Overlay(-9999,null);
|
||||
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.5*z);
|
||||
FLineTraceData d;
|
||||
LineTrace(angle,80,pitch,TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
|
||||
SWWMBulletTrail.DoTrail(self,origin,x,80,0);
|
||||
bool gone = false;
|
||||
if ( d.HitType != TRACE_HitNone )
|
||||
{
|
||||
A_QuakeEx(8,8,8,12,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:.8);
|
||||
A_AlertMonsters(swwm_uncapalert?0:1600);
|
||||
int dmg = int(240*invoker.chargelevel);
|
||||
if ( d.HitType == TRACE_HitActor )
|
||||
{
|
||||
double diff = deltaangle(self.angle,AngleTo(d.HitActor));
|
||||
self.angle += clamp(diff,-5.,5.);
|
||||
SWWMUtility.DoKnockback(d.HitActor,d.HitDir,85000);
|
||||
d.HitActor.A_QuakeEx(9,9,9,15,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:1.1);
|
||||
let p = SWWMPuff.Setup(d.HitLocation,d.HitDir,invoker,self,d.HitActor);
|
||||
dmg = d.HitActor.DamageMobj(p,self,dmg,'Tenderize',DMG_THRUSTLESS|DMG_INFLICTOR_IS_PUFF);
|
||||
if ( d.HitActor.bNOBLOOD || d.HitActor.bDORMANT || d.HitActor.bINVULNERABLE )
|
||||
{
|
||||
let p = Spawn("BigPusherImpact",d.HitLocation-d.HitDir*4);
|
||||
p.angle = atan2(-d.HitDir.y,-d.HitDir.x);
|
||||
p.pitch = asin(d.HitDir.z);
|
||||
}
|
||||
else
|
||||
{
|
||||
d.HitActor.TraceBleed(dmg,invoker);
|
||||
d.HitActor.SpawnBlood(d.HitLocation,atan2(d.HitDir.y,d.HitDir.x)+180,dmg);
|
||||
d.HitActor.A_StartSound("pusher/altmeat",CHAN_DAMAGE,CHANF_OVERLAP);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector3 HitNormal = -d.HitDir;
|
||||
if ( d.HitType == TRACE_HitFloor )
|
||||
{
|
||||
if ( d.Hit3DFloor ) HitNormal = -d.Hit3DFloor.top.Normal;
|
||||
else HitNormal = d.HitSector.floorplane.Normal;
|
||||
}
|
||||
else if ( d.HitType == TRACE_HitCeiling )
|
||||
{
|
||||
if ( d.Hit3DFloor ) HitNormal = -d.Hit3DFloor.bottom.Normal;
|
||||
else HitNormal = d.HitSector.ceilingplane.Normal;
|
||||
}
|
||||
else if ( d.HitType == TRACE_HitWall )
|
||||
{
|
||||
HitNormal = (-d.HitLine.delta.y,d.HitLine.delta.x,0).unit();
|
||||
if ( !d.LineSide ) HitNormal *= -1;
|
||||
d.HitLine.RemoteActivate(self,d.LineSide,SPAC_Impact,d.HitLocation+HitNormal*4);
|
||||
}
|
||||
let p = Spawn("BigPusherImpact",d.HitLocation+HitNormal*4);
|
||||
p.angle = atan2(HitNormal.y,HitNormal.x);
|
||||
p.pitch = asin(-HitNormal.z);
|
||||
if ( d.HitType == TRACE_HitFloor ) p.CheckSplash(40);
|
||||
}
|
||||
if ( swwm_omnibust ) BusterWall.BustLinetrace(d,dmg,self,d.HitDir,d.HitLocation.z);
|
||||
}
|
||||
else if ( !Random[Pusher](0,3-int(invoker.chargelevel*3)) )
|
||||
{
|
||||
// didn't hit anything, randomly slip off
|
||||
player.SetPSprite(PSP_WEAPON,ResolveState("AltMiss"));
|
||||
invoker.bNODEATHDESELECT = true; // prevent any glitching that could happen if the sequence is interrupted
|
||||
A_StopSound(CHAN_WEAPON);
|
||||
A_StopSound(CHAN_WEAPONEXTRA);
|
||||
A_StartSound("pusher/miss",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
let p = Spawn("PusherProjectile",origin);
|
||||
p.angle = angle;
|
||||
p.pitch = pitch;
|
||||
p.vel = x*p.speed*invoker.chargelevel;
|
||||
p.target = self;
|
||||
SWWMUtility.DoKnockback(self,x,85000.);
|
||||
}
|
||||
A_AlertMonsters(swwm_uncapalert?0:1200);
|
||||
invoker.chargelevel = 0.;
|
||||
}
|
||||
|
||||
action void A_BeginCharge()
|
||||
{
|
||||
invoker.chargelevel = invoker.vibe = 0.;
|
||||
A_WeaponOffset(0,32);
|
||||
A_QuakeEx(1,1,1,33,0,1,"",QF_RELATIVE|QF_SCALEUP,rollIntensity:.5);
|
||||
A_Overlay(-9999,"Dummy");
|
||||
}
|
||||
|
||||
action void A_ChargeUp()
|
||||
{
|
||||
invoker.chargelevel = min(1.,invoker.chargelevel+.025);
|
||||
if ( invoker.chargelevel >= .5 ) invoker.vibe = min(1.,invoker.vibe+.02);
|
||||
A_WeaponOffset(FRandom[Pusher](-1,1)*(invoker.chargelevel-invoker.vibe),32+FRandom[Pusher](-1,1)*(invoker.chargelevel-invoker.vibe));
|
||||
if ( !(player.cmd.buttons&BT_ALTATTACK) && (invoker.chargelevel > .3) )
|
||||
player.SetPSprite(PSP_WEAPON,ResolveState("AltRelease"));
|
||||
}
|
||||
|
||||
override void MarkPrecacheSounds()
|
||||
{
|
||||
Super.MarkPrecacheSounds();
|
||||
MarkSound("pusher/select");
|
||||
MarkSound("pusher/deselect");
|
||||
MarkSound("pusher/motor");
|
||||
MarkSound("pusher/motorend");
|
||||
MarkSound("pusher/start");
|
||||
MarkSound("pusher/drill");
|
||||
MarkSound("pusher/hit1");
|
||||
MarkSound("pusher/hit2");
|
||||
MarkSound("pusher/hit3");
|
||||
MarkSound("pusher/meat1");
|
||||
MarkSound("pusher/meat2");
|
||||
MarkSound("pusher/meat3");
|
||||
MarkSound("pusher/end");
|
||||
MarkSound("pusher/checkout");
|
||||
MarkSound("pusher/pullback");
|
||||
MarkSound("pusher/altfire1");
|
||||
MarkSound("pusher/altfire2");
|
||||
MarkSound("pusher/miss");
|
||||
MarkSound("pusher/althit1");
|
||||
MarkSound("pusher/althit2");
|
||||
MarkSound("pusher/altmeat1");
|
||||
MarkSound("pusher/altmeat2");
|
||||
MarkSound("pusher/fly");
|
||||
MarkSound("pusher/bounce1");
|
||||
MarkSound("pusher/bounce2");
|
||||
MarkSound("pusher/bounce3");
|
||||
}
|
||||
|
||||
Default
|
||||
{
|
||||
//$Title Pusher
|
||||
//$Group Weapons
|
||||
//$Sprite graphics/HUD/Icons/W_Pusher.png
|
||||
//$Icon weapon
|
||||
Tag "$T_PUSHER";
|
||||
Inventory.PickupMessage "$I_PUSHER";
|
||||
Obituary "$O_PUSHER";
|
||||
SWWMWeapon.Tooltip "$TT_PUSHER";
|
||||
SWWMWeapon.GetLine "getpusherweapon";
|
||||
Inventory.Icon "graphics/HUD/Icons/W_Pusher.png";
|
||||
Weapon.UpSound "pusher/select";
|
||||
Weapon.SlotNumber 1;
|
||||
Weapon.SlotPriority 2.;
|
||||
Weapon.SelectionOrder 1500;
|
||||
Stamina 10000;
|
||||
+WEAPON.MELEEWEAPON;
|
||||
//+WEAPON.NOAUTOSWITCHTO;
|
||||
Radius 20;
|
||||
Height 32;
|
||||
}
|
||||
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
XZW1 A -1;
|
||||
Stop;
|
||||
Select:
|
||||
XZW2 G 2 A_FullRaise();
|
||||
XZW2 HIJKL 2;
|
||||
Goto Ready;
|
||||
Ready:
|
||||
XZW2 A 1 A_WeaponReady(WRF_ALLOWRELOAD|WRF_ALLOWZOOM|WRF_ALLOWUSER1);
|
||||
Wait;
|
||||
Fire:
|
||||
XZW2 A 2
|
||||
{
|
||||
A_WeaponOffset(0,32);
|
||||
invoker.chargelevel = .2;
|
||||
invoker.hitcnt = 0;
|
||||
A_StartSound("pusher/start",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
A_StartSound("pusher/motor",CHAN_WEAPONEXTRA,CHANF_LOOP,pitch:1.5);
|
||||
}
|
||||
XZW2 M 2;
|
||||
XZW2 N 0 A_StartSound("pusher/drill",CHAN_WEAPONEXTRA2,CHANF_LOOP);
|
||||
Hold:
|
||||
XZW2 N 1
|
||||
{
|
||||
A_WeaponOffset(FRandom[Pusher](-1,1),32+FRandom[Pusher](-1,1));
|
||||
A_Recoil(cos(pitch));
|
||||
}
|
||||
XZW2 O 1 A_PusherDrill();
|
||||
XZW2 P 1
|
||||
{
|
||||
A_WeaponOffset(FRandom[Pusher](-1,1),32+FRandom[Pusher](-1,1));
|
||||
A_Recoil(cos(pitch));
|
||||
}
|
||||
XZW2 Q 1 A_PusherDrill();
|
||||
XZW2 R 1
|
||||
{
|
||||
A_WeaponOffset(FRandom[Pusher](-1,1),32+FRandom[Pusher](-1,1));
|
||||
A_Recoil(cos(pitch));
|
||||
}
|
||||
XZW2 S 1 A_PusherDrill();
|
||||
XZW2 N 2
|
||||
{
|
||||
if ( player.cmd.buttons&BT_ATTACK )
|
||||
return ResolveState("Hold");
|
||||
invoker.chargelevel *= .4;
|
||||
A_Recoil(.5*cos(pitch));
|
||||
A_ClearRefire();
|
||||
A_WeaponOffset(0,32);
|
||||
A_StopSound(CHAN_WEAPONEXTRA2);
|
||||
A_StartSound("pusher/stop",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
A_StartSound("pusher/motorend",CHAN_WEAPONEXTRA,CHANF_DEFAULT,pitch:1.5);
|
||||
return ResolveState(null);
|
||||
}
|
||||
XZW2 T 2 { invoker.chargelevel = 0.; }
|
||||
Goto Ready;
|
||||
Dummy:
|
||||
TNT1 A 1 A_ChargeUp();
|
||||
Wait;
|
||||
AltFire:
|
||||
XZW2 A 2
|
||||
{
|
||||
A_StartSound("pusher/start",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
A_StartSound("pusher/motor",CHAN_WEAPONEXTRA,CHANF_LOOP,pitch:1.5);
|
||||
A_StartSound("pusher/pullback",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
}
|
||||
XZW2 UVW 2;
|
||||
XZW2 X 0 A_BeginCharge();
|
||||
XZW2 XYZ 3;
|
||||
XZW3 ABCDEFG 3;
|
||||
XZW3 H 0
|
||||
{
|
||||
A_QuakeEx(1,1,1,8,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:.5);
|
||||
A_StartSound("pusher/motorend",CHAN_WEAPONEXTRA,CHANF_DEFAULT,pitch:1.5);
|
||||
}
|
||||
XZW3 H 3;
|
||||
Wait;
|
||||
AltRelease:
|
||||
#### # 1 A_PusherAlt();
|
||||
XZW5 R 2;
|
||||
XZW3 IJKL 2;
|
||||
XZW3 MNOP 3;
|
||||
Goto Ready;
|
||||
AltMiss:
|
||||
XZW3 QRSTUVW 1;
|
||||
TNT1 A -1
|
||||
{
|
||||
invoker.bNODEATHDESELECT = false;
|
||||
let nw = player.mo.PickNextWeapon();
|
||||
// gross hack (don't prioritize Deep Impact if we have something better than it)
|
||||
if ( nw is 'DeepImpact' )
|
||||
{
|
||||
player.ReadyWeapon = nw;
|
||||
nw = player.mo.PickNextWeapon();
|
||||
player.ReadyWeapon = invoker;
|
||||
}
|
||||
if ( nw != invoker ) player.PendingWeapon = nw;
|
||||
RemoveInventory(invoker);
|
||||
invoker.Destroy();
|
||||
}
|
||||
Stop;
|
||||
Reload:
|
||||
Zoom:
|
||||
XZW2 A 2
|
||||
{
|
||||
A_StartSound("pusher/checkout",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
A_PlayerCheckGun();
|
||||
}
|
||||
XZW3 XYZ 2;
|
||||
XZW4 ABCDEFGHIJKLMNOPQR 2;
|
||||
XZW4 STUVWXYZ 3;
|
||||
Goto Ready;
|
||||
User1:
|
||||
XZW2 A 2
|
||||
{
|
||||
A_StartSound("demolitionist/wswing",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
A_PlayerMelee();
|
||||
}
|
||||
XZW5 ABC 2;
|
||||
XZW5 D 1 A_Parry(9);
|
||||
XZW5 EFGH 1;
|
||||
XZW5 I 0 A_Melee(70,"demolitionist/whitl",1.1,1.2,1.2);
|
||||
XZW5 IJ 2;
|
||||
XZW5 K 2 { invoker.PlayUpSound(self); }
|
||||
XZW5 LM 2;
|
||||
XZW5 NOPQ 3;
|
||||
Goto Ready;
|
||||
Deselect:
|
||||
XZW2 B 2 A_StartSound("pusher/deselect",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
XZW2 CDEF 2;
|
||||
XZW2 F -1 A_FullLower();
|
||||
Stop;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,376 +0,0 @@
|
|||
// Pusher projectiles and effects
|
||||
|
||||
Class PusherImpact : Actor
|
||||
{
|
||||
Default
|
||||
{
|
||||
Radius 0.1;
|
||||
Height 0;
|
||||
+NOGRAVITY;
|
||||
+NOCLIP;
|
||||
+NOTELEPORT;
|
||||
+NOINTERACTION;
|
||||
}
|
||||
override void PostBeginPlay()
|
||||
{
|
||||
Super.PostBeginPlay();
|
||||
A_QuakeEx(2,2,2,12,0,200,"",QF_RELATIVE|QF_SCALEDOWN,falloff:100,rollIntensity:.3);
|
||||
A_StartSound("pusher/hit",CHAN_VOICE);
|
||||
A_SprayDecal("WallCrack",-20);
|
||||
int numpt = Random[Pusher](1,3);
|
||||
Vector3 x = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
|
||||
for ( int i=0; i<numpt; i++ )
|
||||
{
|
||||
Vector3 pvel = (x+(FRandom[Pusher](-.8,.8),FRandom[Pusher](-.8,.8),FRandom[Pusher](-.8,.8))).unit()*FRandom[Pusher](.1,1.2);
|
||||
let s = Spawn("SWWMSmoke",pos);
|
||||
s.vel = pvel;
|
||||
s.SetShade(Color(1,1,1)*Random[Pusher](128,192));
|
||||
}
|
||||
numpt = Random[Pusher](0,2);
|
||||
for ( int i=0; i<numpt; i++ )
|
||||
{
|
||||
Vector3 pvel = (FRandom[Pusher](-1,1),FRandom[Pusher](-1,1),FRandom[Pusher](-1,1)).unit()*FRandom[Pusher](2,8);
|
||||
let s = Spawn("SWWMSpark",pos);
|
||||
s.vel = pvel;
|
||||
}
|
||||
numpt = Random[Pusher](1,3);
|
||||
for ( int i=0; i<numpt; i++ )
|
||||
{
|
||||
Vector3 pvel = (FRandom[Pusher](-1,1),FRandom[Pusher](-1,1),FRandom[Pusher](-1,1)).unit()*FRandom[Pusher](2,8);
|
||||
let s = Spawn("SWWMChip",pos);
|
||||
s.vel = pvel;
|
||||
}
|
||||
Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
Class BigPusherImpact : Actor
|
||||
{
|
||||
Default
|
||||
{
|
||||
Radius 0.1;
|
||||
Height 0;
|
||||
+NOGRAVITY;
|
||||
+NOCLIP;
|
||||
+NOTELEPORT;
|
||||
+NOINTERACTION;
|
||||
}
|
||||
override void PostBeginPlay()
|
||||
{
|
||||
Super.PostBeginPlay();
|
||||
A_QuakeEx(5,5,5,15,0,300,"",QF_RELATIVE|QF_SCALEDOWN,falloff:200,rollIntensity:.8);
|
||||
A_StartSound("pusher/althit",CHAN_VOICE);
|
||||
A_SprayDecal("ImpactMark",-20);
|
||||
int numpt = Random[Pusher](8,16);
|
||||
Vector3 x = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
|
||||
for ( int i=0; i<numpt; i++ )
|
||||
{
|
||||
Vector3 pvel = (x+(FRandom[Pusher](-.8,.8),FRandom[Pusher](-.8,.8),FRandom[Pusher](-.8,.8))).unit()*FRandom[Pusher](.8,2.6);
|
||||
let s = Spawn("SWWMSmoke",pos);
|
||||
s.vel = pvel;
|
||||
s.SetShade(Color(1,1,1)*Random[Pusher](128,192));
|
||||
}
|
||||
numpt = Random[Pusher](4,10);
|
||||
for ( int i=0; i<numpt; i++ )
|
||||
{
|
||||
Vector3 pvel = (FRandom[Pusher](-1,1),FRandom[Pusher](-1,1),FRandom[Pusher](-1,1)).unit()*FRandom[Pusher](2,12);
|
||||
let s = Spawn("SWWMSpark",pos);
|
||||
s.vel = pvel;
|
||||
}
|
||||
numpt = Random[Pusher](8,20);
|
||||
for ( int i=0; i<numpt; i++ )
|
||||
{
|
||||
Vector3 pvel = (FRandom[Pusher](-1,1),FRandom[Pusher](-1,1),FRandom[Pusher](-1,1)).unit()*FRandom[Pusher](2,16);
|
||||
let s = Spawn("SWWMChip",pos);
|
||||
s.vel = pvel;
|
||||
}
|
||||
Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
Class PusherProjectile : Actor
|
||||
{
|
||||
Vector3 oldvel;
|
||||
double oldangle, oldpitch;
|
||||
Actor lasthit;
|
||||
int hittics;
|
||||
bool bUsePickup;
|
||||
|
||||
Default
|
||||
{
|
||||
Obituary "$O_PUSHER";
|
||||
Speed 50;
|
||||
Radius 10;
|
||||
Height 10;
|
||||
DamageFunction clamp(int(4*vel.length()),0,200);
|
||||
DamageType 'Tenderize';
|
||||
BounceType "Hexen";
|
||||
BounceFactor 1.0;
|
||||
WallBounceFactor 1.0;
|
||||
Gravity 0.3;
|
||||
PROJECTILE;
|
||||
+USEBOUNCESTATE;
|
||||
+CANBOUNCEWATER;
|
||||
+INTERPOLATEANGLES;
|
||||
+DONTBOUNCEONSHOOTABLES;
|
||||
-BOUNCEAUTOOFF;
|
||||
+NODAMAGETHRUST;
|
||||
-BOUNCEONUNRIPPABLES;
|
||||
-ALLOWBOUNCEONACTORS;
|
||||
+RIPPER;
|
||||
-NOGRAVITY;
|
||||
}
|
||||
override void PostBeginPlay()
|
||||
{
|
||||
Super.PostBeginPlay();
|
||||
A_StartSound("pusher/fly",CHAN_BODY,CHANF_LOOP,1.,2.);
|
||||
A_StartSound("pusher/altfire",CHAN_VOICE);
|
||||
oldvel = vel;
|
||||
oldangle = angle;
|
||||
oldpitch = pitch;
|
||||
}
|
||||
void A_Reorient()
|
||||
{
|
||||
oldvel = vel;
|
||||
oldangle = angle;
|
||||
oldpitch = pitch;
|
||||
if ( vel.length() <= 0. ) return;
|
||||
Vector3 dir = vel.unit();
|
||||
angle += clamp(deltaangle(angle,atan2(dir.y,dir.x)),-2,2);
|
||||
pitch += clamp(deltaangle(pitch,asin(-dir.z)),-2,2);
|
||||
// cancel if we hit a wall dead-on
|
||||
FLineTraceData d;
|
||||
LineTrace(oldangle,30,oldpitch,TRF_THRUACTORS|TRF_NOSKY,5,data:d);
|
||||
if ( d.HitType != TRACE_HitNone )
|
||||
{
|
||||
angle = oldangle;
|
||||
pitch = oldpitch;
|
||||
ClearBounce();
|
||||
special1 = 1;
|
||||
ExplodeMissile(BlockingLine,BlockingMobj);
|
||||
}
|
||||
}
|
||||
private bool HitSkyLine( Line l, int hitside )
|
||||
{
|
||||
if ( !l ) return false;
|
||||
// if it's onesided, check if it's a Line_Horizon
|
||||
if ( !l.sidedef[1] ) return (l.special == Line_Horizon);
|
||||
Sector outs, ins;
|
||||
if ( hitside )
|
||||
{
|
||||
ins = l.backsector;
|
||||
outs = l.frontsector;
|
||||
}
|
||||
else
|
||||
{
|
||||
ins = l.frontsector;
|
||||
outs = l.backsector;
|
||||
}
|
||||
// return true if we're in a sector with sky and we hit the upper part of the line
|
||||
if ( ins.GetTexture(1) != skyflatnum ) return false;
|
||||
return (outs.ceilingplane.ZAtPoint(pos.xy) <= pos.z);
|
||||
}
|
||||
void A_HandleBounce()
|
||||
{
|
||||
Vector3 HitNormal = -vel.unit();
|
||||
F3DFloor ff;
|
||||
int lineside = 1;
|
||||
if ( BlockingFloor )
|
||||
{
|
||||
// find closest 3d floor for its normal
|
||||
for ( int i=0; i<BlockingFloor.Get3DFloorCount(); i++ )
|
||||
{
|
||||
if ( !(BlockingFloor.Get3DFloor(i).flags&F3DFloor.FF_SOLID) ) continue;
|
||||
if ( !(BlockingFloor.Get3DFloor(i).top.ZAtPoint(pos.xy) ~== floorz) ) continue;
|
||||
ff = BlockingFloor.Get3DFloor(i);
|
||||
break;
|
||||
}
|
||||
if ( ff ) HitNormal = -ff.top.Normal;
|
||||
else HitNormal = BlockingFloor.floorplane.Normal;
|
||||
}
|
||||
else if ( BlockingCeiling )
|
||||
{
|
||||
// find closest 3d floor for its normal
|
||||
for ( int i=0; i<BlockingCeiling.Get3DFloorCount(); i++ )
|
||||
{
|
||||
if ( !(BlockingCeiling.Get3DFloor(i).flags&F3DFloor.FF_SOLID) ) continue;
|
||||
if ( !(BlockingCeiling.Get3DFloor(i).bottom.ZAtPoint(pos.xy) ~== ceilingz) ) continue;
|
||||
ff = BlockingCeiling.Get3DFloor(i);
|
||||
break;
|
||||
}
|
||||
if ( ff ) HitNormal = -ff.bottom.Normal;
|
||||
else HitNormal = BlockingCeiling.ceilingplane.Normal;
|
||||
}
|
||||
else if ( BlockingLine )
|
||||
{
|
||||
HitNormal = (-BlockingLine.delta.y,BlockingLine.delta.x,0).unit();
|
||||
if ( !SWWMUtility.PointOnLineSide(pos.xy,BlockingLine) )
|
||||
{
|
||||
lineside = 0;
|
||||
HitNormal *= -1;
|
||||
}
|
||||
}
|
||||
else if ( BlockingMobj )
|
||||
{
|
||||
Vector3 diff = level.Vec3Diff(pos,BlockingMobj.pos);
|
||||
if ( (pos.x+radius) <= (BlockingMobj.pos.x-BlockingMobj.radius) )
|
||||
HitNormal = (-1,0,0);
|
||||
else if ( (pos.x-radius) >= (BlockingMobj.pos.x+BlockingMobj.radius) )
|
||||
HitNormal = (1,0,0);
|
||||
else if ( (pos.y+radius) <= (BlockingMobj.pos.y-BlockingMobj.radius) )
|
||||
HitNormal = (0,-1,0);
|
||||
else if ( (pos.y-radius) >= (BlockingMobj.pos.y+BlockingMobj.radius) )
|
||||
HitNormal = (0,1,0);
|
||||
else if ( pos.z >= (BlockingMobj.pos.z+BlockingMobj.height) )
|
||||
HitNormal = (0,0,1);
|
||||
else if ( (pos.z+height) <= BlockingMobj.pos.z )
|
||||
HitNormal = (0,0,-1);
|
||||
}
|
||||
// undo the bounce, we need to hook in our own
|
||||
angle = oldangle;
|
||||
pitch = oldpitch;
|
||||
vel = oldvel;
|
||||
// try to guess if we hit the sky
|
||||
if ( HitSkyLine(BlockingLine,lineside) || (BlockingCeiling && (ceilingpic == skyflatnum)) || (BlockingFloor && (floorpic == skyflatnum)) )
|
||||
{
|
||||
special1 = 0;
|
||||
ExplodeMissile();
|
||||
return;
|
||||
}
|
||||
// re-do the bounce with our formula
|
||||
vel = .8*((vel dot HitNormal)*HitNormal*(-1.8+FRandom[Pusher](.0,.8))+vel);
|
||||
A_StartSound("pusher/bounce",volume:.3);
|
||||
A_AlertMonsters(swwm_uncapalert?0:300);
|
||||
if ( vel.length() < 5 )
|
||||
{
|
||||
special1 = 0;
|
||||
ExplodeMissile();
|
||||
}
|
||||
}
|
||||
void A_BecomePickup()
|
||||
{
|
||||
if ( special1 )
|
||||
{
|
||||
// stuff from direct hit
|
||||
FLineTraceData d;
|
||||
LineTrace(angle,40,pitch,0,5,data:d);
|
||||
Vector3 HitNormal = -d.HitDir;
|
||||
if ( d.HitType == TRACE_HitFloor )
|
||||
{
|
||||
if ( d.Hit3DFloor ) HitNormal = -d.Hit3DFloor.top.Normal;
|
||||
else HitNormal = d.HitSector.floorplane.Normal;
|
||||
}
|
||||
else if ( d.HitType == TRACE_HitCeiling )
|
||||
{
|
||||
if ( d.Hit3DFloor ) HitNormal = -d.Hit3DFloor.bottom.Normal;
|
||||
else HitNormal = d.HitSector.ceilingplane.Normal;
|
||||
}
|
||||
else if ( d.HitType == TRACE_HitWall )
|
||||
{
|
||||
HitNormal = (-d.HitLine.delta.y,d.HitLine.delta.x,0).unit();
|
||||
if ( !d.LineSide ) HitNormal *= -1;
|
||||
}
|
||||
let p = Spawn("BigPusherImpact",d.HitLocation+HitNormal*4);
|
||||
p.angle = atan2(HitNormal.y,HitNormal.x);
|
||||
p.pitch = asin(-HitNormal.z);
|
||||
bool busted = false;
|
||||
if ( swwm_omnibust )
|
||||
{
|
||||
if ( BusterWall.BustLinetrace(d,100,target,d.HitDir,d.HitLocation.z) )
|
||||
busted = true;
|
||||
}
|
||||
if ( busted ) pitch = 0.;
|
||||
else bNOGRAVITY = true;
|
||||
}
|
||||
else pitch = 0;
|
||||
gravity = 1.;
|
||||
ClearBounce();
|
||||
bSPECIAL = true;
|
||||
A_SetSize(20,16);
|
||||
A_ChangeLinkFlags(0);
|
||||
A_StopSound(CHAN_BODY);
|
||||
}
|
||||
override int DoSpecialDamage( Actor target, int damage, Name damagetype )
|
||||
{
|
||||
if ( target == lasthit ) return 0;
|
||||
lasthit = target;
|
||||
if ( target.bNOBLOOD || target.bDORMANT || target.bINVULNERABLE ) A_StartSound("pusher/althit",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
else A_StartSound("pusher/altmeat",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
target.A_QuakeEx(6,6,6,10,0,200,"",QF_RELATIVE|QF_SCALEDOWN,falloff:100,rollIntensity:.7);
|
||||
SWWMUtility.DoKnockback(target,vel.unit(),85000);
|
||||
return damage;
|
||||
}
|
||||
override void Touch( Actor toucher )
|
||||
{
|
||||
if ( toucher.player && swwm_usetopickup && !bUsePickup )
|
||||
return;
|
||||
// cannot pick up swapweapon unless explicitly pressing use
|
||||
let pw = GetDefaultByType("PusherWeapon");
|
||||
SWWMWeapon sw;
|
||||
if ( swwm_swapweapons && (sw = pw.HasSwapWeapon(toucher)) )
|
||||
{
|
||||
if ( toucher.CheckLocalView() )
|
||||
Console.MidPrint(SmallFont,String.Format(StringTable.Localize("$SWWM_SWAPWEAPON"),sw.GetTag(),StringTable.Localize("$T_PUSHER")));
|
||||
return;
|
||||
}
|
||||
let w = toucher.FindInventory("PusherWeapon");
|
||||
if ( toucher.player && w )
|
||||
{
|
||||
let psp = toucher.player.GetPSPrite(PSP_WEAPON);
|
||||
if ( psp && psp.CurState.InStateSequence(w.FindState("AltMiss")) )
|
||||
return;
|
||||
}
|
||||
if ( !toucher.player || !toucher.GiveInventory("PusherWeapon",1) ) return;
|
||||
if ( toucher.CheckLocalView() )
|
||||
{
|
||||
toucher.A_StartSound("misc/w_pkup",CHAN_ITEM,CHANF_NOPAUSE|CHANF_MAYBE_LOCAL);
|
||||
let w = toucher.FindInventory("PusherWeapon");
|
||||
if ( w ) w.PrintPickupMessage(true,w.PickupMessage());
|
||||
}
|
||||
else toucher.A_StartSound("misc/w_pkup",CHAN_ITEM,CHANF_MAYBE_LOCAL);
|
||||
toucher.A_SelectWeapon("PusherWeapon");
|
||||
Spawn("SWWMRedPickupFlash",pos);
|
||||
Destroy();
|
||||
}
|
||||
override bool Used( Actor user )
|
||||
{
|
||||
// test vertical range
|
||||
Vector3 diff = level.Vec3Diff(user.Vec3Offset(0,0,user.Height/2),Vec3Offset(0,0,Height/2));
|
||||
double rang = user.player?PlayerPawn(user.player.mo).UseRange:(user.Height/2);
|
||||
if ( abs(diff.z) > rang ) return false;
|
||||
// if the toucher owns our SwapWeapon, drop it before picking us up
|
||||
let pw = GetDefaultByType("PusherWeapon");
|
||||
SWWMWeapon sw;
|
||||
if ( swwm_swapweapons && (sw = pw.HasSwapWeapon(user)) )
|
||||
{
|
||||
bool swapto = false;
|
||||
if ( sw == user.player.ReadyWeapon ) swapto = true;
|
||||
user.DropInventory(sw);
|
||||
// don't autoswitch just yet (hacky)
|
||||
if ( swapto )
|
||||
{
|
||||
user.player.ReadyWeapon = null;
|
||||
user.player.PendingWeapon = WP_NOCHANGE;
|
||||
}
|
||||
}
|
||||
bUsePickup = true;
|
||||
Touch(user);
|
||||
bUsePickup = false;
|
||||
return bDestroyed;
|
||||
}
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
XZW1 A 1 A_Reorient();
|
||||
Wait;
|
||||
Bounce:
|
||||
XZW1 A 0 A_HandleBounce();
|
||||
Goto Spawn;
|
||||
Death:
|
||||
XZW1 A 0 A_BecomePickup();
|
||||
XZW1 A 1 A_JumpIf(pos.z<=floorz,1);
|
||||
Wait;
|
||||
XZW1 A -1 A_StartSound("pusher/bounce");
|
||||
Stop;
|
||||
}
|
||||
}
|
||||
|
|
@ -1063,7 +1063,7 @@ Class TheBall : Actor
|
|||
override void PostBeginPlay()
|
||||
{
|
||||
Super.PostBeginPlay();
|
||||
A_StartSound("pusher/fly",CHAN_WEAPON,CHANF_LOOP,.6,3.,2.);
|
||||
A_StartSound("spreadgun/ballfly",CHAN_WEAPON,CHANF_LOOP,.6,3.,2.);
|
||||
heat = 1.;
|
||||
}
|
||||
override void Tick()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue