1 #ifndef GAME_MWMECHANICS_CHARACTER_HPP 2 #define GAME_MWMECHANICS_CHARACTER_HPP 3 4 #include <deque> 5 6 #include "../mwworld/ptr.hpp" 7 #include "../mwworld/containerstore.hpp" 8 9 #include "../mwrender/animation.hpp" 10 11 #include "weapontype.hpp" 12 13 namespace MWWorld 14 { 15 class InventoryStore; 16 } 17 18 namespace MWRender 19 { 20 class Animation; 21 } 22 23 namespace MWMechanics 24 { 25 26 struct Movement; 27 class CreatureStats; 28 29 enum Priority { 30 Priority_Default, 31 Priority_WeaponLowerBody, 32 Priority_SneakIdleLowerBody, 33 Priority_SwimIdle, 34 Priority_Jump, 35 Priority_Movement, 36 Priority_Hit, 37 Priority_Weapon, 38 Priority_Block, 39 Priority_Knockdown, 40 Priority_Torch, 41 Priority_Storm, 42 Priority_Death, 43 Priority_Persistent, 44 45 Num_Priorities 46 }; 47 48 enum CharacterState { 49 CharState_None, 50 51 CharState_SpecialIdle, 52 CharState_Idle, 53 CharState_Idle2, 54 CharState_Idle3, 55 CharState_Idle4, 56 CharState_Idle5, 57 CharState_Idle6, 58 CharState_Idle7, 59 CharState_Idle8, 60 CharState_Idle9, 61 CharState_IdleSwim, 62 CharState_IdleSneak, 63 64 CharState_WalkForward, 65 CharState_WalkBack, 66 CharState_WalkLeft, 67 CharState_WalkRight, 68 69 CharState_SwimWalkForward, 70 CharState_SwimWalkBack, 71 CharState_SwimWalkLeft, 72 CharState_SwimWalkRight, 73 74 CharState_RunForward, 75 CharState_RunBack, 76 CharState_RunLeft, 77 CharState_RunRight, 78 79 CharState_SwimRunForward, 80 CharState_SwimRunBack, 81 CharState_SwimRunLeft, 82 CharState_SwimRunRight, 83 84 CharState_SneakForward, 85 CharState_SneakBack, 86 CharState_SneakLeft, 87 CharState_SneakRight, 88 89 CharState_TurnLeft, 90 CharState_TurnRight, 91 CharState_SwimTurnLeft, 92 CharState_SwimTurnRight, 93 94 CharState_Jump, 95 96 CharState_Death1, 97 CharState_Death2, 98 CharState_Death3, 99 CharState_Death4, 100 CharState_Death5, 101 CharState_SwimDeath, 102 CharState_SwimDeathKnockDown, 103 CharState_SwimDeathKnockOut, 104 CharState_DeathKnockDown, 105 CharState_DeathKnockOut, 106 107 CharState_Hit, 108 CharState_SwimHit, 109 CharState_KnockDown, 110 CharState_KnockOut, 111 CharState_SwimKnockDown, 112 CharState_SwimKnockOut, 113 CharState_Block 114 }; 115 116 enum UpperBodyCharacterState { 117 UpperCharState_Nothing, 118 UpperCharState_EquipingWeap, 119 UpperCharState_UnEquipingWeap, 120 UpperCharState_WeapEquiped, 121 UpperCharState_StartToMinAttack, 122 UpperCharState_MinAttackToMaxAttack, 123 UpperCharState_MaxAttackToMinHit, 124 UpperCharState_MinHitToHit, 125 UpperCharState_FollowStartToFollowStop, 126 UpperCharState_CastingSpell 127 }; 128 129 enum JumpingState { 130 JumpState_None, 131 JumpState_InAir, 132 JumpState_Landing 133 }; 134 135 struct WeaponInfo; 136 137 class CharacterController : public MWRender::Animation::TextKeyListener 138 { 139 MWWorld::Ptr mPtr; 140 MWWorld::Ptr mWeapon; 141 MWRender::Animation *mAnimation; 142 143 struct AnimationQueueEntry 144 { 145 std::string mGroup; 146 size_t mLoopCount; 147 bool mPersist; 148 }; 149 typedef std::deque<AnimationQueueEntry> AnimationQueue; 150 AnimationQueue mAnimQueue; 151 152 CharacterState mIdleState; 153 std::string mCurrentIdle; 154 155 CharacterState mMovementState; 156 std::string mCurrentMovement; 157 float mMovementAnimSpeed; 158 bool mAdjustMovementAnimSpeed; 159 bool mHasMovedInXY; 160 bool mMovementAnimationControlled; 161 162 CharacterState mDeathState; 163 std::string mCurrentDeath; 164 bool mFloatToSurface; 165 166 CharacterState mHitState; 167 std::string mCurrentHit; 168 169 UpperBodyCharacterState mUpperBodyState; 170 171 JumpingState mJumpState; 172 std::string mCurrentJump; 173 174 int mWeaponType; 175 std::string mCurrentWeapon; 176 177 float mAttackStrength; 178 179 bool mSkipAnim; 180 181 // counted for skill increase 182 float mSecondsOfSwimming; 183 float mSecondsOfRunning; 184 185 MWWorld::ConstPtr mHeadTrackTarget; 186 187 float mTurnAnimationThreshold; // how long to continue playing turning animation after actor stopped turning 188 189 std::string mAttackType; // slash, chop or thrust 190 191 bool mAttackingOrSpell; 192 bool mCastingManualSpell; 193 194 float mTimeUntilWake; 195 196 bool mIsMovingBackward; 197 osg::Vec2f mSmoothedSpeed; 198 199 void setAttackTypeBasedOnMovement(); 200 201 void refreshCurrentAnims(CharacterState idle, CharacterState movement, JumpingState jump, bool force=false); 202 void refreshHitRecoilAnims(CharacterState& idle); 203 void refreshJumpAnims(const std::string& weapShortGroup, JumpingState jump, CharacterState& idle, bool force=false); 204 void refreshMovementAnims(const std::string& weapShortGroup, CharacterState movement, CharacterState& idle, bool force=false); 205 void refreshIdleAnims(const std::string& weapShortGroup, CharacterState idle, bool force=false); 206 207 void clearAnimQueue(bool clearPersistAnims = false); 208 209 bool updateWeaponState(CharacterState& idle); 210 bool updateCreatureState(); 211 void updateIdleStormState(bool inwater); 212 213 std::string chooseRandomAttackAnimation() const; 214 bool isRandomAttackAnimation(const std::string& group) const; 215 216 bool isPersistentAnimPlaying(); 217 218 void updateAnimQueue(); 219 220 void updateHeadTracking(float duration); 221 222 void updateMagicEffects(); 223 224 void playDeath(float startpoint, CharacterState death); 225 CharacterState chooseRandomDeathState() const; 226 void playRandomDeath(float startpoint = 0.0f); 227 228 /// choose a random animation group with \a prefix and numeric suffix 229 /// @param num if non-nullptr, the chosen animation number will be written here 230 std::string chooseRandomGroup (const std::string& prefix, int* num = nullptr) const; 231 232 bool updateCarriedLeftVisible(int weaptype) const; 233 234 std::string fallbackShortWeaponGroup(const std::string& baseGroupName, MWRender::Animation::BlendMask* blendMask = nullptr); 235 236 std::string getWeaponAnimation(int weaponType) const; 237 238 public: 239 CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim); 240 virtual ~CharacterController(); 241 242 void handleTextKey(const std::string &groupname, SceneUtil::TextKeyMap::ConstIterator key, const SceneUtil::TextKeyMap& map) override; 243 244 // Be careful when to call this, see comment in Actors 245 void updateContinuousVfx(); 246 247 void updatePtr(const MWWorld::Ptr &ptr); 248 249 void update(float duration); 250 251 bool onOpen(); 252 void onClose(); 253 254 void persistAnimationState(); 255 void unpersistAnimationState(); 256 257 bool playGroup(const std::string &groupname, int mode, int count, bool persist=false); 258 void skipAnim(); 259 bool isAnimPlaying(const std::string &groupName); 260 261 enum KillResult 262 { 263 Result_DeathAnimStarted, 264 Result_DeathAnimPlaying, 265 Result_DeathAnimJustFinished, 266 Result_DeathAnimFinished 267 }; 268 KillResult kill(); 269 270 void resurrect(); isDead() const271 bool isDead() const 272 { return mDeathState != CharState_None; } 273 274 void forceStateUpdate(); 275 276 bool isAttackPreparing() const; 277 bool isCastingSpell() const; 278 bool isReadyToBlock() const; 279 bool isKnockedDown() const; 280 bool isKnockedOut() const; 281 bool isRecovery() const; 282 bool isSneaking() const; 283 bool isRunning() const; 284 bool isTurning() const; 285 bool isAttackingOrSpell() const; 286 287 void setVisibility(float visibility); 288 void setAttackingOrSpell(bool attackingOrSpell); 289 void castSpell(const std::string spellId, bool manualSpell=false); 290 void setAIAttackType(const std::string& attackType); 291 static void setAttackTypeRandomly(std::string& attackType); 292 293 bool readyToPrepareAttack() const; 294 bool readyToStartAttack() const; 295 296 float getAttackStrength() const; 297 298 /// @see Animation::setActive 299 void setActive(int active); 300 301 /// Make this character turn its head towards \a target. To turn off head tracking, pass an empty Ptr. 302 void setHeadTrackTarget(const MWWorld::ConstPtr& target); 303 304 void playSwishSound(float attackStrength); 305 }; 306 } 307 308 #endif /* GAME_MWMECHANICS_CHARACTER_HPP */ 309