Weapon swap adjustments for dual-wieldables.

Weapon swap fix for Candygun.
This commit is contained in:
Mari the Deer 2021-12-30 01:52:21 +01:00
commit c782fec486
6 changed files with 232 additions and 12 deletions

View file

@ -1,3 +1,3 @@
[default]
SWWM_MODVER="\chSWWM \czGZ\c- \cw1.2pre r101 \cu(Wed 29 Dec 21:46:20 CET 2021)\c-";
SWWM_SHORTVER="\cw1.2pre r101 \cu(2021-12-29 21:46:20)\c-";
SWWM_MODVER="\chSWWM \czGZ\c- \cw1.2pre r102 \cu(Thu 30 Dec 01:52:21 CET 2021)\c-";
SWWM_SHORTVER="\cw1.2pre r102 \cu(2021-12-30 01:52:21)\c-";

View file

@ -570,3 +570,16 @@ Model "DualExplodiumGun"
FrameIndex XZWN O 1 306
FrameIndex XZWN P 1 307
}
Model "SWWMDualWeaponGiver"
{
Path "models"
Model 0 "ExplodiumGunPickupDual_d.3d"
Skin 0 "ExplodiumGun.png"
Scale 0.05 0.05 0.05
ZOffset 16
ROTATING
FrameIndex XZW1 A 0 0
}

Binary file not shown.

Binary file not shown.

View file

