Tag colors and animated face using A_ChangeModel.

This commit is contained in:
Mari the Deer 2022-07-26 18:36:38 +02:00
commit 2d2dcf7ad5
28 changed files with 350 additions and 189 deletions

View file

@ -142,7 +142,7 @@ extend Class SWWMHandler
if ( !lastcombat || (gametic > lastcombat+20) )
{
lastcombat = AddOneliner("hitfriend",1,10);
if ( Demolitionist(e.DamageSource) ) Demolitionist(e.DamageSource).lastsad = gametic;
if ( Demolitionist(e.DamageSource) ) Demolitionist(e.DamageSource).facesad = true;
}
highesttic = gametic;
}
@ -173,7 +173,7 @@ extend Class SWWMHandler
if ( e.Thing.IsFriend(src) )
{
lastcombat = AddOneliner("friendkill",1,5);
if ( Demolitionist(e.DamageSource) ) Demolitionist(e.DamageSource).lastsad = gametic;
if ( Demolitionist(e.DamageSource) ) Demolitionist(e.DamageSource).facesad = true;
}
else if ( (!lastcombat || (gametic > lastcombat+50)) && !SWWMHDoomHandler.IsCuteGirl(e.Thing) ) // [HDoom] don't shout at the girls
{

View file

@ -109,7 +109,7 @@ extend Class SWWMHandler
}
SendNetworkEvent("swwmremoteliner."..onelinersnd,consoleplayer,onelinerlevel);
// hack due to the fact this one can be cancelled early
if ( onelinertype == "falling" ) Demolitionist(players[consoleplayer].mo).lastgrin = gametic;
if ( onelinertype == "falling" ) Demolitionist(players[consoleplayer].mo).facegrin = true;
}
onelinertic = 0;
onelinerspan = 0;

View file

