// 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; int whichgesture, nextgesture; bool deaded, queued; Class whichweapon; Array > 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 void DoEffect() { Super.DoEffect(); // 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() { let hnd = SWWMHandler(EventHandler.Find("SWWMHandler")); if ( !hnd ) return; for ( int i=0; i 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); 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")); mo.AddInventory(w); } if ( mo.player.PendingWeapon != WP_NOCHANGE ) w.formerweapon = mo.player.PendingWeapon; else w.formerweapon = mo.player.ReadyWeapon; 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 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 for ( int i=0; i 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 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; for ( int k=0; k 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; } 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; } }