Replaced gib sound (sorry).

Finetuned DoBlast/DoKnockback behavior.
Added separate voice line for friend kills.
HDoom detection.
More sneaky stuff for future Strife compat.
This commit is contained in:
Mari the Deer 2020-04-27 20:05:22 +02:00
commit a9d1f0d691
25 changed files with 341 additions and 39 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Before After
Before After

BIN
graphics/HDScreen.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View file

@ -116,9 +116,6 @@ GOTREDSKUL = "Red Skull Key";
// edited vanilla pickup messages
TXT_DEFAULTPICKUPMSG = "Unidentified Item";
// other edited messages
ENDGAME = "This will trigger the crash handler.\n"
"\n"
"Press Y or N.";
QUITMSG = "You really want to go?\n"
"What a shame...";
QUITMSG1 = "Wow, don't just go and leave,\n"

View file

@ -127,6 +127,12 @@ SWWM_SUBS_DEFAULT_SCOREKILL24 = "Get outta my way.";
SWWM_SUBS_DEFAULT_SCOREKILL25 = "Want some more?";
SWWM_SUBS_DEFAULT_SCOREKILL26 = "Done and done.";
SWWM_SUBS_DEFAULT_SCOREKILL27 = "It's done.";
// oopsies
SWWM_SUBS_DEFAULT_NFRIENDKILL = "4";
SWWM_SUBS_DEFAULT_FRIENDKILL1 = "Oh my god.";
SWWM_SUBS_DEFAULT_FRIENDKILL2 = "My god. I'm so sorry.";
SWWM_SUBS_DEFAULT_FRIENDKILL3 = "Oh god...";
SWWM_SUBS_DEFAULT_FRIENDKILL4 = "Oh my god. Are you alright?";
// getting hurt by monsters
SWWM_SUBS_DEFAULT_NGETHIT = "18";
SWWM_SUBS_DEFAULT_GETHIT1 = "Whatever...";

View file

@ -109,9 +109,6 @@ GOTREDSKUL = "Calavera Llave Roja";
// edited vanilla pickup messages
TXT_DEFAULTPICKUPMSG = "Item No Identificado";
// other edited messages
ENDGAME = "Esto activará el handler de crasheo.\n"
"\n"
"Pulsa Y ó N.";
QUITMSG = "¿En serio quieres irte?\n"
"Pues que pena...";
QUITMSG1 = "Wow, pero no te vayas aun,\n"

View file

@ -117,6 +117,12 @@ SWWM_SUBS_DEFAULT_SCOREKILL24 = "Quita de en medio.";
SWWM_SUBS_DEFAULT_SCOREKILL25 = "¿Quieres más?";
SWWM_SUBS_DEFAULT_SCOREKILL26 = "Hecho y hecho.";
SWWM_SUBS_DEFAULT_SCOREKILL27 = "Hecho.";
// oopsies
SWWM_SUBS_DEFAULT_NFRIENDKILL = "4";
SWWM_SUBS_DEFAULT_FRIENDKILL1 = "Oh dios mío.";
SWWM_SUBS_DEFAULT_FRIENDKILL2 = "Dios mío. Lo siento mucho.";
SWWM_SUBS_DEFAULT_FRIENDKILL3 = "Oh dios...";
SWWM_SUBS_DEFAULT_FRIENDKILL4 = "Oh dios mío. ¿Estás bien?";
// getting hurt by monsters
SWWM_SUBS_DEFAULT_GETHIT1 = "Pues vale...";
SWWM_SUBS_DEFAULT_GETHIT2 = "*suspiro*";

View file

@ -719,7 +719,12 @@ misc/chat2 sounds/menu/chatsnd.ogg
Chat sounds/menu/chatsnd.ogg // hexen what the fuck
misc/sundowner sounds/SUNDOWNER.ogg
misc/emone sounds/EMONE.ogg
misc/gibbed sounds/DEARGODWHY.ogg // probably the "sloppiest" gib sound I've ever heard. thanks, freedoom
misc/gibbed1 sounds/general/Gib1.ogg
misc/gibbed2 sounds/general/Gib2.ogg
misc/gibbed3 sounds/general/Gib3.ogg
misc/gibbed4 sounds/general/Gib4.ogg
misc/gibbed5 sounds/general/Gib5.ogg
$random misc/gibbed { misc/gibbed1 misc/gibbed2 misc/gibbed3 misc/gibbed4 misc/gibbed5 }
misc/underwater sounds/general/uWater1a.ogg
misc/underslime sounds/general/uGoop1.ogg

