Hack together correct positioning of grenades from attached items

This commit is contained in:
2025-06-28 22:32:12 +01:00
parent 6af2a8cc36
commit d88aed10c7
12 changed files with 225 additions and 178 deletions
+77 -76
View File
@@ -46,12 +46,12 @@ import RandomHelp
import qualified SDL
import Sound.Data
gadgetEffect :: PressType -> LocationLDT ItemLink CItem -> Creature -> World -> World
gadgetEffect :: PressType -> LocationLDT ItemLink OItem -> Creature -> World -> World
gadgetEffect pt loc
| UseHeld{} <- loc ^. locLDT . ldtValue . _1 . itUse =
heldEffect
pt
(bimap id (^. _1) (loc ^. locLDT))
(loc ^. locLDT)
| DROPPER x <- loc ^. locLDT . ldtValue . _1 . itType
, Just i <- loc ^? locLDT . ldtValue . _1 . itUse . uInt
, pt == InitialPress =
@@ -61,46 +61,46 @@ gadgetEffect pt loc
useInventoryPath pt i x loc
| otherwise = const id
heldEffect :: PressType -> LDTree ItemLink Item -> Creature -> World -> World
heldEffect :: PressType -> LDTree ItemLink OItem -> Creature -> World -> World
heldEffect = useTimeCheck . hammerCheck heldEffectMuzzles
heldEffectNoHammerCheck :: LDTree ItemLink Item -> Creature -> World -> World
heldEffectNoHammerCheck :: LDTree ItemLink OItem -> Creature -> World -> World
heldEffectNoHammerCheck = useTimeCheck heldEffectMuzzles
type ChainEffect =
(LDTree ItemLink Item -> Creature -> World -> World) ->
LDTree ItemLink Item ->
(LDTree ItemLink OItem -> Creature -> World -> World) ->
LDTree ItemLink OItem ->
Creature ->
World ->
World
hammerCheck ::
(LDTree ItemLink Item -> Creature -> World -> World) ->
(LDTree ItemLink OItem -> Creature -> World -> World) ->
PressType ->
LDTree ItemLink Item ->
LDTree ItemLink OItem ->
Creature ->
World ->
World
hammerCheck f pt it cr w
| BurstTrigger is <- itemTriggerType (it ^. ldtValue)
| BurstTrigger is <- itemTriggerType (it ^. ldtValue . _1)
, pt == InitialPress =
w & f it cr & cWorld . lWorld . delayedEvents .++~ map g is
| BurstTrigger{} <- itemTriggerType (it ^. ldtValue) = w
| VolleyGunTrigger i <- itemTriggerType (it ^. ldtValue)
| BurstTrigger{} <- itemTriggerType (it ^. ldtValue . _1) = w
| VolleyGunTrigger i <- itemTriggerType (it ^. ldtValue . _1)
, pt == InitialPress =
let (is, gen) = getVolleyBurst i (w ^. randGen)
in w & f it cr
& cWorld . lWorld . delayedEvents .++~ map g is
& randGen .~ gen
| VolleyGunTrigger{} <- itemTriggerType (it ^. ldtValue) = w
| t <- itemTriggerType (it ^. ldtValue)
| VolleyGunTrigger{} <- itemTriggerType (it ^. ldtValue . _1) = w
| t <- itemTriggerType (it ^. ldtValue . _1)
, t == HammerTrigger || t == AlwaysSingleTrigger
, isNothing $ lookup MakeAutoLink (it ^. ldtRight)
, pt /= InitialPress =
w
| otherwise = f it cr w
where
g x = (x, WdWdBurstFireRepetition (_crID cr) (it ^?! ldtValue . itLocation . ilInvID))
g x = (x, WdWdBurstFireRepetition (_crID cr) (it ^?! ldtValue . _1 . itLocation . ilInvID))
getVolleyBurst :: (Random a, RandomGen b, Num a) => Int -> b -> ([a], b)
getVolleyBurst i g =
@@ -111,50 +111,50 @@ getVolleyBurst i g =
input buffering?
-}
useTimeCheck :: ChainEffect
useTimeCheck f item cr w = case useDelay $ item ^. ldtValue of
useTimeCheck f item cr w = case useDelay $ item ^. ldtValue . _1 of
FixedRate rate
| w ^. cWorld . lWorld . lClock - rate > lastused -> f item cr w
-- note that the time last used must be updated later in the chain!
FixedRate{} -> w
WarmUpNoDelay wm
| _wTime (_itParams $ _ldtValue item) < wm ->
| _wTime (_itParams $ _ldtValue $ fmap (^. _1) item) < wm ->
w & setwarming
& soundContinue (CrWeaponSound cid 0) (_crPos cr) (warmupSound $ item ^. ldtValue . itType) (Just 2)
& soundContinue (CrWeaponSound cid 0) (_crPos cr) (warmupSound $ item ^. ldtValue . _1 . itType) (Just 2)
& cWorld . lWorld . creatures . ix cid . crInv . ix itRef . itParams . wTime +~ 1
WarmUpNoDelay{} -> f item cr w & setwarming
WarmUpCoolDown ws _ _
| _wTime (_itParams $ _ldtValue item) < ws ->
| _wTime (_itParams $ _ldtValue $ fmap (^. _1) item) < ws ->
w & setwarming
& soundContinue (CrWeaponSound cid 0) (_crPos cr) (warmupSound $ item ^. ldtValue . itType) (Just 2)
& soundContinue (CrWeaponSound cid 0) (_crPos cr) (warmupSound $ item ^. ldtValue . _1 . itType) (Just 2)
& cWorld . lWorld . creatures . ix cid . crInv . ix itRef . itParams . wTime +~ 1
WarmUpCoolDown _ cs _
| _wTime (_itParams $ _ldtValue item) < cs ->
| _wTime (_itParams $ _ldtValue $ fmap (^. _1) item) < cs ->
f item cr w & setwarming
& cWorld . lWorld . creatures . ix cid . crInv . ix itRef . itParams . wTime +~ 1
WarmUpCoolDown{} -> w & setwarming
NoDelay -> f item cr w
where
lastused = item ^. ldtValue . itTimeLastUsed
lastused = item ^. ldtValue . _1 . itTimeLastUsed
cid = _crID cr
setwarming =
cWorld . lWorld . creatures . ix cid . crInv . ix itRef . itParams . isWarming
%~ const True
-- the following is unsafe, but if ilInvID isn't correctly set we probably
-- will have problems elsewhere also
itRef = item ^?! ldtValue . itLocation . ilInvID
itRef = item ^?! ldtValue . _1 . itLocation . ilInvID
heldEffectMuzzles :: LDTree ItemLink Item -> Creature -> World -> World
heldEffectMuzzles :: LDTree ItemLink OItem -> Creature -> World -> World
heldEffectMuzzles t cr w =
setusetime . doHeldUseEffect t cr
. uncurry (applyCME (_ldtValue t) cr)
. uncurry (applyCME (_ldtValue t ^. _1) cr)
. foldl' (useLoadedAmmo t cr) (False, w)
$ loadedmuzzles
where
(_, loadedmuzzles) = mapAccumR loadMuzzle t . itemMuzzles $ t ^. ldtValue
(_, loadedmuzzles) = mapAccumR loadMuzzle t . itemMuzzles $ t ^. ldtValue . _1
setusetime =
cWorld . lWorld . creatures . ix (_crID cr) . crInv . ix itid . itTimeLastUsed
.~ w ^. cWorld . lWorld . lClock
itid = t ^?! ldtValue . itLocation . ilInvID
itid = t ^?! ldtValue . _1 . itLocation . ilInvID
itemMuzzles :: Item -> [Muzzle]
itemMuzzles itm = case itm ^. itType of
@@ -337,8 +337,8 @@ vgunMuzzles i =
-- <*> ZipList [0 .. i -1]
)
doHeldUseEffect :: LDTree ItemLink Item -> Creature -> World -> World
doHeldUseEffect t cr w = case t ^. ldtValue . itType of
doHeldUseEffect :: LDTree ItemLink OItem -> Creature -> World -> World
doHeldUseEffect t cr w = case t ^. ldtValue . _1 . itType of
HELD (VOLLEYGUN j) -> case itm ^? itParams . unfiredBarrels of
Just [_] -> fromMaybe w $ do
let (is, g) = runState (shuffle [0 .. j -1]) $ w ^. randGen
@@ -360,7 +360,7 @@ doHeldUseEffect t cr w = case t ^. ldtValue . itType of
%~ tail
_ -> w
HELD ALTERIFLE -> fromMaybe w $ do
i <- t ^? ldtValue . itLocation . ilInvID
i <- t ^? ldtValue . _1 . itLocation . ilInvID
return $
w
& cWorld . lWorld . creatures . ix (_crID cr) . crInv . ix i
@@ -373,7 +373,7 @@ doHeldUseEffect t cr w = case t ^. ldtValue . itType of
%~ ((`mod` 2) . (+ 1))
_ -> w
where
itm = t ^. ldtValue
itm = t ^. ldtValue . _1
--doHeldUseEffect t cr w = case t ^? ldtValue . itUse . heldUseEffect of
-- Just (RandomiseMuzzleFrames x) -> fromMaybe w $ do
@@ -678,15 +678,15 @@ heldTorqueAmount = \case
-- (Muzzle,Int,Int) = (muzzle, amountloaded, id of mag taken from)
loadMuzzle ::
LDTree ItemLink Item ->
LDTree ItemLink OItem ->
Muzzle ->
(LDTree ItemLink Item, Maybe (Muzzle, Int, LDTree ItemLink Item))
(LDTree ItemLink OItem, Maybe (Muzzle, Int, LDTree ItemLink OItem))
loadMuzzle t@(LDT _ l _) mz = fromMaybe (t, Nothing) $ do
-- guard $ mz ^? mzFrame == t ^? ldtValue . itUse . heldFrame
let as = _mzAmmoSlot mz
amamount = _mzAmmoPerShot mz
(i, (_, mag)) <- findWithIx (isAmmoIntLink as . fst) l
availableammo <- mag ^. ldtValue . itConsumables
availableammo <- mag ^. ldtValue . _1 . itConsumables
let usedammo = case amamount of
UseUpTo x -> min x availableammo
UseExactly x
@@ -694,11 +694,11 @@ loadMuzzle t@(LDT _ l _) mz = fromMaybe (t, Nothing) $ do
| otherwise -> 0
guard $ usedammo > 0
return
( t & ldtLeft . ix i . _2 . ldtValue . itConsumables . _Just -~ usedammo
( t & ldtLeft . ix i . _2 . ldtValue . _1 . itConsumables . _Just -~ usedammo
, Just (mz, usedammo, mag)
)
makeMuzzleFlare :: Muzzle -> LDTree ItemLink Item -> Creature -> World -> World
makeMuzzleFlare :: Muzzle -> LDTree ItemLink OItem -> Creature -> World -> World
makeMuzzleFlare mz itmtree cr = case mz ^. mzFlareType of
NoFlare -> id
BasicFlare -> basicMuzFlare pos dir
@@ -708,14 +708,14 @@ makeMuzzleFlare mz itmtree cr = case mz ^. mzFlareType of
. muzFlareAt (V4 10 10 1 3) (pos `v2z` 20) dir
HeavySmokeFlare -> basicMuzFlare pos dir
LasGunFlare ->
flareCircleAt (getLaserColor itmtree) 0.8 (pos `v2z` 20)
flareCircleAt (getLaserColor $ fmap (^. _1) itmtree) 0.8 (pos `v2z` 20)
. ( cWorld . lWorld . lights
.:~ LSParam (pos `v2z` 10) 100 (xyzV4 $ getLaserColor itmtree)
.:~ LSParam (pos `v2z` 10) 100 (xyzV4 $ getLaserColor $ fmap (^. _1)itmtree)
)
TeslaGunFlare -> cWorld . lWorld . lights .:~ LSParam (pos `v2z` 10) 100 (V3 0 0 1)
where
itm = itmtree ^. ldtValue
(moff, mrot) = heldItemOrient2D itm cr (_mzPos mz) (_mzRot mz)
(moff, mrot) = heldItemOrient2D' itm cr (_mzPos mz) (_mzRot mz)
pos = _crPos cr + rotateV (_crDir cr) moff
dir = _crDir cr + mrot
oddcheck f w
@@ -768,10 +768,10 @@ isAmmoIntLink i (AmmoInLink j _) = i == j
isAmmoIntLink _ _ = False
useLoadedAmmo ::
LDTree ItemLink Item ->
LDTree ItemLink OItem ->
Creature ->
(Bool, World) ->
Maybe (Muzzle, Int, LDTree ItemLink Item) ->
Maybe (Muzzle, Int, LDTree ItemLink OItem) ->
(Bool, World)
useLoadedAmmo _ _ (cme, w) Nothing = (cme, w)
useLoadedAmmo itmtree cr (_, w) (Just (mz, x, magtree)) = (,) True $
@@ -783,29 +783,29 @@ useLoadedAmmo itmtree cr (_, w) (Just (mz, x, magtree)) = (,) True $
MuzzleRLauncher -> createProjectileR itmtree magtree mz cr w
MuzzleGLauncher ->
createProjectile
(0, Q.qID)
(Grenade (getGrenadeHitEffect itmtree))
(itmtree ^. ldtValue . _3)
(Grenade (getGrenadeHitEffect $ fmap (^. _1) itmtree))
magtree
(getPJStabiliser itmtree)
(getPJStabiliser $ fmap (^. _1) itmtree)
mz
cr
w
MuzzleNozzle{} -> useGasParams mid mz itm cr $ walkNozzle mz itm cr w
MuzzleShatter -> shootShatter itm cr w
MuzzleNozzle{} -> useGasParams mid mz (itm ^. _1) cr $ walkNozzle mz (itm ^. _1) cr w
MuzzleShatter -> shootShatter (itm ^. _1) cr w
MuzzleDetector ->
itemDetectorEffect
itm
(getAttachedSFLink MapperSF itmtree)
(getAttachedSFLink ARHUDSF itmtree)
(itm ^. _1)
(getAttachedSFLink MapperSF $ fmap (^. _1) itmtree)
(getAttachedSFLink ARHUDSF $ fmap (^. _1) itmtree)
cr
w
MuzzleBlink -> unsafeBlinkAction cr w
MuzzleUnsafeBlink -> blinkActionMousePos cr w
MuzzleRewind -> useRewindGun (itm ^. itID) w
MuzzleStopper -> useStopWatch itm cr w
MuzzleScroller -> useTimeScrollGun itm cr w
MuzzleRewind -> useRewindGun (itm ^. _1 . itID) w
MuzzleStopper -> useStopWatch (itm ^. _1) cr w
MuzzleScroller -> useTimeScrollGun (itm ^. _1) cr w
where
mid = magtree ^? ldtValue . itLocation . ilInvID
mid = magtree ^? ldtValue . _1 . itLocation . ilInvID
itm = itmtree ^. ldtValue
getAttachedSFLink ::
@@ -871,7 +871,7 @@ tractorBeamAt pos outpos dir power =
d = unitVectorAtAngle dir * power
creatureShootLaser ::
LDTree ItemLink Item ->
LDTree ItemLink OItem ->
Creature ->
Muzzle ->
World ->
@@ -881,14 +881,15 @@ creatureShootLaser itmtree cr mz w =
& randGen .~ g
& shootLaser
(CrWeaponSound (_crID cr) 0)
(getLaserDamage itmtree)
(getLaserPhaseV itmtree)
(getLaserDamage istree)
(getLaserPhaseV istree)
pos
dir
(getLaserColor itmtree)
(getLaserColor istree)
where
istree = fmap (\(x,_,_) -> x) itmtree
itm = itmtree ^. ldtValue
(moff, mrot) = heldItemOrient2D itm cr (_mzPos mz) (_mzRot mz)
(moff, mrot) = heldItemOrient2D' itm cr (_mzPos mz) (_mzRot mz)
pos = _crPos cr + rotateV (_crDir cr) moff
dir = _crDir cr + mrot + a
(a, g) = randomR (- inacc, inacc) $ _randGen w
@@ -981,14 +982,14 @@ magAmmoParams itm = case itm ^. itType of
-- _ -> 0
shootBullet ::
LDTree ItemLink Item ->
LDTree ItemLink OItem ->
Creature ->
(Muzzle, Int, LDTree ItemLink Item) ->
(Muzzle, Int, LDTree ItemLink OItem) ->
World ->
World
shootBullet itmtree cr (mz, x, magtree) w = fromMaybe w $ do
thebullet <- getBulletType magtree
return $ foldl' (&) w (replicate x (makeBullet' thebullet (itmtree ^. ldtValue) cr mz))
thebullet <- getBulletType $ fmap (^. _1) magtree
return $ foldl' (&) w (replicate x (makeBullet' thebullet (itmtree ^. ldtValue . _1) cr mz))
makeBullet' :: Bullet -> Item -> Creature -> Muzzle -> World -> World
makeBullet' bu itm cr mz w = makeBullet bu itm bulpos dir . (randGen .~ g) $ w
@@ -1255,15 +1256,15 @@ mcShootAuto itm mc w
dir = mc ^?! mcType . _McTurret . tuDir
-- | assumes that the item is held
shootTeslaArc :: Item -> Creature -> Muzzle -> World -> World
shootTeslaArc :: OItem -> Creature -> Muzzle -> World -> World
shootTeslaArc itm cr mz w =
w' & cWorld . lWorld . creatures . ix (_crID cr) . crInv . ix itRef . itParams .~ ip
& soundContinue (CrWeaponSound (_crID cr) 0) pos elecCrackleS (Just 2)
where
-- use items item location instead
itRef = cr ^?! crManipulation . manObject . imRootSelectedItem -- unsafe!! TODO change
(w', ip) = makeTeslaArc (_itParams itm) pos dir w
(moff, mrot) = heldItemOrient2D itm cr (_mzPos mz) (_mzRot mz)
(w', ip) = makeTeslaArc (_itParams (itm ^. _1)) pos dir w
(moff, mrot) = heldItemOrient2D' itm cr (_mzPos mz) (_mzRot mz)
pos = _crPos cr + rotateV (_crDir cr) moff
dir = _crDir cr + mrot
@@ -1282,21 +1283,21 @@ determineProjectileTracking magtree itmtree =
return $ HomeUsingTargeting (targetingtree ^. ldtValue . itID)
createProjectileR ::
LDTree ItemLink Item ->
LDTree ItemLink Item ->
LDTree ItemLink OItem ->
LDTree ItemLink OItem ->
Muzzle ->
Creature ->
World ->
World
createProjectileR itmtree magtree =
createProjectile
(0, Q.qID)
(itmtree ^. ldtValue . _3)
( Rocket
(determineProjectileTracking magtree itmtree)
(determineProjectileTracking (fmap (^. _1) magtree) $ fmap (^. _1) itmtree)
smoke
)
magtree
(getPJStabiliser itmtree)
(getPJStabiliser $ fmap (^. _1) itmtree)
where
smoke
| isJust $ lookup SmokeReducerLink (magtree ^. ldtLeft) = Just ReducedRocketSmoke
@@ -1320,23 +1321,23 @@ getGrenadeHitEffect t = case lookup GrenadeHitEffectLink (t ^. ldtRight) of
createProjectile ::
(Point3, Q.Quaternion Float) ->
ProjectileType ->
LDTree ItemLink Item ->
LDTree ItemLink OItem ->
Maybe PJStabiliser ->
Muzzle ->
Creature ->
World ->
World
createProjectile x pjtype magtree stab muz cr = fromMaybe failsound $ do
magid <- magtree ^? ldtValue . itLocation . ilInvID
magid <- magtree ^? ldtValue . _1 . itLocation . ilInvID
ammoitem <- cr ^? crInv . ix magid
let rdetonate =
(^. ldtValue . itID)
(^. ldtValue . _1 . itID)
<$> lookup RemoteDetonatorLink (magtree ^. ldtLeft)
rscreen =
(^. ldtValue . itID)
(^. ldtValue . _1 . itID)
<$> lookup RemoteScreenLink (magtree ^. ldtLeft)
aparams <-
((magtree ^? ldtLeft) >>= lookup AmmoPayloadLink >>= (^? ldtValue . itType . ibtAttach . shellPayload))
((magtree ^? ldtLeft) >>= lookup AmmoPayloadLink >>= (^? ldtValue . _1 . itType . ibtAttach . shellPayload))
-- <|> ammoitem ^? itConsumables . magParams . ampPayload
<|> magAmmoParams ammoitem ^? _Just . ampPayload
return $
@@ -1400,7 +1401,7 @@ useRewindGun i =
dropInventoryPath ::
Int ->
InventoryPathing ->
LocationLDT ItemLink CItem ->
LocationLDT ItemLink OItem ->
Creature ->
World ->
World
@@ -1432,7 +1433,7 @@ useInventoryPath ::
PressType ->
Int ->
InventoryPathing ->
LocationLDT ItemLink CItem ->
LocationLDT ItemLink OItem ->
Creature ->
World ->
World