Allow for no-ammo muzzles

This commit is contained in:
2025-08-10 08:09:03 +01:00
parent 9d973b2570
commit aa412f1911
9 changed files with 283 additions and 283 deletions
+69 -72
View File
@@ -8,8 +8,6 @@ module Dodge.HeldUse (
heldEffectMuzzles,
) where
import qualified IntMapHelp as IM
import Dodge.IsPulseLaser
import Color
import Control.Applicative
import Control.Monad
@@ -26,6 +24,7 @@ import Dodge.Data.World
import Dodge.Gas
import Dodge.Inventory.Lock
import Dodge.Inventory.Path
import Dodge.IsPulseLaser
import Dodge.Item.HeldOffset
import Dodge.Item.Weapon.Bullet
import Dodge.Item.Weapon.Shatter
@@ -34,6 +33,7 @@ import Dodge.RadarSweep
import Dodge.SoundLogic
import Dodge.Tesla
import Geometry
import qualified IntMapHelp as IM
import LensHelp
import ListHelp
import NewInt
@@ -47,7 +47,6 @@ gadgetEffect :: Int -> LocationDT OItem -> Creature -> World -> World
gadgetEffect pt loc
| UseHeld{} <- loc ^. locDT . dtValue . _1 . itUse = heldEffect pt loc
| PulseBallSF <- loc ^. locDT . dtValue . _2 = heldEffect pt loc
-- hammerCheck (\a b c -> creatureShootPulseBall a b cmuz c) pt loc
| DROPPER x <- loc ^. locDT . dtValue . _1 . itType
, Just i <- loc ^? locDT . dtValue . _1 . itUse . uInt
, pt == 0 =
@@ -57,7 +56,6 @@ gadgetEffect pt loc
useInventoryPath pt i x loc
| otherwise = const id
heldEffect :: Int -> LocationDT OItem -> Creature -> World -> World
heldEffect = hammerCheck heldEffectMuzzles
@@ -80,7 +78,6 @@ hammerCheck f pt loc cr w = case itemTriggerType loc of
& itmset . itParams . wTime +~ 1
WarmUpNoDelay{} -> f loc cr w & setwarming
WarmUpCoolDown ws _ _
-- UNSAFE:
| _wTime (_itParams it) < ws ->
w & setwarming
& soundContinue
@@ -95,32 +92,27 @@ hammerCheck f pt loc cr w = case itemTriggerType loc of
& itmset . itParams . wTime +~ 1
WarmUpCoolDown{} -> w & setwarming
BurstTrigger is t
| w ^. cWorld . lWorld . lClock - t > timelastused
| timetest t
, pt == 0 ->
w & f loc cr & cWorld . lWorld . delayedEvents .++~ map g is
VolleyGunTrigger i t
| w ^. cWorld . lWorld . lClock - t > timelastused
| timetest t
, pt == 0 ->
let (is, gen) = getVolleyBurst i (w ^. randGen)
in w & f loc cr
& cWorld . lWorld . delayedEvents .++~ map g is
& randGen .~ gen
HammerTrigger t
| w ^. cWorld . lWorld . lClock - t > timelastused
, isNothing $ find ((== MakeAutoSF) . (^. dtValue . _2)) (loc ^. locDT . dtRight)
, pt == 0 ->
f loc cr w
HammerTrigger t | timetest t , pt == 0 -> f loc cr w
SemiAutoTrigger t
| w ^. cWorld . lWorld . lClock - t > timelastused
, isNothing $ find ((== MakeAutoSF) . (^. dtValue . _2)) (loc ^. locDT . dtRight)
, pt < w ^. cWorld . lWorld . lClock - timelastused ->
-- , pt == 0 ->
| timetest t
, isJust (find ((== MakeAutoSF) . (^. dtValue . _2)) (loc ^. locDT . dtRight))
|| pt == 0 ->
f loc cr w
AutoTrigger t
| w ^. cWorld . lWorld . lClock - t > timelastused -> f loc cr w
AutoTrigger t | timetest t -> f loc cr w
NoTrigger -> f loc cr w
_ -> w
where
timetest t = w ^. cWorld . lWorld . lClock - t > timelastused
it = loc ^. locDT . dtValue . _1
cid = _crID cr
-- the following is unsafe, but if ilInvID isn't correctly set we probably
@@ -138,12 +130,13 @@ getVolleyBurst i g =
heldEffectMuzzles :: LocationDT OItem -> Creature -> World -> World
heldEffectMuzzles loc cr w =
setusetime . doHeldUseEffect t cr
setusetime
. doHeldUseEffect t cr
. uncurry (applyCME loc cr)
$ bw
where
t = loc ^. locDT
bw = foldl' (loadMuzzle loc cr) (False,w) (locMuzzles loc)
bw = foldl' (loadMuzzle loc cr) (False, w) (locMuzzles loc)
setusetime =
cWorld . lWorld . creatures . ix (_crID cr) . crInv . ix itid . itTimeLastUsed
.~ w ^. cWorld . lWorld . lClock
@@ -151,18 +144,17 @@ heldEffectMuzzles loc cr w =
locMuzzles :: LocationDT OItem -> [Muzzle]
locMuzzles loc
| isPulseLaser loc =
| isPulseLaser loc =
dbwMuzzles
& ix 0 . mzPos .~ V2 6 0
& ix 0 . mzInaccuracy .~ 0
& ix 0 . mzFlareType .~ TeslaGunFlare
& ix 0 . mzEffect .~ MuzzlePulseLaser
& ix 0 . mzAmmoPerShot .~ UseExactly 200
& ix 0 . mzAmmoSlot .~ CapacitorBelow
| PulseBallSF <- loc ^. locDT . dtValue . _2 = dbwMuzzles
& ix 0 . mzAmmoSlot .~ CapacitorBelow (UseExactly 200)
| PulseBallSF <- loc ^. locDT . dtValue . _2 =
dbwMuzzles
& ix 0 . mzEffect .~ MuzzlePulseBall
& ix 0 . mzAmmoPerShot .~ UseExactly 200
& ix 0 . mzAmmoSlot .~ CapacitorSelf
& ix 0 . mzAmmoSlot .~ CapacitorSelf (UseExactly 200)
& ix 0 . mzInaccuracy .~ 0
& ix 0 . mzFlareType .~ TeslaGunFlare
| otherwise = itemMuzzles $ loc ^. locDT . dtValue . _1
@@ -171,7 +163,7 @@ itemMuzzles :: Item -> [Muzzle]
itemMuzzles itm = case itm ^. itType of
HELD ALTERIFLE ->
dbwMuzzles & ix 0 . mzPos .~ V2 25 0
& ix 0 . mzAmmoSlot .~ MagBelow (_alteRifleSwitch (_itParams itm))
& ix 0 . mzAmmoSlot .~ MagBelow (_alteRifleSwitch (_itParams itm)) (UseExactly 1)
HELD (VOLLEYGUN i) -> fromMaybe [] $ do
j <- itm ^? itParams . unfiredBarrels . ix 0
x <- vgunMuzzles i ^? ix j
@@ -179,7 +171,7 @@ itemMuzzles itm = case itm ^. itType of
HELD hit -> heldItemMuzzles hit
DETECTOR{} ->
dbwMuzzles & ix 0 . mzEffect .~ MuzzleDetector
& ix 0 . mzAmmoPerShot .~ UseExactly 100
& ix 0 . mzAmmoSlot . aps .~ UseExactly 100
LASER ->
dbwMuzzles
& ix 0 . mzPos .~ V2 6 0
@@ -195,10 +187,9 @@ heldItemMuzzles = \case
(V2 10 0)
a
0.01
(MagBelow 0)
(MagBelow 0 (UseExactly 1))
NoFlare
MuzzleShootBullet
(UseExactly 1)
0
| -- 0
a <- spreadAroundCenter i baseStickSpread
@@ -206,16 +197,16 @@ heldItemMuzzles = \case
& ix 0 . mzFlareType .~ NoLightFlare
& ix (i `div` 2) . mzFlareType .~ BasicFlare
& ix (i -1) . mzFlareType .~ NoLightFlare
PISTOL -> [Muzzle (V2 10 0) 0 0.05 (MagBelow 0) BasicFlare MuzzleShootBullet (UseExactly 1) 0]
MACHINEPISTOL -> [Muzzle (V2 10 0) 0 0.3 (MagBelow 0) MiniGunFlare MuzzleShootBullet (UseExactly 1) 0]
AUTOPISTOL -> [Muzzle (V2 10 0) 0 0 (MagBelow 0) BasicFlare MuzzleShootBullet (UseExactly 1) 0]
SMG -> [Muzzle (V2 20 0) 0 0.05 (MagBelow 0) BasicFlare MuzzleShootBullet (UseExactly 1) 0]
PISTOL -> [Muzzle (V2 10 0) 0 0.05 maguse1 BasicFlare MuzzleShootBullet 0]
MACHINEPISTOL -> [Muzzle (V2 10 0) 0 0.3 maguse1 MiniGunFlare MuzzleShootBullet 0]
AUTOPISTOL -> [Muzzle (V2 10 0) 0 0 maguse1 BasicFlare MuzzleShootBullet 0]
SMG -> [Muzzle (V2 20 0) 0 0.05 maguse1 BasicFlare MuzzleShootBullet 0]
RIFLE -> dbwMuzzles & ix 0 . mzPos .~ V2 25 0
BURSTRIFLE -> dbwMuzzles & ix 0 . mzPos .~ V2 25 0 & ix 0 . mzInaccuracy .~ 0.05
MINIGUNX i ->
replicate
i
(Muzzle (V2 30 0) 0 0.05 (MagBelow 0) NoFlare MuzzleShootBullet (UseExactly 1) 10)
(Muzzle (V2 30 0) 0 0.05 maguse1 NoFlare MuzzleShootBullet 10)
& ix 0 . mzFlareType .~ MiniGunFlare
BANGROD ->
dbwMuzzles
@@ -241,9 +232,9 @@ heldItemMuzzles = \case
& ix 0 . mzPos .~ V2 30 0
& ix 0 . mzFlareType .~ HeavySmokeFlare
& ix 0 . mzInaccuracy .~ 0
BANGCONE -> [Muzzle (V2 15 0) 0 0.5 (MagBelow 0) BasicFlare MuzzleShootBullet (UseUpTo 15) 12]
BLUNDERBUSS -> [Muzzle (V2 30 0) 0 0.5 (MagBelow 0) BasicFlare MuzzleShootBullet (UseUpTo 15) 12]
GRAPECANNON i -> [Muzzle (V2 30 0) 0 0.5 (MagBelow 0) BasicFlare MuzzleShootBullet (UseUpTo 15) (12 + 4 * fromIntegral i)]
BANGCONE -> [Muzzle (V2 15 0) 0 0.5 magupto15 BasicFlare MuzzleShootBullet 12]
BLUNDERBUSS -> [Muzzle (V2 30 0) 0 0.5 magupto15 BasicFlare MuzzleShootBullet 12]
GRAPECANNON i -> [Muzzle (V2 30 0) 0 0.5 magupto15 BasicFlare MuzzleShootBullet (12 + 4 * fromIntegral i)]
TORCH -> dbwMuzzles & ix 0 . mzPos .~ V2 10 0
VOLLEYGUN{} -> error "should get volleygun muzzles earlier"
FLAMETHROWER -> flameMuzzles
@@ -261,10 +252,9 @@ heldItemMuzzles = \case
RLAUNCHERX i ->
getZipList
( ZipList [Muzzle (V2 20 0) a 0 | a <- take i [0, 2 * pi / fromIntegral i ..]]
<*> ZipList (fmap MagBelow [0 ..])
<*> ZipList (fmap (\j -> MagBelow j (UseExactly 1)) [0 ..])
<*> pure NoFlare
<*> pure MuzzleRLauncher
<*> pure (UseExactly 1)
<*> pure 0
)
TESLAGUN ->
@@ -287,41 +277,43 @@ heldItemMuzzles = \case
BLINKER ->
dbwMuzzles
& ix 0 . mzEffect .~ MuzzleBlink
& ix 0 . mzAmmoPerShot .~ UseExactly 10000000
& ix 0 . mzAmmoSlot . aps .~ UseExactly 10000000
BLINKERUNSAFE ->
dbwMuzzles
& ix 0 . mzEffect .~ MuzzleUnsafeBlink
& ix 0 . mzAmmoPerShot .~ UseExactly 10000000
& ix 0 . mzAmmoSlot . aps .~ UseExactly 10000000
REWINDER ->
dbwMuzzles
& ix 0 . mzEffect .~ MuzzleRewind
& ix 0 . mzAmmoPerShot .~ UseExactly 100000
& ix 0 . mzAmmoSlot . aps .~ UseExactly 100000
TIMESTOPPER ->
dbwMuzzles
& ix 0 . mzEffect .~ MuzzleStopper
& ix 0 . mzAmmoPerShot .~ UseExactly 100000
& ix 0 . mzAmmoSlot . aps .~ UseExactly 100000
TIMESCROLLER ->
dbwMuzzles
& ix 0 . mzEffect .~ MuzzleScroller
& ix 0 . mzAmmoPerShot .~ UseExactly 100000
& ix 0 . mzAmmoSlot . aps .~ UseExactly 100000
_ ->
[ Muzzle
{ _mzPos = V2 20 0
, _mzRot = 0
, _mzInaccuracy = 0.05
, _mzAmmoSlot = MagBelow 0
, _mzAmmoSlot = maguse1
, _mzFlareType = NoFlare
, _mzEffect = MuzzleShootBullet
, _mzAmmoPerShot = UseExactly 1
, _mzRandomOffset = 0
}
]
where
maguse1 = MagBelow 0 (UseExactly 1)
magupto15 = MagBelow 0 (UseUpTo 15)
baseStickSpread :: Float
baseStickSpread = 0.2
dbwMuzzles :: [Muzzle]
dbwMuzzles = [Muzzle (V2 15 0) 0 0.01 (MagBelow 0) BasicFlare MuzzleShootBullet (UseExactly 1) 0]
dbwMuzzles = [Muzzle (V2 15 0) 0 0.01 (MagBelow 0 (UseExactly 1)) BasicFlare MuzzleShootBullet 0]
flameMuzzles :: [Muzzle]
flameMuzzles =
@@ -329,14 +321,13 @@ flameMuzzles =
(V2 18 0)
0
0
(MagBelow 0)
(MagBelow 0 (UseExactly 1))
NoFlare
MuzzleNozzle
{ _nzPressure = ConstFloat 4
, _nzMaxWalkAngle = 0.2
, _nzWalkSpeed = 0.01
}
(UseExactly 1)
0
]
@@ -344,10 +335,9 @@ vgunMuzzles :: Int -> [Muzzle]
vgunMuzzles i =
getZipList
( ZipList [Muzzle (V2 15 x) 0 0.01 | x <- spreadAroundCenter i 6]
<*> ZipList (fmap MagBelow [0 .. i -1])
<*> ZipList (fmap (\j -> MagBelow j (UseExactly 1)) [0 .. i -1])
<*> pure BasicFlare
<*> pure MuzzleShootBullet
<*> pure (UseExactly 1)
<*> pure 0
)
@@ -642,24 +632,27 @@ heldTorqueAmount = \case
BLINKER -> 0
BLINKERUNSAFE -> 0
loadMuzzle :: LocationDT OItem -> Creature -> (Bool,World) -> Muzzle -> (Bool,World)
loadMuzzle loc cr (b,w) mz = fromMaybe (b,w) $ do
let as = _mzAmmoSlot mz
amamount = _mzAmmoPerShot mz
mag <- case as of
MagBelow mi -> find (isAmmoIntLink mi . (^. dtValue . _2)) (loc ^. locDT . dtLeft)
CapacitorSelf -> loc ^? locDT
CapacitorBelow -> find
((== PulseBallSF) . (^. dtValue . _2)) (loc ^. locDT . dtLeft)
mid <- mag ^? dtValue . _1 . itLocation . ilInvID
availableammo <- w ^? cWorld . lWorld . creatures . ix (_crID cr) . crInv . ix mid . itConsumables . _Just
let usedammo = case amamount of
UseUpTo x -> min x availableammo
UseExactly x
| x <= availableammo -> x
| otherwise -> 0
guard $ usedammo > 0
return $ useLoadedAmmo loc cr (b,w) (Just (mz,usedammo,mag))
loadMuzzle :: LocationDT OItem -> Creature -> (Bool, World) -> Muzzle -> (Bool, World)
loadMuzzle loc cr (b, w) mz = fromMaybe (b, w) $ do
case mz ^. mzAmmoSlot of
NoAmmoRequired -> return (True, doMuzzleEffect loc cr mz Nothing w)
as -> do
mag <- case as of
MagBelow mi _ -> find (isAmmoIntLink mi . (^. dtValue . _2)) (loc ^. locDT . dtLeft)
CapacitorSelf _ -> loc ^? locDT
CapacitorBelow _ ->
find
((== PulseBallSF) . (^. dtValue . _2))
(loc ^. locDT . dtLeft)
mid <- mag ^? dtValue . _1 . itLocation . ilInvID
availableammo <- w ^? cWorld . lWorld . creatures . ix (_crID cr) . crInv . ix mid . itConsumables . _Just
let usedammo = case as ^?! aps of
UseUpTo x -> min x availableammo
UseExactly x
| x <= availableammo -> x
| otherwise -> 0
guard $ usedammo > 0
return $ useLoadedAmmo loc cr (b, w) (Just (mz, usedammo, mag))
makeMuzzleFlare :: Muzzle -> LocationDT OItem -> Creature -> World -> World
makeMuzzleFlare mz loc cr = case mz ^. mzFlareType of
@@ -733,6 +726,10 @@ isAmmoIntLink i sf = Just i == sf ^? amsfLink
-- (AmmoMagSF j _) = i == j
--isAmmoIntLink _ _ = False
doMuzzleEffect :: LocationDT OItem -> Creature -> Muzzle
-> Maybe (LocationDT OItem, Item) -> World -> World
doMuzzleEffect _ _ _ _ = id
useLoadedAmmo ::
LocationDT OItem ->
Creature ->
@@ -931,8 +928,8 @@ creatureShootPulseBall loc cr mz w = w & randGen .~ g & shootPulseBall pos dir
shootPulseBall :: Point2 -> Float -> World -> World
shootPulseBall p dir w =
w
& cWorld . lWorld . pulseBalls . at i ?~
PulseBall
& cWorld . lWorld . pulseBalls . at i
?~ PulseBall
{ _pbPos = p
, _pbVel = 3.5 * unitVectorAtAngle dir
, _pbTimer = 200