diff --git a/language.version b/language.version index ed16a6c7c..3ff93378d 100644 --- a/language.version +++ b/language.version @@ -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-"; diff --git a/modeldef.explodiumgun2 b/modeldef.explodiumgun2 index 91faa2578..eeec5cb05 100644 --- a/modeldef.explodiumgun2 +++ b/modeldef.explodiumgun2 @@ -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 +} diff --git a/models/ExplodiumGunPickupDual_a.3d b/models/ExplodiumGunPickupDual_a.3d new file mode 100644 index 000000000..a7e512b88 Binary files /dev/null and b/models/ExplodiumGunPickupDual_a.3d differ diff --git a/models/ExplodiumGunPickupDual_d.3d b/models/ExplodiumGunPickupDual_d.3d new file mode 100644 index 000000000..0bc243ca8 Binary files /dev/null and b/models/ExplodiumGunPickupDual_d.3d differ diff --git a/zscript/weapons/swwm_baseweapon.zsc b/zscript/weapons/swwm_baseweapon.zsc index 695c6182f..0a686de37 100644 --- a/zscript/weapons/swwm_baseweapon.zsc +++ b/zscript/weapons/swwm_baseweapon.zsc @@ -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 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 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); }