Binary file not shown.

BIN
sounds/general/Gib1.ogg Normal file

Binary file not shown.

BIN
sounds/general/Gib2.ogg Normal file

Binary file not shown.

BIN
sounds/general/Gib3.ogg Normal file

Binary file not shown.

BIN
sounds/general/Gib4.ogg Normal file

Binary file not shown.

BIN
sounds/general/Gib5.ogg Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,6 +1,6 @@
GameInfo
{
AddEventHandlers = "SWWMFontPreloader", "SWWMCrashHandler", "SWWMBrutalHandler", "SWWMVanillaBossHandler", "SWWMHandler"
AddEventHandlers = "SWWMFontPreloader", "SWWMCrashHandler", "SWWMBrutalHandler", "SWWMHDoomHandler", "SWWMVanillaBossHandler", "SWWMHandler"
PlayerClasses = "Demolitionist"
StatusBarClass = "SWWMStatusBar"
BackpackType = "HammerspaceEmbiggener"

View file

@ -73,11 +73,12 @@ Class SWWMUtility
return (((p.y-l.v1.p.y)*l.delta.x+(l.v1.p.x-p.x)*l.delta.y) > double.epsilon);
}
// not portal aware, will have to fix that later
// sphere intersection check, useful for proximity detection
static bool SphereIntersect( Actor a, Vector3 p, double radius )
{
Vector3 amin = a.pos+(-a.radius,-a.radius,0),
amax = a.pos+(a.radius,a.radius,a.height);
Vector3 ap = p+level.Vec3Diff(p,a.pos); // portal-relative actor position
Vector3 amin = ap+(-a.radius,-a.radius,0),
amax = ap+(a.radius,a.radius,a.height);
double distsq = 0.;
if ( p.x < amin.x ) distsq += (amin.x-p.x)**2;
if ( p.x > amax.x ) distsq += (p.x-amax.x)**2;
@ -87,6 +88,81 @@ Class SWWMUtility
if ( p.z > amax.z ) distsq += (p.z-amax.z)**2;
return (distsq <= (radius**2));
}
// THANKS FOR NOT GIVING US ANY OTHER WAY TO CHECK IF A LOCK NUMBER IS VALID
static bool IsValidLockNum( int l )
{
if ( (l < 1) || (l > 255) ) return true;
Array<Int> valid;
valid.Clear();
for ( int i=0; i<Wads.GetNumLumps(); i++ )
{
String lname = Wads.GetLumpName(i);
if ( !(lname ~== "LOCKDEFS") ) continue;
String data = Wads.ReadLump(i);
Array<String> lines;
lines.Clear();
data.Split(lines,"\n");
for ( int j=0; j<lines.Size(); j++ )
{
if ( lines[j].Left(10) ~== "CLEARLOCKS" ) valid.Clear();
else if ( Lines[j].Left(5) ~== "LOCK " )
{
Array<String> spl;
spl.Clear();
lines[j].Split(spl," ",TOK_SKIPEMPTY);
// check game string (if any)
if ( spl.Size() > 2 )
{
if ( (spl[2] ~== "DOOM") && !(gameinfo.gametype&GAME_Doom) ) continue;
else if ( (spl[2] ~== "HERETIC") && !(gameinfo.gametype&GAME_Heretic) ) continue;
else if ( (spl[2] ~== "HEXEN") && !(gameinfo.gametype&GAME_Hexen) ) continue;
else if ( (spl[2] ~== "STRIFE") && !(gameinfo.gametype&GAME_Strife) ) continue;
else if ( (spl[2] ~== "CHEX") && !(gameinfo.gametype&GAME_Chex) ) continue;
}
valid.Push(spl[1].ToInt());
}
}
}
for ( int i=0; i<valid.Size(); i++ )
{
if ( valid[i] == l ) return true;
}
return false;
}
// wheeeeeeee, let's play a game of "who is who"
static bool IsCivilian( Actor a )
{
if ( a is 'Beggar' )
{
if ( (a.level.mapname ~== "MAP32") && (a is 'Beggar1') )
return false; // Prisoner (sorry but we have to)
return true;
}
if ( a is 'Peasant' )
{
// exclude certain key NPCs
if ( (a.level.mapname ~== "MAP01") && (a is 'Peasant9') )
return false; // Beldin (sorry but we have to)
if ( (a.level.mapname ~== "MAP02") && (a is 'Peasant22') )
return false; // Mourel (fuck that guy)
if ( (a.level.mapname ~== "MAP02") && (a is 'Peasant4') )
return false; // Harris (also fuck that guy)
if ( (a.level.mapname ~== "MAP04") && (a is 'Peasant5') )
return false; // Derwin (fat bastard)
if ( (a.level.mapname ~== "MAP04") && (a is 'Peasant7') )
return false; // Ketrick (THIS IS GARBAGE)
if ( (a.level.mapname ~== "MAP05") && (a is 'Peasant7') )
return false; // Montag (gimme the damn key)
if ( (a.level.mapname ~== "MAP05") && (a is 'Peasant8') )
return false; // Wolenick (gimme a hand)
if ( (a.level.mapname ~== "MAP33") && (a is 'Peasant5') )
return false; // Harris (also fuck that guy)
return true;
}
return false;
}
}
// Stats
@ -1338,7 +1414,11 @@ Class SWWMBulletTrail : LineTracer
t.ShootThroughList.Clear();
t.Trace(pos,level.PointInSector(pos.xy),dir,dist,0);
for ( int i=0; i<t.ShootThroughList.Size(); i++ )
{
t.ShootThroughList[i].Activate(target,0,SPAC_PCross);
if ( t.ShootThroughList[i].special == GlassBreak ) // fuck glass
t.ShootThroughList[i].Activate(target,0,SPAC_Impact);
}
for ( int i=0; i<t.WaterHitList.Size(); i++ )
{
let b = Actor.Spawn("InvisibleSplasher",t.WaterHitList[i].hitpos);
@ -1952,9 +2032,17 @@ Class SWWMHandler : EventHandler
Actor a;
while ( a = Actor(ti.Next()) )
{
if ( !a.player && !a.bIsMonster && !a.bCountKill ) continue;
if ( !a.player && !a.bISMONSTER ) continue;
// ignore the dead
if ( (a.Health <= 0) || a.bKILLED || a.bCORPSE ) continue;
// ignore friends
if ( a.IsFriend(players[consoleplayer].mo) ) continue;
// [Strife] ignore if not in combat
if ( (gameinfo.gametype&GAME_Strife) && !a.bINCOMBAT && !a.bJUSTATTACKED ) continue;
// [Strife] ignore certain classes
if ( (a is 'RatBuddy') || (a is 'Peasant') || (a is 'Beggar') ) continue;
// [Strife] ignore Oracle's spectre while it's inactive
if ( (a is 'AlienSpectre3') && a.InStateSequence(a.CurState,a.FindState("Spawn")) ) continue;
// ignore if not targetted or either actor can't see the other
if ( (a.target != players[consoleplayer].mo)
|| !a.CheckSight(players[consoleplayer].mo)
@ -2070,7 +2158,7 @@ Class SWWMHandler : EventHandler
if ( (e.DamageSource == players[consoleplayer].mo) && (e.Thing.bISMONSTER || e.Thing.player) )
{
// make sure it's not a moth, because otherwise they won't shut up about accidentally hurting them (it happens a lot)
if ( e.Thing.IsFriend(e.DamageSource) && !(e.Thing is 'LampMoth') )
if ( (e.Thing.IsFriend(e.DamageSource) || SWWMUtility.IsCivilian(e.Thing)) && !(e.Thing is 'LampMoth') )
{
if ( !lastcombat || (gametic > lastcombat+20) )
lastcombat = AddOneliner("hitfriend",1,15);
@ -2093,7 +2181,11 @@ Class SWWMHandler : EventHandler
{
highesttic = gametic;
if ( !lastcombat || (gametic > lastcombat+20) )
lastcombat = AddOneliner("scorekill",1,15);
{
if ( e.Thing.IsFriend(e.DamageSource) || SWWMUtility.IsCivilian(e.Thing) )
lastcombat = AddOneliner("friendkill",1,15);
else lastcombat = AddOneliner("scorekill",1,15);
}
}
if ( !e.Thing.default.bCountKill ) // no credits
return;
@ -2272,11 +2364,15 @@ Class SWWMHandler : EventHandler
// oneliner on locked doors
if ( !e.Thing ) return;
int locknum = SWWMUtility.GetLineLock(e.ActivatedLine);
if ( !locknum ) return;
if ( (locknum < 1) || (locknum > 255) ) return;
if ( e.Thing.CheckLocalView() && !e.Thing.CheckKeys(locknum,false,true) )
{
if ( !lastlock || (gametic > lastlock+20) )
lastlock = AddOneliner("locked",2);
{
if ( SWWMUtility.IsValidLockNum(locknum) )
lastlock = AddOneliner("locked",2);
else lastlock = AddOneliner("jammed",2);
}
}
}
@ -2525,7 +2621,6 @@ 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;
// TODO redo these as fake weapons
switch ( e.Args[0] )
{
case 1:
@ -2759,28 +2854,62 @@ Class SWWMHandler : EventHandler
hnd.flashes.push(qf);
}
// Doom's explosions aren't fully 3D
static void DoBlast( Actor Source, double ExplosionRadius, double MomentumTransfer, Actor ignoreme = null )
// Doom's explosions aren't fully 3D in their knockback
static void DoBlast( Actor Source, double ExplosionRadius, double MomentumTransfer, Actor ignoreme = null, bool forceblast = false )
{
BlockThingsIterator bi = BlockThingsIterator.Create(Source,ExplosionRadius);
while ( bi.Next() )
{
Actor a = bi.Thing;
if ( !a || (a == ignoreme) || !a.bSHOOTABLE || !Source.CheckSight(a,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) || (a == Source) || (Source.Distance3D(a) > ExplosionRadius) || a.bCANNOTPUSH || (a.Mass >= 10000000) )
// early checks for self and ignored actor (usually the instigator)
if ( !a || (a == ignoreme) || (a == Source) )
continue;
// can't be affected
if ( !a.bSHOOTABLE && !a.bVULNERABLE )
continue;
// no blasting if no radius dmg (unless forced)
if ( a.bNORADIUSDMG && !Source.bFORCERADIUSDMG && !forceblast )
continue;
// massive, no knockback
if ( a.bCANNOTPUSH || (a.Mass >= 10000000) )
continue;
// check the DONTHARMCLASS/DONTHARMSPECIES flags
if ( !a.player && ((Source.bDONTHARMCLASS && (a.GetClass() == Source.GetClass())) || (Source.bDONTHARMSPECIES && (a.GetSpecies() == Source.GetSpecies()))) )
continue;
// can we see it
if ( !Source.CheckSight(a,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) )
continue;
// make use of GetRadiusDamage to see if it's in range
if ( Source.GetRadiusDamage(a,int(MomentumTransfer),int(ExplosionRadius),oldradiusdmg:Source.bOLDRADIUSDMG) <= 0 )
continue;
// perform our own blasting code, based partially on Unreal's HurtRadius
Vector3 midpoint = a.Vec3Offset(0,0,a.height*0.5);
Vector3 dir = Level.Vec3Diff(Source.pos,midpoint);
double dist = max(1,dir.length());
double damagescale = 1-max(0,(dist-a.radius)/ExplosionRadius);
// intersecting, randomize direction
if ( dir.length() <= double.epsilon )
{
double ang = FRandom[DoBlast](0,360);
double pt = FRandom[DoBlast](-90,90);
dir = (cos(ang)*cos(pt),sin(ang)*cos(pt),-sin(pt));
}
dir = dir/dist;
a.vel += dir*damagescale*(MomentumTransfer/(Thinker.TICRATE*max(50,a.mass)));
Vector3 momentum = dir*damagescale*(MomentumTransfer/Thinker.TICRATE);
momentum /= max(50,a.mass); // cap minimum mass to prevent ridiculously strong pushing
a.vel += momentum;
}
}
// Same for this
static void DoKnockback( Actor Victim, Vector3 HitDirection, double MomentumTransfer )
{
if ( !Victim || !Victim.bSHOOTABLE || Victim.bCANNOTPUSH || (Victim.Mass >= 10000000) ) return;
if ( !Victim )
return;
if ( !Victim.bSHOOTABLE && !Victim.bVULNERABLE )
return;
if ( Victim.bCANNOTPUSH || (Victim.Mass >= 10000000) )
return;
Victim.vel += HitDirection*(MomentumTransfer/(Thinker.TICRATE*max(50,Victim.Mass)));
}
@ -2815,7 +2944,7 @@ Class SWWMCrashHandler : StaticEventHandler
wasinmap = true;
timer = 0;
}
else if ( (gamestate == GS_FULLCONSOLE) && (wasinmap || (timer > 0)) )
else if ( (gamestate == GS_FULLCONSOLE) && ((wasinmap && !players[consoleplayer].viewheight) || (timer > 0)) )
{
wasinmap = false;
if ( timer == 1 )
@ -2883,9 +3012,53 @@ Class SWWMBrutalHandler : StaticEventHandler
override void RenderOverlay( RenderEvent e )
{
if ( !detected ) return;
if ( scr.IsNull() ) scr = TexMan.CheckForTexture("graphics/bdscreen.png",TexMan.Type_Any);
if ( !scr ) scr = TexMan.CheckForTexture("graphics/bdscreen.png",TexMan.Type_Any);
Screen.Dim("Red",(timer/350.)-.2,0,0,Screen.GetWidth(),Screen.GetHeight());
Screen.DrawTexture(scr,false,FRandom[bdscreen](-1,1)*max(timer-40,0)**3*.000003,FRandom[bdscreen](-1,1)*max(timer-40,0)**3*.000003,DTA_VirtualWidth,1280,DTA_VirtualHeight,960,DTA_Alpha,min(1.,timer/50.));
double ar = Screen.GetAspectRatio();
Vector2 tsize = TexMan.GetScaledSize(scr);
Vector2 vsize = (Screen.GetWidth(),Screen.GetHeight());
if ( (tsize.x > vsize.x) || (tsize.y > vsize.y) )
{
double sar = tsize.x/tsize.y;
if ( sar > ar ) vsize = (tsize.x,tsize.x/ar);
else if ( sar < ar ) vsize = (tsize.y*ar,tsize.y);
else vsize = tsize;
}
Screen.DrawTexture(scr,false,(vsize.x-tsize.x)/2.+FRandom[bdscreen](-1,1)*max(timer-40,0)**3*.000003,(vsize.y-tsize.y)/2.+FRandom[bdscreen](-1,1)*max(timer-40,0)**3*.000003,DTA_VirtualWidthF,vsize.x,DTA_VirtualHeightF,vsize.y,DTA_KeepRatio,true,DTA_Alpha,min(1.,timer/50.));
Screen.Dim("Red",(timer/70.)-3.5,0,0,Screen.GetWidth(),Screen.GetHeight());
}
}
// HORNY
Class SWWMHDoomHandler : StaticEventHandler
{
ui TextureID scr;
bool detected;
override void OnRegister()
{
for ( int i=0; i<AllActorClasses.size(); i++ )
{
if ( AllActorClasses[i].GetClassName() != "HDoomPlayer" ) continue;
detected = true;
break;
}
}
override void RenderOverlay( RenderEvent e )
{
if ( !detected ) return;
if ( !scr ) scr = TexMan.CheckForTexture("graphics/hdscreen.png",TexMan.Type_Any);
double ar = Screen.GetAspectRatio();
Vector2 tsize = TexMan.GetScaledSize(scr);
Vector2 vsize = (Screen.GetWidth(),Screen.GetHeight());
if ( (tsize.x > vsize.x) || (tsize.y > vsize.y) )
{
double sar = tsize.x/tsize.y;
if ( sar > ar ) vsize = (tsize.x,tsize.x/ar);
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);
}
}

View file

@ -589,7 +589,7 @@ Class SWWMStatusBar : BaseStatusBar
Screen.DrawTexture(i.Icon,false,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_Alpha,Powerup(i).IsBlinking()?alpha*.5:alpha,DTA_TopOffset,0,DTA_LeftOffset,0);
String nstr = String.Format("%ds",Powerup(i).EffectTics/Thinker.TICRATE);
int len = mTewiFont.mFont.StringWidth(nstr);
Screen.DrawText(mTewiFont.mFont,Font.CR_FIRE,(xx+30)-len,(yy+30)-11,nstr,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_Alpha,Powerup(i).IsBlinking()?alpha*.5:alpha);
Screen.DrawText(mTewiFont.mFont,Font.CR_FIRE,(xx+30)-len,(yy+30)-11,nstr,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,Powerup(i).IsBlinking()?alpha*.5:alpha);
return;
}
if ( (i is 'SWWMLamp') && aspowerup )
@ -597,7 +597,7 @@ Class SWWMStatusBar : BaseStatusBar
Screen.DrawTexture(i.Icon,false,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_Alpha,SWWMLamp(i).isBlinking()?alpha*.5:alpha,DTA_TopOffset,0,DTA_LeftOffset,0);
String nstr = String.Format("%d%%",SWWMLamp(i).Charge);
int len = mTewiFont.mFont.StringWidth(nstr);
Screen.DrawText(mTewiFont.mFont,Font.CR_FIRE,(xx+30)-len,(yy+30)-11,nstr,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_Alpha,SWWMLamp(i).isBlinking()?alpha*.5:alpha);
Screen.DrawText(mTewiFont.mFont,Font.CR_FIRE,(xx+30)-len,(yy+30)-11,nstr,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,SWWMLamp(i).isBlinking()?alpha*.5:alpha);
return;
}
Screen.DrawTexture(i.Icon,false,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_Alpha,alpha,DTA_TopOffset,0,DTA_LeftOffset,0);
@ -607,7 +607,7 @@ Class SWWMStatusBar : BaseStatusBar
if ( (i.Amount > 99999) && !forceamt ) nstr = "99999";
else nstr = String.Format("%d",i.Amount);
int len = mTewiFont.mFont.StringWidth(nstr);
Screen.DrawText(mTewiFont.mFont,Font.CR_FIRE,(xx+30)-len,(yy+30)-11,nstr,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_Alpha,alpha);
Screen.DrawText(mTewiFont.mFont,Font.CR_FIRE,(xx+30)-len,(yy+30)-11,nstr,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alpha);
}
}