@ -65,19 +65,6 @@ Enum EMiniHUDFontColor
NUM_MINIHUD_COLOR
};
Enum EDemoFaceState
{
FS_DEFAULT,
FS_EVIL,
FS_GRIN,
FS_WINK,
FS_BLINK,
FS_SAD,
FS_PAIN,
FS_OUCH,
FS_DEAD // UNUSED
};
Class SWWMStatusBar : BaseStatusBar
{
TextureID StatusTex, WeaponTex, ScoreTex, InventoryTex, ChatTex[6],
@ -188,10 +175,6 @@ Class SWWMStatusBar : BaseStatusBar
SmoothDynamicValueInterpolator HealthInter, FuelInter, DashInter;
SmoothLinearValueInterpolator LagHealthInter;
EDemoFaceState facestate;
int paindir;
int facetimer;
int blinktime;
transient ui int rss;
override void FlushNotify()
@ -1043,89 +1026,9 @@ Class SWWMStatusBar : BaseStatusBar
qsort_playerscore(a,p+1,h);
}
private void UpdateMugState()
{
let d = Demolitionist(CPlayer.mo);
if ( !d ) return;
// damage handling
if ( d.lastdamagetic && (d.lastdamagetic == gametic) )
{
if ( d.lastdamage > 70 )
{
facestate = FS_OUCH;
facetimer = (d.lastdamagetimer-gametic)+10;
}
else if ( facestate < FS_OUCH )
{
facestate = FS_PAIN;
facetimer = (d.lastdamagetimer-gametic)+10;
paindir = 0;
// paraphrased from vanilla, with some tweaks
if ( CPlayer.attacker && (CPlayer.attacker != d) && d )
{
double atkang = d.AngleTo(CPlayer.attacker);
double angdiff = Actor.deltaangle(CPlayer.mo.angle,atkang);
if ( abs(angdiff) < 135 )
{
if ( angdiff > 45 ) paindir = -1;
else if ( angdiff < -45 ) paindir = 1;
}
}
}
}
if ( d.lastgrin && (d.lastgrin == gametic) && (facestate < FS_SAD) )
{
facestate = FS_GRIN;
facetimer = 50;
}
if ( d.lastwink && (d.lastwink == gametic) && (facestate < FS_SAD) )
{
facestate = FS_WINK;
facetimer = 20;
}
if ( d.lastblink && (d.lastblink == gametic) && (facestate < FS_PAIN) )
{
facestate = FS_BLINK;
facetimer = 30;
}
if ( d.lastsad && (d.lastsad == gametic) && (facestate <= FS_SAD) )
{
facestate = FS_SAD;
facetimer = 50;
}
if ( CPlayer.mo.FindInventory("RagekitPower") && (facestate < FS_PAIN) )
{
facestate = FS_EVIL;
facetimer = 10;
}
if ( facetimer > 0 )
{
facetimer--;
if ( facetimer <= 0 )
{
facestate = FS_DEFAULT;
blinktime = 30;
}
}
if ( !(gametic&1) )
{
if ( blinktime <= 0 )
{
blinktime--;
if ( blinktime < -3 )
{
rss = int(MSTimeF());
blinktime = (abs(GetRandom())%10)?(40+abs(GetRandom())%40):6;
}
}
else blinktime--;
}
}
// separated so they can be auto-ticked by the demolitionist menu
void TickInterpolators()
{
UpdateMugState();
ScoreInter.Update(SWWMCredits.Get(CPlayer));
int hp = CPlayer.Health;
HealthInter.Update(hp);
@ -1553,7 +1456,6 @@ Class SWWMStatusBar : BaseStatusBar
FaceTex[17] = TexMan.CheckForTexture("graphics/HUD/DemoFace_Sad.png",TexMan.Type_Any);
FaceTex[18] = TexMan.CheckForTexture("graphics/HUD/DemoFace_Wink.png",TexMan.Type_Any);
// other expressions will be added when needed
blinktime = 30;
mSmallFont = Font.GetFont('TewiFont');
mBigFont = Font.GetFont('TewiFontOutline');
mTinyFont = Font.GetFont('MiniwiFont');
@ -3026,10 +2928,14 @@ Class SWWMStatusBar : BaseStatusBar
return ((abs(sd)%11)-5)*.1;
}
private int GetFaceTex()
private int GetFaceTex( Demolitionist demo )
{
let facestate = demo.facestate;
let paindir = demo.paindir;
let facetimer = demo.facetimer;
let blinktime = demo.blinktime;
if ( CPlayer.Health <= 0 ) return 11;
if ( (isInvulnerable() || CPlayer.mo.FindInventory("InvinciballPower")) && (facestate >= FS_PAIN) ) return 12;
if ( (isInvulnerable() || demo.FindInventory("InvinciballPower")) && (facestate >= FS_PAIN) ) return 12;
if ( facestate == FS_OUCH ) return 10;
if ( facestate == FS_PAIN ) return (paindir==1)?8:(paindir==-1)?9:7;
if ( facestate == FS_GRIN ) return 5;
@ -3075,7 +2981,7 @@ Class SWWMStatusBar : BaseStatusBar
Screen.DrawTexture(FaceTex[0],false,margin+shake.x,ss.y-(margin+32)+shake.y,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_FillColor,Color(0,0,0),DTA_Alpha,.25*(1.-min(1.,noiz)));
Screen.DrawTexture(FaceTex[1],false,margin+shake.x,ss.y-(margin+32)+shake.y,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_FillColor,Color(255,0,0),DTA_Alpha,.25*min(1.,noiz));
}
Screen.DrawTexture(FaceTex[GetFaceTex()],false,margin+shake.x,ss.y-(margin+32)+shake.y,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
Screen.DrawTexture(FaceTex[GetFaceTex(demo)],false,margin+shake.x,ss.y-(margin+32)+shake.y,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
if ( CPlayer.mo.FindInventory("BarrierPower") ) Screen.DrawTexture(FaceTex[14],false,margin+shake.x,ss.y-(margin+32)+shake.y,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,.5,DTA_LegacyRenderStyle,STYLE_Add);
}

View file

@ -83,7 +83,7 @@ Class SayaBeanGesture : SWWMItemGesture
{
action void A_PreSquish()
{
if ( Demolitionist(self) ) Demolitionist(self).lastgrin = gametic;
if ( Demolitionist(self) ) Demolitionist(self).facegrin = true;
}
action void A_Squish1()
{
@ -259,7 +259,7 @@ Class KirinPlushGesture : SWWMItemGesture
}
action void A_PreKiss()
{
if ( Demolitionist(self) ) Demolitionist(self).lastblink = gametic;
if ( Demolitionist(self) ) Demolitionist(self).faceblink = true;
}
action void A_PetPlush()
{

View file

@ -90,7 +90,7 @@ Class GrilledCheeseSandwich : Inventory
if ( (Owner.player == players[consoleplayer]) && (swwm_mutevoice < 2) )
{
SWWMHandler.AddOneliner("eat",2);
if ( Owner is 'Demolitionist' ) Demolitionist(Owner).lastgrin = gametic;
if ( Owner is 'Demolitionist' ) Demolitionist(Owner).facegrin = true;
}
DoTheThing();
return true;

View file

@ -1,5 +1,18 @@
// The Demolitionist
Enum EDemoFaceState
{
FS_DEFAULT,
FS_EVIL,
FS_GRIN,
FS_WINK,
FS_BLINK,
FS_SAD,
FS_PAIN,
FS_OUCH,
FS_DEAD // UNUSED
};
Class Demolitionist : PlayerPawn
{
int last_jump_held, last_boost, last_kick;
@ -88,12 +101,23 @@ Class Demolitionist : PlayerPawn
int invwipe; // inventory wipe flags for next level
transient int lastbang, lastgrin, lastsad, lastwink, lastblink;
transient int lastbang;
transient bool ingivecheat;
Property DashFuel : dashfuel;
EDemoFaceState facestate;
int paindir;
int facetimer;
int blinktime;
transient int oldfaceidx;
transient int rss;
transient bool facedamage, facegrin, facesad, facewink, faceblink;
transient CVar tagcolor;
transient int oldtagcolor;
Default
{
Tag "$T_DEMOLITIONIST";
@ -128,6 +152,156 @@ Class Demolitionist : PlayerPawn
+DONTDRAIN;
+DONTCORPSE;
}
private int GetRandom()
{
return (rss = (rss<<1)*35447+(rss/87));
}
private void UpdateTags()
{
if ( !tagcolor ) tagcolor = CVar.GetCVar('swwm_tagcolor',player);
static const String colname[] =
{
"",
"Blue",
"Cyan",
"Dragonfly",
"Gold",
"Magenta",
"Orange",
"Peach",
"Pink",
"Purple",
"Red",
"Violet",
"White",
"Yellow"
};
int idx = tagcolor.GetInt();
if ( (idx < 0) || (idx >= colname.Size()) ) idx = 0;
if ( idx != oldtagcolor )
A_ChangeModel("",0,"models","DemolitionistPlayer_d.3d",0,"models","DemoTags"..colname[idx]..".png",CMDL_USESURFACESKIN,0);
oldtagcolor = idx;
}
private void UpdateFace()
{
// damage handling
if ( facedamage )
{
if ( lastdamage > 70 )
{
facestate = FS_OUCH;
facetimer = (lastdamagetimer-gametic)+10;
}
else if ( facestate < FS_OUCH )
{
facestate = FS_PAIN;
facetimer = (lastdamagetimer-gametic)+10;
paindir = 0;
// paraphrased from vanilla, with some tweaks
if ( player.attacker && (player.attacker != self) )
{
double atkang = AngleTo(player.attacker);
double angdiff = deltaangle(angle,atkang);
if ( abs(angdiff) < 135 )
{
if ( angdiff > 45 ) paindir = -1;
else if ( angdiff < -45 ) paindir = 1;
}
}
}
}
facedamage = false;
if ( facegrin && (facestate < FS_SAD) )
{
facestate = FS_GRIN;
facetimer = 50;
}
facegrin = false;
if ( facewink && (facestate < FS_SAD) )
{
facestate = FS_WINK;
facetimer = 20;
}
facewink = false;
if ( faceblink && (facestate < FS_PAIN) )
{
facestate = FS_BLINK;
facetimer = 30;
}
faceblink = false;
if ( facesad && (facestate <= FS_SAD) )
{
facestate = FS_SAD;
facetimer = 50;
}
facesad = false;
if ( FindInventory("RagekitPower") && (facestate < FS_PAIN) )
{
facestate = FS_EVIL;
facetimer = 10;
}
if ( facetimer > 0 )
{
facetimer--;
if ( facetimer <= 0 )
{
facestate = FS_DEFAULT;
blinktime = 30;
}
}
if ( !(gametic&1) )
{
if ( blinktime <= 0 )
{
blinktime--;
if ( blinktime < -3 )
{
rss = int(MSTimeF());
blinktime = (abs(GetRandom())%10)?(40+abs(GetRandom())%40):6;
}
}
else blinktime--;
}
// update our face texture if different
static const String facetex[] =
{
"Blank", "Blink", "Booty", "Dead",
"Default", "Dizzy", "Evil", "Grin",
"Hurt", "HurtLeft", "HurtRight",
"Off", "Ouch", "Sad", "Smug",
"Unamused", "Wink"
};
int faceidx = GetFaceTex();
if ( !oldfaceidx || (faceidx != oldfaceidx) )
A_ChangeModel("",0,"models","DemolitionistPlayer_d.3d",1,"models","DemoFace_"..facetex[faceidx]..".png",CMDL_USESURFACESKIN,0);
oldfaceidx = faceidx;
}
private int GetFaceTex()
{
if ( player.Health <= 0 ) return 3;
if ( (bInvulnerable || (player.cheats&(CF_GODMODE|CF_GODMODE2)) || FindInventory("InvinciballPower")) && (facestate >= FS_PAIN) ) return 14;
if ( facestate == FS_OUCH ) return 12;
if ( facestate == FS_PAIN ) return (paindir==1)?10:(paindir==-1)?9:8;
if ( facestate == FS_GRIN ) return 7;
if ( facestate == FS_EVIL ) return 6;
if ( facestate == FS_SAD ) return 13;
if ( facestate == FS_WINK ) return 16;
if ( facestate == FS_BLINK ) return ((facetimer>28)||(facetimer<2))?15:1;
switch ( blinktime )
{
case -1:
case -3:
return 15;
break;
case -2:
return 1;
break;
}
return 4;
}
// oof
Vector2 NormalizedMove()
{
@ -399,6 +573,7 @@ Class Demolitionist : PlayerPawn
{
Super.PostBeginPlay();
lastground = true; // prevent sudden landing sound on map start
blinktime = 30;
// swap ourselves for a voodoo doll
if ( !player || (player.mo != self) )
{
@ -944,6 +1119,8 @@ Class Demolitionist : PlayerPawn
PoisonDamageReceived = 0;
Super.Tick();
if ( (gamestate != GS_LEVEL) || !player || (player.mo != self) ) return;
UpdateFace();
UpdateTags();
if ( hasteleported )
{
// we just got teleported, don't count the travel distance
@ -1742,6 +1919,7 @@ Class Demolitionist : PlayerPawn
PainChance = oldpchance;
if ( (Health <= 0) && (source == self) && (flags&DMG_EXPLOSION) )
SWWMUtility.MarkAchievement("dime",player);
facedamage = true;
return realdmg;
}
override void CalcHeight()
@ -2278,6 +2456,7 @@ Class Demolitionist : PlayerPawn
player.damagecount = 0;
player.bonuscount = 0;
player.poisoncount = 0;
blinktime = 30;
SetState(FindState("Spawn")+1); // skip tweening
roll = 0;
let s = Spawn("DemolitionistShockwave",pos);
@ -2772,7 +2951,7 @@ Class Demolitionist : PlayerPawn
{
Console.Printf(StringTable.Localize("$SWWM_LASTSECRET"),score);
SWWMHandler.AddOneliner("findsecret",2,40);
lastgrin = gametic;
facegrin = true;
}
else Console.Printf(StringTable.Localize("$SWWM_LASTSECRETREM"),player.GetUserName(),score);
SWWMUtility.AchievementProgressInc("allsecrets",1,player);
@ -2781,7 +2960,7 @@ Class Demolitionist : PlayerPawn
{
Console.Printf(StringTable.Localize("$SWWM_FINDSECRET"),score);
SWWMHandler.AddOneliner("findsecret",2,40);
lastgrin = gametic;
facegrin = true;
}
else Console.Printf(StringTable.Localize("$SWWM_FINDSECRETREM"),player.GetUserName(),score);
SWWMCredits.Give(player,score);
@ -2826,7 +3005,7 @@ Class Demolitionist : PlayerPawn
SWWMHandler.AddOneliner("getweapon",2);
}
else SWWMHandler.AddOneliner("getweapon",2);
lastgrin = gametic;
facegrin = true;
}
}
if ( (item is 'Key') && !key_reentrant && !deathmatch && !bInDefaultInventory )
@ -2847,7 +3026,7 @@ Class Demolitionist : PlayerPawn
SWWMHandler.AddOneliner("keyget",2);
}
else SWWMHandler.AddOneliner("keyget",2);
lastgrin = gametic;
facegrin = true;
}
// share all keys in mp
for ( int i=0; i<MAXPLAYERS; i++ )
@ -2867,7 +3046,7 @@ Class Demolitionist : PlayerPawn
if ( !ingivecheat )
{
SWWMHandler.AddOneliner(SWWMCollectible(item).GetLine,2);
lastgrin = gametic;
facegrin = true;
}
if ( !mystats ) return;
let cls = item.GetClass();
@ -2879,7 +3058,7 @@ Class Demolitionist : PlayerPawn
{
mystats.gotyorick = true;
SWWMHandler.AddOneliner("skullget",2);
lastgrin = gametic;
facegrin = true;
}
// notify key obtained to flash icon
if ( item is 'Key' )
@ -3116,6 +3295,7 @@ Class Demolitionist : PlayerPawn
last_boost = 0;
last_kick = 0;
hasrevived = false;
blinktime = 30;
// cancel dash/boost
A_StopSound(CHAN_JETPACK);
fuelcooldown = 0.;
@ -3455,34 +3635,34 @@ Class Demolitionist : PlayerPawn
Approve:
#### # 3;
XZW5 NOPQR 3;
XZW5 S 3 { lastgrin = gametic; }
XZW5 S 3 { facegrin = true; }
XZW5 TUVWXYZ 3;
XZW6 ABCD 3;
Goto Spawn+1;
Victory:
#### # 3;
XZW6 EFGH 3;
XZW6 I 3 { lastgrin = gametic; }
XZW6 I 3 { facegrin = true; }
XZW6 JKLMNOPQRSTUVW 3;
Goto Spawn+1;
BlowKiss:
#### # 3;
XZWD EFGH 3;
XZWD I 3 { lastblink = gametic; }
XZWD I 3 { faceblink = true; }
XZWD JKLMNO 3;
XZWD P 3 { lastwink = gametic; }
XZWD P 3 { facewink = true; }
XZWD QRSTUVW 3;
Goto Spawn+1;
Headpat:
#### # 3;
XZWH ST 3;
XZWH U 2;
XZWH V 2 { lastgrin = gametic; }
XZWH V 2 { facegrin = true; }
XZWH W 2;
XZWH XYZ 1;
XZWI A 1;
XZWI B 2;
XZWI C 2 { lastgrin = gametic; }
XZWI C 2 { facegrin = true; }
XZWI DE 2;
XZWI FG 1;
HeadpatLoop:
@ -3490,7 +3670,7 @@ Class Demolitionist : PlayerPawn
XZWH XYZ 1;
XZWI A 1;
XZWI B 2;
XZWI C 2 { lastgrin = gametic; }
XZWI C 2 { facegrin = true; }
XZWI DE 2;
XZWI FGH 1;
XZWI IJK 2;
@ -3588,23 +3768,23 @@ Class Demolitionist : PlayerPawn
CrouchApprove:
#### # 3;
XZWF PQRST 3;
XZWF U 3 { lastgrin = gametic; }
XZWF U 3 { facegrin = true; }
XZWF VWXYZ 3;
XZWG ABCDEF 3;
Goto Crouch+1;
CrouchVictory:
#### # 3;
XZWG GHIJ 3;
XZWG K 3 { lastgrin = gametic; }
XZWG K 3 { facegrin = true; }
XZWG LMNOPQRSTUVWXY 3;
Goto Crouch+1;
CrouchBlowKiss:
#### # 3;
XZWG Z 3;
XZWH ABC 3;
XZWH D 3 { lastblink = gametic; }
XZWH D 3 { faceblink = true; }
XZWH EFGHIJ 3;
XZWH K 3 { lastwink = gametic; }
XZWH K 3 { facewink = true; }
XZWH LMNOPQR 3;
Goto Crouch+1;
CrouchMissile:

View file

@ -510,20 +510,13 @@ Class DemolitionistSelfLight : Thinker
{
bool oldactive;
bool oldglow;
transient Color tagcolor;
Actor target;
transient CVar tagcolor;
bool activelight()
{
// active all the time except when invisible or in certain
// animation frames
// active all the time except when invisible
if ( target.bINVISIBLE || (target.alpha <= double.epsilon) ) return false;
if ( target.InStateSequence(target.CurState,target.FindState("Death")) && ((target.frame == 20) || (target.frame == 22) || (target.frame == 23) || (target.frame == 25) || (target.frame == 27) || (target.frame == 28) || (target.frame == 30) || (target.frame == 31) || (target.frame == 32) || (target.frame == 33) || (target.frame == 34)) )
return false;
if ( target.InStateSequence(target.CurState,target.FindState("CrouchDeath")) && ((target.frame == 7) || (target.frame == 10) || (target.frame == 11)) )
return false;
if ( target.InStateSequence(target.CurState,target.FindState("VoodooDeath")) && ((target.frame == 9) || (target.frame == 11) || (target.frame == 12) || (target.frame == 14) || (target.frame == 16) || (target.frame == 18)) )
return false;
return true;
}
override void Tick()
@ -533,18 +526,26 @@ Class DemolitionistSelfLight : Thinker
Destroy();
return;
}
if ( tagcolor.a == 0 )
if ( !tagcolor ) tagcolor = CVar.GetCVar('swwm_tagcolor',target.player);
static const Color litecolor[] =
{
let lmp = Wads.FindLump("tagcolor.txt");
if ( lmp != -1 )
{
String str = Wads.ReadLump(lmp);
Array<String> rgb;
str.Split(rgb,",",0);
tagcolor = Color(255,rgb[0].ToInt(),rgb[1].ToInt(),rgb[2].ToInt());
}
else tagcolor = Color(255,32,48,24);
}
Color(255,32,48,24), // Green
Color(255,24,24,48), // Blue
Color(255,24,48,48), // Cyan
Color(255,24,48,32), // Dragonfly
Color(255,48,40,24), // Gold
Color(255,48,24,48), // Magenta
Color(255,48,32,24), // Orange
Color(255,48,40,32), // Peach
Color(255,48,32,40), // Pink
Color(255,32,24,48), // Purple
Color(255,48,24,24), // Red
Color(255,32,24,48), // Violet
Color(255,48,48,48), // White
Color(255,48,48,24) // Yellow
};
int idx = tagcolor.GetInt();
if ( (idx < 0) || (idx >= litecolor.Size()) ) idx = 0;
bool doselflight = swwm_selflight;
bool curactive = doselflight&&activelight();
// setting the pitch to a value outside [-90,90] makes it auto-update to the actor's own pitch
@ -556,7 +557,7 @@ Class DemolitionistSelfLight : Thinker
target.A_AttachLight('DemoSelfLight',DynamicLight.PointLight,0,0,0);
oldactive = curactive;
bool curglow = doselflight&&(!(target.bINVISIBLE||(target.alpha <= double.epsilon)));
if ( curglow && !oldglow ) target.A_AttachLight('DemoSelfLight2',DynamicLight.PointLight,tagcolor,80,0,DynamicLight.LF_DONTLIGHTSELF|DynamicLight.LF_ATTENUATE,(0,0,target.height/2));
if ( curglow && !oldglow ) target.A_AttachLight('DemoSelfLight2',DynamicLight.PointLight,litecolor[idx],80,0,DynamicLight.LF_DONTLIGHTSELF|DynamicLight.LF_ATTENUATE,(0,0,target.height/2));
else if ( !curglow && oldglow ) target.A_AttachLight('DemoSelfLight2',DynamicLight.PointLight,0,0,0);
oldglow = curglow;
}

View file

@ -63,7 +63,7 @@ Class ExplodiumGun : SWWMWeapon
if ( demo && demo.mystats && !demo.mystats.GotWeapon(SisterWeapon.GetClass()) && (Owner.player == players[consoleplayer]) && !demo.ingivecheat )
{
SWWMHandler.AddOneliner(SWWMWeapon(SisterWeapon).GetLine,2);
demo.lastgrin = gametic;
demo.facegrin = true;
}
item.bPickupGood = true;
}