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

PhysicsObj.cpp 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. #include "StdAfx.h"
  2. #include "PhysicsObj.h"
  3. #include "ObjectMsgs.h"
  4. #include "World.h"
  5. #include "BinaryWriter.h"
  6. #include "ChatMsgs.h"
  7. #include "Item.h"
  8. #include "Player.h"
  9. #include "Client.h"
  10. #include "ClientCommands.h"
  11. CPhysicsObj::CPhysicsObj()
  12. {
  13. m_dwGUID = 0;
  14. m_strName = "Unknown";
  15. m_WeenieBitfield = BF_STUCK | BF_ATTACKABLE;
  16. m_wNumMovements = 0x0000;
  17. m_wNumAnimInteracts = 0x0001;
  18. m_wNumBubbleModes = 0x0001;
  19. m_wNumJumps = 0x0000;
  20. m_wNumPortals = 0x0000;
  21. m_wAnimCount = 0x0000;
  22. m_wNumOverride = 0x0000;
  23. m_wNumModelChanges = 0x0000;
  24. m_wInstance = 0x0001;
  25. m_wSeagreen10 = 0x0000;
  26. m_wNumCombat = 0x0000;
  27. m_dwModel = 0x0200026B; //0x02000006 = turbine box
  28. m_fScale = 1.0f;
  29. m_wTypeID = 0x0001;
  30. m_wIcon = 0x1036;
  31. m_ItemType = TYPE_GEM;
  32. m_AmmoType = (AMMO_TYPE) 0;
  33. m_bRemoveMe = FALSE;
  34. m_pBlock = NULL;
  35. m_pfnThink = NULL;
  36. m_dwEffectSet = 0; // 0x34000004;
  37. m_dwSoundSet = 0; //0x2000000A = lugians
  38. memset(m_dwStats, 0, sizeof(m_dwStats));
  39. memset(&m_Origin, 0, sizeof(loc_t));
  40. memset(&m_Angles, 0, sizeof(heading_t));
  41. m_PhysicsState = PhysicsState::EDGE_SLIDE_PS | PhysicsState::LIGHTING_ON_PS | PhysicsState::GRAVITY_PS | PhysicsState::REPORT_COLLISIONS_PS;
  42. m_fNextThink = g_pGlobals->Time();
  43. m_Usability = USEABLE_NO;
  44. m_UseDistance = USEDISTANCE_ANYWHERE;
  45. m_RadarVis = ShowAlways_RadarEnum;
  46. m_Value = 0;
  47. m_Burden = 0;
  48. m_AnimOverrideData = NULL;
  49. m_AnimOverrideDataLen = 0;
  50. m_AutonomousMovement = 0;
  51. Movement_Init();
  52. Animation_Init();
  53. Container_Init();
  54. m_bUseModelOverride = false;
  55. m_bDontClear = false;
  56. m_BlipColor = 0;
  57. m_TargetType = (ITEM_TYPE)0;
  58. m_Translucency = 0.0f;
  59. m_bLifestoneBound = false;
  60. m_UIEffects = 0;
  61. m_dwEquipSlot = eEquipTypeNone;
  62. m_dwEquipType = eEquipSlotNone;
  63. m_dwCoverage1 = 0; //What it CAN cover?
  64. m_dwCoverage2 = 0; //What it IS covering?
  65. m_dwCoverage3 = 0; //??
  66. }
  67. CPhysicsObj::~CPhysicsObj()
  68. {
  69. Container_Shutdown();
  70. Animation_Shutdown();
  71. Movement_Shutdown();
  72. }
  73. void CPhysicsObj::Spawn()
  74. {
  75. //initialize children
  76. }
  77. void CPhysicsObj::Attach(CLandBlock *pBlock)
  78. {
  79. m_pBlock = pBlock;
  80. }
  81. void CPhysicsObj::Detach()
  82. {
  83. m_pBlock = NULL;
  84. }
  85. BOOL CPhysicsObj::HasOwner()
  86. {
  87. if (IsContained())
  88. return TRUE;
  89. if (IsWielded())
  90. return TRUE;
  91. return FALSE;
  92. }
  93. CLandBlock* CPhysicsObj::GetBlock()
  94. {
  95. return m_pBlock;
  96. }
  97. void CPhysicsObj::MakeLive(void)
  98. {
  99. if (!m_pBlock)
  100. return;
  101. if (m_pfnThink) //already live
  102. return;
  103. m_pBlock->SetEntityLive(this);
  104. }
  105. BOOL CPhysicsObj::Think(void)
  106. {
  107. if (!m_pfnThink) //Entity isn't thinking.
  108. return FALSE;
  109. if (m_fNextThink > g_pGlobals->Time()) //We need to wait to think.
  110. return TRUE;
  111. if (!(this->*m_pfnThink)()) //Entity going dormant.
  112. return FALSE;
  113. return TRUE;
  114. }
  115. void CPhysicsObj::SetLocation(DWORD landcell, float x, float y, float z)
  116. {
  117. m_Origin.landcell = landcell;
  118. m_Origin.x = x;
  119. m_Origin.y = y;
  120. m_Origin.z = z;
  121. }
  122. void CPhysicsObj::SetAngles(float w, float x, float y, float z)
  123. {
  124. m_Angles.w = w;
  125. m_Angles.x = x;
  126. m_Angles.y = y;
  127. m_Angles.z = z;
  128. }
  129. const char* CPhysicsObj::GetDescription()
  130. {
  131. if (!m_strDescription.length())
  132. {
  133. ModelInfo miCurrentModel;
  134. std::string palettes;
  135. if (!IsPlayer() || (m_dwModel == 0x02000001 || m_dwModel == 0x0200004E))
  136. {
  137. miCurrentModel.bUnknown = m_miBaseModel.bUnknown; //0x11
  138. miCurrentModel.dwBasePalette = m_miBaseModel.dwBasePalette;
  139. miCurrentModel.MergeData(&m_miBaseModel, NULL);
  140. ItemVector vItems;
  141. Container_GetEquippedArmor(&vItems);
  142. ItemVector::iterator iit = vItems.begin();
  143. ItemVector::iterator iend = vItems.end();
  144. while (iit != iend)
  145. {
  146. CBaseItem* pItem = *iit; iit++;
  147. if (pItem->IsWearable())
  148. {
  149. miCurrentModel.MergeData(&pItem->m_miWornModel, NULL);
  150. }
  151. }
  152. palettes = csprintf("Replacement Palettes (%d):", miCurrentModel.lPalettes.size());
  153. for (auto& palette : miCurrentModel.lPalettes)
  154. {
  155. palettes += csprintf("\n0x%X (0x%X 0x%X)", palette.dwPaletteID, palette.bOffset, palette.bLength);
  156. }
  157. }
  158. return csprintf(
  159. "GUID: 0x%08X\n"
  160. "ClassID: 0x%X\n"
  161. "Type: 0x%X\n"
  162. "State: 0x%X\n"
  163. "Bitfield: 0x%X\n"
  164. "Model: 0x%X\n"
  165. "Base Palette: 0x%X\n"
  166. "%s\n",
  167. m_dwGUID, m_wTypeID, m_ItemType, m_PhysicsState, m_WeenieBitfield, m_dwModel,
  168. m_miBaseModel.dwBasePalette, palettes.c_str());
  169. }
  170. return m_strDescription.c_str();
  171. }
  172. void CPhysicsObj::SetDescription(const char* szDescription)
  173. {
  174. m_strDescription = szDescription;
  175. }
  176. void CPhysicsObj::Identify(CPhysicsObj *pSource)
  177. {
  178. if (pSource->IsPlayer())
  179. {
  180. ((CBasePlayer *)pSource)->SendNetMessage(IdentifyObject(this), PRIVATE_MSG, TRUE, TRUE);
  181. }
  182. }
  183. BinaryWriter* CPhysicsObj::CreateMessage()
  184. {
  185. return CreateObject(this);
  186. }
  187. BinaryWriter* CPhysicsObj::UpdateMessage()
  188. {
  189. return UpdateObject(this);
  190. }
  191. void CPhysicsObj::RemovePreviousInstance()
  192. {
  193. DWORD RPI[3];
  194. RPI[0] = 0xF747;
  195. RPI[1] = m_dwGUID;
  196. RPI[2] = m_wInstance - 1;
  197. g_pWorld->BroadcastPVS(GetLandcell(), RPI, sizeof(RPI), 10/*OBJECT_MSG*/, 0, FALSE);
  198. }
  199. float CPhysicsObj::DistanceTo(CPhysicsObj *pOther)
  200. {
  201. return (float) (Vector(m_Origin)-(pOther->m_Origin)).Length();
  202. }
  203. void CPhysicsObj::UpdateModel()
  204. {
  205. if (HasOwner())
  206. return;
  207. BinaryWriter MU;
  208. MU.WriteDWORD(0xF625);
  209. MU.WriteDWORD(m_dwGUID);
  210. BinaryWriter *MD = GetModelData();
  211. MU.AppendData(MD->GetData(), MD->GetSize());
  212. delete MD;
  213. MU.WriteWORD(m_wInstance);
  214. MU.WriteWORD(++m_wNumModelChanges);
  215. g_pWorld->BroadcastPVS(GetLandcell(), MU.GetData(), MU.GetSize());
  216. }
  217. void CPhysicsObj::SetAppearanceOverride(ModelInfo *pAppearance)
  218. {
  219. if (pAppearance)
  220. {
  221. m_miModelOverride = *pAppearance;
  222. m_bUseModelOverride = true;
  223. }
  224. else
  225. m_bUseModelOverride = false;
  226. UpdateModel();
  227. }
  228. BinaryWriter* CPhysicsObj::GetModelData()
  229. {
  230. if (m_bUseModelOverride)
  231. {
  232. return m_miModelOverride.NetData();
  233. }
  234. else
  235. {
  236. ModelInfo miCurrentModel;
  237. // temporary, replace later
  238. if (!IsPlayer() || (m_dwModel == 0x02000001 || m_dwModel == 0x0200004E))
  239. {
  240. miCurrentModel.bUnknown = m_miBaseModel.bUnknown; //0x11
  241. miCurrentModel.dwBasePalette = m_miBaseModel.dwBasePalette;
  242. miCurrentModel.MergeData(&m_miBaseModel, NULL);
  243. ItemVector vItems;
  244. Container_GetEquippedArmor(&vItems);
  245. ItemVector::iterator iit = vItems.begin();
  246. ItemVector::iterator iend = vItems.end();
  247. while (iit != iend)
  248. {
  249. CBaseItem* pItem = *iit; iit++;
  250. if (pItem->IsWearable())
  251. {
  252. miCurrentModel.MergeData(&pItem->m_miWornModel, NULL);
  253. }
  254. }
  255. }
  256. return miCurrentModel.NetData();
  257. }
  258. }
  259. void CPhysicsObj::ChangeVIS(DWORD dwFlags)
  260. {
  261. m_wNumBubbleModes++;
  262. if (!HasOwner())
  263. {
  264. DWORD UVF[4];
  265. UVF[0] = 0xF74B;
  266. UVF[1] = m_dwGUID;
  267. UVF[2] = dwFlags;
  268. UVF[3] = (m_wNumBubbleModes << 16) | m_wInstance;
  269. g_pWorld->BroadcastPVS(GetLandcell(), UVF, sizeof(UVF));
  270. }
  271. m_PhysicsState = dwFlags;
  272. }
  273. void CPhysicsObj::EmitSound(DWORD dwIndex, float fSpeed)
  274. {
  275. if (HasOwner())
  276. return;
  277. BinaryWriter SoundMsg;
  278. SoundMsg.WriteDWORD(0xF750);
  279. SoundMsg.WriteDWORD(m_dwGUID);
  280. SoundMsg.WriteDWORD(dwIndex);
  281. SoundMsg.WriteFloat(fSpeed);
  282. g_pWorld->BroadcastPVS(GetLandcell(), SoundMsg.GetData(), SoundMsg.GetSize(), OBJECT_MSG, 0);
  283. }
  284. void CPhysicsObj::EmitEffect(DWORD dwIndex, float flScale)
  285. {
  286. if (HasOwner())
  287. return;
  288. BinaryWriter EffectMsg;
  289. EffectMsg.WriteDWORD(0xF755);
  290. EffectMsg.WriteDWORD(m_dwGUID);
  291. EffectMsg.WriteDWORD(dwIndex);
  292. EffectMsg.WriteFloat(flScale);
  293. g_pWorld->BroadcastPVS(GetLandcell(), EffectMsg.GetData(), EffectMsg.GetSize(), OBJECT_MSG, 0);
  294. }
  295. void CPhysicsObj::SpeakLocal(const char* szText, long lColor)
  296. {
  297. if (HasOwner())
  298. return;
  299. extern bool g_bSilence;
  300. if (g_bSilence)
  301. {
  302. if (IsPlayer())
  303. {
  304. CBasePlayer *pPlayer = (CBasePlayer *)this;
  305. if (pPlayer->GetClient()->GetAccessLevel() < ADMIN_ACCESS)
  306. {
  307. return;
  308. }
  309. }
  310. }
  311. BinaryWriter *LC = LocalChat(szText, GetName(), m_dwGUID, lColor);
  312. g_pWorld->BroadcastPVS(GetLandcell(), LC->GetData(), LC->GetSize(), PRIVATE_MSG);
  313. delete LC;
  314. }
  315. void CPhysicsObj::EmoteLocal(const char* szText)
  316. {
  317. if (HasOwner())
  318. return;
  319. extern bool g_bSilence;
  320. if (g_bSilence)
  321. {
  322. if (IsPlayer())
  323. {
  324. CBasePlayer *pPlayer = (CBasePlayer *)this;
  325. if (pPlayer->GetClient()->GetAccessLevel() < ADMIN_ACCESS)
  326. {
  327. return;
  328. }
  329. }
  330. }
  331. BinaryWriter *EL = EmoteChat(szText, GetName(), m_dwGUID);
  332. g_pWorld->BroadcastPVS(GetLandcell(), EL->GetData(), EL->GetSize(), PRIVATE_MSG);
  333. delete EL;
  334. }
  335. void CPhysicsObj::ActionLocal(const char* szText)
  336. {
  337. if (HasOwner())
  338. return;
  339. extern bool g_bSilence;
  340. if (g_bSilence)
  341. {
  342. if (IsPlayer())
  343. {
  344. CBasePlayer *pPlayer = (CBasePlayer *)this;
  345. if (pPlayer->GetClient()->GetAccessLevel() < ADMIN_ACCESS)
  346. {
  347. return;
  348. }
  349. }
  350. }
  351. BinaryWriter *AL = ActionChat(szText, GetName(), m_dwGUID);
  352. g_pWorld->BroadcastPVS(GetLandcell(), AL->GetData(), AL->GetSize(), PRIVATE_MSG);
  353. delete AL;
  354. }
  355. /*
  356. DWORD CPhysicsObj::GetDescFlags()
  357. {
  358. DWORD dwFlags = 0;
  359. if (IsInscribable())
  360. dwFlags |= BF_INSCRIBABLE;
  361. if (!CanPickup())
  362. dwFlags |= BF_STUCK;
  363. if (IsPlayer())
  364. dwFlags |= BF_PLAYER;
  365. if (IsAttackable())
  366. dwFlags |= BF_ATTACKABLE;
  367. if (IsLifestone())
  368. dwFlags |= BF_LIFESTONE;
  369. if (IsPlayer())
  370. dwFlags |= BF_PLAYER_KILLER; // Player Killer
  371. return dwFlags;
  372. }
  373. */
  374. DWORD CPhysicsObj::GetObjectStat(eObjectStat index)
  375. {
  376. if (index >= 0x100)
  377. return NULL;
  378. return m_dwStats[index];
  379. }
  380. DWORD CPhysicsObj::SetObjectStat(eObjectStat index, DWORD value)
  381. {
  382. DWORD oldvalue;
  383. if (index >= 0x100)
  384. return NULL;
  385. oldvalue = m_dwStats[index];
  386. m_dwStats[index] = value;
  387. return oldvalue;
  388. }