View file

@ -35,10 +35,33 @@ Class SWWMArmor : Armor abstract
Super.AttachToOwner(other);
// find last armor that's better than us
Inventory found = null;
bool foundarmor = false;
for ( Inventory i=other.Inv; i; i=i.Inv )
{
if ( i is 'SWWMArmor' ) foundarmor = true;
if ( !(i is 'SWWMArmor') || (i == self) || (SWWMArmor(i).priority < priority) ) continue;
found = i;
Console.Printf("%s is better",i.GetTag());
}
if ( !found && !foundarmor )
{
// check if first item in inventory is health or a sandwich
if ( (other.Inv is 'SWWMHealth') || (other.Inv is 'GrilledCheeseSandwich') )
{
// place ourselves before it
Console.Printf("Moving before %s",other.Inv.GetTag());
Inv = other.Inv;
other.Inv = self;
return;
}
// find first item with health or sandwich after it
for ( Inventory i=other.Inv; i; i=i.Inv )
{
if ( (i == self) || (!(i.Inv is 'SWWMHealth' ) && !(i.Inv is 'GrilledCheeseSandwich')) ) continue;
Console.Printf("%s is right next to %s",i.GetTag(),i.Inv.GetTag());
found = i;
break;
}
}
if ( !found ) return;
// place ourselves right after it
@ -161,6 +184,55 @@ Class SWWMHealth : Inventory abstract
Property GiveHealth : giveme;
override void AttachToOwner( Actor other )
{
Super.AttachToOwner(other);
// find last health item that's better than us
Inventory found = null;
for ( Inventory i=other.Inv; i; i=i.Inv )
{
if ( !(i is 'SWWMHealth') || (i == self) || (GetDefaultByType(SWWMHealth(i).giveme).Amount < GetDefaultByType(giveme).Amount) ) continue;
found = i;
Console.Printf("%s is better",i.GetTag());
}
if ( !found )
{
// find last armor item
for ( Inventory i=other.Inv; i; i=i.Inv )
{
if ( !(i is 'SWWMArmor') ) continue;
found = i;
Console.Printf("Moving next to armor %s",i.GetTag());
}
}
if ( !found )
{
// check if the first item in inventory is a sandwich
if ( other.Inv is 'GrilledCheeseSandwich' )
{
Console.Printf("Moving before %s",other.Inv.GetTag());
// place ourselves before it
Inv = other.Inv;
other.Inv = self;
return;
}
// find first item next to a sandwich
for ( Inventory i=other.Inv; i; i=i.Inv )
{
if ( (i == self) || !(i.Inv is 'GrilledCheeseSandwich') ) continue;
Console.Printf("%s is right next to %s",i.GetTag(),i.Inv.GetTag());
found = i;
break;
}
}
if ( !found ) return;
// place ourselves right after it
Inventory saved = found.Inv;
found.Inv = self;
other.Inv = Inv;
Inv = saved;
}
override bool Use( bool pickup )
{
bool shouldautouse = false;
@ -778,6 +850,7 @@ Class UseList
Class UseLineTracer : LineTracer
{
Array<UseList> uses;
Array<Line> glass;
override ETraceStatus TraceCallback()
{
@ -805,6 +878,8 @@ Class UseLineTracer : LineTracer
{
if ( !Results.HitLine.sidedef[1] || (Results.HitLine.Flags&(Line.ML_BlockHitscan|Line.ML_BlockEverything|Line.ML_BlockUse)) )
return TRACE_Stop;
if ( Results.HitLine.special == GlassBreak ) // fuck glass
glass.Push(Results.HitLine);
return TRACE_Skip;
}
}
@ -971,21 +1046,11 @@ Class SWWMWeapon : Weapon abstract
{
// temporarily disable parry field so we can trace through
if ( invoker.pfield ) invoker.pfield.bSHOOTABLE = false;
let raging = RagekitPower(FindInventory("RagekitPower"));
int maxang = raging?18:12;
for ( int i=0; i<maxang; i++ )
{
if ( TryMelee(angle+i*(45./16),dmg) || TryMelee(angle-i*(45./16),dmg) )
{
if ( invoker.pfield ) invoker.pfield.bSHOOTABLE = true;
return;
}
}
// check for usables
let ut = new("UseLineTracer");
ut.uses.Clear();
ut.glass.Clear();
ut.Trace(Vec3Offset(0,0,player.viewheight),CurSector,(cos(angle)*cos(pitch),sin(angle)*cos(pitch),sin(-pitch)),DEFMELEERANGE,0);
if ( invoker.pfield ) invoker.pfield.bSHOOTABLE = true;
for ( int i=0; i<ut.uses.Size(); i++ )
{
if ( ut.uses[i].hitactor )
@ -1001,6 +1066,22 @@ Class SWWMWeapon : Weapon abstract
if ( !(ut.uses[i].hitline.activation&SPAC_UseThrough) ) break;
}
}
// fuck glass
for ( int i=0; i<ut.glass.Size(); i++ )
{
ut.glass[i].Activate(self,0,SPAC_Impact);
}
let raging = RagekitPower(FindInventory("RagekitPower"));
int maxang = raging?18:12;
for ( int i=0; i<maxang; i++ )
{
if ( TryMelee(angle+i*(45./16),dmg) || TryMelee(angle-i*(45./16),dmg) )
{
if ( invoker.pfield ) invoker.pfield.bSHOOTABLE = true;
return;
}
}
if ( invoker.pfield ) invoker.pfield.bSHOOTABLE = true;
// check for walls instead
FTranslatedLineTarget t;
double slope = AimLineAttack(angle,DEFMELEERANGE,t,0.,ALF_CHECK3D);

View file

@ -62,6 +62,23 @@ Class GrilledCheeseSandwich : Inventory
Super.DoEffect();
if ( Amount <= 0 ) DepleteOrDestroy();
}
override void AttachToOwner( Actor other )
{
Super.AttachToOwner(other);
// find last armor or health item
Inventory found = null;
for ( Inventory i=other.Inv; i; i=i.Inv )
{
if ( !(i is 'SWWMHealth') && !(i is 'SWWMArmor') ) continue;
found = i;
}
if ( !found ) return;
// place ourselves right after it
Inventory saved = found.Inv;
found.Inv = self;
other.Inv = Inv;
Inv = saved;
}
Default
{

View file

@ -647,7 +647,11 @@ Class SaltBeam : Actor
t.ignore = target;
t.Trace(pos,cursector,x,32,TRACE_HitSky);
for ( int i=0; i<t.ShootThroughList.Size(); i++ )
{
t.ShootThroughList[i].Activate(target,0,SPAC_PCross);
if ( t.ShootThroughList[i].special == GlassBreak ) // fuck glass
t.ShootThroughList[i].Activate(target,0,SPAC_Impact);
}
for ( int i=0; i<t.WaterHitList.Size(); i++ )
{
let b = Actor.Spawn("InvisibleSplasher",t.WaterHitList[i].hitpos);
@ -2014,7 +2018,11 @@ Class Spreadgun : SWWMWeapon
action void ProcessTraceHit( SpreadgunTracer t, Vector3 origin, Vector3 dir, int dmg, double mm, Class<Actor> impact = "SpreadImpact", int bc = 1, bool large = false )
{
for ( int i=0; i<t.ShootThroughList.Size(); i++ )
{
t.ShootThroughList[i].Activate(self,0,SPAC_PCross);
if ( t.ShootThroughList[i].special == GlassBreak ) // fuck glass
t.ShootThroughList[i].Activate(target,0,SPAC_Impact);
}
for ( int i=0; i<t.WaterHitList.Size(); i++ )
{
let b = Spawn(large?"InvisibleSplasher":"SmolInvisibleSplasher",t.WaterHitList[i].hitpos);

View file

@ -714,7 +714,11 @@ Class BiosparkBeam : Actor
t.ShootThroughList.Clear();
t.Trace(pos,CurSector,x,speed,TRACE_HitSky);
for ( int i=0; i<t.ShootThroughList.Size(); i++ )
{
t.ShootThroughList[i].Activate(target,0,SPAC_PCross);
if ( t.ShootThroughList[i].special == GlassBreak ) // fuck glass
t.ShootThroughList[i].Activate(target,0,SPAC_Impact);
}
for ( int i=0; i<t.hitlist.Size(); i++ )
{
if ( t.hitlist[i].hitactor is 'BiosparkHitbox' )
@ -1033,7 +1037,11 @@ Class BiosparkArc : Actor
t.ShootThroughList.Clear();
t.Trace(pos,CurSector,x,speed,TRACE_HitSky);
for ( int i=0; i<t.ShootThroughList.Size(); i++ )
{
t.ShootThroughList[i].Activate(target,0,SPAC_PCross);
if ( t.ShootThroughList[i].special == GlassBreak ) // fuck glass
t.ShootThroughList[i].Activate(target,0,SPAC_Impact);
}
for ( int i=0; i<t.hitlist.Size(); i++ )
{
SWWMHandler.DoKnockback(t.hitlist[i].hitactor,-t.hitlist[i].x,GetMissileDamage(0,0)*1000);

View file

@ -106,7 +106,11 @@ Class CandyBeam : Actor
t.ShootThroughList.Clear();
t.Trace(pos,CurSector,x,dist,0);
for ( int i=0; i<t.ShootThroughList.Size(); i++ )
{
t.ShootThroughList[i].Activate(target,0,SPAC_PCross);
if ( t.ShootThroughList[i].special == GlassBreak ) // fuck glass
t.ShootThroughList[i].Activate(target,0,SPAC_Impact);
}
for ( int i=0; i<t.hitlist.Size(); i++ )
{
SWWMHandler.DoKnockback(t.hitlist[i].hitactor,t.hitlist[i].x,12000);