Clone of PhatAC @ https://github.com/floaterxk/PhatAC

Animate.cpp 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. #include "StdAfx.h"
  2. #include "PhysicsObj.h"
  3. #include "World.h"
  4. #include "AnimationPackage.h"
  5. AnimationPackage::AnimationPackage(WORD wStance, WORD wIndex, float fSpeed)
  6. {
  7. m_wStance = wStance;
  8. m_wIndex = wIndex;
  9. m_fSpeed = fSpeed;
  10. m_dwTarget = 0;
  11. m_dwAction = 0;
  12. }
  13. bool AnimationPackage::Initialize()
  14. {
  15. #if _TODO // Should be looking up the animation/s from the set.
  16. #else
  17. m_fStartTime = g_pGlobals->Time();
  18. m_dwCurrentFrame = 0x80000000; //Magic number for "null frame"
  19. m_dwStartFrame = 0;
  20. m_dwEndFrame = -1;
  21. if (!m_fSpeed)
  22. m_fSpeed = 30.0f;
  23. #endif
  24. return true;
  25. }
  26. SequencedAnimation::SequencedAnimation(WORD wSequence, WORD wStance, WORD wIndex, float fSpeed)
  27. : AnimationPackage(wStance, wIndex, fSpeed)
  28. {
  29. m_wSequence = wSequence;
  30. }
  31. void CPhysicsObj::Animation_Init()
  32. {
  33. m_dwAnimationSet = 0;
  34. m_bAnimUpdate = FALSE;
  35. m_wStance = 0x3D;
  36. m_wForwardAnim = 0;
  37. m_wStrafAnim = 0;
  38. m_wTurnAnim = 0;
  39. m_fForwardSpeed = 0.0f;
  40. m_fStrafSpeed = 0.0f;
  41. m_fTurnSpeed = 0.0f;
  42. m_fSpeedMod = 1.0f;
  43. m_wAnimSequence = 0;
  44. m_bForced = FALSE;
  45. }
  46. void CPhysicsObj::Animation_Shutdown()
  47. {
  48. }
  49. void CPhysicsObj::Animation_PlayEmote(WORD wIndex, float fSpeed)
  50. {
  51. animation_t anim;
  52. anim.bType = 0;
  53. anim.wIndex = wIndex;
  54. anim.wSequence = 0x8000 | (++m_wAnimSequence);
  55. anim.fSpeed = fSpeed;
  56. anim.dwAction = ANIM_EMOTE;
  57. anim.dwTarget = 0;
  58. //TODO: Calculate animation length.
  59. anim.fStartTime = g_pGlobals->Time();
  60. anim.fEndTime = g_pGlobals->Time() + 1.0;//flTime;
  61. m_lAnimQueue.push_back(anim);
  62. m_wAnimCount += 2;
  63. m_bAnimUpdate = TRUE;
  64. m_bForced = FALSE;
  65. //Animation_Update();
  66. }
  67. void CPhysicsObj::Animation_ClipMotions(int iMaxCount)
  68. {
  69. int iIndex = 0;
  70. for (animation_list::iterator it = m_lAnimQueue.begin(); it != m_lAnimQueue.end();)
  71. {
  72. if (iIndex >= iMaxCount)
  73. {
  74. it = m_lAnimQueue.erase(it);
  75. }
  76. else
  77. {
  78. it++;
  79. iIndex++;
  80. }
  81. }
  82. }
  83. BOOL CPhysicsObj::Animation_IsActive()
  84. {
  85. return (m_lAnimQueue.size()) ? TRUE : FALSE;
  86. }
  87. void CPhysicsObj::Animation_PlayPrimary(WORD wAnim, float fSpeed, float fDelay)
  88. {
  89. m_wAnimCount++;
  90. //This is only for primary, forced animations
  91. m_wForwardAnim = wAnim;
  92. m_fForwardSpeed = fSpeed;
  93. m_bForced = TRUE;
  94. m_bAnimUpdate = TRUE;
  95. Animation_Update();
  96. }
  97. void CPhysicsObj::Animation_Jump(float fPower, float fDir1, float fDir2, float fHeight)
  98. {
  99. /*
  100. CL: F61B:
  101. 56 89 E8 3D - power
  102. 00 00 00 00 00 00 00 00 52 A0 27 40 - dir1, dir2, height?
  103. 28 02 63 03 - landcell
  104. 96 5E 56 42 D3 34 44 C2 F0 D6 A3 3B - x, y, z
  105. 9F 57 1E BF 00 00 00 00 00 00 00 00 EE 27 49 BF - angles x y z w
  106. 27 00 2F 00 00 00 00 00
  107. SV: F74E
  108. AF 78 0C 50 - player guid
  109. 00 00 00 00 00 00 00 00 52 A0 27 40 - ..? ..? height?
  110. 00 00 00 00 00 00 00 00 00 00 00 00 - blah blah blah
  111. 27 00 15 00
  112. */
  113. if (HasOwner())
  114. return;
  115. BinaryWriter JumpMove;
  116. JumpMove.WriteDWORD(0xF74E);
  117. JumpMove.WriteDWORD(m_dwGUID);
  118. JumpMove.WriteFloat(fDir1);
  119. JumpMove.WriteFloat(fDir2);
  120. JumpMove.WriteFloat(fHeight);
  121. JumpMove.WriteDWORD(0);
  122. JumpMove.WriteDWORD(0);
  123. JumpMove.WriteDWORD(0);
  124. JumpMove.WriteWORD(m_wInstance);
  125. JumpMove.WriteWORD(++m_wNumJumps);
  126. g_pWorld->BroadcastPVS(GetLandcell(), JumpMove.GetData(), JumpMove.GetSize(), OBJECT_MSG);
  127. }
  128. void CPhysicsObj::Animation_SetCombatStance(WORD wStance)
  129. {
  130. if (m_wStance != wStance)
  131. {
  132. m_wAnimCount++;
  133. m_wStance = wStance;
  134. m_bForced = TRUE;
  135. m_wForwardAnim = 0;
  136. m_wStrafAnim = 0;
  137. m_wTurnAnim = 0;
  138. m_fForwardSpeed = 0.0f;
  139. m_fStrafSpeed = 0.0f;
  140. m_fTurnSpeed = 0.0f;
  141. Animation_Update();
  142. }
  143. }
  144. void CPhysicsObj::Animation_SetCombatMode(WORD wMode)
  145. {
  146. // 0x003D = peace
  147. // 0x0049 = spellcasting
  148. // 0x00E9 = weird weapon stance, like crossbow held down [unaimed].
  149. if (wMode == 0x01)
  150. Animation_SetCombatStance(0x003D);
  151. else if (wMode == 0x02)
  152. Animation_SetCombatStance(0x003C);
  153. else if (wMode == 0x04)
  154. Animation_SetCombatStance(0x003F);
  155. else if (wMode == 0x08)
  156. Animation_SetCombatStance(0x0049);
  157. }
  158. void CPhysicsObj::Animation_Attack(DWORD dwTarget, WORD wAnim, float fSpeed, DWORD dwWeaponID)
  159. {
  160. animation_t anim;
  161. anim.bType = 0;
  162. anim.wIndex = wAnim;
  163. anim.fSpeed = fSpeed;
  164. anim.dwTarget = dwTarget;
  165. anim.dwAction = ANIM_ATTACK;
  166. anim.dwActionData[0] = dwWeaponID; //Used for damage calculations after animation.
  167. //TODO: Calculate animation length.
  168. anim.fStartTime = g_pGlobals->Time();
  169. anim.fEndTime = g_pGlobals->Time() + (fSpeed ? (2.0 / fSpeed) : 0);
  170. Animation_PlayAnimation(&anim);
  171. }
  172. void CPhysicsObj::Animation_PlaySimpleAnimation(WORD wIndex, float fSpeed, float fDelay, DWORD dwAction, DWORD dwActionEx)
  173. {
  174. if (!fSpeed)
  175. fSpeed = 1.0f;
  176. animation_t anim;
  177. anim.bType = 0;
  178. anim.wIndex = wIndex;
  179. anim.fSpeed = fSpeed;
  180. anim.dwTarget = 0;
  181. anim.dwAction = dwAction;
  182. anim.dwActionData[0] = dwActionEx;
  183. //TODO: Calculate animation length.
  184. anim.fStartTime = g_pGlobals->Time();
  185. anim.fEndTime = g_pGlobals->Time() + (fDelay / fSpeed);
  186. Animation_PlayAnimation(&anim);
  187. }
  188. void CPhysicsObj::Animation_PlayAnimation(animation_t* data)
  189. {
  190. animation_t anim;
  191. anim.bType = data->bType;
  192. anim.wIndex = data->wIndex;
  193. anim.wSequence = ++m_wAnimSequence;
  194. anim.fSpeed = data->fSpeed;
  195. if (anim.dwAction = data->dwAction)
  196. memcpy(anim.dwActionData, data->dwActionData, sizeof(DWORD) * 10);
  197. anim.dwTarget = data->dwTarget;
  198. //TODO: Calculation animation length.
  199. if (!data->fStartTime || !data->fEndTime) {
  200. anim.fStartTime = g_pGlobals->Time();
  201. anim.fEndTime = g_pGlobals->Time() + 1.0f;//flTime;
  202. }
  203. else {
  204. anim.fStartTime = data->fStartTime;
  205. anim.fEndTime = data->fEndTime;
  206. }
  207. m_lAnimQueue.push_back(anim);
  208. m_wAnimCount += 2;
  209. m_bAnimUpdate = TRUE;
  210. m_bForced = TRUE;
  211. Animation_Update();
  212. }
  213. BinaryWriter* CPhysicsObj::Animation_GetAnimationInfo()
  214. {
  215. BYTE bType;
  216. DWORD dwTarget;
  217. BinaryWriter* AnimInfo = new BinaryWriter;
  218. if (m_lAnimQueue.empty())
  219. {
  220. bType = 0;
  221. dwTarget = 0;
  222. }
  223. else
  224. {
  225. animation_t anim = m_lAnimQueue.front();
  226. bType = anim.bType;
  227. dwTarget = anim.dwTarget;
  228. }
  229. AnimInfo->WriteBYTE(bType);
  230. AnimInfo->WriteBYTE(dwTarget ? TRUE : FALSE);
  231. AnimInfo->WriteWORD(m_wStance);
  232. switch (bType)
  233. {
  234. case 255:
  235. case 0:
  236. BinaryWriter *Desc = new BinaryWriter;
  237. DWORD dwFlags = 0;
  238. if (m_wStance != 0x3D)
  239. {
  240. dwFlags |= 1;
  241. Desc->WriteWORD(m_wStance);
  242. }
  243. #define CONDITIONAL_WORD(cond, flags, value) if (cond) { dwFlags |= flags; Desc->WriteWORD(value); }
  244. #define CONDITIONAL_FLOAT(cond, flags, value) if (cond) { dwFlags |= flags; Desc->WriteFloat(value); }
  245. CONDITIONAL_WORD(m_wForwardAnim, 0x00000002, m_wForwardAnim);
  246. CONDITIONAL_WORD(m_wStrafAnim, 0x00000008, m_wStrafAnim);
  247. CONDITIONAL_WORD(m_wTurnAnim, 0x00000020, m_wTurnAnim);
  248. CONDITIONAL_FLOAT(m_wForwardAnim && (m_fForwardSpeed != 1.0f), 0x00000004, m_fForwardSpeed);
  249. CONDITIONAL_FLOAT(m_wStrafAnim && (m_fStrafSpeed != 1.0f), 0x00000010, m_fStrafSpeed);
  250. CONDITIONAL_FLOAT(m_wTurnAnim && (m_fTurnSpeed != 1.0f), 0x00000040, m_fTurnSpeed);
  251. if (!m_lAnimQueue.empty())
  252. {
  253. DWORD dwQueueCount = 0;
  254. for (animation_list::iterator it = m_lAnimQueue.begin(); it != m_lAnimQueue.end(); it++)
  255. {
  256. if (it->bType == 0)
  257. {
  258. Desc->WriteWORD(it->wIndex);
  259. Desc->WriteWORD(it->wSequence);
  260. Desc->WriteFloat(it->fSpeed);
  261. dwQueueCount++;
  262. if (dwQueueCount == MAX_MOTION_QUEUE)
  263. break;
  264. }
  265. else
  266. break;
  267. }
  268. dwFlags |= dwQueueCount << 7;
  269. }
  270. //** 0x026DF000 = turbine got high **
  271. AnimInfo->WriteDWORD(0x026DF000 | dwFlags);
  272. AnimInfo->AppendData(Desc->GetData(), Desc->GetSize());
  273. AnimInfo->Align();
  274. delete Desc;
  275. break;
  276. }
  277. if (dwTarget)
  278. AnimInfo->WriteDWORD(dwTarget);
  279. return AnimInfo;
  280. }
  281. void CPhysicsObj::Animation_Complete(animation_t *data)
  282. {
  283. Animation_Update();
  284. }
  285. void CPhysicsObj::Animation_Think()
  286. {
  287. if (!m_lAnimQueue.empty())
  288. {
  289. for (animation_list::iterator it = m_lAnimQueue.begin(); it != m_lAnimQueue.end();)
  290. {
  291. if (it->fEndTime <= g_pGlobals->Time())
  292. {
  293. Animation_Complete(&(*it));
  294. it = m_lAnimQueue.erase(it);
  295. }
  296. else
  297. it++;
  298. }
  299. }
  300. if (m_bAnimUpdate)
  301. Animation_Update();
  302. }
  303. void CPhysicsObj::Animation_Update()
  304. {
  305. m_bAnimUpdate = FALSE;
  306. if (HasOwner())
  307. return;
  308. BinaryWriter AnimUpdate;
  309. AnimUpdate.WriteDWORD(0xF74C);
  310. AnimUpdate.WriteDWORD(m_dwGUID);
  311. AnimUpdate.WriteWORD(m_wInstance);
  312. AnimUpdate.WriteWORD(++m_wNumAnimInteracts);
  313. AnimUpdate.WriteWORD(m_wAnimCount);
  314. AnimUpdate.WriteBYTE((m_bForced) ? FALSE : TRUE);
  315. AnimUpdate.Align();
  316. m_bForced = FALSE;
  317. BinaryWriter *AnimInfo = Animation_GetAnimationInfo();
  318. AnimUpdate.AppendData(AnimInfo->GetData(), AnimInfo->GetSize());
  319. delete AnimInfo;
  320. g_pWorld->BroadcastPVS(GetLandcell(), AnimUpdate.GetData(), AnimUpdate.GetSize(), OBJECT_MSG);
  321. }
  322. int CPhysicsObj::Animation_EmoteQueueCount()
  323. {
  324. int iCount = 0;
  325. for (animation_list::iterator i = m_lAnimQueue.begin(); i != m_lAnimQueue.end(); i++)
  326. {
  327. if (i->dwAction == ANIM_EMOTE)
  328. iCount++;
  329. }
  330. return iCount;
  331. }