#include "StdAfx.h" #include "PhysicsObj.h" #include "World.h" #include "AnimationPackage.h" AnimationPackage::AnimationPackage(WORD wStance, WORD wIndex, float fSpeed) { m_wStance = wStance; m_wIndex = wIndex; m_fSpeed = fSpeed; m_dwTarget = 0; m_dwAction = 0; } bool AnimationPackage::Initialize() { #if _TODO // Should be looking up the animation/s from the set. #else m_fStartTime = g_pGlobals->Time(); m_dwCurrentFrame = 0x80000000; //Magic number for "null frame" m_dwStartFrame = 0; m_dwEndFrame = -1; if (!m_fSpeed) m_fSpeed = 30.0f; #endif return true; } SequencedAnimation::SequencedAnimation(WORD wSequence, WORD wStance, WORD wIndex, float fSpeed) : AnimationPackage(wStance, wIndex, fSpeed) { m_wSequence = wSequence; } void CPhysicsObj::Animation_Init() { m_dwAnimationSet = 0; m_bAnimUpdate = FALSE; m_wStance = 0x3D; m_wForwardAnim = 0; m_wStrafAnim = 0; m_wTurnAnim = 0; m_fForwardSpeed = 0.0f; m_fStrafSpeed = 0.0f; m_fTurnSpeed = 0.0f; m_fSpeedMod = 1.0f; m_wAnimSequence = 0; m_bForced = FALSE; } void CPhysicsObj::Animation_Shutdown() { } void CPhysicsObj::Animation_PlayEmote(WORD wIndex, float fSpeed) { animation_t anim; anim.bType = 0; anim.wIndex = wIndex; anim.wSequence = 0x8000 | (++m_wAnimSequence); anim.fSpeed = fSpeed; anim.dwAction = ANIM_EMOTE; anim.dwTarget = 0; //TODO: Calculate animation length. anim.fStartTime = g_pGlobals->Time(); anim.fEndTime = g_pGlobals->Time() + 1.0;//flTime; m_lAnimQueue.push_back(anim); m_wAnimCount += 2; m_bAnimUpdate = TRUE; m_bForced = FALSE; //Animation_Update(); } void CPhysicsObj::Animation_ClipMotions(int iMaxCount) { int iIndex = 0; for (animation_list::iterator it = m_lAnimQueue.begin(); it != m_lAnimQueue.end();) { if (iIndex >= iMaxCount) { it = m_lAnimQueue.erase(it); } else { it++; iIndex++; } } } BOOL CPhysicsObj::Animation_IsActive() { return (m_lAnimQueue.size()) ? TRUE : FALSE; } void CPhysicsObj::Animation_PlayPrimary(WORD wAnim, float fSpeed, float fDelay) { m_wAnimCount++; //This is only for primary, forced animations m_wForwardAnim = wAnim; m_fForwardSpeed = fSpeed; m_bForced = TRUE; m_bAnimUpdate = TRUE; Animation_Update(); } void CPhysicsObj::Animation_Jump(float fPower, float fDir1, float fDir2, float fHeight) { /* CL: F61B: 56 89 E8 3D - power 00 00 00 00 00 00 00 00 52 A0 27 40 - dir1, dir2, height? 28 02 63 03 - landcell 96 5E 56 42 D3 34 44 C2 F0 D6 A3 3B - x, y, z 9F 57 1E BF 00 00 00 00 00 00 00 00 EE 27 49 BF - angles x y z w 27 00 2F 00 00 00 00 00 SV: F74E AF 78 0C 50 - player guid 00 00 00 00 00 00 00 00 52 A0 27 40 - ..? ..? height? 00 00 00 00 00 00 00 00 00 00 00 00 - blah blah blah 27 00 15 00 */ if (HasOwner()) return; BinaryWriter JumpMove; JumpMove.WriteDWORD(0xF74E); JumpMove.WriteDWORD(m_dwGUID); JumpMove.WriteFloat(fDir1); JumpMove.WriteFloat(fDir2); JumpMove.WriteFloat(fHeight); JumpMove.WriteDWORD(0); JumpMove.WriteDWORD(0); JumpMove.WriteDWORD(0); JumpMove.WriteWORD(m_wInstance); JumpMove.WriteWORD(++m_wNumJumps); g_pWorld->BroadcastPVS(GetLandcell(), JumpMove.GetData(), JumpMove.GetSize(), OBJECT_MSG); } void CPhysicsObj::Animation_SetCombatStance(WORD wStance) { if (m_wStance != wStance) { m_wAnimCount++; m_wStance = wStance; m_bForced = TRUE; m_wForwardAnim = 0; m_wStrafAnim = 0; m_wTurnAnim = 0; m_fForwardSpeed = 0.0f; m_fStrafSpeed = 0.0f; m_fTurnSpeed = 0.0f; Animation_Update(); } } void CPhysicsObj::Animation_SetCombatMode(WORD wMode) { // 0x003D = peace // 0x0049 = spellcasting // 0x00E9 = weird weapon stance, like crossbow held down [unaimed]. if (wMode == 0x01) Animation_SetCombatStance(0x003D); else if (wMode == 0x02) Animation_SetCombatStance(0x003C); else if (wMode == 0x04) Animation_SetCombatStance(0x003F); else if (wMode == 0x08) Animation_SetCombatStance(0x0049); } void CPhysicsObj::Animation_Attack(DWORD dwTarget, WORD wAnim, float fSpeed, DWORD dwWeaponID) { animation_t anim; anim.bType = 0; anim.wIndex = wAnim; anim.fSpeed = fSpeed; anim.dwTarget = dwTarget; anim.dwAction = ANIM_ATTACK; anim.dwActionData[0] = dwWeaponID; //Used for damage calculations after animation. //TODO: Calculate animation length. anim.fStartTime = g_pGlobals->Time(); anim.fEndTime = g_pGlobals->Time() + (fSpeed ? (2.0 / fSpeed) : 0); Animation_PlayAnimation(&anim); } void CPhysicsObj::Animation_PlaySimpleAnimation(WORD wIndex, float fSpeed, float fDelay, DWORD dwAction, DWORD dwActionEx) { if (!fSpeed) fSpeed = 1.0f; animation_t anim; anim.bType = 0; anim.wIndex = wIndex; anim.fSpeed = fSpeed; anim.dwTarget = 0; anim.dwAction = dwAction; anim.dwActionData[0] = dwActionEx; //TODO: Calculate animation length. anim.fStartTime = g_pGlobals->Time(); anim.fEndTime = g_pGlobals->Time() + (fDelay / fSpeed); Animation_PlayAnimation(&anim); } void CPhysicsObj::Animation_PlayAnimation(animation_t* data) { animation_t anim; anim.bType = data->bType; anim.wIndex = data->wIndex; anim.wSequence = ++m_wAnimSequence; anim.fSpeed = data->fSpeed; if (anim.dwAction = data->dwAction) memcpy(anim.dwActionData, data->dwActionData, sizeof(DWORD) * 10); anim.dwTarget = data->dwTarget; //TODO: Calculation animation length. if (!data->fStartTime || !data->fEndTime) { anim.fStartTime = g_pGlobals->Time(); anim.fEndTime = g_pGlobals->Time() + 1.0f;//flTime; } else { anim.fStartTime = data->fStartTime; anim.fEndTime = data->fEndTime; } m_lAnimQueue.push_back(anim); m_wAnimCount += 2; m_bAnimUpdate = TRUE; m_bForced = TRUE; Animation_Update(); } BinaryWriter* CPhysicsObj::Animation_GetAnimationInfo() { BYTE bType; DWORD dwTarget; BinaryWriter* AnimInfo = new BinaryWriter; if (m_lAnimQueue.empty()) { bType = 0; dwTarget = 0; } else { animation_t anim = m_lAnimQueue.front(); bType = anim.bType; dwTarget = anim.dwTarget; } AnimInfo->WriteBYTE(bType); AnimInfo->WriteBYTE(dwTarget ? TRUE : FALSE); AnimInfo->WriteWORD(m_wStance); switch (bType) { case 255: case 0: BinaryWriter *Desc = new BinaryWriter; DWORD dwFlags = 0; if (m_wStance != 0x3D) { dwFlags |= 1; Desc->WriteWORD(m_wStance); } #define CONDITIONAL_WORD(cond, flags, value) if (cond) { dwFlags |= flags; Desc->WriteWORD(value); } #define CONDITIONAL_FLOAT(cond, flags, value) if (cond) { dwFlags |= flags; Desc->WriteFloat(value); } CONDITIONAL_WORD(m_wForwardAnim, 0x00000002, m_wForwardAnim); CONDITIONAL_WORD(m_wStrafAnim, 0x00000008, m_wStrafAnim); CONDITIONAL_WORD(m_wTurnAnim, 0x00000020, m_wTurnAnim); CONDITIONAL_FLOAT(m_wForwardAnim && (m_fForwardSpeed != 1.0f), 0x00000004, m_fForwardSpeed); CONDITIONAL_FLOAT(m_wStrafAnim && (m_fStrafSpeed != 1.0f), 0x00000010, m_fStrafSpeed); CONDITIONAL_FLOAT(m_wTurnAnim && (m_fTurnSpeed != 1.0f), 0x00000040, m_fTurnSpeed); if (!m_lAnimQueue.empty()) { DWORD dwQueueCount = 0; for (animation_list::iterator it = m_lAnimQueue.begin(); it != m_lAnimQueue.end(); it++) { if (it->bType == 0) { Desc->WriteWORD(it->wIndex); Desc->WriteWORD(it->wSequence); Desc->WriteFloat(it->fSpeed); dwQueueCount++; if (dwQueueCount == MAX_MOTION_QUEUE) break; } else break; } dwFlags |= dwQueueCount << 7; } //** 0x026DF000 = turbine got high ** AnimInfo->WriteDWORD(0x026DF000 | dwFlags); AnimInfo->AppendData(Desc->GetData(), Desc->GetSize()); AnimInfo->Align(); delete Desc; break; } if (dwTarget) AnimInfo->WriteDWORD(dwTarget); return AnimInfo; } void CPhysicsObj::Animation_Complete(animation_t *data) { Animation_Update(); } void CPhysicsObj::Animation_Think() { if (!m_lAnimQueue.empty()) { for (animation_list::iterator it = m_lAnimQueue.begin(); it != m_lAnimQueue.end();) { if (it->fEndTime <= g_pGlobals->Time()) { Animation_Complete(&(*it)); it = m_lAnimQueue.erase(it); } else it++; } } if (m_bAnimUpdate) Animation_Update(); } void CPhysicsObj::Animation_Update() { m_bAnimUpdate = FALSE; if (HasOwner()) return; BinaryWriter AnimUpdate; AnimUpdate.WriteDWORD(0xF74C); AnimUpdate.WriteDWORD(m_dwGUID); AnimUpdate.WriteWORD(m_wInstance); AnimUpdate.WriteWORD(++m_wNumAnimInteracts); AnimUpdate.WriteWORD(m_wAnimCount); AnimUpdate.WriteBYTE((m_bForced) ? FALSE : TRUE); AnimUpdate.Align(); m_bForced = FALSE; BinaryWriter *AnimInfo = Animation_GetAnimationInfo(); AnimUpdate.AppendData(AnimInfo->GetData(), AnimInfo->GetSize()); delete AnimInfo; g_pWorld->BroadcastPVS(GetLandcell(), AnimUpdate.GetData(), AnimUpdate.GetSize(), OBJECT_MSG); } int CPhysicsObj::Animation_EmoteQueueCount() { int iCount = 0; for (animation_list::iterator i = m_lAnimQueue.begin(); i != m_lAnimQueue.end(); i++) { if (i->dwAction == ANIM_EMOTE) iCount++; } return iCount; }