{-# OPTIONS -Wno-incomplete-uni-patterns #-} {-# LANGUAGE TupleSections #-} module Dodge.HeldUse ( heldEffect, heldEffectNoHammerCheck, mcUseHeld, ) where import NewInt import Dodge.Creature.Action.Blink import Dodge.RadarSweep import Color import Control.Monad import Data.Maybe import Dodge.Base.Collide import Dodge.Base.Coordinate import Dodge.Data.ComposedItem import Dodge.Data.DoubleTree import Dodge.Data.MuzzleEffect import Dodge.Data.World import Dodge.Gas import Dodge.Inventory.Lock import Dodge.Item.HeldOffset import Dodge.Item.Weapon.Shatter import Dodge.Item.Weapon.TriggerType import Dodge.Projectile.Create import Dodge.SoundLogic import Dodge.Tesla.Arc import Geometry import LensHelp import ListHelp import Picture.Base import RandomHelp import qualified SDL heldEffect :: LabelDoubleTree ComposeLinkType Item -> Creature -> World -> World heldEffect = hammerCheck $ heldEffectNoHammerCheck heldEffectNoHammerCheck :: LabelDoubleTree ComposeLinkType Item -> Creature -> World -> World heldEffectNoHammerCheck = useTimeCheck heldEffectMuzzles hammerCheck :: ChainEffect hammerCheck f it cr w = case it ^? ldtValue . itUse . heldTriggerType of Just HammerTrigger -> case w ^? input . mouseButtons . ix SDL.ButtonLeft of Just 0 -> f it cr w _ -> w _ -> f it cr w heldEffectMuzzles :: LabelDoubleTree ComposeLinkType Item -> Creature -> World -> World heldEffectMuzzles t cr w = uncurry (applyCME (_ldtValue t) cr) cmew -- & cWorld . lWorld . lTestString .~ map (show . _mzAmmoSlot) muzzles & doWeaponRepetitions upitm cr where muzzles = t ^. ldtValue . itUse . heldAim . aimMuzzles (upitm, loadedmuzzles) = mapAccumR loadMuzzle t muzzles cmew = foldl' (useLoadedAmmo t cr) (CME 0 0 False, w) $ zip [0 ..] loadedmuzzles -- need to be careful about inventory lock or item ids here doWeaponRepetitions :: LabelDoubleTree ComposeLinkType Item -> Creature -> World -> World doWeaponRepetitions itm cr = case itm ^? ldtValue . itUse . heldParams . weaponRepeat of Just (x : xs) -> cWorld . lWorld . delayedEvents .++~ ((x : xs) <&> (,WdWdFromItCrixWdWd upitm (_crID cr) ItCrWdItemHeldEffect)) _ -> id where upitm = itm & ldtValue . itUse . heldParams . weaponRepeat .~ [] & ldtValue . itUse . heldTriggerType .~ AutoTrigger applyCME :: Item -> Creature -> CumulativeMuzzleEffect -> World -> World applyCME itm cr cme | _cmeSound cme = applyInvLock itm cr . applySoundCME itm cr . applySidePush spush cr . applyTorqueCME itm cr . applyRecoil itm cr | otherwise = failsound where spush = fromMaybe 0 $ itm ^? itUse . heldParams . sidePush failsound w = case w ^? input . mouseButtons . ix SDL.ButtonLeft of Just 0 -> soundStart (CrWeaponFailSound (_crID cr)) (_crPos cr) click1S Nothing w _ -> soundContinue (CrWeaponFailSound (_crID cr)) (_crPos cr) click1S Nothing w applyInvLock :: Item -> Creature -> World -> World applyInvLock itm cr = case itm ^? itUse . heldParams . weaponInvLock of Just i | i > 0 -> (cWorld . lWorld . delayedEvents .:~ (i, UnlockInv cid)) . lockInv cid _ -> id where cid = _crID cr applySoundCME :: Item -> Creature -> World -> World applySoundCME itm cr = fromMaybe id $ do (soundid, x) <- itm ^? itUse . heldParams . bulGunSound . _Just if x > 0 then return $ soundContinue (CrWeaponSound (_crID cr) 0) (_crPos cr) soundid (Just x) else return $ soundMultiFrom [CrWeaponSound cid j | j <- [0 .. 5]] (_crPos cr) soundid Nothing where cid = _crID cr applyRecoil :: Item -> Creature -> World -> World applyRecoil itm cr = over (cWorld . lWorld . creatures . ix cid) pushback where cid = _crID cr recoilAmount = fromMaybe 0 $ itm ^? itUse . heldParams . recoil pushback = over crPos (+.+ rotateV (_crDir cr) (V2 ((- recoilAmount) / _crMass cr) 0)) applySidePush :: Float -> Creature -> World -> World applySidePush 0 _ w = w applySidePush maxSide cr w = w & cWorld . lWorld . creatures . ix cid %~ push & randGen .~ g where cid = _crID cr push = over crPos (+.+ rotateV (_crDir cr) (V2 0 (pushAmount / _crMass cr))) (pushAmount, g) = randomR (- maxSide, maxSide) $ _randGen w applyTorqueCME :: Item -> Creature -> World -> World applyTorqueCME itm cr w | cid == 0 = w & wCam . camRot -~ rot & cWorld . lWorld . creatures . ix cid . crDir +~ rot & randGen .~ g | otherwise = w & cWorld . lWorld . creatures . ix cid . crDir +~ rot & randGen .~ g where cid = _crID cr (rot, g) = randomR (- torque, torque) $ _randGen w torque = fromMaybe 0 $ itm ^? itUse . heldParams . torqueAfter -- (Muzzle,Int,Int) = (muzzle, amountloaded, id of mag taken from) loadMuzzle :: LabelDoubleTree ComposeLinkType Item -> Muzzle -> (LabelDoubleTree ComposeLinkType Item, Maybe (Muzzle, Int, LabelDoubleTree ComposeLinkType Item)) loadMuzzle t@(LDT _ l _) mz = fromMaybe (t, Nothing) $ do let as = _mzAmmoSlot mz amamount = _mzAmmoPerShot mz (i, (_, mag)) <- findWithIx (isAmmoIntLink as . fst) l availableammo <- mag ^? ldtValue . itConsumables . magLoadStatus . iaLoaded let usedammo = case amamount of UseUpTo x -> min x availableammo UseExactly x | x <= availableammo -> x | otherwise -> 0 guard $ usedammo > 0 return ( t & ldtLeft . ix i . _2 . ldtValue . itConsumables . magLoadStatus . iaLoaded -~ usedammo , Just (mz, usedammo, mag) ) makeMuzzleFlare :: Muzzle -> LabelDoubleTree ComposeLinkType Item -> Creature -> World -> World makeMuzzleFlare mz itmtree cr = case mz ^. mzFlareType of DefaultFlareType -> id PistolFlare -> basicMuzFlare pos dir MiniGunFlare -> --makeTlsTimeRadColPos 2 100 (V3 1 1 0.5) (pos `v2z` 20) (cWorld . lWorld . lights .:~ LSParam (pos `v2z` 20) 100 (V3 1 1 0.5)) . muzFlareAt (V4 10 10 1 3) (pos `v2z` 20) dir HeavySmokeFlare -> basicMuzFlare pos dir LasGunFlare -> flareCircleAt (getLaserColor itmtree) 0.8 (pos `v2z` 20) -- . ( cWorld . lWorld . tempLightSources -- .:~ tlsTimeRadColPos 1 100 (xyzV4 $ getLaserColor itmtree) (pos `v2z` 10) . ( cWorld . lWorld . lights .:~ LSParam (pos `v2z` 10) 100 (xyzV4 $ getLaserColor itmtree) ) TeslaGunFlare -> cWorld . lWorld . lights .:~ LSParam (pos `v2z` 10) 100 (V3 0 0 1) where -- .:~ tlsTimeRadColPos 1 100 (V3 0 0 1) (pos `v2z` 10) itm = itmtree ^. ldtValue (moff, mrot) = heldItemOrient2D itm cr (_mzPos mz) (_mzRot mz) pos = _crPos cr + rotateV (_crDir cr) moff dir = _crDir cr + mrot --{-# OPTIONS -Wno-incomplete-uni-patterns #-} muzFlareAt :: Color -> Point3 -> Float -> World -> World muzFlareAt col tranv dir w = w & randGen .~ g & cWorld . lWorld . flares <>~ thepic where thepic = setLayer BloomNoZWrite . translate3 tranv . color col . rotate dir . polygon $ [ V2 0 0 , V2 a (- b) , V2 c d ] thestate = replicateM 4 $ state $ randomR (2, 20) (a : b : c : d : _, g) = runState thestate $ _randGen w -- randomRs (2, 20) (_randGen w) flareCircleAt :: Color -> Float -> Point3 -> World -> World flareCircleAt col alphax tranv = cWorld . lWorld . flares <>~ setLayer BloomNoZWrite ( translate3 tranv $ circleSolidCol (withAlpha 0 0) (withAlpha alphax col) 50 ) -- previous phaseV parameters: 0.2, 1, 5 getLaserPhaseV :: LabelDoubleTree ComposeLinkType Item -> Float getLaserPhaseV = const 1 getLaserDamage :: LabelDoubleTree ComposeLinkType Item -> LaserType getLaserDamage = const (DamageLaser 11) getLaserColor :: LabelDoubleTree ComposeLinkType Item -> Color getLaserColor = const yellow basicMuzFlare :: Point2 -> Float -> World -> World basicMuzFlare pos dir = -- makeTlsTimeRadColPos 2 100 (V3 1 1 0.5) (pos `v2z` 20) (cWorld . lWorld . lights .:~ LSParam (pos `v2z` 20) 100 (V3 1 1 0.5)) . muzFlareAt (V4 10 10 1 3) (pos `v2z` 20) dir . muzFlareAt (V4 10 10 1 3) (pos `v2z` 20) dir . muzFlareAt (V4 10 10 1 3) (pos `v2z` 20) dir isAmmoIntLink :: Int -> ComposeLinkType -> Bool isAmmoIntLink i (AmmoInLink j _) = i == j isAmmoIntLink _ _ = False useLoadedAmmo :: LabelDoubleTree ComposeLinkType Item -> Creature -> (CumulativeMuzzleEffect, World) -> (Int, Maybe (Muzzle, Int, LabelDoubleTree ComposeLinkType Item)) -> (CumulativeMuzzleEffect, World) useLoadedAmmo _ _ (cme, w) (_, Nothing) = (cme, w) useLoadedAmmo itmtree cr (cme, w) (mzid, Just (mz, x, magtree)) = (,) (cme & cmeSound .~ True) $ removeAmmoFromMag x mid cr . makeMuzzleFlare mz itmtree cr $ case _mzEffect mz of MuzzleShootBullet -> shootBullet itmtree cr (mz, x, magtree) w MuzzleLaser -> shootLaser itmtree cr mz w MuzzleTesla -> shootTeslaArc itm cr mz w MuzzleTractor -> shootTractorBeam cr w MuzzleLauncher -> createProjectile magtree mz itmtree cr w MuzzleNozzle{} -> useGasParams mid mz itm cr $ walkNozzle mzid mz itm cr w MuzzleShatter -> shootShatter itm cr w MuzzleDetector -> itemDetectorEffect itm 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 where mid = magtree ^? ldtValue . itLocation . ilInvID itm = itmtree ^. ldtValue itemDetectorEffect :: Item -> Creature -> World -> World itemDetectorEffect itm cr w = fromMaybe w $ do DETECTOR dt <- itm ^? itType . ibtHeld return $ case dt of ITEMDETECTOR -> aRadarPulse ObItem cr w CREATUREDETECTOR -> aRadarPulse ObCreature cr w WALLDETECTOR -> aRadarPulse ObWall cr w walkNozzle :: Int -> Muzzle -> Item -> Creature -> World -> World walkNozzle mzid mz itm cr w = fromMaybe w $ do invid <- itm ^? itLocation . ilInvID return $ w & cWorld . lWorld . creatures . ix (_crID cr) . crInv . ix invid . itUse . heldAim . aimMuzzles . ix mzid . mzEffect . nzCurrentWalkAngle .~ wa & randGen .~ g where nz = _mzEffect mz (walkamount, g) = randomR (- aspeed, aspeed) (_randGen w) aspeed = _nzWalkSpeed nz maxa = _nzMaxWalkAngle nz wa = min maxa $ max (negate maxa) (_nzCurrentWalkAngle nz + walkamount) shootTractorBeam :: Creature -> World -> World shootTractorBeam cr w = w & cWorld . lWorld . tractorBeams .:~ tractorBeamAt spos outpos dir power where cpos = _crPos cr spos = cpos +.+ (_crRad cr + 10) *.* unitVectorAtAngle dir xpos = cpos +.+ 400 *.* unitVectorAtAngle dir dir = _crDir cr outpos = fst $ collidePointWallsFilter (const True) cpos xpos w power = 1 tractorBeamAt :: Point2 -> Point2 -> Float -> Point2 -> TractorBeam tractorBeamAt pos outpos dir power = TractorBeam { _tbPos = pos , _tbStartPos = outpos , _tbVel = d , _tbTime = 10 } where d = unitVectorAtAngle dir * power shootLaser :: LabelDoubleTree ComposeLinkType Item -> Creature -> Muzzle -> World -> World shootLaser itmtree cr mz w = w & randGen .~ g & cWorld . lWorld . lasers .:~ LaserStart { _lpType = getLaserDamage itmtree , _lpPhaseV = getLaserPhaseV itmtree , _lpPos = pos , _lpDir = dir , _lpColor = getLaserColor itmtree } where itm = itmtree ^. ldtValue (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 inacc = _mzInaccuracy mz lasRayAt :: Color -> Int -> Float -> Point2 -> Float -> LaserStart lasRayAt col dam phasev pos dir = LaserStart { _lpType = DamageLaser dam , _lpPhaseV = phasev , _lpPos = pos , _lpDir = dir , _lpColor = col } removeAmmoFromMag :: Int -> Maybe Int -> Creature -> World -> World removeAmmoFromMag x mid cr = fromMaybe id $ do magid <- mid return $ cWorld . lWorld . creatures . ix (_crID cr) . crInv . ix magid . itConsumables . magLoadStatus . iaLoaded -~ x getBulletType :: LabelDoubleTree ComposeLinkType Item -> LabelDoubleTree ComposeLinkType Item -> Muzzle -> Creature -> World -> Maybe Bullet getBulletType itmtree magtree mz cr w = magtree ^? ldtValue . itConsumables . magParams . ampBullet <&> buTrajectory .~ btraj <&> buPayload .~ bpayload <&> buEffect .~ beffect where btraj = fromMaybe BasicBulletTrajectory $ do targetingtree <- lookup WeaponTargetingLink (itmtree ^. ldtRight) -- left or right for these? tp <- targetingtree ^? ldtValue . itTargeting . itTgPos . _Just attree <- lookup AmmoTargetingLink (magtree ^. ldtLeft) bt <- attree ^? ldtValue . itUse . ubMod . bmTrajectory return $ getBulletTrajectory mz (itmtree ^. ldtValue) bt tp cr w bpayload = fromMaybe BulSpark $ do attree <- lookup AmmoPayloadLink (magtree ^. ldtLeft) attree ^? ldtValue . itUse . ubMod . bmPayload beffect = fromMaybe DestroyBullet $ do attree <- lookup AmmoEffectLink (magtree ^. ldtLeft) attree ^? ldtValue . itUse . ubMod . bmEffect getBulletTrajectory :: Muzzle -> Item -> BulletTrajectoryType -> Point2 -> Creature -> World -> BulletTrajectory getBulletTrajectory mz itm bt tp cr w = case bt of BasicBulletTrajectoryType -> BasicBulletTrajectory FlechetteTrajectoryType -> FlechetteTrajectory tp BezierTrajectoryType -> BezierTrajectory bulpos tp (mouseWorldPos (w ^. input) (w ^. wCam)) MagnetTrajectoryType -> MagnetTrajectory tp where (moff, _) = heldItemOrient2D itm cr (_mzPos mz + V2 0 offset) (_mzRot mz) bulpos = _crPos cr + rotateV (_crDir cr) moff offset = case itm ^? itUse . heldParams . randomOffset of Just x | x /= 0 -> fst . randomR (- x, x) $ _randGen w _ -> 0 shootBullet :: LabelDoubleTree ComposeLinkType Item -> Creature -> (Muzzle, Int, LabelDoubleTree ComposeLinkType Item) -> World -> World shootBullet itmtree cr (mz, x, magtree) w = fromMaybe w $ do thebullet <- getBulletType itmtree magtree mz cr w return $ foldl' (&) w (replicate x (makeBullet thebullet (itmtree ^. ldtValue) cr mz)) -- & makeMuzzleSmoke mz itm cr -- the random generator is not updated here, not sure if that is a problem makeBullet :: Bullet -> Item -> Creature -> Muzzle -> World -> World makeBullet thebullet itm cr mz w = w & randGen .~ g & cWorld . lWorld . instantBullets .:~ ( thebullet & buPos .~ bulpos -- & buTrajectory .~ BasicBulletTrajectory & buVel %~ (rotateV dir . (muzvel *.*)) & buDrag *~ drag ) where (moff, mrot) = heldItemOrient2D itm cr (_mzPos mz + V2 0 offset) (_mzRot mz) bulpos = _crPos cr + rotateV (_crDir cr) moff (a, g'') = randomR (- inacc, inacc) $ _randGen w inacc = _mzInaccuracy mz (drag, g') = case _rifling (_heldParams $ _itUse itm) of ConstFloat x -> (x, g'') UniRandFloat x y -> randomR (x, y) g'' (muzvel, g) = case _muzVel $ _heldParams $ _itUse itm of ConstFloat x -> (x, g') UniRandFloat x y -> randomR (x, y) g' dir = _crDir cr + mrot + a offset = case itm ^? itUse . heldParams . randomOffset of Just x | x /= 0 -> fst . randomR (- x, x) $ _randGen w _ -> 0 mcUseHeld :: HeldItemType -> Item -> Machine -> World -> World mcUseHeld hit = case hit of LASER -> mcShootLaser _ -> \_ _ -> id useGasParams :: Maybe Int -> Muzzle -> Item -> Creature -> World -> World useGasParams mmagid mz itm cr w = createGas gastype pressure pos dir cr w & randGen .~ g' where (pressure, g) = doGenFloat (_nzPressure $ _mzEffect mz) (_randGen w) gastype = fromMaybe (error "cannot find gas ammo") $ do magid <- mmagid fueltype <- cr ^? crInv . ix magid . itConsumables . magParams . ampCreateGas gc <- itm ^? itUse . heldParams . gasCreation return $ gasCreate fueltype gc --pos = _crPos cr + rotateV (_crDir cr) (_mzPos mz + aimingWeaponZeroPos cr itm) (moff, mrot) = heldItemOrient2D itm cr (_mzPos mz) (_mzRot mz) pos = _crPos cr + rotateV (_crDir cr) moff (a, g') = randomR (- inacc, inacc) g inacc = _mzInaccuracy mz dir = _crDir cr + mrot + a + _nzCurrentWalkAngle (_mzEffect mz) gasCreate :: GasFuel -> GasCreate -> GasCreate gasCreate = const id doGenFloat :: RandomGen g => GenFloat -> g -> (Float, g) doGenFloat (ConstFloat x) g = (x, g) doGenFloat (UniRandFloat x y) g = randomR (x, y) g --caneStickSoundChoice :: Item -> SoundID --caneStickSoundChoice _ = tap3S -- -- | (it ^?! itUse . heldConsumption . laSource . _InternalSource . iaLoaded) < 2 = tap3S -- -- | otherwise = shotgunS --bangStickSoundChoice :: Item -> SoundID --bangStickSoundChoice = caneStickSoundChoice -- do -- wth <- state $ randomR (1, 5) -- return (itUse . heldConsumption . laAmmoType . amBullet . buWidth .~ wth) --coneRandItemParams :: State StdGen (Item -> Item) --coneRandItemParams = do -- muzv <- state $ randomR (0.5, 1) -- rifl <- state $ randomR (0.3, 0.9) -- return $ \it -> -- it & itUse . heldParams . muzVel .~ muzv -- & itUse . heldParams . rifling .~ rifl mcShootLaser :: Item -> Machine -> World -> World mcShootLaser _ mc = cWorld . lWorld . lasers .:~ lasRayAt yellow dam phasev pos dir where pos = _mcPos mc +.+ 20 *.* unitVectorAtAngle dir dir = mc ^?! mcType . _McTurret . tuDir phasev = 1 dam = 11 -- | assumes that the item is held shootTeslaArc :: Item -> Creature -> Muzzle -> World -> World shootTeslaArc itm cr mz w = w' & cWorld . lWorld . creatures . ix (_crID cr) . crInv . ix itRef . itParams .~ ip 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) pos = _crPos cr + rotateV (_crDir cr) moff dir = _crDir cr + mrot determineProjectileTracking :: LabelDoubleTree ComposeLinkType Item -> LabelDoubleTree ComposeLinkType Item -> ProjectileHoming determineProjectileTracking magtree itmtree = case lookup RemoteScreenLink (magtree ^. ldtLeft) of Just screen -> HomeUsingRemoteScreen (screen ^. ldtValue . itID) Nothing -> fromMaybe NoHoming $ do _ <- lookup AmmoTargetingLink (magtree ^. ldtLeft) -- should not have to give a direction targetingtree <- lookup WeaponTargetingLink (itmtree ^. ldtRight) -- left or right for these return $ HomeUsingTargeting (targetingtree ^. ldtValue . itID) createProjectile :: LabelDoubleTree ComposeLinkType Item -> Muzzle -> LabelDoubleTree ComposeLinkType Item -> Creature -> World -> World createProjectile magtree muz itmtree cr = fromMaybe failsound $ do magid <- magtree ^? ldtValue . itLocation . ilInvID ammoitem <- cr ^? crInv . ix magid let homing = determineProjectileTracking magtree itmtree aparams <- ammoitem ^? itConsumables . magParams . ampPayload return $ createShell homing aparams muz cr . startthesound where -- the sound should be moved to the projectile firing startthesound = soundMultiFrom [CrWeaponSound (_crID cr) j | j <- [0 .. 3]] (_crPos cr) tap4S Nothing failsound w' = case w' ^? input . mouseButtons . ix SDL.ButtonLeft of Just 0 -> soundStart (CrWeaponSound (_crID cr) 0) (_crPos cr) click1S Nothing w' _ -> soundContinue (CrWeaponSound (_crID cr) 0) (_crPos cr) click1S Nothing w' ---- need to add these to muzzle flare? --makeMuzzleSmoke :: Muzzle -> Item -> Creature -> World -> World --makeMuzzleSmoke mz itm cr w = case mz ^. mzFlareType of -- DefaultFlareType -> w -- PistolFlare -> foldl' (flip $ smokeCloudAt (greyN 0.5) 5 400 5 . (+.+.+ pos) . (* 8)) w ps -- MiniGunFlare -> smokeCloudAt (greyN 0.5) 5 400 5 pos w -- HeavySmokeFlare -> foldl' (flip $ smokeCloudAt black 20 400 5 . (+.+.+ pos) . (* 8)) w ps' -- LasGunFlare -> w -- TeslaGunFlare -> w -- where -- ps = replicateM 2 randOnUnitSphere & evalState $ _randGen w -- ps' = replicateM 4 randOnUnitSphere & evalState $ _randGen w -- pos = addZ 10 $ _crPos cr + rotateV (_crDir cr) (_mzPos mz + aimingWeaponZeroPos cr itm) ---- , withSmoke 1 black 20 200 5 useStopWatch :: Item -> Creature -> World -> World useStopWatch itm _ = timeFlow .~ PausedTimeFlow { _timeFlowCharge = 100 , _scrollItemID = _itID itm } useTimeScrollGun :: Item -> Creature -> World -> World useTimeScrollGun itm _ = timeFlow .~ ItemScrollTimeFlow { _scrollSmoothing = 0 --, _reverseAmount = itm ^?! itUse . leftConsumption . wpCharge , _reverseAmount = 100 , _futureWorlds = [] , _scrollItemID = _itID itm } useRewindGun :: NewInt ItmInt -> World -> World useRewindGun i = timeFlow .~ RewindLeftClick -- { _reverseAmount = itm ^?! itUse . leftConsumption . wpCharge { _reverseAmount = 100 , _scrollItemID = i } --useRewindGun _ _ w = case w ^. cwTime . rewindWorlds of -- [w'] -> w & cwTime . maybeWorld .~ Just' w' -- (w' : ws) -> w -- & cwTime . maybeWorld -- .~ Just' w' -- & cwTime . rewindWorlds .~ ws -- _ -> w