- Try to get rid of all implicit casts from string to name, color or class. - Use FindClass where needed. - Used a map in a case where a dictionary was unneeded. - Use new bounce flags where needed. - Replace Legacy of Rust weapons/ammo.
784 lines
21 KiB
Text
784 lines
21 KiB
Text
// stuff related to gestures
|
|
|
|
Class HHitList
|
|
{
|
|
Actor a;
|
|
Vector3 dir;
|
|
}
|
|
|
|
enum EGestureSlot
|
|
{
|
|
// special use
|
|
GS_Headpat = -50,
|
|
GS_Grenade,
|
|
GS_EmptyMelee,
|
|
// no gesture
|
|
GS_Null = 0,
|
|
// general gestures
|
|
GS_Wave = 1,
|
|
GS_ThumbsUp,
|
|
GS_Victory,
|
|
GS_BlowKiss
|
|
};
|
|
|
|
// First person gestures
|
|
Class SWWMGesture : SWWMWeapon
|
|
{
|
|
Weapon formerweapon, lastformerweapon;
|
|
int whichgesture, nextgesture;
|
|
bool deaded, queued;
|
|
Class<SWWMItemGesture> whichweapon;
|
|
Array<Class<SWWMItemGesture> > sweapon;
|
|
int gonect;
|
|
HeadpatTracker pats; // for headpat gesture, our current tracker
|
|
|
|
// these should prevent autoswitch when out of ammo
|
|
override bool ReportHUDAmmo()
|
|
{
|
|
return false;
|
|
}
|
|
override bool CheckAmmo( int firemode, bool autoswitch, bool requireammo, int ammocount )
|
|
{
|
|
return false;
|
|
}
|
|
override bool Use( bool pickup )
|
|
{
|
|
return false;
|
|
}
|
|
override bool Used( Actor user )
|
|
{
|
|
return false;
|
|
}
|
|
override void Touch( Actor toucher )
|
|
{
|
|
}
|
|
override void DoEffect()
|
|
{
|
|
Super.DoEffect();
|
|
// show nametag if former weapon changes
|
|
if ( (lastformerweapon != formerweapon) && Owner && (Owner.player == players[consoleplayer]) && (displaynametags&2) )
|
|
EventHandler.SendInterfaceEvent(consoleplayer,"swwmnametag."..formerweapon.GetTag());
|
|
lastformerweapon = formerweapon;
|
|
// if we're supposed to headpat but we're NOT the pending/ready weapon, something's very wrong here
|
|
// try to fix that by force
|
|
if ( pats && Owner && Owner.player && (Owner.player.ReadyWeapon != self) && (Owner.player.PendingWeapon != self) )
|
|
SetGesture(Owner.player.mo,GS_Headpat,true);
|
|
if ( !Owner || !Owner.player || (Owner.player.ReadyWeapon != self) )
|
|
return;
|
|
let psp = Owner.player.FindPSprite(PSP_WEAPON);
|
|
if ( !psp ) return;
|
|
if ( (Owner.Health <= 0) && (psp.CurState != ResolveState('Deselect')) )
|
|
Owner.player.SetPSprite(PSP_WEAPON,ResolveState('Deselect'));
|
|
// check if we're waving at a dying enemy
|
|
if ( (psp.frame >= 3) && (psp.frame <= 12) && (psp.sprite == GetSpriteIndex('XZW1')) )
|
|
CheckWave();
|
|
}
|
|
|
|
private void CheckWave()
|
|
{
|
|
bool breakout = false;
|
|
foreach ( s:level.Sectors )
|
|
{
|
|
for ( Actor a=s.thinglist; a; a=a.snext )
|
|
{
|
|
if ( (a.Health > 0) || (a.tics == -1) || !(a.bISMONSTER || a.player) || !a.IsHostile(Owner) ) continue;
|
|
// check if we can see it
|
|
if ( !SWWMUtility.InPlayerFOV(Owner.player,a) ) continue;
|
|
// someone's dying
|
|
SWWMUtility.MarkAchievement("wave",Owner.player);
|
|
breakout = true;
|
|
break;
|
|
}
|
|
if ( breakout ) break;
|
|
}
|
|
}
|
|
|
|
static SWWMGesture SetGesture( PlayerPawn mo, int which, bool force = false )
|
|
{
|
|
if ( !mo || !(mo is 'Demolitionist') ) return null; // only Demo
|
|
if ( mo.Health <= 0 ) return null; // dead
|
|
if ( !force && (mo.player.cheats&CF_TOTALLYFROZEN) ) return null; // frozen today (unless forced)
|
|
SWWMGesture w = SWWMGesture(mo.FindInventory('SWWMGesture'));
|
|
if ( w && ((mo.player.PendingWeapon is 'SWWMGesture') || (mo.player.ReadyWeapon is 'SWWMGesture')
|
|
|| (mo.player.PendingWeapon is 'SWWMItemGesture') || (mo.player.ReadyWeapon is 'SWWMItemGesture')) )
|
|
{
|
|
// already gesturing
|
|
// just queue another one
|
|
if ( which <= 0 ) return null; // these gestures can't be queued
|
|
else
|
|
{
|
|
w.nextgesture = which;
|
|
w.queued = true;
|
|
}
|
|
return null;
|
|
}
|
|
if ( !w )
|
|
{
|
|
w = SWWMGesture(Spawn('SWWMGesture'));
|
|
w.AttachToOwner(mo);
|
|
}
|
|
if ( mo.player.PendingWeapon != WP_NOCHANGE ) w.formerweapon = mo.player.PendingWeapon;
|
|
else w.formerweapon = mo.player.ReadyWeapon;
|
|
w.lastformerweapon = w.formerweapon;
|
|
w.whichweapon = null;
|
|
w.whichgesture = which;
|
|
mo.player.PendingWeapon = w;
|
|
return w;
|
|
}
|
|
|
|
// "special" gestures are run by switching to another "weapon"
|
|
static SWWMGesture SetSpecialGesture( PlayerPawn mo, Class<SWWMItemGesture> a, bool forced = false )
|
|
{
|
|
if ( !mo || !(mo is 'Demolitionist') ) return null; // only Demo
|
|
if ( mo.Health <= 0 ) return null; // dead
|
|
if ( !forced && (mo.player.cheats&CF_TOTALLYFROZEN) ) return null; // frozen today (unless forced)
|
|
if ( !a ) return null;
|
|
SWWMGesture w = SWWMGesture(mo.FindInventory('SWWMGesture'));
|
|
if ( w && ((mo.player.PendingWeapon is 'SWWMGesture') || (mo.player.ReadyWeapon is 'SWWMGesture')
|
|
|| (mo.player.PendingWeapon is 'SWWMItemGesture') || (mo.player.ReadyWeapon is 'SWWMItemGesture')) )
|
|
{
|
|
// already gesturing
|
|
// queue if unique
|
|
foreach ( sw:w.sweapon )
|
|
{
|
|
if ( sw != a ) continue;
|
|
return null;
|
|
}
|
|
w.sweapon.Push(a);
|
|
return null;
|
|
}
|
|
if ( !w )
|
|
{
|
|
w = SWWMGesture(Spawn('SWWMGesture'));
|
|
w.AttachToOwner(mo);
|
|
}
|
|
if ( mo.player.PendingWeapon != WP_NOCHANGE ) w.formerweapon = mo.player.PendingWeapon;
|
|
else w.formerweapon = mo.player.ReadyWeapon;
|
|
w.lastformerweapon = w.formerweapon;
|
|
w.whichgesture = GS_Null;
|
|
w.whichweapon = a;
|
|
mo.player.PendingWeapon = w;
|
|
return w;
|
|
}
|
|
|
|
action void A_CallPlayerGesture( statelabel st, statelabel cst )
|
|
{
|
|
if ( invoker.Owner.Health <= 0 ) return;
|
|
if ( (player.crouchdir == -1) && invoker.Owner.FindState(cst) )
|
|
invoker.Owner.SetStateLabel(cst);
|
|
else if ( invoker.Owner.FindState(st) )
|
|
invoker.Owner.SetStateLabel(st);
|
|
}
|
|
|
|
action void A_FinishGesture()
|
|
{
|
|
if ( invoker.sweapon.Size() > 0 )
|
|
{
|
|
invoker.whichgesture = GS_Null;
|
|
invoker.whichweapon = invoker.sweapon[0];
|
|
// push back
|
|
invoker.sweapon.Delete(0);
|
|
player.SetPSprite(PSP_WEAPON,ResolveState('Ready'));
|
|
return;
|
|
}
|
|
if ( invoker.queued )
|
|
{
|
|
invoker.whichweapon = null;
|
|
invoker.whichgesture = invoker.nextgesture;
|
|
invoker.queued = false;
|
|
player.SetPSprite(PSP_WEAPON,ResolveState('Ready'));
|
|
return;
|
|
}
|
|
if ( invoker.formerweapon ) player.PendingWeapon = invoker.formerweapon;
|
|
else
|
|
{
|
|
player.PendingWeapon = player.mo.BestWeapon(null);
|
|
if ( (player.PendingWeapon is 'SWWMGesture') || (player.PendingWeapon is 'SWWMItemGesture') )
|
|
player.PendingWeapon = null;
|
|
}
|
|
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 = SWWMUtility.Vec3FromAngles(angle,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()) )
|
|
SWWMHandler.DoFlash(pt.target,Color(32,224,128,255),10);
|
|
}
|
|
let s = Demolitionist(self).mystats;
|
|
if ( s ) s.pats++;
|
|
}
|
|
|
|
action void A_HeadpatEnd()
|
|
{
|
|
player.cheats &= ~CF_TOTALLYFROZEN;
|
|
Demolitionist(player.mo).scriptedinvul = false;
|
|
let pt = invoker.pats;
|
|
if ( !pt ) return;
|
|
invoker.pats = null;
|
|
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--;
|
|
}
|
|
if ( t.special && !(t.ActivationType&THINGSPEC_NoDeathSpecial) )
|
|
{
|
|
Actor whomst = level.actownspecial?t:self;
|
|
if ( t.ActivationType&THINGSPEC_ThingActs ) whomst = t;
|
|
else if ( t.ActivationType&THINGSPEC_TriggerActs ) whomst = self;
|
|
level.ExecuteSpecial(t.special,whomst,null,false,t.args[0],t.args[1],t.args[2],t.args[3],t.args[4]);
|
|
t.special = 0;
|
|
}
|
|
if ( !t.bFRIENDLY )
|
|
{
|
|
let s = Demolitionist(self).mystats;
|
|
if ( s ) s.befriend++;
|
|
if ( SWWMUtility.IdentifyingCaco(t) || SWWMUtility.IdentifyingDrug(t) || SWWMUtility.IdentifyingDoubleBoi(t) )
|
|
SWWMUtility.AchievementProgressInc("friend",1,player);
|
|
}
|
|
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);
|
|
if ( !weap ) return;
|
|
Vector3 origin = SWWMUtility.GetFireOffset(self,10,-2,-3);
|
|
double a = FRandom[Spread](0,360), s = FRandom[Spread](0,.005);
|
|
let [x2, y2, z2] = SWWMUtility.GetPlayerAxesAutoAimed(self);
|
|
Vector3 dir = SWWMUtility.ConeSpread(x2,y2,z2,a,s);
|
|
let p = Spawn('ExplodiumMagProj',origin);
|
|
p.special1 = 7;
|
|
p.target = self;
|
|
p.angle = atan2(dir.y,dir.x);
|
|
p.pitch = asin(-dir.z);
|
|
p.vel = dir*p.speed*1.5;
|
|
if ( FindInventory('RagekitPower') ) p.vel *= 4.;
|
|
p.ClearBounce();
|
|
p.bEXPLODEONWATER = true;
|
|
p.bSKYEXPLODE = true;
|
|
if ( p.waterlevel <= 0 ) p.vel.z += 5.;
|
|
p.vel += vel*.5;
|
|
}
|
|
|
|
action bool CanPlantGrenade()
|
|
{
|
|
let weap = Weapon(invoker);
|
|
if ( !weap ) return false;
|
|
Vector3 origin = SWWMUtility.GetFireOffset(self,10,0,0);
|
|
FLineTraceData d;
|
|
LineTrace(angle+viewangle,DEFMELEERANGE*1.5,pitch+viewpitch,TRF_ABSPOSITION|TRF_THRUACTORS,origin.z,origin.x,origin.y,d);
|
|
return (d.HitType != TRACE_HitNone);
|
|
}
|
|
|
|
action void A_PlantMag()
|
|
{
|
|
let weap = Weapon(invoker);
|
|
if ( !weap ) return;
|
|
Vector3 x = SWWMUtility.GetPlayerViewDir(self);
|
|
Vector3 origin = SWWMUtility.GetFireOffset(self,10,0,0);
|
|
let p = Spawn('ExplodiumMagAttach',origin);
|
|
p.special1 = 7;
|
|
p.target = self;
|
|
p.angle = angle;
|
|
p.pitch = pitch;
|
|
p.vel = x*p.speed;
|
|
}
|
|
|
|
action void A_Smooch()
|
|
{
|
|
if ( swwm_mutevoice < 4 )
|
|
{
|
|
String myvoice = CVar.GetCVar('swwm_voicetype',player).GetString();
|
|
int loudlv = swwm_voiceamp;
|
|
int maxkiss = StringTable.Localize("$SWWM_"..myvoice.."_NKISS").ToInt();
|
|
int idx = (maxkiss<=1)?1:Random[DemoLines](1,maxkiss);
|
|
A_StartSound(String.Format("voice/%s/kiss%d",myvoice,idx),CHAN_DEMOVOICE,CHANF_OVERLAP);
|
|
if ( loudlv > 1 ) A_StartSound(String.Format("voice/%s/kiss%d",myvoice,idx),CHAN_DEMOVOICEAUX,CHANF_OVERLAP);
|
|
if ( loudlv > 2 ) A_StartSound(String.Format("voice/%s/kiss%d",myvoice,idx),CHAN_DEMOVOICEAUX2,CHANF_OVERLAP);
|
|
if ( loudlv > 3 ) A_StartSound(String.Format("voice/%s/kiss%d",myvoice,idx),CHAN_DEMOVOICEAUX3,CHANF_OVERLAP);
|
|
}
|
|
}
|
|
|
|
action void A_BlowKiss()
|
|
{
|
|
let weap = Weapon(invoker);
|
|
if ( !weap ) return;
|
|
Vector3 dir;
|
|
Vector3 origin = SWWMUtility.GetFireOffset(self,10,0,-1);
|
|
let [x2, y2, z2] = SWWMUtility.GetPlayerAxesAutoAimed(self);
|
|
let p = Spawn('LoveHeart',origin);
|
|
p.target = self;
|
|
p.angle = atan2(x2.y,x2.x);
|
|
p.pitch = asin(-x2.z);
|
|
p.vel = x2*p.speed;
|
|
// try to catch target in cone of vision
|
|
Array<HHitList> hits;
|
|
hits.Clear();
|
|
int rings = 1;
|
|
FLineTraceData d;
|
|
for ( double i=0; i<.2; i+=.02 )
|
|
{
|
|
for ( int j=0; j<360; j+=(360/rings) )
|
|
{
|
|
dir = SWWMUtility.ConeSpread(x2,y2,z2,j,i);
|
|
LineTrace(atan2(dir.y,dir.x),8000.,asin(-dir.z),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
|
|
if ( d.HitType != TRACE_HitActor ) continue;
|
|
bool addme = true;
|
|
foreach ( hit:hits )
|
|
{
|
|
if ( hit.a != d.HitActor ) continue;
|
|
if ( (hit.dir dot x2) < (dir dot x2) )
|
|
hit.dir = dir; // closer to centerpoint
|
|
addme = false;
|
|
break;
|
|
}
|
|
if ( !addme ) continue;
|
|
let nhit = new('HHitList');
|
|
nhit.a = d.HitActor;
|
|
nhit.dir = dir;
|
|
hits.Push(nhit);
|
|
}
|
|
rings += 5;
|
|
}
|
|
int closest = -1;
|
|
double closestdot = -1;
|
|
for ( int i=0; i<hits.Size(); i++ )
|
|
{
|
|
double thisdot = (hits[i].dir dot x2);
|
|
if ( thisdot < closestdot ) continue;
|
|
closest = i;
|
|
closestdot = thisdot;
|
|
}
|
|
if ( closest != -1 ) p.tracer = hits[closest].a;
|
|
}
|
|
|
|
override void SetTags( String colname )
|
|
{
|
|
// gestures use model 0
|
|
A_ChangeModel("",0,"","",0,"models","DemoTags"..colname..".png",CMDL_USESURFACESKIN,-1);
|
|
}
|
|
|
|
Default
|
|
{
|
|
+WEAPON.CHEATNOTWEAPON;
|
|
+WEAPON.NO_AUTO_SWITCH;
|
|
+WEAPON.WIMPY_WEAPON;
|
|
+WEAPON.NOAUTOSWITCHTO;
|
|
+SWWMWEAPON.HIDEINMENU;
|
|
+INVENTORY.UNDROPPABLE;
|
|
+INVENTORY.UNTOSSABLE;
|
|
+INVENTORY.UNCLEARABLE;
|
|
Weapon.SelectionOrder int.max;
|
|
SWWMWeapon.BobFactor 0., 0.;
|
|
}
|
|
States
|
|
{
|
|
Select:
|
|
XZW1 A 1 A_FullRaise();
|
|
Goto Ready;
|
|
Ready:
|
|
XZW1 A 1
|
|
{
|
|
if ( invoker.whichweapon )
|
|
{
|
|
SWWMItemGesture g = SWWMItemGesture(FindInventory(invoker.whichweapon));
|
|
if ( !g )
|
|
{
|
|
g = SWWMItemGesture(Spawn(invoker.whichweapon));
|
|
g.AttachToOwner(self);
|
|
}
|
|
g.gest = invoker;
|
|
player.ReadyWeapon = g;
|
|
player.SetPSPrite(PSP_WEAPON,g.FindState('Fire'));
|
|
return ResolveState(null);
|
|
}
|
|
switch ( invoker.whichgesture )
|
|
{
|
|
case GS_Headpat:
|
|
return ResolveState('Headpat');
|
|
case GS_Grenade:
|
|
return ResolveState('QuickGrenade');
|
|
case GS_EmptyMelee:
|
|
return ResolveState('EmptyMelee');
|
|
case GS_Wave:
|
|
return ResolveState('Wave');
|
|
case GS_ThumbsUp:
|
|
return ResolveState('Approve');
|
|
case GS_Victory:
|
|
return ResolveState('Victory');
|
|
case GS_BlowKiss:
|
|
return ResolveState('BlowKiss');
|
|
}
|
|
return ResolveState('NoGesture');
|
|
}
|
|
Wait;
|
|
Fire:
|
|
XZW1 A 1;
|
|
Goto Ready;
|
|
Headpat:
|
|
XZW1 A 0 A_JumpIf(CountInv('RagekitPower'),'Ragepat');
|
|
XZW1 A 3 A_CallPlayerGesture('Headpat','Headpat');
|
|
XZW3 TU 3;
|
|
XZW3 V 2 A_StartSound("demolitionist/handsup",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZW3 WX 2;
|
|
XZW3 YZ 1;
|
|
XZW4 AB 1;
|
|
XZW4 C 2;
|
|
XZW4 D 2 A_Headpat();
|
|
XZW4 EF 2;
|
|
XZW4 GH 1;
|
|
HeadpatLoop:
|
|
XZW4 I 1;
|
|
XZW3 YZ 1;
|
|
XZW4 AB 1;
|
|
XZW4 C 2;
|
|
XZW4 D 2 A_Headpat();
|
|
XZW4 EF 2;
|
|
XZW4 GH 1;
|
|
XZW4 I 1
|
|
{
|
|
if ( player.cmd.buttons&BT_USE )
|
|
{
|
|
if ( FindInventory('RagekitPower') )
|
|
{
|
|
A_CallPlayerGesture('RagepatLoop','RagepatLoop');
|
|
return ResolveState('RagepatLoop');
|
|
}
|
|
else
|
|
{
|
|
A_CallPlayerGesture('HeadpatLoop','HeadpatLoop');
|
|
return ResolveState('HeadpatLoop');
|
|
}
|
|
}
|
|
return ResolveState(null);
|
|
}
|
|
XZW4 JK 2;
|
|
XZW4 L 2 A_StartSound("demolitionist/handsdown",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZW4 MNOP 3;
|
|
XZW1 A 0 A_HeadpatEnd();
|
|
XZW1 A -1 A_FinishGesture();
|
|
Stop;
|
|
Ragepat:
|
|
XZW1 A 3 A_CallPlayerGesture('Ragepat','Ragepat');
|
|
XZW3 TU 2;
|
|
XZW3 V 1 A_StartSound("demolitionist/handsup",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZW3 WX 1;
|
|
XZW3 Y 1;
|
|
XZW4 AC 1;
|
|
XZW4 D 1 A_Headpat();
|
|
XZW4 EF 1;
|
|
XZW4 GI 1;
|
|
XZW3 Y 1;
|
|
XZW4 AC 1;
|
|
XZW4 D 1 A_Headpat();
|
|
XZW4 EF 1;
|
|
XZW4 GI 1;
|
|
XZW3 Y 1;
|
|
XZW4 AC 1;
|
|
XZW4 D 1 A_Headpat();
|
|
XZW4 EF 1;
|
|
XZW4 G 1;
|
|
RagepatLoop:
|
|
XZW4 I 1;
|
|
XZW3 Y 1;
|
|
XZW4 AC 1;
|
|
XZW4 D 1 A_Headpat();
|
|
XZW4 EF 1;
|
|
XZW4 G 1;
|
|
XZW4 I 1
|
|
{
|
|
if ( player.cmd.buttons&BT_USE )
|
|
{
|
|
if ( FindInventory('RagekitPower') )
|
|
{
|
|
A_CallPlayerGesture('RagepatLoop','RagepatLoop');
|
|
return ResolveState('RagepatLoop');
|
|
}
|
|
else
|
|
{
|
|
A_CallPlayerGesture('HeadpatLoop','HeadpatLoop');
|
|
return ResolveState('HeadpatLoop');
|
|
}
|
|
}
|
|
return ResolveState(null);
|
|
}
|
|
XZW4 JK 1;
|
|
XZW4 L 1 A_StartSound("demolitionist/handsup",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZW4 MNOP 2;
|
|
XZW1 A 0 A_HeadpatEnd();
|
|
XZW1 A -1 A_FinishGesture();
|
|
Stop;
|
|
QuickGrenade:
|
|
XZW4 Q 3;
|
|
XZW4 R 3 A_StartSound("demolitionist/handsup",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZW4 ST 3;
|
|
XZW4 U 3 A_PlayerReload();
|
|
XZW4 V 2 A_StartSound("explodium/magpin",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZW4 WX 2;
|
|
XZW4 Y 3 A_JumpIf(CanPlantGrenade(),'QuickGrenadePlant');
|
|
XZW4 Z 2
|
|
{
|
|
A_StartSound("explodium/throwmag",CHAN_WEAPON,CHANF_OVERLAP);
|
|
A_PlayerMelee();
|
|
}
|
|
XZW5 AB 2;
|
|
XZW5 CDEF 2;
|
|
XZW5 G 2 A_ThrowMag();
|
|
XZW5 HIJ 3;
|
|
XZW5 KL 4;
|
|
XZW4 Q 0 A_JumpIf(player.cmd.buttons&BT_USER4,'QuickGrenade');
|
|
XZW4 Q -1 A_FinishGesture();
|
|
Stop;
|
|
QuickGrenadePlant:
|
|
XZW4 Y 3;
|
|
XZW5 M 2 A_PlayerMelee();
|
|
XZW5 NOPQRSTU 2;
|
|
XZW5 V 2 A_PlantMag();
|
|
XZW5 W 4 A_StartSound("demolitionist/handsdown",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZW5 XY 4;
|
|
XZW4 Q 0 A_JumpIf(player.cmd.buttons&BT_USER4,'QuickGrenade');
|
|
XZW4 Q -1 A_FinishGesture();
|
|
Stop;
|
|
EmptyMelee:
|
|
XZW0 ABC 1;
|
|
XZW0 D 1
|
|
{
|
|
A_PlayerMelee(true);
|
|
A_StartSound("demolitionist/swing",CHAN_WEAPON,CHANF_OVERLAP);
|
|
A_Parry(9);
|
|
}
|
|
XZW0 EF 1;
|
|
XZW0 G 1 A_Melee();
|
|
XZW0 HIJKLMN 2;
|
|
XZW0 A -1
|
|
{
|
|
if ( player.cmd.buttons&(BT_ATTACK|BT_ALTATTACK|BT_USER1) )
|
|
return ResolveState('EmptyMelee')+3;
|
|
A_FinishGesture();
|
|
return ResolveState(null);
|
|
}
|
|
Stop;
|
|
Wave:
|
|
XZW1 A 3 A_CallPlayerGesture('Wave','CrouchWave');
|
|
XZW1 B 3;
|
|
XZW1 C 3 A_StartSound("demolitionist/handsup",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZW1 DEFGHIJ 3;
|
|
XZW1 K 3 A_StartSound("demolitionist/handsdown",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZW1 LMNOP 3;
|
|
XZW1 A -1 A_FinishGesture();
|
|
Stop;
|
|
Approve:
|
|
XZW1 A 3 A_CallPlayerGesture('Approve','CrouchApprove');
|
|
XZW1 QR 3;
|
|
XZW1 S 3 A_StartSound("demolitionist/handsup",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZW1 TUVWXY 3;
|
|
XZW1 Z 3 A_StartSound("demolitionist/handsdown",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZW2 A 3;
|
|
XZW2 BCDEFG 3;
|
|
XZW1 A -1 A_FinishGesture();
|
|
Stop;
|
|
Victory:
|
|
XZW1 A 3 A_CallPlayerGesture('Victory','CrouchVictory');
|
|
XZW2 HI 3;
|
|
XZW2 J 3 A_StartSound("demolitionist/handsup",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZW2 KLMNOPQR 3;
|
|
XZW2 S 3 A_StartSound("demolitionist/handsdown",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZW2 TUVWXYZ 3;
|
|
XZW1 A -1 A_FinishGesture();
|
|
Stop;
|
|
BlowKiss:
|
|
XZW1 A 3 A_CallPlayerGesture('BlowKiss','CrouchBlowKiss');
|
|
XZW3 A 3;
|
|
XZW3 B 3;
|
|
XZW3 C 3 A_StartSound("demolitionist/handsup",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZW3 DE 3;
|
|
XZW3 F 3 A_Smooch();
|
|
XZW3 GHIJ 3;
|
|
XZW3 K 3 A_StartSound("demolitionist/handsdown",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZW3 L 3 A_BlowKiss();
|
|
XZW3 MNOPQRS 3;
|
|
XZW1 A -1 A_FinishGesture();
|
|
Stop;
|
|
NoGesture:
|
|
XZW1 A -1 A_FinishGesture();
|
|
Stop;
|
|
SoftDeselect: // needed for item gestures so the weapon select sound doesn't get eaten up (dunno why)
|
|
XZW1 A 1;
|
|
Deselect:
|
|
XZW1 A -1 A_FullLower();
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
// item gestures
|
|
|
|
Class SWWMItemGesture : SWWMWeapon abstract
|
|
{
|
|
SWWMGesture gest; // the base gesture weapon that we got picked from
|
|
bool gotused;
|
|
|
|
// these should prevent autoswitch when out of ammo
|
|
override bool ReportHUDAmmo()
|
|
{
|
|
return false;
|
|
}
|
|
override bool CheckAmmo( int firemode, bool autoswitch, bool requireammo, int ammocount )
|
|
{
|
|
return false;
|
|
}
|
|
override bool Use( bool pickup )
|
|
{
|
|
return false;
|
|
}
|
|
override bool Used( Actor user )
|
|
{
|
|
return false;
|
|
}
|
|
override void Touch( Actor toucher )
|
|
{
|
|
}
|
|
override void DoEffect()
|
|
{
|
|
Super.DoEffect();
|
|
if ( gotused )
|
|
{
|
|
// clear ourselves after use (don't pollute inventory list)
|
|
DepleteOrDestroy();
|
|
return;
|
|
}
|
|
if ( !Owner || !Owner.player || (Owner.player.ReadyWeapon != self) )
|
|
return;
|
|
let psp = Owner.player.FindPSprite(PSP_WEAPON);
|
|
if ( !psp ) return;
|
|
if ( (Owner.Health <= 0) && (psp.CurState != ResolveState('Deselect')) )
|
|
Owner.player.SetPSprite(PSP_WEAPON,ResolveState('Deselect'));
|
|
}
|
|
|
|
action void A_FinishGesture()
|
|
{
|
|
A_WeaponOffset(0,32); // fix key punch offset
|
|
let gest = invoker.gest;
|
|
if ( !gest )
|
|
{
|
|
ThrowAbortException("Call to A_FinishGesture() without owned SWWMGesture");
|
|
return;
|
|
}
|
|
if ( gest.sweapon.Size() > 0 )
|
|
{
|
|
gest.whichgesture = GS_Null;
|
|
gest.whichweapon = gest.sweapon[0];
|
|
// push back
|
|
gest.sweapon.Delete(0);
|
|
// go back to the main gesture
|
|
player.ReadyWeapon = gest;
|
|
player.SetPSPrite(PSP_WEAPON,gest.ResolveState('Ready'));
|
|
invoker.gotused = true;
|
|
return;
|
|
}
|
|
if ( gest.queued )
|
|
{
|
|
gest.whichweapon = null;
|
|
gest.whichgesture = gest.nextgesture;
|
|
gest.queued = false;
|
|
// go back to the main gesture
|
|
player.ReadyWeapon = gest;
|
|
player.SetPSPrite(PSP_WEAPON,gest.ResolveState('Ready'));
|
|
invoker.gotused = true;
|
|
return;
|
|
}
|
|
// switch to old weapon
|
|
player.ReadyWeapon = gest;
|
|
if ( gest.formerweapon ) player.PendingWeapon = gest.formerweapon;
|
|
else
|
|
{
|
|
player.PendingWeapon = player.mo.BestWeapon(null);
|
|
if ( (player.PendingWeapon is 'SWWMGesture') || (player.PendingWeapon is 'SWWMItemGesture') )
|
|
player.PendingWeapon = null;
|
|
}
|
|
player.SetPSPrite(PSP_WEAPON,gest.ResolveState('SoftDeselect'));
|
|
invoker.gotused = true;
|
|
}
|
|
|
|
override void SetTags( String colname )
|
|
{
|
|
// gestures use model 0
|
|
A_ChangeModel("",0,"","",0,"models","DemoTags"..colname..".png",CMDL_USESURFACESKIN,-1);
|
|
}
|
|
|
|
Default
|
|
{
|
|
+WEAPON.CHEATNOTWEAPON;
|
|
+WEAPON.NO_AUTO_SWITCH;
|
|
+WEAPON.WIMPY_WEAPON;
|
|
+WEAPON.NOAUTOSWITCHTO;
|
|
+SWWMWEAPON.HIDEINMENU;
|
|
+INVENTORY.UNDROPPABLE;
|
|
+INVENTORY.UNTOSSABLE;
|
|
+INVENTORY.UNCLEARABLE;
|
|
Weapon.SelectionOrder int.max;
|
|
SWWMWeapon.BobFactor 0., 0.;
|
|
}
|
|
States
|
|
{
|
|
Select:
|
|
XZW1 A 1 A_FullRaise();
|
|
Goto Ready;
|
|
Ready:
|
|
Fire:
|
|
XZW1 A 1 A_Log("\cgUnimplemented pickup sequence for "..invoker.GetClassName().."\c-");
|
|
XZW1 A -1 A_FinishGesture();
|
|
Stop;
|
|
AltFire:
|
|
XZW1 A 1 A_Log("\cgUnimplemented use sequence for "..invoker.GetClassName().."\c-");
|
|
XZW1 A -1 A_FinishGesture();
|
|
Stop;
|
|
Deselect:
|
|
XZW1 A -1 A_FullLower();
|
|
Stop;
|
|
}
|
|
}
|