Tweak wall cutting, removes inverse walls

This commit is contained in:
2021-04-23 21:17:37 +02:00
parent 4c611ba4aa
commit 108b66f3ad
7 changed files with 289 additions and 121 deletions
+194 -98
View File
@@ -1,3 +1,6 @@
{-
Weapon effects when pulling the trigger.
-}
module Dodge.Item.Weapon.TriggerType
where
import Dodge.Data
@@ -6,20 +9,20 @@ import Dodge.CreatureAction (reloadWeapon)
import Dodge.WorldEvent (muzzleFlashAt,tempLightForAt)
import Dodge.WorldEvent.Cloud
import Dodge.RandomHelp
import Dodge.Item.Weapon.Bullet
import Geometry
import System.Random
import Control.Lens
import Control.Monad.State
import Data.Maybe
import qualified Data.IntMap.Strict as IM
withThinSmoke :: (Int -> World -> World) -> Int -> World -> World
withThinSmoke
:: (Int -> World -> World) -- ^ Underlying effect
-> Int -- ^ Creature id
-> World
-> World
withThinSmoke eff cid w = eff cid . foldr makeThinSmokeAt w $ map (+.+ pos) ps
where
cr = _creatures w IM.! cid
@@ -27,7 +30,11 @@ withThinSmoke eff cid w = eff cid . foldr makeThinSmokeAt w $ map (+.+ pos) ps
pos = _crPos cr +.+ ((_crRad cr +0.5) *.* unitVectorAtAngle dir)
ps = (sequence . replicate 5 . randInCirc) 8 & evalState $ _randGen w
withThickSmoke :: (Int -> World -> World) -> Int -> World -> World
withThickSmoke
:: (Int -> World -> World) -- ^ Underlying effect
-> Int -- ^ Creature id
-> World
-> World
withThickSmoke eff cid w = eff cid . foldr makeThickSmokeAt w $ map (+.+ pos) ps
where
cr = _creatures w IM.! cid
@@ -35,27 +42,35 @@ withThickSmoke eff cid w = eff cid . foldr makeThickSmokeAt w $ map (+.+ pos) ps
pos = _crPos cr +.+ ((_crRad cr +15) *.* unitVectorAtAngle dir)
ps = (sequence . replicate 20 . randInCirc) 8 & evalState $ _randGen w
withWarmUp :: Int -> (Int -> World -> World) -> Int -> World -> World
{- Shoot a weapon rapidly after a warm up.
Applies ammo check as well.
-}
withWarmUp
:: Int -- ^ Warm up time (in frames)
-> (Int -> World -> World)
-- ^ Shoot effect
-> Int -- ^ Creature id
-> World
-> World
withWarmUp t f cid w
| reloadCondition = fromMaybe w $ reloadWeapon cid w
| _wpReloadState item /= 0 = w
| fState == 0 = set (pointerToItem . wpFire) (withWarmUp 100 f)
$ set (pointerToItem . wpFireState) 2
w
| t > 2 = set (pointerToItem . wpFire) (withWarmUp (t-1) f)
$ set (pointerToItem . wpFireState) 2
$ soundFrom (CrWeaponSound cid) 26 2 0
w
| t > 0 = set (pointerToItem . wpFire) (withWarmUp (t-1) f)
$ set (pointerToItem . wpFireState) 2
w
| otherwise = set (pointerToItem . wpFire) (withWarmUp 1 f)
$ over (pointerToItem . wpLoadedAmmo) (\ammo -> ammo-1)
$ set (pointerToItem . wpFireState) 2
$ f cid
$ soundFrom (CrWeaponSound cid) 28 2 0
w
| reloadCondition = fromMaybe w $ reloadWeapon cid w
| _wpReloadState item /= 0 = w
| fState == 0 = set (pointerToItem . wpFire) (withWarmUp 100 f)
$ set (pointerToItem . wpFireState) 2
w
| t > 2 = set (pointerToItem . wpFire) (withWarmUp (t-1) f)
$ set (pointerToItem . wpFireState) 2
$ soundFrom (CrWeaponSound cid) 26 2 0
w
| t > 0 = set (pointerToItem . wpFire) (withWarmUp (t-1) f)
$ set (pointerToItem . wpFireState) 2
w
| otherwise = set (pointerToItem . wpFire) (withWarmUp 1 f)
$ over (pointerToItem . wpLoadedAmmo) (\ammo -> ammo-1)
$ set (pointerToItem . wpFireState) 2
$ f cid
$ soundFrom (CrWeaponSound cid) 28 2 0
w
where
cr = _creatures w IM.! cid
itRef = _crInvSel cr
@@ -65,7 +80,13 @@ withWarmUp t f cid w
fRate = _wpFireRate item
reloadCondition = _wpLoadedAmmo item == 0
withSound :: Int -> (Int -> World -> World) -> Int -> World -> World
{- Adds a sound to a creature based world effect.
The sound is emitted from the creature's position. -}
withSound
:: Int -- ^ Sound id
-> (Int -> World -> World) -- ^ Underlying effect
-> Int -- ^ Creature id
-> World -> World
withSound soundid f cid w = (soundOncePos soundid p . f cid) w
where
p = _crPos (_creatures w IM.! cid)
@@ -79,6 +100,7 @@ withRecoil
withRecoil recoilAmount eff cid w = eff cid . over (creatures . ix cid) pushback $ w
where
pushback cr = over crPos (+.+ rotateV (_crDir cr) ((-recoilAmount) / _crMass cr ,0)) cr
withSidePush
:: Float -- ^ Maximal possible side push amount
-> (Int -> World -> World)
@@ -91,7 +113,7 @@ withSidePush maxSide eff cid w = eff cid . over (creatures . ix cid) push $ w
(pushAmount, _) = randomR (-maxSide,maxSide) $ _randGen w
{-
Applies an effect and sound with an ammo check.
Applies a world effect and sound effect after an ammo check.
-}
shootWithSound
:: Int -- ^ Sound identifier
@@ -115,21 +137,26 @@ shootWithSound soundid f cid w
&& _wpFireState item == 0
&& _wpLoadedAmmo item > 0
reloadCondition = _wpLoadedAmmo item == 0
shoot :: (Int -> World -> World) -> Int -> World -> World
{- Applies a world effect after an ammo check. -}
shoot
:: (Int -> World -> World)
-- ^ Underlying effect, takes creature id as input
-> Int -- ^ Creature id
-> World -> World
shoot f cid w | fireCondition = over (pointerToItem . wpLoadedAmmo) (\ammo -> ammo-1)
$ set (pointerToItem . wpFireState) (_wpFireRate item)
$ f cid w
| reloadCondition = fromMaybe w $ reloadWeapon cid w
| otherwise = w
where cr = (_creatures w IM.! cid)
itRef = _crInvSel cr
item = _crInv cr IM.! itRef
pointerToItem = creatures . ix cid . crInv . ix itRef
fireCondition = _wpReloadState item == 0
&& _wpFireState item == 0
&& _wpLoadedAmmo item > 0
reloadCondition = _wpLoadedAmmo item == 0
where
cr = (_creatures w IM.! cid)
itRef = _crInvSel cr
item = _crInv cr IM.! itRef
pointerToItem = creatures . ix cid . crInv . ix itRef
fireCondition = _wpReloadState item == 0
&& _wpFireState item == 0
&& _wpLoadedAmmo item > 0
reloadCondition = _wpLoadedAmmo item == 0
withMuzFlare :: (Int -> World -> World) -> Int -> World -> World
withMuzFlare f cid w = tempLightForAt 3 pos
@@ -139,87 +166,156 @@ withMuzFlare f cid w = tempLightForAt 3 pos
pos = _crPos cr +.+ _crRad cr *.* unitVectorAtAngle (_crDir cr)
pos2 = _crPos cr +.+ (2 * _crRad cr) *.* unitVectorAtAngle (_crDir cr)
withRandomDir :: Float -> (Int -> World -> World) -> Int -> World -> World
{-
Rotates the creature randomly, applies the effect, rotates the creature back.
-}
withRandomDir
:: Float -- ^ Max possible rotation
-> (Int -> World -> World)
-- ^ Underlying effect
-> Int -- ^ Creature id
-> World
-> World
withRandomDir acc f cid w = over (creatures . ix cid . crDir) (\d -> d - a)
. f cid
. over (creatures . ix cid . crDir) (+ a)
$ set randGen g
w
where (a, g) = randomR (-acc,acc) $ _randGen w
withVelWthHiteff :: Point2 -> Float -> HitEffect -> Int -> World -> World
{- Creates a bullet with a given velocity, width, and 'HitEffect'
-}
withVelWthHiteff
:: Point2 -- ^ Velocity, x direction is forward with respect to the creature
-> Float -- ^ Bullet width
-> HitEffect -- ^ Bullet effect when hitting creature, wall etc
-> Int -- ^ Creature id
-> World
-> World
withVelWthHiteff vel width hiteff cid w
= over particles' ((:) newbul)
= over particles' ((:) newbul) $ set randGen g w
where
cr = _creatures w IM.! cid
newbul = aGenBulAt' (Just cid) (numColor colid) pos (rotateV dir vel) hiteff width
(colid, g) = randomR (0,11) $ _randGen w
dir = _crDir cr
pos = _crPos cr +.+ _crRad cr *.* unitVectorAtAngle (_crDir cr)
pos2 = _crPos cr +.+ (2 * _crRad cr) *.* unitVectorAtAngle (_crDir cr)
{- Translate the creature sideways a random amount, apply the effect, translate back. -}
withRandomOffset
:: Float -- ^ Max possible translate
-> (Int -> World -> World)
-- ^ Underlying effect
-> Int -- ^ Creature id
-> World
-> World
withRandomOffset offsetAmount f cid w
= over (creatures . ix cid . crPos) (-.- offV)
. f cid
. over (creatures . ix cid . crPos) (+.+ offV)
$ set randGen g
w
where cr = _creatures w IM.! cid
newbul = aGenBulAt' (Just cid) (numColor colid) pos (rotateV dir vel) hiteff width
(colid, g) = randomR (0,11) $ _randGen w
dir = _crDir cr
pos = _crPos cr +.+ _crRad cr *.* unitVectorAtAngle (_crDir cr)
pos2 = _crPos cr +.+ (2 * _crRad cr) *.* unitVectorAtAngle (_crDir cr)
w
where
(offsetVal , g) = randomR (-offsetAmount,offsetAmount) $ _randGen w
cr = _creatures w IM.! cid
offV = rotateV (_crDir cr) (0,offsetVal)
withRandomOffset :: Float -> (Int -> World -> World) -> Int -> World -> World
withRandomOffset offsetAmount f cid w = over (creatures . ix cid . crPos) (-.- offV)
. f cid
. over (creatures . ix cid . crPos) (+.+ offV)
$ set randGen g
w
where (offsetVal , g) = randomR (-offsetAmount,offsetAmount) $ _randGen w
cr = _creatures w IM.! cid
offV = rotateV (_crDir cr) (0,offsetVal)
torqueBeforeForced :: Float -> (Int -> World -> World) -> Int -> World -> World
-- | Rotates a creature with minimum rotation at least 0.1.
-- Rotates the player creature before applying the effect, other creatures after.
torqueBeforeForced
:: Float -- ^ Max possible rotation (less the 0.1 forced rotation)
-> (Int -> World -> World)
-- ^ Underlying effect
-> Int -- ^ Creature id
-> World
-> World
torqueBeforeForced torque feff cid w
| cid == 0 = feff cid $ set randGen g $ over (creatures . ix cid . crDir) (+rot')
$ over cameraRot (+rot') w
| otherwise = feff cid $ set randGen g $ over (creatures . ix cid . crDir) (+rot') w
where (rot, g) = randomR (-torque,torque) $ _randGen w
rot' | rot < 0 = rot - 0.1
| otherwise = rot + 0.1
where
(rot, g) = randomR (-torque,torque) $ _randGen w
rot' | rot < 0 = rot - 0.1
| otherwise = rot + 0.1
torqueBefore :: Float -> (Int -> World -> World) -> Int -> World -> World
-- | Rotates the player creature before applying an effect, other creatures after.
torqueBefore
:: Float -- ^ Max possible rotation
-> (Int -> World -> World)
-- ^ Underlying effect
-> Int
-- ^ Creature id
-> World
-> World
torqueBefore torque feff cid w
| cid == 0 = feff cid $ set randGen g $ over (creatures . ix cid . crDir) (+rot)
$ over cameraRot (+rot) w
| otherwise = feff cid $ set randGen g $ over (creatures . ix cid . crDir) (+rot) w
where (rot, g) = randomR (-torque,torque) $ _randGen w
torqueAfter :: Float -> (Int -> World -> World) -> Int -> World -> World
where
(rot, g) = randomR (-torque,torque) $ _randGen w
-- | Rotate a randomly creature after applying an effect.
torqueAfter
:: Float -- ^ Max possible rotation
-> (Int -> World -> World)
-- ^ Underlying effect
-> Int
-- ^ Creature id
-> World
-> World
torqueAfter torque feff cid w
| cid == 0 = rotateScope $ set randGen g $ over cameraRot (+rot) $ feff cid w
| otherwise = set randGen g $ over (creatures . ix cid . crDir) (+rot) $ feff cid w
where (rot, g) = randomR (-torque,torque) $ _randGen w
rotateScope w = w & creatures . ix 0 . crInv . ix (_crInvSel (_creatures w IM.! 0))
. itAttachment . _Just . scopePos %~ rotateV rot
spreadNumVelWthHiteff :: Float -> Int -> Point2 -> Float -> HitEffect -> Int -> World -> World
where
(rot, g) = randomR (-torque,torque) $ _randGen w
rotateScope w = w & creatures . ix 0 . crInv . ix (_crInvSel (_creatures w IM.! 0))
. itAttachment . _Just . scopePos %~ rotateV rot
{- Create multiple bullets with a given spread, a given amount, given velocity,
given width and given 'HitEffect'.
-}
spreadNumVelWthHiteff
:: Float -- ^ Spread
-> Int -- ^ Number of bullets
-> Point2 -- ^ Velocity, x is direction of creature
-> Float -- ^ Bullet width
-> HitEffect -- ^ Effect when hitting creature, wall etc
-> Int -- ^ Creature id
-> World
-> World
spreadNumVelWthHiteff spread num vel wth eff cid w
= over particles' (newbuls ++)
w
where cr = _creatures w IM.! cid
newbuls = zipWith3 (\pos d colid -> aGenBulAt' (Just cid) (numColor colid)
pos (rotateV d vel) eff wth
) poss dirs colids
poss = map ((+.+) $ _crPos cr +.+ _crRad cr *.* unitVectorAtAngle (_crDir cr))
$ evalState ((sequence . take num . repeat . randInCirc) 5) $ _randGen w
dirs = map ((+) (_crDir cr))
$ zipWith (+) [-spread,-spread+(2*spread/(fromIntegral num))..]
$ randomRs (0,spread/5) (_randGen w)
colids = take num $ randomRs (0,11) (_randGen w)
= over particles' (newbuls ++) w
where
cr = _creatures w IM.! cid
newbuls = zipWith3 (\pos d colid -> aGenBulAt' (Just cid) (numColor colid)
pos (rotateV d vel) eff wth
) poss dirs colids
poss = map ((+.+) $ _crPos cr +.+ _crRad cr *.* unitVectorAtAngle (_crDir cr))
$ evalState ((sequence . take num . repeat . randInCirc) 5) $ _randGen w
dirs = map ((+) (_crDir cr))
$ zipWith (+) [-spread,-spread+(2*spread/(fromIntegral num))..]
$ randomRs (0,spread/5) (_randGen w)
colids = take num $ randomRs (0,11) (_randGen w)
numVelWthHitEff :: Int -> Point2 -> Float -> HitEffect -> Int -> World -> World
{- Create a number of bullets side by side with a given velocity,
given width and given 'HitEffect'.
-}
numVelWthHitEff
:: Int -- ^ Amount of bullets
-> Point2 -- ^ Velocity, x axis is direction of creature
-> Float -- ^ Bullet width
-> HitEffect -- ^ Effect when hitting creature, wall etc
-> Int -- ^ Creature id
-> World
-> World
numVelWthHitEff num vel wth eff cid w
= over particles' (newbuls ++)
w
where cr = _creatures w IM.! cid
newbuls = zipWith (\pos colid -> aGenBulAt' (Just cid) (numColor colid)
pos (rotateV d vel) eff wth
)
poss colids
d = _crDir cr
poss = map (\o -> o +.+ pos) offsets
maxOffset = fromIntegral num * 2.5 - 2.5
offsets = map (\y -> rotateV d (0,y)) [-maxOffset,5-maxOffset..]
colids = take num $ randomRs (0,11) (_randGen w)
pos = _crPos cr +.+ _crRad cr *.* unitVectorAtAngle d
= over particles' (newbuls ++) w
where
cr = _creatures w IM.! cid
newbuls = zipWith (\pos colid -> aGenBulAt' (Just cid) (numColor colid)
pos (rotateV d vel) eff wth
)
poss colids
d = _crDir cr
poss = map (\o -> o +.+ pos) offsets
maxOffset = fromIntegral num * 2.5 - 2.5
offsets = map (\y -> rotateV d (0,y)) [-maxOffset,5-maxOffset..]
colids = take num $ randomRs (0,11) (_randGen w)
pos = _crPos cr +.+ _crRad cr *.* unitVectorAtAngle d