@ -26,6 +26,13 @@ Class SWWMWeapon : Weapon abstract
let w = SWWMWeapon(i);
if ( w && !w.bNoSwapWeapon && (SlotNumber != -1) && (w.SlotNumber == SlotNumber) )
return true;
let wg = SWWMDualWeaponGiver(i);
if ( wg )
{
let w = wg.giveme[0];
if ( w && !w.bNoSwapWeapon && (SlotNumber != -1) & (w.SlotNumber == SlotNumber) )
return true;
}
return false;
}
@ -79,20 +86,33 @@ Class SWWMWeapon : Weapon abstract
SWWMWeapon sw;
if ( swwm_swapweapons && (sw = HasSwapWeapon(user)) )
{
// special case, otherwise candy gun won't drop itself
if ( sw is 'CandyGun' ) CandyGun(sw).swapdrop = true;
if ( (sw == user.player.ReadyWeapon) || (sw.SisterWeapon && (sw.SisterWeapon == user.player.ReadyWeapon)) )
swapto = true;
int ngun = sw.Amount;
double ang = -15*(ngun-1);
for ( int i=0; i<ngun; i++ )
if ( ngun == 2 )
{
// create a dual giver
let dg = SWWMDualWeaponGiver(Spawn("SWWMDualWeaponGiver",pos));
dg.angle = angle;
dg.vel = vel;
dg.FloatBobPhase = FloatBobPhase;
// transfer both guns
dg.giveme[0] = SWWMWeapon(sw.CreateTossable(1));
dg.giveme[0].AttachToOwner(dg);
dg.giveme[1] = SWWMWeapon(sw.CreateTossable(1));
dg.giveme[1].AttachToOwner(dg);
dg.SetPickupState();
}
else
{
// swap in-place
let d = user.DropInventory(sw);
if ( !d || (ngun <= 1) ) continue;
// adjust angle for multi-drops
d.angle = user.angle+ang;
d.vel.xy = RotateVector((5,0),d.angle);
d.vel.z = 1;
d.vel += user.vel;
ang += 30;
d.SetOrigin(pos,false);
d.angle = angle;
d.vel = vel;
d.FloatBobPhase = FloatBobPhase;
}
// don't autoswitch just yet (hacky)
if ( swapto )
@ -443,3 +463,188 @@ Class SWWMWeapon : Weapon abstract
FloatBobStrength 0.25;
}
}
// used for dual swapweapons
Class SWWMDualWeaponGiver : Inventory
{
Mixin SWWMOverlapPickupSound;
Mixin SWWMRespawn;
bool bUsePickup;
SWWMWeapon giveme[2];
Default
{
Inventory.PickupSound "misc/w_pkup";
Inventory.RestrictedTo "Demolitionist";
Inventory.PickupFlash "SWWMRedPickupFlash";
+WEAPONSPAWN;
+FLOATBOB;
+INVENTORY.NEVERRESPAWN;
+INVENTORY.QUIET;
FloatBobStrength 0.25;
}
override void Touch( Actor toucher )
{
// show prompt to swap weapon, and prevent normal pickup
SWWMWeapon sw;
if ( bSPECIAL && swwm_swapweapons && (sw = giveme[0].HasSwapWeapon(toucher)) )
{
if ( toucher.CheckLocalView() )
{
// use sisterweapon tag for dual wield (slot 2 weapons)
if ( sw.SisterWeapon && (sw.Amount > 1) )
Console.MidPrint(SmallFont,String.Format(StringTable.Localize("$SWWM_SWAPWEAPON"),sw.SisterWeapon.GetTag(),GetTag()));
else Console.MidPrint(SmallFont,String.Format(StringTable.Localize("$SWWM_SWAPWEAPON"),sw.GetTag(),GetTag()));
}
return;
}
// explicit use-to pickup, function must be called from Used() virtual
if ( toucher.player && swwm_usetopickup && !bUsePickup )
return;
Super.Touch(toucher);
}
override bool Used( Actor user )
{
// can't pick up
if ( !bSPECIAL ) return false;
// no use through melee
if ( (user.player.ReadyWeapon is 'SWWMWeapon') && SWWMWeapon(user.player.ReadyWeapon).wallponch && !swwm_meleepickup )
return false;
Vector3 itempos = Vec3Offset(0,0,Height/2),
userpos = user.Vec2OffsetZ(0,0,user.player.viewz);
// test vertical range
Vector3 diff = level.Vec3Diff(user.Vec3Offset(0,0,user.Height/2),Vec3Offset(0,0,Height/2));
double rang = user.player?PlayerPawn(user.player.mo).UseRange:(user.Height/2);
if ( abs(diff.z) > rang ) return false;
// if the toucher owns our SwapWeapon, drop it before picking us up
bool swapto = false;
SWWMWeapon sw;
if ( swwm_swapweapons && (sw = giveme[0].HasSwapWeapon(user)) )
{
// no need for candygun check here
if ( (sw == user.player.ReadyWeapon) || (sw.SisterWeapon && (sw.SisterWeapon == user.player.ReadyWeapon)) )
swapto = true;
int ngun = sw.Amount;
if ( ngun == 2 )
{
// create a dual giver
let dg = SWWMDualWeaponGiver(Spawn("SWWMDualWeaponGiver",pos));
dg.angle = angle;
dg.vel = vel;
dg.FloatBobPhase = FloatBobPhase;
// transfer both guns
dg.giveme[0] = SWWMWeapon(sw.CreateTossable(1));
dg.giveme[0].AttachToOwner(dg);
dg.giveme[1] = SWWMWeapon(sw.CreateTossable(1));
dg.giveme[1].AttachToOwner(dg);
dg.SetPickupState();
}
else
{
// swap in-place
let d = user.DropInventory(sw);
d.SetOrigin(pos,false);
d.angle = angle;
d.vel = vel;
d.FloatBobPhase = FloatBobPhase;
}
// don't autoswitch just yet (hacky)
if ( swapto )
{
user.player.ReadyWeapon = null;
user.player.PendingWeapon = WP_NOCHANGE;
}
}
bUsePickup = true;
Touch(user);
bUsePickup = false;
// we got picked up
if ( bDestroyed || Owner || !bSPECIAL )
{
// autoswitch to us if we got swapped
if ( swapto ) user.A_SelectWeapon(giveme[0].GetClass());
Vector3 tracedir = level.Vec3Diff(userpos,itempos);
double dist = tracedir.length();
tracedir /= dist;
let cf = new("CrossLineFinder");
cf.Trace(userpos,level.PointInSector(userpos.xy),tracedir,dist,0);
// trigger all player cross lines found between user and item
for ( int i=0; i<cf.clines.Size(); i++ )
cf.clines[i].Activate(user,cf.csides[i],SPAC_Cross);
return true;
}
return false;
}
override bool TryPickup( in out Actor toucher )
{
if ( giveme[0].HasSwapWeapon(toucher) )
return false;
let cur = toucher.FindInventory(giveme[0].GetClass());
if ( !cur )
{
// give both guns and go away
if ( !giveme[1].CallTryPickup(toucher) ) giveme[1].Destroy();
if ( !giveme[0].CallTryPickup(toucher) ) giveme[0].Destroy();
Spawn(PickupFlash,pos,ALLOW_REPLACE);
PrintPickupMessage(toucher.CheckLocalView(),GetTag());
PlayPickupSound(toucher);
if ( toucher.player ) toucher.player.bonuscount = BONUSADD;
GoAwayAndDie();
return true;
}
else if ( cur.Amount < 2 )
{
// give one gun
if ( !giveme[1].CallTryPickup(toucher) ) giveme[1].Destroy();
// drop the other where we stand
giveme[0].BecomePickup();
giveme[0].SetOrigin(pos,false);
giveme[0].Angle = Angle;
giveme[0].Vel = Vel;
giveme[0].bNoGravity = false;
giveme[0].ClearCounters();
giveme[0].FloatBobPhase = FloatBobPhase;
// don't forget to reattach its glow
if ( (giveme[1].PickupFlash is 'SWWMPickupFlash') && swwm_itemglows )
{
let p = Spawn(giveme[0].PickupFlash,giveme[0].Vec3Offset(0,0,16));
p.target = giveme[0];
p.SetStateLabel("Pickup");
}
// and then go away
Spawn(PickupFlash,pos,ALLOW_REPLACE);
PrintPickupMessage(toucher.CheckLocalView(),giveme[0].PickupMessage());
PlayPickupSound(toucher);
if ( toucher.player ) toucher.player.bonuscount = BONUSADD;
GoAwayAndDie();
return true;
}
return false;
}
void SetPickupState()
{
if ( giveme[0] is 'PlasmaBlast' )
{
SetTag("$T_PLASMABLAST2");
SetState(SpawnState+1);
}
else
{
SetTag("$T_EXPLODIUM2");
SetState(SpawnState);
}
A_SetSize(giveme[0].default.radius,giveme[0].default.height);
}
States
{
Spawn:
XZW1 AB -1; // A: Explodium Gun, B: Plasma Blaster
Stop;
}
}

View file

@ -8,6 +8,7 @@ Class CandyGun : SWWMWeapon
double casex, casey;
transient ui TextureID WeaponBox;
bool tospecial;
bool swapdrop; // used by weapon swapping so CreateTossable actually tosses the gun, rather than spares
Property ClipCount : ClipCount;
@ -324,7 +325,7 @@ Class CandyGun : SWWMWeapon
override Inventory CreateTossable( int amt )
{
if ( Ammo2.Amount > 0 )
if ( (Ammo2.Amount > 0) && !swapdrop )
{
// drop an empty spare
let spare = Inventory(Spawn('CandyGun',Owner.Pos,NO_REPLACE));
@ -339,6 +340,7 @@ Class CandyGun : SWWMWeapon
Ammo2.Amount--;
return spare;
}
swapdrop = false;
return Super.CreateTossable(amt);
}