123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065 |
- #include "StdAfx.h"
- #include "Client.h"
- #include "ClientCommands.h"
- #include "ClientEvents.h"
- #include "World.h"
- // Database access
- #include "Database.h"
- #include "CharacterDatabase.h"
- // Network helpers
- #include "BinaryWriter.h"
- #include "ChatMsgs.h"
- #include "ObjectMsgs.h"
- // Objects
- #include "PhysicsObj.h"
- #include "Item.h"
- #include "Monster.h"
- #include "Player.h"
- #include "Door.h"
- #include "ChatMsgs.h"
- CClientEvents::CClientEvents(CClient *parent)
- {
- m_pClient = parent;
- m_pPlayer = NULL;
- m_fLogout = 0;
- }
- CClientEvents::~CClientEvents()
- {
- if (m_pPlayer)
- {
- g_pWorld->RemoveEntity(m_pPlayer);
- }
- }
- void CClientEvents::DetachPlayer()
- {
- m_pPlayer = NULL;
- }
- DWORD CClientEvents::GetPlayerID()
- {
- if (!m_pPlayer)
- return NULL;
- return m_pPlayer->m_dwGUID;
- }
- CBasePlayer* CClientEvents::GetPlayer()
- {
- return m_pPlayer;
- }
- void CClientEvents::ExitWorld()
- {
- if (m_pPlayer)
- {
- g_pWorld->RemoveEntity(m_pPlayer);
- DetachPlayer();
- }
- m_pClient->ExitWorld();
- m_fLogout = 0;
- }
- void CClientEvents::Think()
- {
- if (m_fLogout && ((m_fLogout + 5.00f) < g_pGlobals->Time()))
- {
- ExitWorld();
- }
- }
- void CClientEvents::BeginLogout()
- {
- if (m_pPlayer && !m_fLogout)
- {
- m_pPlayer->Animation_ClipMotions(0);
- m_pPlayer->Animation_PlayPrimary(286, 1.0f, 5.0f);
- m_fLogout = g_pGlobals->Time();
- }
- }
- void CClientEvents::LoginError(int iError)
- {
- DWORD ErrorPackage[2];
- ErrorPackage[0] = 0xF659;
- ErrorPackage[1] = iError;
- m_pClient->SendNetMessage(ErrorPackage, sizeof(ErrorPackage), PRIVATE_MSG);
- }
- void CClientEvents::LoginCharacter(DWORD dwGUID, const char *szAccount)
- {
- _CHARDESC desc;
- if (m_pPlayer || g_pWorld->FindPlayer(dwGUID))
- {
- // LOG(Temp, Normal, "Character already logged in!\n");
- LoginError(13);
- LOG(Client, Warning, "Login request, but character already logged in!\n");
- return;
- }
- if (!g_pDB->CharDB()->GetCharacterDesc(dwGUID, &desc))
- return;
- if (stricmp(szAccount, desc.szAccount))
- {
- LoginError(15);
- LOG(Client, Warning, "Bad account for login: \"%s\" \"%s\"\n", szAccount, desc.szAccount);
- return;
- }
- m_pPlayer = new CBasePlayer(m_pClient, dwGUID);
- g_pWorld->CreateEntity(m_pPlayer);
- m_pPlayer->LoginCharacter();
- return;
- }
- void CClientEvents::SendText(const char *szText, long lColor)
- {
- m_pClient->SendNetMessage(ServerText(szText, lColor), PRIVATE_MSG, FALSE, TRUE);
- }
- void CClientEvents::UpdateBurdenUI()
- {
- }
- void CClientEvents::Attack(DWORD dwTarget, DWORD dwHeight, float flPower)
- {
- m_pPlayer->Attack(dwTarget, dwHeight, flPower);
- }
- void CClientEvents::SendTellByGUID(const char* szText, DWORD dwGUID)
- {
- if (strlen(szText) > 300)
- return;
- //should really check for invalid characters and such ;]
- while (szText[0] == ' ') //Skip leading spaces.
- szText++;
- if (szText[0] == '\0') //Make sure the text isn't blank
- return;
- if (dwGUID == m_pPlayer->m_dwGUID)
- {
- m_pPlayer->SendNetMessage(ServerText("You really need some new friends..", 1), PRIVATE_MSG, FALSE);
- return;
- }
- CBasePlayer *pTarget;
- if (!(pTarget = g_pWorld->FindPlayer(dwGUID)))
- return;
- char szResponse[300];
- _snprintf(szResponse, 300, "You tell %s, \"%s\"", pTarget->GetName(), szText);
- m_pPlayer->SendNetMessage(ServerText(szResponse, 4), PRIVATE_MSG, FALSE);
- pTarget->SendNetMessage(DirectChat(szText, m_pPlayer->GetName(), m_pPlayer->m_dwGUID, dwGUID, 3), PRIVATE_MSG, TRUE);
- }
- void CClientEvents::SendTellByName(const char* szText, const char* szName)
- {
- if (strlen(szName) > 300)
- return;
- if (strlen(szText) > 300)
- return;
- //should really check for invalid characters and such ;]
- while (szText[0] == ' ') //Skip leading spaces.
- szText++;
- if (szText[0] == '\0') //Make sure the text isn't blank
- return;
- CBasePlayer *pTarget;
- if (!(pTarget = g_pWorld->FindPlayer(szName)))
- return;
- if (pTarget->m_dwGUID == m_pPlayer->m_dwGUID)
- {
- m_pPlayer->SendNetMessage(ServerText("You really need some new friends..", 1), PRIVATE_MSG, FALSE);
- return;
- }
- char szResponse[300];
- _snprintf(szResponse, 300, "You tell %s, \"%s\"", pTarget->GetName(), szText);
- m_pPlayer->SendNetMessage(ServerText(szResponse, 4), PRIVATE_MSG, FALSE, TRUE);
- pTarget->SendNetMessage(DirectChat(szText, m_pPlayer->GetName(), m_pPlayer->m_dwGUID, pTarget->m_dwGUID, 3), PRIVATE_MSG, TRUE);
- }
- void CClientEvents::ClientText(char* szText)
- {
- if (strlen(szText) > 1000)
- return;
- //should really check for invalid characters and such ;]
- while (szText[0] == ' ') //Skip leading spaces.
- szText++;
- if (szText[0] == '\0') //Make sure the text isn't blank
- return;
- if (szText[0] == '!' || szText[0] == '@' || szText[0] == '/')
- {
- CommandBase::Execute(++szText, m_pPlayer, m_pClient->GetAccessLevel());
- }
- else
- m_pPlayer->SpeakLocal(szText);
- }
- void CClientEvents::EmoteText(char* szText)
- {
- if (strlen(szText) > 300)
- return;
- //TODO: Check for invalid characters and such ;)
- while (szText[0] == ' ') //Skip leading spaces.
- szText++;
- if (szText[0] == '\0') //Make sure the text isn't blank
- return;
- m_pPlayer->EmoteLocal(szText);
- }
- void CClientEvents::ActionText(char* szText)
- {
- if (strlen(szText) > 300)
- return;
- //TODO: Check for invalid characters and such ;)
- while (szText[0] == ' ') //Skip leading spaces.
- szText++;
- if (szText[0] == '\0') //Make sure the text isn't blank
- return;
- m_pPlayer->ActionLocal(szText);
- }
- void CClientEvents::ChannelText(DWORD dwChannel, const char* szText)
- {
- if (strlen(szText) > 300)
- return;
- //TODO: Check for invalid characters and such ;)
- while (szText[0] == ' ')
- szText++;
- if (szText[0] == '\0')
- return;
- // 0x00000400 = Urgent Assistance "help channel"
- // 0x00000800 = Fellowship
- switch (dwChannel)
- {
- case 0x400:
- case 0x800:
- //For now we'll just spam them to everyone!
- // g_pWorld->BroadcastGlobal(ChannelChat(dwChannel, m_pPlayer->GetName(), szText), PRIVATE_MSG, m_pPlayer->m_dwGUID, TRUE);
- g_pWorld->BroadcastGlobal(ServerText(csprintf("%s says to your fellow testers, \"%s\"", m_pPlayer->GetName(), szText), 3), PRIVATE_MSG, m_pPlayer->m_dwGUID, TRUE);
- }
- //Give a special copy to this player?
- switch (dwChannel)
- {
- case 0x400:
- case 0x800:
- m_pClient->SendNetMessage(ServerText(csprintf("You say to your fellow testers, \"%s\"", szText), 3), PRIVATE_MSG, TRUE);
- break;
- default:
- SendText("The server does not support this channel.", 1);
- break;
- }
- if (dwChannel == 0x800)
- {
- LOG(Client, Normal, "[%s] %s says, \"%s\"\n", timestamp(), m_pPlayer->GetName(), szText);
- }
- }
- void CClientEvents::RequestHealthUpdate(DWORD dwGUID)
- {
- CPhysicsObj *pEntity = g_pWorld->FindWithinPVS(m_pPlayer, dwGUID);
- if (pEntity) {
- if (pEntity->IsMonster())
- {
- m_pClient->SendNetMessage(HealthUpdate((CBaseMonster *)pEntity), PRIVATE_MSG, TRUE, TRUE);
- }
- }
- }
- void CClientEvents::EquipItem(DWORD dwItemID, DWORD dwCoverage)
- {
- // Scenarios to consider:
- // 1. Item being equipped from the GROUND!
- // 2. Item being equipped from different equip slot.
- // 3. Item being equipped from the player's inventory.
- CPhysicsObj * pEntity;
- CBaseItem * pItem;
- //Does the player have an inventory?
- if (!(m_pPlayer->Container_HasContents()))
- return;
- //Find the item.
- if (!(pEntity = g_pWorld->FindWithinPVS(m_pPlayer, dwItemID)))
- return;
- if (!(pEntity->IsItem()))
- return;
- pItem = (CBaseItem *)pEntity;
- //Can this item be equipped?
- if (!(pItem->CanEquip()))
- return;
- if (!(m_pPlayer->Container_CanEquip(pItem, dwCoverage)))
- return;
- //Equip it
- DWORD dwCell = m_pPlayer->GetLandcell();
- //Take it out of whatever slot it may be in.
- if (pItem->HasOwner())
- m_pPlayer->Container_ReleaseItem(pItem, FALSE);
- if (!(pItem->m_ItemType & (TYPE_ARMOR | TYPE_CLOTHING)))
- {
- pItem->SetWorldWielder(dwCell, m_pPlayer);
- }
- pItem->SetWorldContainer(dwCell, NULL);
- pItem->SetWorldCoverage(dwCell, dwCoverage);
- //The container will auto-correct this slot into a valid range.
- m_pPlayer->Container_EquipItem(dwCell, pItem, dwCoverage);
- m_pPlayer->EmitSound(0x77, 1.0f);
- m_pClient->SendNetMessage(InventoryEquip(dwItemID, dwCoverage), PRIVATE_MSG, TRUE);
- UpdateBurdenUI();
- if (pItem->m_ItemType & (TYPE_ARMOR|TYPE_CLOTHING))
- {
- m_pPlayer->UpdateModel();
- }
- }
- void CClientEvents::StoreItem(DWORD dwItemID, DWORD dwContainer, char cSlot)
- {
- if (cSlot < 0)
- return;
- // Scenarios to consider:
- // 1. Item being stored is equipped.
- // 2. Item being stored is on the GROUND!
- // 3. Item being stored is already in the inventory.
- CPhysicsObj * pEntity;
- CPhysicsObj * pContainer;
- CBaseItem * pItem;
- //Find the container.
- if (!(m_pPlayer->Container_HasContents()))
- return;
- if (!(pContainer = m_pPlayer->Container_FindContainer(dwContainer)))
- return;
- //Find the item.
- if (!(pEntity = g_pWorld->FindWithinPVS(m_pPlayer, dwItemID)))
- return;
- if (!(pEntity->IsItem()))
- return;
- pItem = (CBaseItem *)pEntity;
- if (!(pItem->CanPickup()))
- return;
- if (!(pContainer->Container_CanStore(pItem)))
- return;
- if (pItem->GetSlotType()) //Only store/move ordinary items for now.
- return;
- DWORD dwCell = m_pPlayer->GetLandcell();
- //Take it out of whatever slot it's in.
- pItem->SetWorldContainer(dwCell, pContainer);
- if (pItem->IsWielded())
- pItem->SetWorldWielder(dwCell, NULL);
- m_pPlayer->Container_ReleaseItem(pItem, FALSE);
- //The container will auto-correct this slot into a valid range.
- cSlot = pContainer->Container_InsertInventoryItem(dwCell, pItem, cSlot);
- m_pPlayer->EmitSound(0x78, 1.0f);
- m_pClient->SendNetMessage(InventoryMove(dwItemID, dwContainer, cSlot, 0), PRIVATE_MSG, TRUE);
- UpdateBurdenUI();
- if (pItem->m_ItemType & (TYPE_ARMOR | TYPE_CLOTHING))
- m_pPlayer->UpdateModel();
- }
- void CClientEvents::DropItem(DWORD dwItemID)
- {
- // Scenarios to consider:
- // 1. Item being stored is equipped.
- // 3. Item being stored is in the inventory.
- CBaseItem * pItem;
- //Find the container.
- if (!(m_pPlayer->Container_HasContents()))
- return;
- //Find the item.
- if (!(pItem = m_pPlayer->Container_FindItem(dwItemID)))
- return;
- m_pPlayer->Animation_PlayPrimary(24, 1.0f, 2.0f);
- DWORD dwCell = m_pPlayer->GetLandcell();
- //Take it out of whatever slot it's in.
- m_pPlayer->Container_ReleaseItem(pItem, FALSE);
- pItem->SetWorldContainer(dwCell, NULL);
- //if ( pItem->IsWielded() )
- pItem->SetWorldWielder(dwCell, NULL);
- m_pPlayer->EmitSound(0x7B, 1.0f);
- m_pClient->SendNetMessage(InventoryDrop(dwItemID), PRIVATE_MSG, TRUE);
- g_pWorld->InsertEntity(pItem);
- pItem->Movement_Teleport(m_pPlayer->m_Origin, m_pPlayer->m_Angles);
- UpdateBurdenUI();
- if (pItem->m_ItemType & (TYPE_ARMOR | TYPE_CLOTHING))
- m_pPlayer->UpdateModel();
- }
- void CClientEvents::ChangeCombatStance(DWORD dwStance)
- {
- m_pPlayer->Animation_SetCombatMode((WORD)dwStance);
- ActionComplete();
- }
- void CClientEvents::ExitPortal()
- {
- m_pPlayer->ExitPortal();
- }
- void CClientEvents::Ping()
- {
- // Pong!
- DWORD Pong = 0x1EA;
- m_pClient->SendNetMessage(&Pong, sizeof(Pong), PRIVATE_MSG, TRUE);
- }
- void CClientEvents::UseItemEx(DWORD dwSourceID, DWORD dwDestID)
- {
- CPhysicsObj *pSource = m_pPlayer->FindChild(dwSourceID);
- CPhysicsObj *pDest = m_pPlayer->FindChild(dwDestID);
- if (!pSource)
- pSource = g_pWorld->FindWithinPVS(m_pPlayer, dwSourceID);
- if (!pDest)
- pDest = g_pWorld->FindWithinPVS(m_pPlayer, dwDestID);
- if (pSource && pDest)
- pDest->UseEx(m_pPlayer, pSource);
- else
- ActionComplete();
- }
- void CClientEvents::UseObject(DWORD dwEID)
- {
- CPhysicsObj *pTarget = m_pPlayer->FindChild(dwEID);
- if (!pTarget)
- pTarget = g_pWorld->FindWithinPVS(m_pPlayer, dwEID);
- if (pTarget)
- pTarget->Use(m_pPlayer);
- else
- ActionComplete();
- }
- void CClientEvents::ActionComplete()
- {
- DWORD ActionComplete[2];
- ActionComplete[0] = 0x1C7;
- ActionComplete[1] = 0;
- m_pClient->SendNetMessage(ActionComplete, sizeof(ActionComplete), PRIVATE_MSG, TRUE);
- }
- void CClientEvents::Identify(DWORD dwObjectID)
- {
- SendText("Identify will be incomplete -- it's not done!", 9);
- CPhysicsObj *pTarget = m_pPlayer->FindChild(dwObjectID);
- if (!pTarget)
- pTarget = g_pWorld->FindWithinPVS(m_pPlayer, dwObjectID);
- if (pTarget)
- {
- pTarget->Identify(m_pPlayer);
- m_pPlayer->SetLastAssessed(pTarget->m_dwGUID);
- }
- ActionComplete();
- }
- void CClientEvents::SpendAttributeXP(DWORD dwAttribute, DWORD dwXP)
- {
- if (dwAttribute < 1 || dwAttribute > 6)
- return;
- DWORD dwUnassignedXP = m_pPlayer->GetObjectStat(eUnassignedXP);
- if (dwUnassignedXP < dwXP)
- return;
- m_pPlayer->GiveAttributeXP((eAttribute)dwAttribute, dwXP);
- m_pPlayer->SetObjectStat(eUnassignedXP, dwUnassignedXP - dwXP);
- }
- void CClientEvents::SpendVitalXP(DWORD dwVital, DWORD dwXP)
- {
- if (dwVital != 1 && dwVital != 3 && dwVital != 5)
- return;
- DWORD dwUnassignedXP = m_pPlayer->GetObjectStat(eUnassignedXP);
- if (dwUnassignedXP < dwXP)
- return;
- m_pPlayer->GiveVitalXP((eVital)dwVital, dwXP);
- m_pPlayer->SetObjectStat(eUnassignedXP, dwUnassignedXP - dwXP);
- }
- void CClientEvents::SpendSkillXP(DWORD dwSkill, DWORD dwXP)
- {
- if (dwSkill < 1 || dwSkill > 0x27)
- return;
- DWORD dwUnassignedXP = m_pPlayer->GetObjectStat(eUnassignedXP);
- if (dwUnassignedXP < dwXP)
- return;
- m_pPlayer->GiveSkillXP((eSkill)dwSkill, dwXP);
- m_pPlayer->SetObjectStat(eUnassignedXP, dwUnassignedXP - dwXP);
- }
- void CClientEvents::LifestoneRecall()
- {
- //150 or 163?
- if (m_pPlayer->m_bLifestoneBound)
- {
- m_pPlayer->Animation_PlaySimpleAnimation(0x163, 1.0f, 18.0f, ANIM_LSRECALL);
- }
- else
- {
- m_pClient->SendNetMessage(ServerText("You are not bound to a Lifestone!", 7), PRIVATE_MSG);
- }
- }
- void CClientEvents::MarketplaceRecall()
- {
- //150 or 163?
- m_pPlayer->Animation_PlaySimpleAnimation(0x163, 1.0f, 18.0f, ANIM_MPRECALL);
- }
- // This is it!
- void CClientEvents::ProcessEvent(BinaryReader *in)
- {
- if (!m_pPlayer) return;
- DWORD dwSequence = in->ReadDWORD();
- DWORD dwEvent = in->ReadDWORD();
- if (in->GetLastError()) return;
- #ifdef _DEBUG
- LOG(Client, Verbose, "Processing event: 0x%X\n", dwEvent);
- #endif
- switch (dwEvent)
- {
- case 0x0008: //Attack
- {
- DWORD dwTarget = in->ReadDWORD();
- DWORD dwHeight = in->ReadDWORD();
- float flPower = in->ReadFloat();
- if (in->GetLastError()) break;
- Attack(dwTarget, dwHeight, flPower);
- break;
- }
- case 0x0015: //Client Text
- {
- char *szText = in->ReadString();
- if (in->GetLastError()) break;
- ClientText(szText);
- break;
- }
- case 0x0019: //Store Item
- {
- DWORD dwItemID = in->ReadDWORD();
- DWORD dwContainer = in->ReadDWORD();
- DWORD dwSlot = in->ReadDWORD();
- if (in->GetLastError()) break;
- StoreItem(dwItemID, dwContainer, (char)dwSlot);
- break;
- }
- case 0x001A: //Equip Item
- {
- DWORD dwItemID = in->ReadDWORD();
- DWORD dwCoverage = in->ReadDWORD();
- if (in->GetLastError()) break;
- EquipItem(dwItemID, dwCoverage);
- break;
- }
- case 0x001B: //Drop Item
- {
- DWORD dwItemID = in->ReadDWORD();
- if (in->GetLastError()) break;
- DropItem(dwItemID);
- break;
- }
- case 0x001F: // TOD 2017
- {
- DWORD dwUnk = in->ReadDWORD(); // value was "1"
- if (in->GetLastError()) break;
- break;
- }
- case 0x0032: //Send Tell by GUID
- {
- char* szText = in->ReadString();
- DWORD dwGUID = in->ReadDWORD();
- if (in->GetLastError()) break;
- SendTellByGUID(szText, dwGUID);
- break;
- }
- case 0x0035: //Use Item Ex
- {
- //SendText("Use extended not implemented yet.", 9);
- DWORD dwSourceID = in->ReadDWORD();
- DWORD dwDestID = in->ReadDWORD();
- if (in->GetLastError()) break;
- UseItemEx(dwSourceID, dwDestID);
- break;
- }
- case 0x0036: //Use Object
- {
- //SendText("Use not implemented yet.", 9);
- DWORD dwEID = in->ReadDWORD();
- if (in->GetLastError()) break;
- UseObject(dwEID);
- break;
- }
- case 0x0044: //Spend Vital XP
- {
- DWORD dwVital = in->ReadDWORD();
- DWORD dwXP = in->ReadDWORD();
- if (in->GetLastError()) break;
- SpendVitalXP(dwVital, dwXP);
- break;
- }
- case 0x0045: //Spend Attribute XP
- {
- DWORD dwAttribute = in->ReadDWORD();
- DWORD dwXP = in->ReadDWORD();
- if (in->GetLastError()) break;
- SpendAttributeXP(dwAttribute, dwXP);
- break;
- }
- case 0x0046: //Spend Skill XP
- {
- DWORD dwSkill = in->ReadDWORD();
- DWORD dwXP = in->ReadDWORD();
- if (in->GetLastError()) break;
- SpendSkillXP(dwSkill, dwXP);
- break;
- }
- case 0x0053: //Change Combat Mode
- {
- DWORD dwStance = in->ReadDWORD();
- if (in->GetLastError()) break;
- ChangeCombatStance(dwStance);
- break;
- }
- case 0x005D: //Send Tell by Name
- {
- char* szText = in->ReadString();
- char* szName = in->ReadString();
- if (in->GetLastError()) break;
- SendTellByName(szText, szName);
- break;
- }
- case 0x0063: //Lifestone Recall
- {
- LifestoneRecall();
- break;
- }
- case 0x00A1: // "Login Complete"
- {
- ExitPortal();
- break;
- }
- case 0x00C8: //Identify
- {
- DWORD dwObjectID = in->ReadDWORD();
- if (in->GetLastError()) break;
- Identify(dwObjectID);
- break;
- }
- case 0x00D6: // Advocate teleport (triggered by having an admin flag set, clicking the mini-map)
- {
- // Starts with string (was empty when I tested)
- in->ReadString();
- // Then position (target)
- loc_t loc = in->Read<loc_t>();
- heading_t angles = in->Read<heading_t>();
- m_pPlayer->Movement_Teleport(loc, angles);
- break;
- }
- case 0x0147: //Channel Text
- {
- DWORD dwChannel = in->ReadDWORD();
- char* szText = in->ReadString();
- if (in->GetLastError()) break;
- ChannelText(dwChannel, szText);
- }
- break;
- case 0x01BF: //Request health update
- {
- DWORD dwGUID = in->ReadDWORD();
- if (in->GetLastError()) break;
- RequestHealthUpdate(dwGUID);
- break;
- }
- case 0x01DF: //Indirect Text (@me)
- {
- char *szText = in->ReadString();
- if (in->GetLastError()) break;
- EmoteText(szText);
- break;
- }
- case 0x01E1: //Emote Text (*laugh* sends 'laughs')
- {
- char *szText = in->ReadString();
- if (in->GetLastError()) break;
- ActionText(szText);
- break;
- }
- case 0x01E9: //Ping
- {
- Ping();
- break;
- }
- case 0x028D: //Marketplace Recall
- {
- MarketplaceRecall();
- break;
- }
- case 0xF61B: //Jump Movement
- {
- float flPower = in->ReadFloat();
- float flDir1 = in->ReadFloat();
- float flDir2 = in->ReadFloat();
- float flHeight = in->ReadFloat();
- loc_t *location = (loc_t *)in->ReadArray(sizeof(loc_t));
- heading_t *angles = (heading_t *)in->ReadArray(sizeof(heading_t));
- if (in->GetLastError()) break;
- memcpy(&m_pPlayer->m_Origin, location, sizeof(loc_t));
- memcpy(&m_pPlayer->m_Angles, angles, sizeof(heading_t));
- m_pPlayer->Animation_Jump(flPower, flDir1, flDir2, flHeight);
- m_pPlayer->m_bAnimUpdate = TRUE;
- break;
- }
- case 0xF61C: //Update Vector Movement
- {
- float fSpeedMod = m_pPlayer->m_fSpeedMod;
- float flForwardMod = 0;
- float flStrafMod = 0;
- float flTurnMod = 0;
- WORD wForwardAnim = 0;
- WORD wStrafAnim = 0;
- WORD wTurnAnim = 0;
- WORD wStance = 0x3D;
- BOOL bRun = FALSE;
- DWORD dwFlags = in->ReadDWORD();
- if (dwFlags & 1)
- {
- DWORD dwRunUnk = in->ReadDWORD();
- #ifdef _DEBUG
- if (dwRunUnk != 2)
- {
- LOG(Temp, Normal, "RunUnk is %08X??\n", dwRunUnk);
- }
- else
- #endif
- bRun = TRUE;
- }
- if (!bRun)
- fSpeedMod = 1.0f;
- if (dwFlags & 2)
- {
- wStance = in->ReadWORD();
- in->ReadWORD(); //0x8000?? sequence maybe
- }
- if (dwFlags & 4)
- {
- DWORD dwForwardAnim = in->ReadDWORD();
- flForwardMod = fSpeedMod;
- switch (dwForwardAnim)
- {
- case 0x45000006: //backwards
- dwForwardAnim--;
- flForwardMod *= -backwards_factor;
- break;
- case 0x45000005: //forwards
- if (bRun)
- dwForwardAnim += 2;
- break;
- default:
- //0x45 = run/walk forward/back
- //0x44 = run/walk change
- //0x43 = emotes?
- //0x41 = change position? (kneel, sleep..)
- //0x40 = attack animations?
- //0x13 = drink something
- if ((dwForwardAnim >> 24) != 0x45)
- LOG(Temp, Normal, "Forward: %08X\n", dwForwardAnim);
- flForwardMod = 1.0000f;
- break;
- }
- wForwardAnim = (WORD)dwForwardAnim;
- }
- if (dwFlags & 8) {
- DWORD dwAutorunUnk = in->ReadDWORD();
- if (dwAutorunUnk != 2)
- {
- SendText("You cannot use right-click movement at this time!", 1);
- LOG(Temp, Normal, "Autorun is %08X?\n", dwAutorunUnk);
- }
- else
- {
- if (!bRun)
- wForwardAnim = 0x0005;
- else
- wForwardAnim = 0x0007;
- flForwardMod = fSpeedMod;
- }
- }
- if (dwFlags & 0x20) {
- DWORD dwStrafAnim = in->ReadDWORD();
- flStrafMod = fSpeedMod;
- switch (dwStrafAnim)
- {
- case 0x65000010: //left?
- dwStrafAnim--;
- flStrafMod *= -1.0f;
- case 0x6500000F: //right?
- flStrafMod *= (walk_anim_speed / sidestep_anim_speed) * sidestep_factor;
- if (flStrafMod > max_sidestep_anim_rate)
- flStrafMod = max_sidestep_anim_rate;
- else if (flStrafMod < -max_sidestep_anim_rate)
- flStrafMod = -max_sidestep_anim_rate;
- break;
- default:
- if ((dwStrafAnim >> 24) != 0x65)
- {
- // DebugMe();
- LOG(Animation, Warning, "Strafe anim == 0x%02X", dwStrafAnim >> 24);
- }
- flStrafMod = 1.0000f;
- break;
- }
- wStrafAnim = (WORD)dwStrafAnim;
- }
- if (dwFlags & 0x100) {
- DWORD dwTurnAnim = in->ReadDWORD();
- flTurnMod = 1.0f;
- switch (dwTurnAnim)
- {
- case 0x6500000E: //turn left
- dwTurnAnim--;
- flTurnMod *= -1.0f;
- case 0x6500000D: //turn right
- if (bRun)
- flTurnMod *= run_turn_factor;
- break;
- default:
- if ((dwTurnAnim >> 24) != 0x65)
- {
- LOG(Animation, Warning, "Turn anim == 0x%02X\n", dwTurnAnim >> 24);
- }
- break;
- }
- wTurnAnim = (WORD)dwTurnAnim;
- }
- DWORD dwEmotes = (dwFlags >> 11) & 7;
- animation_list lEmotes;
- for (unsigned int i = 0; i < dwEmotes; i++)
- {
- animation_t emote;
- emote.wIndex = in->ReadWORD(); //animation
- emote.wSequence = in->ReadWORD(); //counter
- emote.fSpeed = in->ReadFloat(); //play speed
- lEmotes.push_back(emote);
- }
- loc_t *location = (loc_t *)in->ReadArray(sizeof(loc_t));
- heading_t *angles = (heading_t *)in->ReadArray(sizeof(heading_t));
- if (in->GetLastError())
- {
- LOG(Animation, Verbose, "Bad animation message:\n");
- LOG_BYTES(Animation, Verbose, in->GetDataStart(), in->GetDataLen());
- break;
- }
- memcpy(&m_pPlayer->m_Origin, location, sizeof(loc_t));
- memcpy(&m_pPlayer->m_Angles, angles, sizeof(heading_t));
- m_pPlayer->m_fForwardSpeed = flForwardMod;
- m_pPlayer->m_fStrafSpeed = flStrafMod;
- m_pPlayer->m_fTurnSpeed = flTurnMod;
- m_pPlayer->m_wForwardAnim = wForwardAnim;
- m_pPlayer->m_wStrafAnim = wStrafAnim;
- m_pPlayer->m_wTurnAnim = wTurnAnim;
- m_pPlayer->m_wStance = wStance;
- DWORD dwAnimQueued = m_pPlayer->Animation_EmoteQueueCount();
- DWORD dwAnimNeeded = lEmotes.size();
- DWORD dwLastSequence = 0;
- for (unsigned int i = 0; i < dwAnimNeeded; i++)
- {
- if (dwAnimQueued >= MAX_EMOTE_QUEUE)
- break;
- dwAnimQueued++;
- for (animation_list::iterator it = lEmotes.begin(); it != lEmotes.end(); it++)
- {
- //find 0x800x
- if ((it->wSequence & 0xFF) == i)
- {
- m_pPlayer->Animation_PlayEmote(it->wIndex, it->fSpeed);
- break;
- }
- }
- }
- m_pPlayer->m_bAnimUpdate = TRUE;
- m_pPlayer->Movement_UpdatePos();
- break;
- }
- case 0xF753: //Update Exact Position
- {
- loc_t* location = reinterpret_cast<loc_t*> (in->ReadArray(sizeof(loc_t)));
- heading_t* angles = reinterpret_cast<heading_t*>(in->ReadArray(sizeof(heading_t)));
- WORD instance = in->ReadWORD();
- if (in->GetLastError()) break;
- if (instance != m_pPlayer->m_wInstance)
- {
- LOG(Temp, Normal, "Bad instance!!!!!!!!!!!!\n");
- break;
- }
- memcpy(&m_pPlayer->m_Origin, location, sizeof(loc_t));
- memcpy(&m_pPlayer->m_Angles, angles, sizeof(heading_t));
- m_pPlayer->Movement_UpdatePos();
- break;
- }
- default:
- {
- //Unknown Event
- // LOG(Temp, Normal, "Unhandled client event 0x%X:\n", dwEvent );
- // LOG_BYTES(Temp, Verbose, in->GetDataPtr(), in->GetDataEnd() - in->GetDataPtr() );
- }
- }
- }
|