module Dodge.Creature.Impulse.Movement where import Dodge.Data import Dodge.Creature.Statistics import Geometry --import Data.Maybe --import qualified Data.IntMap.Strict as IM import Control.Lens {- | Creature attempts to moves under its own steam. The idea is that this may or may not work, depending on the status of the creature. For now, though, this cannot fail. -} crMvBy :: Point2 -- ^ Movement translation vector, will be made relative to creature direction -> Creature -> Creature crMvBy p cr = crMvAbsolute (rotateV (_crDir cr) p) cr crMvAbsolute :: Point2 -- ^ Movement translation vector -> Creature -> Creature crMvAbsolute p' cr = advanceStepCounter (magV p) cr & crPos %~ (+.+ p) & crMvDir .~ argV p where p = strengthFactor (getCrStrength cr) *.* p' strengthFactor :: Int -> Float strengthFactor i | i > 9 = 1 | i < 1 = 0 | otherwise = 0.1 * fromIntegral i crMvForward :: Float -- ^ Speed -> Creature -> Creature crMvForward speed = crMvBy (V2 speed 0) advanceStepCounter :: Float -- ^ Speed -> Creature -> Creature advanceStepCounter speed = crStance . carriage %~ f where f car = case car of Standing -> f (Walking 0 RightForward) Walking i ff -> Walking (i + ceiling speed) ff _ -> car creatureTurn :: Float -> Creature -> Creature creatureTurn a = crDir +~ a creatureTurnTo :: Point2 -> Creature -> Creature creatureTurnTo p cr | vToTarg == V2 0 0 = cr -- this should deal with the angleVV error | otherwise = cr & crDir .~ dirToTarget where vToTarg = p -.- _crPos cr dirToTarget = argV vToTarg -- the following is perhaps not ideal because it mixes normalizeAngle with -- angleVV, but it seems to work creatureTurnTowardDir :: Float -- ^ Angle -> Float -- ^ Turn speed -> Creature -> Creature creatureTurnTowardDir a turnSpeed cr | normalizeAngle (abs (a - cdir)) <= turnSpeed = cr & crDir .~ dirToTarget | isLeftOfA (normalizeAngle dirToTarget) (normalizeAngle $ _crDir cr) = cr & crDir +~ turnSpeed | otherwise = cr & crDir -~ turnSpeed where cdir = _crDir cr vToTarg = rotateV a (V2 1 0) dirToTarget = argV vToTarg creatureTurnToward :: Point2 -> Float -> Creature -> Creature creatureTurnToward p turnSpeed cr | vToTarg == V2 0 0 = cr -- this should deal with the angleVV error | errorAngleVV 3 vToTarg (unitVectorAtAngle (_crDir cr)) <= turnSpeed = cr & crDir .~ dirToTarget | isLeftOfA (normalizeAngle dirToTarget) (normalizeAngle $ _crDir cr) = cr & crDir +~ turnSpeed | otherwise = cr & crDir -~ turnSpeed where vToTarg = p -.- _crPos cr dirToTarget = argV vToTarg {- | Speed modifier of an item when not aiming. -} equipSpeed :: Item -> Float equipSpeed _ = 1