Finally fix gestures breaking on weapon switch.

This commit is contained in:
Mari the Deer 2022-12-26 23:22:30 +01:00
commit 7b8111c40d
5 changed files with 167 additions and 7 deletions

View file

@ -1,3 +1,3 @@
[default]
SWWM_MODVER="\cyDEMOLITIONIST \cw1.3pre r708 \cu(Mon 26 Dec 13:45:57 CET 2022)\c-";
SWWM_SHORTVER="\cw1.3pre r708 \cu(2022-12-26 13:45:57)\c-";
SWWM_MODVER="\cyDEMOLITIONIST \cw1.3pre r709 \cu(Mon 26 Dec 23:22:30 CET 2022)\c-";
SWWM_SHORTVER="\cw1.3pre r709 \cu(2022-12-26 23:22:30)\c-";

View file

@ -172,8 +172,8 @@ extend Class Demolitionist
// the default PickWeapon code breaks when dual weapons are involved
// so we gotta roll out our own here
//
// I could rewrite PickNextWeapon and PickPrevWeapon as well, but nah
// those always call CheckAmmo so it's fine
// we also need to override PickNextWeapon and PickPrevWeapon due to quirks of
// gestures
private Weapon TraverseSlot( int slot, bool checkammo, int start, int end, Weapon cur )
{
for ( int i=start; i>=end; i-- )
@ -197,7 +197,12 @@ extend Class Demolitionist
let cur = player.ReadyWeapon;
bool found = false;
int cs, ci;
if ( cur ) [found, cs, ci] = player.weapons.LocateWeapon(cur.GetClass());
if ( cur )
{
if ( cur is 'SWWMGesture' ) [found, cs, ci] = player.weapons.LocateWeapon(SWWMGesture(cur).formerweapon.GetClass());
else if ( cur is 'SWWMItemGesture' ) [found, cs, ci] = player.weapons.LocateWeapon(SWWMItemGesture(cur).gest.formerweapon.GetClass());
else [found, cs, ci] = player.weapons.LocateWeapon(cur.GetClass());
}
if ( found && (cs == slot) )
{
// traverse the slot down from current index
@ -208,4 +213,79 @@ extend Class Demolitionist
let w = TraverseSlot(slot,checkammo,slotsize-1,0,cur);
return w?w:cur;
}
// we have to reimplement this because of gestures
private bool, int, int FindMostRecentWeaponSWWM()
{
let cur = player.ReadyWeapon;
if ( player.PendingWeapon != WP_NOCHANGE ) cur = player.PendingWeapon;
if ( cur )
{
bool found = false;
int cs, ci;
if ( cur is 'SWWMGesture' ) [found, cs, ci] = player.weapons.LocateWeapon(SWWMGesture(cur).formerweapon.GetClass());
else if ( cur is 'SWWMItemGesture' ) [found, cs, ci] = player.weapons.LocateWeapon(SWWMItemGesture(cur).gest.formerweapon.GetClass());
else [found, cs, ci] = player.weapons.LocateWeapon(cur.GetClass());
return found, cs, ci;
}
return false, 0 ,0;
}
private Weapon PickPNWeapon( bool bPrev = false )
{
bool found;
int sslot, sidx;
[found, sslot, sidx] = FindMostRecentWeaponSWWM();
let cur = player.ReadyWeapon;
if ( cur is 'SWWMGesture' ) cur = SWWMGesture(cur).formerweapon;
else if ( cur is 'SWWMItemGesture' ) cur = SWWMItemGesture(cur).gest.formerweapon;
if ( !cur || found )
{
int slot, idx;
if ( !cur )
{
sslot = bPrev?0:(NUM_WEAPON_SLOTS-1);
sidx = bPrev?0:player.Weapons.SlotSize(sslot);
}
slot = sslot;
idx = sidx;
int checked = 0;
do
{
if ( bPrev )
{
if ( --idx < 0 )
{
checked++;
if ( --slot < 0 ) slot = NUM_WEAPON_SLOTS-1;
idx = player.Weapons.SlotSize(slot)-1;
}
}
else
{
if ( ++idx >= player.Weapons.SlotSize(slot) )
{
idx = 0;
checked++;
if ( ++slot >= NUM_WEAPON_SLOTS ) slot = 0;
}
}
let type = player.Weapons.GetWeapon(slot,idx);
let w = Weapon(FindInventory(type));
if ( w && w.CheckAmmo(Weapon.EitherFire,false) )
return w;
}
while ( ((slot != sslot) || (idx != sidx)) && (checked <= NUM_WEAPON_SLOTS) );
}
return player.ReadyWeapon;
}
override Weapon PickPrevWeapon()
{
return PickPNWeapon(true);
}
override Weapon PickNextWeapon()
{
return PickPNWeapon();
}
}

