diff --git a/src/Dodge/Creature.hs b/src/Dodge/Creature.hs index 90bf09a32..a9f99c879 100644 --- a/src/Dodge/Creature.hs +++ b/src/Dodge/Creature.hs @@ -159,7 +159,7 @@ startCr = defaultCreature startInventory :: IM.IntMap Item startInventory = IM.fromList (zip [0..20] ( - [ltAutoGun + [spreadGun ,autoGun ,hvAutoGun ,pistol diff --git a/src/Dodge/Creature/Action/UseItem.hs b/src/Dodge/Creature/Action/UseItem.hs index 54f165610..decb18fe3 100644 --- a/src/Dodge/Creature/Action/UseItem.hs +++ b/src/Dodge/Creature/Action/UseItem.hs @@ -33,7 +33,7 @@ itemEffect -> World itemEffect cr Consumable{_cnEffect=eff } w = maybe w (rmSelectedInvItem (_crID cr)) (eff (_crID cr) w) itemEffect cr it@Weapon{_itUse=eff} w = foldr ($) eff (_itUseModifiers it) it cr w -itemEffect cr it@Throwable{_itUse = eff} w = eff it cr w +itemEffect cr it@Throwable{_itUse = eff} w = foldr ($) eff (_itUseModifiers it) it cr w itemEffect _ _ w = w useLeftItem diff --git a/src/Dodge/Data.hs b/src/Dodge/Data.hs index 33ea18718..951c9471c 100644 --- a/src/Dodge/Data.hs +++ b/src/Dodge/Data.hs @@ -247,6 +247,7 @@ data Item , _itTargeting :: Maybe (World -> Maybe Point2, Int -> Item -> Creature -> World -> Picture) , _itWorldTrigger :: Maybe (Int -> World -> Bool) , _itAimStance :: AimStance + , _wpNumBarrels :: Int } | Consumable { _itName :: String @@ -302,6 +303,7 @@ data Item , _itUse :: Item -> Creature -> World -> World , _itUseRate :: Int , _itUseTime :: Int + , _itUseModifiers :: [(Item -> Creature -> World -> World) -> Item -> Creature -> World -> World] , _itAimingSpeed :: Float , _itAimingRange :: Float , _itZoom :: ItZoom diff --git a/src/Dodge/Default/Weapon.hs b/src/Dodge/Default/Weapon.hs index 8b84a4447..fecfaa7ee 100644 --- a/src/Dodge/Default/Weapon.hs +++ b/src/Dodge/Default/Weapon.hs @@ -43,6 +43,7 @@ defaultGun = Weapon , _itTargeting = Nothing , _itWorldTrigger = Nothing , _itAimStance = OneHand + , _wpNumBarrels = 1 } defaultAutoGun :: Item defaultAutoGun = defaultGun diff --git a/src/Dodge/Item/Attachment.hs b/src/Dodge/Item/Attachment.hs index ed09c6012..ae75e64e3 100644 --- a/src/Dodge/Item/Attachment.hs +++ b/src/Dodge/Item/Attachment.hs @@ -52,6 +52,19 @@ charFiringStrat strats cr w = case w ^? creatures . ix cid . crInv _ -> w where cid = _crID cr +charFiringStratI + :: [(Char, (Item -> Creature -> World -> World) -> Item -> Creature -> World -> World)] -- ^ Different firing effects for different characters + -> (Item -> Creature -> World -> World) + -> Item + -> Creature + -> World + -> World +charFiringStratI strats eff item cr w = case w ^? creatures . ix cid . crInv + . ix (_crInvSel $ _creatures w IM.! cid) . itAttachment . _Just . itCharMode of + Just (c :<| _) -> fromJust (Prelude.lookup c strats) eff item cr w + _ -> w + where + cid = _crID cr increaseFuse :: Int -- ^ Old fuse time diff --git a/src/Dodge/Item/Weapon.hs b/src/Dodge/Item/Weapon.hs index adfeef0e8..994af6fd6 100644 --- a/src/Dodge/Item/Weapon.hs +++ b/src/Dodge/Item/Weapon.hs @@ -14,7 +14,7 @@ import Dodge.WorldEvent import Dodge.Default --import Dodge.Default.Shell import Dodge.Item.Draw -import Dodge.Particle.Bullet.HitEffect +--import Dodge.Particle.Bullet.HitEffect import Dodge.Item.Data import Dodge.Item.Weapon.InventoryDisplay import Dodge.Item.Weapon.TriggerType @@ -23,6 +23,7 @@ import Dodge.Item.Weapon.UseEffect import Dodge.Item.Weapon.Laser import Dodge.Item.Weapon.Shell import Dodge.Item.Weapon.Bullet +import Dodge.Item.Weapon.AmmoParams import Dodge.Default.Weapon import Dodge.Item.Weapon.Booster import Dodge.Item.Weapon.Grenade @@ -87,10 +88,6 @@ pistol = defaultGun pistolPic :: Picture pistolPic = color green $ polygon $ rectNESW 5 5 (-5) (-5) -useAmmoParams :: Item -> Creature -> World -> World -useAmmoParams it = withVelWthHiteff (_amBulVel b) (_amBulWth b) (_amBulEff b) - where - b = _wpAmmo it effectGun :: String -> (Creature -> World -> World) -> Item effectGun name eff = defaultGun @@ -111,7 +108,9 @@ rezGun = defaultGun , _wpReloadState = 0 , _itUseRate = 0 , _itUseTime = 0 - , _itUse = \_ -> shoot aTeslaArc + , _itUse = \_ -> aTeslaArc + , _itUseModifiers = + [] , _wpSpread = 0.001 , _wpRange = 20 , _itFloorPict = onLayer FlItLayer $ color chartreuse $ pictures @@ -228,7 +227,10 @@ tractorGun = defaultAutoGun , _wpReloadState = 0 , _itUseRate = 0 , _itUseTime = 0 - , _itUse = \_ -> shoot $ aTractorBeam 0 + , _itUse = \_ -> aTractorBeam 0 + , _itUseModifiers = + [ ammoUseCheckI + ] , _wpSpread = 0.00001 , _wpRange = 20 , _itFloorPict = onLayer FlItLayer $ color blue $ pictures [polygon $ rectNESW 1.5 6 (-1.5) 0 ] @@ -275,9 +277,12 @@ hvAutoGun = defaultAutoGun , _wpReloadState = 0 , _itUseRate = 25 , _itUseTime = 0 - , _itUse = \it -> mkHvBul it + , _itUse = useAmmoParams , _itUseModifiers = [ rateIncABI 24 10 (torqueBeforeForcedI 0.1) (torqueAfterI 0.2) + , withSoundI longGunSound + , withThinSmokeI + , withMuzFlareI ] , _wpRange = 20 , _itFloorPict = onLayer FlItLayer hvAutoGunPic @@ -286,11 +291,6 @@ hvAutoGun = defaultAutoGun , _itEquipPict = pictureWeaponOnAim hvAutoGunPic , _wpAmmo = hvBullet } - where - mkHvBul it = withSound longGunSound - . withThinSmoke - . withMuzFlare - $ useAmmoParams it hvAutoGunPic :: Picture hvAutoGunPic = color orange $ polygon $ rectNESW 5 12 (-5) (-12) ltAutoGun :: Item @@ -336,16 +336,15 @@ miniGun = defaultAutoGun , _wpMaxWarmUp = 100 , _itUseRate = 1 , _itUseTime = 0 - , _itUse = \it -> withWarmUp 26 - . shootWithSoundFor 28 2 - . torqueBefore 0.1 --- . torqueBefore 0.03 - . withSidePush 50 - . withRecoil 15 --- . withRandomDir 0.1 - . withRandomOffset 9 - . withMuzFlare - $ useAmmoParams it + , _itUse = useAmmoParams + , _itUseModifiers = + [ withWarmUpI 26 + , shootWithSoundForI 28 2 + , torqueBeforeForcedI 0.1 + , withSidePushI 50 + , withRandomOffsetI 9 + , withMuzFlareI + ] , _wpRange = 20 , _itFloorPict = onLayer FlItLayer miniGunPict , _itAimingSpeed = 0.4 @@ -358,7 +357,6 @@ miniGunPict = pictures [ translate 5 0 . color red $ polygon $ rectNESW 9 7 (-9) (-5) , color red . polygon $ rectNESW 4 12 (-4) (-12) ] - spreadGun :: Item spreadGun = defaultGun { _itName = "SPREAD" @@ -369,17 +367,25 @@ spreadGun = defaultGun , _wpReloadState = 0 , _itUseRate = 20 , _itUseTime = 0 - , _itUse = \_ -> shootWithSound shotgunSound - . withRecoil 100 - . withMuzFlare - $ spreadNumVelWthHiteff spreadGunSpread 9 (V2 30 0) 2 basicBulletEffect + --, _itUse = \_ -> spreadNumVelWthHiteff spreadGunSpread 9 (V2 30 0) 2 basicBulletEffect + , _itUse = useAmmoParams + , _itUseModifiers = + [ shootWithSoundI shotgunSound + , withRecoilI 100 + , withMuzFlareI + , spreadNumI + ] , _wpSpread = spreadGunSpread , _wpRange = 20 - , _itFloorPict = onLayer FlItLayer $ color green $ pictures [ polygon $ map toV2[(-3,0),(3,6),(3,-6)] ] + , _itFloorPict = onLayer FlItLayer $ spreadGunPic , _itAimingSpeed = 1 , _itAimingRange = 0 - , _itEquipPict = pictureWeaponOnAim $ color green $ pictures [ polygon $ map toV2[(-3,0),(3,6),(3,-6)] ] + , _itEquipPict = pictureWeaponOnAim $ spreadGunPic + , _wpAmmo = basicBullet + , _wpNumBarrels = 50 } +spreadGunPic :: Picture +spreadGunPic = color green $ pictures [ polygon $ map toV2[(-3,0),(3,6),(3,-6)] ] multGun :: Item multGun = defaultGun { _itName = "MULTGUN" @@ -390,10 +396,13 @@ multGun = defaultGun , _wpReloadState = 0 , _itUseRate = 20 , _itUseTime = 0 - , _itUse = \_ -> shootWithSound shotgunSound - . withRecoil 200 - . withMuzFlare - $ numVelWthHitEff 5 (V2 50 0) 5 basicBulletEffect + , _itUse = useAmmoParams + , _itUseModifiers = + [ shootWithSoundI shotgunSound + , withRecoilI 200 + , withMuzFlareI + , numI + ] , _wpSpread = spreadGunSpread , _wpRange = 20 , _itFloorPict = onLayer FlItLayer multGunPic @@ -402,6 +411,8 @@ multGun = defaultGun , _itZoom = defaultItZoom {_itAimZoomFac = 1.5} , _itEquipPict = pictureWeaponOnAim multGunPic , _itAimStance = TwoHandTwist + , _wpAmmo = basicBullet + , _wpNumBarrels = 5 } multGunPic :: Picture multGunPic = color red $ pictures @@ -426,11 +437,13 @@ longGun = defaultGun , _wpReloadType = PassiveReload skwareFadeTwoSecSound , _itUseRate = 100 , _itUseTime = 0 - , _itUse = shootWithSound longGunSound - . withThickSmoke - . torqueAfter 0.05 - . withMuzFlare - . useAmmoParams + , _itUse = useAmmoParams + , _itUseModifiers = + [ shootWithSoundI longGunSound + , withThickSmokeI + , torqueAfterI 0.05 + , withMuzFlareI + ] , _wpRange = 200 , _itFloorPict = onLayer FlItLayer longGunPic , _itAimingSpeed = 0.2 @@ -468,7 +481,10 @@ poisonSprayer = defaultAutoGun , _wpReloadState = 0 , _itUseRate = 0 , _itUseTime = 0 - , _itUse = \_ -> shoot aGasCloud + , _itUse = \_ -> aGasCloud + , _itUseModifiers = + [shootWithSoundI buzzSound + ] , _wpSpread = 0.3 , _wpRange = 8 , _itFloorPict = onLayer FlItLayer $ color yellow $ polygon $ rectNESW 4 4 (-4) (-4) @@ -487,7 +503,12 @@ flamer = defaultAutoGun , _wpReloadState = 0 , _itUseRate = 0 , _itUseTime = 0 - , _itUse = \_ -> shoot $ withSidePush 5 $ withSidePushAfter 10 $ randWalkAngle 0.2 0.01 aFlame + , _itUse = \_ -> randWalkAngle 0.2 0.01 aFlame + , _itUseModifiers = + [ ammoUseCheckI + , withSidePushI 5 + , withSidePushAfterI 10 + ] , _wpSpread = 0 , _wpRange = 8 , _itFloorPict = onLayer FlItLayer flamerPic @@ -512,7 +533,11 @@ blinkGun = defaultGun , _wpReloadState = 0 , _itUseRate = 0 , _itUseTime = 0 - , _itUse = \_ -> hammerCheck $ shoot aSelf + , _itUse = \_ -> aSelf + , _itUseModifiers = + [ hammerCheckI + , ammoUseCheckI + ] , _itLeftClickUse = Just $ hammerCheckL $ shootL aSelfL , _wpSpread = 0.05 , _wpRange = 20 @@ -630,7 +655,7 @@ retireRemoteBomb itid 0 pjid w = w & pointToItem (_itemPositions w IM.! itid) %~ ( (itAttachment . _Just . scopePos .~ V2 0 0) . (itZoom .~ defaultItZoom) - . (itUse .~ (\_ -> hammerCheck throwRemoteBomb)) + . (itUse .~ (\_ -> throwRemoteBomb)) ) & projectiles %~ IM.delete pjid retireRemoteBomb itid t pjid w = setScope w @@ -707,7 +732,10 @@ grenade = Throwable , _itFloorPict = onLayer FlItLayer $ polygon $ map toV2 [(-3,-3),(-3,3),(3,3),(3,-3)] , _twMaxRange = 150 , _twAccuracy = 30 - , _itUse = \_ -> useTimeCheck $ throwGrenade makeExplosionAt + , _itUse = \_ -> throwGrenade makeExplosionAt + , _itUseModifiers = + [ useTimeCheckI + ] , _itAimingSpeed = 1 , _itAimingRange = 0 , _itZoom = defaultItZoom {_itAimZoomMax = f fuseTime, _itAimZoomMin = f fuseTime} @@ -757,7 +785,10 @@ remoteBomb = defaultThrowable , _itFloorPict = onLayer FlItLayer $ polygon $ map toV2 [(-3,-3),(-3,3),(3,3),(3,-3)] , _twMaxRange = 150 , _twAccuracy = 30 - , _itUse = \_ -> hammerCheck throwRemoteBomb + , _itUse = \_ -> throwRemoteBomb + , _itUseModifiers = + [ hammerCheckI + ] , _itAttachment = Just $ ItScope (V2 0 0) 0 1 True , _itEquipPict = pictureWeaponOnAim remoteBombUnarmedPic } @@ -881,7 +912,7 @@ throwRemoteBomb cr w = setLocation resetName = set (creatures . ix cid . crInv . ix j . itName) "REMOTE" removePict = set (creatures . ix cid . crInv . ix j . itEquipPict) $ \ _ _ -> blank resetFire = set (creatures . ix cid . crInv . ix j . itUse) - $ \_ -> hammerCheck $ explodeRemoteBomb itid i + $ \_ -> explodeRemoteBomb itid i p' = _crPos cr +.+ rotateV (_crDir cr) (V2 (_crRad cr) 0) p | circOnSomeWall p' 4 w = _crPos cr +.+ rotateV (_crDir cr) (V2 (_crRad cr-4) 0) | otherwise = p' @@ -949,7 +980,10 @@ radar = defaultGun , _wpReloadState = 0 , _itUseRate = 120 , _itUseTime = 0 - , _itUse = \_ -> shoot aRadarPulse + , _itUse = \_ -> aRadarPulse + , _itUseModifiers = + [ ammoUseCheckI + ] , _wpSpread = autogunSpread , _wpRange = 20 , _itHammer = HammerUp @@ -972,7 +1006,10 @@ sonar = defaultGun , _wpReloadState = 0 , _itUseRate = 120 , _itUseTime = 0 - , _itUse = \_ -> shoot aSonarPulse + , _itUse = \_ -> aSonarPulse + , _itUseModifiers = + [ ammoUseCheckI + ] , _wpRange = 20 , _itHammer = HammerUp , _itFloorPict = onLayer FlItLayer $ color blue $ polygon $ rectNESW 5 5 (-5) (-5) @@ -1024,7 +1061,10 @@ spawnGun cr = defaultGun , _wpReloadTime = 80 , _wpReloadState = 0 , _itUseRate = 100 - , _itUse = \_ -> hammerCheck $ spawnCrNextTo cr + , _itUse = \_ -> spawnCrNextTo cr + , _itUseModifiers = + [ hammerCheckI + ] } spawnCrNextTo :: Creature -- ^ Creature to spawn diff --git a/src/Dodge/Item/Weapon/AutoGun.hs b/src/Dodge/Item/Weapon/AutoGun.hs index 7c7faee5f..9968fcf3f 100644 --- a/src/Dodge/Item/Weapon/AutoGun.hs +++ b/src/Dodge/Item/Weapon/AutoGun.hs @@ -7,6 +7,7 @@ import Dodge.Item.Attachment import Dodge.Item.Attachment.Data import Dodge.Item.Weapon.ExtraEffect import Dodge.Item.Weapon.InventoryDisplay +import Dodge.Item.Weapon.AmmoParams import Dodge.Item.Data import Dodge.Picture.Layer import Dodge.Item.Draw @@ -30,9 +31,14 @@ autoGun = defaultAutoGun , _wpReloadState = 0 , _itUseRate = 5 , _itUseTime = 0 - , _itUse = \_ -> charFiringStrat - [('M',autoFireMode) - ,('S',singleFireMode) + , _itUse = useAmmoParams + , _itUseModifiers = + [ charFiringStratI + [('M',shootWithSoundI autoGunSound . torqueBeforeForcedI 0.05) + ,('S',hammerCheckI . shootWithSoundI autoGunSound) + ] + , withRandomDirI (autogunSpread/2) + , withMuzFlareI ] , _wpSpread = autogunSpread , _wpRange = 20 diff --git a/src/Dodge/Item/Weapon/Launcher.hs b/src/Dodge/Item/Weapon/Launcher.hs index 1cac73481..b7352d645 100644 --- a/src/Dodge/Item/Weapon/Launcher.hs +++ b/src/Dodge/Item/Weapon/Launcher.hs @@ -37,7 +37,10 @@ launcher = defaultGun , _wpReloadState = 0 , _itUseRate = 20 , _itUseTime = 0 - , _itUse = shootWithSound launcherSound . aRocketWithItemParams + , _itUse = aRocketWithItemParams + , _itUseModifiers = + [ shootWithSoundI launcherSound + ] , _wpSpread = 0.02 , _wpRange = 20 , _itFloorPict = onLayer FlItLayer launcherPic diff --git a/src/Dodge/Item/Weapon/TriggerType.hs b/src/Dodge/Item/Weapon/TriggerType.hs index 38837b720..fb70721d0 100644 --- a/src/Dodge/Item/Weapon/TriggerType.hs +++ b/src/Dodge/Item/Weapon/TriggerType.hs @@ -1,6 +1,32 @@ {- | Weapon effects when pulling the trigger. -} module Dodge.Item.Weapon.TriggerType + -- ( hammerCheckI + -- , shootWithSoundI + -- , shootWithSoundForI + -- , withMuzFlareI + -- , withVelWthHiteff + -- , ammoUseCheckI + -- , rateIncABI + -- , torqueBeforeForcedI + -- , torqueAfterI + -- , withSoundI + -- , withThickSmokeI + -- , withThinSmokeI + -- , withRandomOffsetI + -- , withRandomDirI + -- , withRecoilI + -- , withSidePushAfterI + -- , withSidePushI + -- , withWarmUpI + -- , spreadNumI + -- , numI + -- , randWalkAngle -- ^ should be made into a modifier, perhaps + -- , hammerCheckI + -- , hammerCheckL + -- , shootL + -- , useTimeCheckI + -- ) where where import Dodge.Data import Dodge.SoundLogic @@ -20,6 +46,18 @@ import Data.Maybe import qualified Data.IntMap.Strict as IM import Data.Foldable +withThinSmokeI + :: (Item -> Creature -> World -> World) -- ^ Underlying effect + -> Item + -> Creature + -> World + -> World +withThinSmokeI eff item cr w = eff item cr $ foldl' (flip $ makeThinSmokeAt . (+.+ pos)) w ps + where + dir = _crDir cr + pos = _crPos cr +.+ (_crRad cr +0.5) *.* unitVectorAtAngle dir + ps = (replicateM 5 . randInCirc) 8 & evalState $ _randGen w + withThinSmoke :: (Creature -> World -> World) -- ^ Underlying effect -> Creature @@ -31,6 +69,17 @@ withThinSmoke eff cr w = eff cr $ foldl' (flip $ makeThinSmokeAt . (+.+ pos)) w pos = _crPos cr +.+ (_crRad cr +0.5) *.* unitVectorAtAngle dir ps = (replicateM 5 . randInCirc) 8 & evalState $ _randGen w +withThickSmokeI + :: (Item -> Creature -> World -> World) -- ^ Underlying effect + -> Item + -> Creature + -> World + -> World +withThickSmokeI eff item cr w = eff item cr $ foldl' (flip $ makeThickSmokeAt . (+.+ pos)) w ps + where + dir = _crDir cr + pos = _crPos cr +.+ (_crRad cr + 15) *.* unitVectorAtAngle dir + ps = (replicateM 20 . randInCirc) 8 & evalState $ _randGen w withThickSmoke :: (Creature -> World -> World) -- ^ Underlying effect -> Creature @@ -121,9 +170,32 @@ rateIncABI startRate fastRate exeffFirst exeffCont eff item cr w && _itUseTime item == 0 && _wpLoadedAmmo item > 0 reloadCondition = _wpLoadedAmmo item == 0 -{- | -Shoot a weapon rapidly after a warm up. -Applies ammo check as well. -} +{- | Apply effect after a warm up. -} +withWarmUpI + :: Int -- ^ warm up sound id + -> (Item -> Creature -> World -> World) + -- ^ underlying effect + -> Item + -> Creature + -> World + -> World +withWarmUpI soundID f item cr w + | reloadCondition = fromMaybe w $ startReloadingWeapon cr w + | _wpReloadState item /= 0 = w + | curWarmUp < maxWarmUp = w + & pointerToItem . wpCurWarmUp +~ 2 + & soundFrom (CrWeaponSound cid) soundID 2 0 + | otherwise = w + & pointerToItem . wpCurWarmUp .~ maxWarmUp + & f item cr + where + cid = _crID cr + itRef = _crInvSel cr + pointerToItem = creatures . ix cid . crInv . ix itRef + curWarmUp = _wpCurWarmUp item + maxWarmUp = _wpMaxWarmUp item + reloadCondition = _wpLoadedAmmo item == 0 +{- | Apply effect after a warm up. -} withWarmUp :: Int -- ^ warm up sound id -> (Creature -> World -> World) @@ -156,7 +228,26 @@ withSound -> Creature -> World -> World withSound soundid f cr = soundOncePos soundid (_crPos cr) . f cr +{- | Adds a sound to a creature based world effect. +The sound is emitted from the creature's position. -} +withSoundI + :: Int -- ^ Sound id + -> (Item -> Creature -> World -> World) -- ^ Underlying effect + -> Item + -> Creature + -> World -> World +withSoundI soundid f item cr = soundOncePos soundid (_crPos cr) . f item cr +withRecoilI + :: Float -- ^ Recoil amount + -> (Item -> Creature -> World -> World) + -> Item + -> Creature + -> World -> World +withRecoilI recoilAmount eff item cr = eff item cr . over (creatures . ix cid) pushback + where + cid = _crID cr + pushback = over crPos (+.+ rotateV (_crDir cr) (V2 ((-recoilAmount) / _crMass cr ) 0)) withRecoil :: Float -- ^ Recoil amount -> (Creature -> World -> World) @@ -198,6 +289,19 @@ withSidePush maxSide eff cr w = eff cr . over (creatures . ix cid) push $ w -- consider unifying the pushes using a direction vector {- | Pushes a creature sideways by a random amount. Applied after the underlying effect. -} +withSidePushAfterI + :: Float -- ^ Maximal possible side push amount + -> (Item -> Creature -> World -> World) + -> Item + -> Creature -- ^ Creature id + -> World -> World +withSidePushAfterI maxSide eff item cr w = over (creatures . ix cid) push . eff item cr $ w + where + cid = _crID cr + push = over crPos (+.+ rotateV (_crDir cr) (V2 0 (pushAmount / _crMass cr))) + (pushAmount, _) = randomR (-maxSide,maxSide) $ _randGen w +{- | Pushes a creature sideways by a random amount. +Applied after the underlying effect. -} withSidePushAfter :: Float -- ^ Maximal possible side push amount -> (Creature -> World -> World) @@ -327,6 +431,22 @@ useTimeCheck f cr w = case theItem ^? itUseTime of setUseTime = creatures . ix cid . crInv . ix (_crInvSel cr) . itUseTime +~ useRate theItem = _crInv cr IM.! _crInvSel cr useRate = fromMaybe 0 $ theItem ^? itUseRate +{- | +Applies a world effect after an item use cooldown check. -} +useTimeCheckI + :: (Item -> Creature -> World -> World) -- ^ Underlying effect + -> Item + -> Creature + -> World + -> World +useTimeCheckI f item cr w = case item ^? itUseTime of + Just 0 -> f item cr $ setUseTime w + _ -> w + where + cid = _crID cr + setUseTime = creatures . ix cid . crInv . ix (_crInvSel cr) . itUseTime +~ useRate + useRate = fromMaybe 0 $ item ^? itUseRate + {- | Applies a world effect after a hammer position check. -} hammerCheck :: (Creature -> World -> World) -- ^ Underlying effect @@ -353,6 +473,27 @@ hammerCheckI f it cr w = case it ^? itHammer of cid = _crID cr setHammerDown = creatures . ix cid . crInv . ix (_crInvSel cr) . itHammer .~ HammerDown {- | Applies a world effect after an ammo check. -} +ammoUseCheckI + :: (Item -> Creature -> World -> World) + -- ^ Underlying effect + -> Item + -> Creature + -> World + -> World +ammoUseCheckI f item cr w + | fireCondition = f item cr w & pointerToItem %~ + ( (wpLoadedAmmo -~ 1) . (itUseTime .~ _itUseRate item) ) + | reloadCondition = fromMaybe w $ startReloadingWeapon cr w + | otherwise = w + where + cid = _crID cr + itRef = _crInvSel cr + pointerToItem = creatures . ix cid . crInv . ix itRef + fireCondition = _wpReloadState item == 0 + && _itUseTime item == 0 + && _wpLoadedAmmo item > 0 + reloadCondition = _wpLoadedAmmo item == 0 +{- | Applies a world effect after an ammo check. -} shoot :: (Creature -> World -> World) -- ^ Underlying effect @@ -468,6 +609,19 @@ withVelWthHiteff vel width hiteff cr = over particles (newbul : ) dir = _crDir cr pos = _crPos cr +.+ _crRad cr *.* unitVectorAtAngle (_crDir cr) {- | Apply the effect to a translated creature. -} +withRandomOffsetI + :: Float -- ^ Max possible translate + -> (Item -> Creature -> World -> World) + -- ^ Underlying effect + -> Item + -> Creature + -> World + -> World +withRandomOffsetI offsetAmount f item cr w = f item (cr & crPos %~ (+.+ offV)) $ set randGen g w + where + (offsetVal , g) = randomR (-offsetAmount,offsetAmount) $ _randGen w + offV = rotateV (_crDir cr) (V2 0 offsetVal) +{- | Apply the effect to a translated creature. -} withRandomOffset :: Float -- ^ Max possible translate -> (Creature -> World -> World) @@ -568,6 +722,20 @@ torqueAfter torque feff cr w (rot, g) = randomR (-torque,torque) $ _randGen w rotateScope = creatures . ix 0 . crInv . ix (_crInvSel (_creatures w IM.! 0)) . itAttachment . _Just . scopePos %~ rotateV rot +spreadNumI + :: (Item -> Creature -> World -> World) + -> Item + -> Creature + -> World + -> World +spreadNumI eff item cr w = foldr f w dirs + where + dirs = zipWith (+) + [-spread,-spread+(2*spread/fromIntegral numBul)..spread] + (randomRs (0,spread/fromIntegral numBul) (_randGen w)) + f dir = eff item (cr & crDir +~ dir) + spread = _wpSpread item + numBul = _wpNumBarrels item {- | Create multiple bullets with a given spread, a given amount, given velocity, given width and given 'HitEffect'. -} spreadNumVelWthHiteff @@ -590,6 +758,20 @@ spreadNumVelWthHiteff spread num vel wth eff cr w = over particles (newbuls ++) dirs = map (_crDir cr +) $ zipWith (+) [-spread,-spread+(2*spread/fromIntegral num)..] (randomRs (0,spread/5) (_randGen w)) +numI + :: (Item -> Creature -> World -> World) + -> Item + -> Creature + -> World + -> World +numI eff item cr w = foldr f w poss + where + cp :: Float + cp = -0.5 * fromIntegral numBul + poss :: [V2 Float] + poss = map (rotateV (_crDir cr) . V2 0 . (*5) . (+ cp) . fromIntegral) [0 .. numBul - 1] + f pos = eff item (cr & crPos %~ (+.+ pos)) + numBul = _wpNumBarrels item {- | Create a number of bullets side by side with a given velocity, given width and given 'HitEffect'. -} numVelWthHitEff diff --git a/src/Dodge/Item/Weapon/UseEffect.hs b/src/Dodge/Item/Weapon/UseEffect.hs index ad3b6149f..7526c1607 100644 --- a/src/Dodge/Item/Weapon/UseEffect.hs +++ b/src/Dodge/Item/Weapon/UseEffect.hs @@ -9,7 +9,7 @@ import Dodge.Base.Zone import Dodge.Base.Collide import Dodge.Picture.Layer --import Dodge.Item.Weapon.Decoration -import Dodge.Item.Weapon.TriggerType +--import Dodge.Item.Weapon.TriggerType --import Dodge.WorldEvent.Flash --import Dodge.WorldEvent.ThingsHit import Picture @@ -114,7 +114,7 @@ aTractorBeam -> World aTractorBeam col cr w = set (creatures . ix cid . crInv . ix itRef . itUse) - (\_ -> shoot $ aTractorBeam ((col + 1) `mod` 10)) + (\_ -> aTractorBeam ((col + 1) `mod` 10)) $ over projectiles (IM.insert i (tractorBeamAt col i pos dir)) w where i = newProjectileKey w diff --git a/src/Geometry.hs b/src/Geometry.hs index fe89928f7..6209e4f0b 100644 --- a/src/Geometry.hs +++ b/src/Geometry.hs @@ -258,6 +258,7 @@ ssaTri ab bc a -- the point which lies between pa and pc' on a line from pb of length bc. -- Note that there are likely two such points, this should return the point -- closer to pc'. +-- TODO this still causes errors, should be made error free ssaTriPoint :: Point2 -> Point2 -> Point2 -> Float -> Point2 ssaTriPoint pa pb pc' bc = let ab = magV (pa -.- pb)