View file

@ -24,7 +24,7 @@ enum EGestureSlot
// First person gestures
Class SWWMGesture : SWWMWeapon
{
Weapon formerweapon;
Weapon formerweapon, lastformerweapon;
int whichgesture, nextgesture;
bool deaded, queued;
Class<SWWMItemGesture> whichweapon;
@ -48,6 +48,10 @@ Class SWWMGesture : SWWMWeapon
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) )
@ -104,6 +108,7 @@ Class SWWMGesture : SWWMWeapon
}
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;
@ -138,6 +143,7 @@ Class SWWMGesture : SWWMWeapon
}
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;

View file

@ -386,13 +386,65 @@ Class SWWMWeapon : Weapon abstract
if ( Owner.player )
{
if ( !Owner.player.GetNeverSwitch() && !bNo_Auto_Switch && ReportHUDAmmo() ) // hey, as long as it works
Owner.player.PendingWeapon = self;
{
// if the player's current/next weapon is a gesture, set ourselves as the former weapon, to avoid breaking gesture sequences
if ( Owner.player.ReadyWeapon is 'SWWMGesture' )
{
let g = SWWMGesture(Owner.player.ReadyWeapon);
g.formerweapon = self;
}
else if ( Owner.player.PendingWeapon is 'SWWMGesture' )
{
let g = SWWMGesture(Owner.player.PendingWeapon);
g.formerweapon = self;
}
else if ( Owner.player.ReadyWeapon is 'SWWMItemGesture' )
{
let ig = SWWMItemGesture(Owner.player.ReadyWeapon);
ig.gest.formerweapon = self;
}
else if ( Owner.player.PendingWeapon is 'SWWMItemGesture' )
{
let ig = SWWMItemGesture(Owner.player.PendingWeapon);
ig.gest.formerweapon = self;
}
else Owner.player.PendingWeapon = self;
}
if ( Owner.player.mo == players[consoleplayer].camera )
StatusBar.ReceivedWeapon(self);
}
GivenAsMorphWeapon = false;
bSwappedTo = false;
}
override bool Use( bool pickup )
{
// we can simplify this
if ( !Owner.player || (Owner.player.ReadyWeapon == self) )
return false;
// if the player's current/next weapon is a gesture, set ourselves as the former weapon, to avoid breaking gesture sequences
if ( Owner.player.ReadyWeapon is 'SWWMGesture' )
{
let g = SWWMGesture(Owner.player.ReadyWeapon);
g.formerweapon = self;
}
else if ( Owner.player.PendingWeapon is 'SWWMGesture' )
{
let g = SWWMGesture(Owner.player.PendingWeapon);
g.formerweapon = self;
}
else if ( Owner.player.ReadyWeapon is 'SWWMItemGesture' )
{
let ig = SWWMItemGesture(Owner.player.ReadyWeapon);
ig.gest.formerweapon = self;
}
else if ( Owner.player.PendingWeapon is 'SWWMItemGesture' )
{
let ig = SWWMItemGesture(Owner.player.PendingWeapon);
ig.gest.formerweapon = self;
}
else Owner.player.PendingWeapon = self;
return false;
}
override void OwnerDied()
{
ClearBufferedAmmo();

View file

@ -211,6 +211,28 @@ Class ExplodiumGun : SWWMWeapon
// switch to dual if already selected
if ( Owner.player && (Owner.player.ReadyWeapon == self) && (Amount > 1) )
{
// if the player's current weapon is a gesture, set sister as the former weapon, to avoid breaking gesture sequences
if ( Owner.player.ReadyWeapon is 'SWWMGesture' )
{
let g = SWWMGesture(Owner.player.ReadyWeapon);
g.formerweapon = SisterWeapon;
}
else if ( Owner.player.PendingWeapon is 'SWWMGesture' )
{
let g = SWWMGesture(Owner.player.PendingWeapon);
g.formerweapon = SisterWeapon;
}
else if ( Owner.player.ReadyWeapon is 'SWWMItemGesture' )
{
let ig = SWWMItemGesture(Owner.player.ReadyWeapon);
ig.gest.formerweapon = SisterWeapon;
}
else if ( Owner.player.PendingWeapon is 'SWWMItemGesture' )
{
let ig = SWWMItemGesture(Owner.player.PendingWeapon);
ig.gest.formerweapon = SisterWeapon;
}
else Owner.player.PendingWeapon = self;
Owner.player.PendingWeapon = SisterWeapon;
return false;
}