/src/main/datatypes/MQ2RaidType.cpp

https://gitlab.com/mxdog/mqnext-mxdog · C++ · 506 lines · 421 code · 63 blank · 22 comment · 85 complexity · a334856bd2148746e9fc3d1d252f3774 MD5 · raw file

  1. /*
  2. * MacroQuest: The extension platform for EverQuest
  3. * Copyright (C) 2002-2022 MacroQuest Authors
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License, version 2, as published by
  7. * the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. */
  14. #include "pch.h"
  15. #include "MQ2DataTypes.h"
  16. namespace mq::datatypes {
  17. enum class RaidMembers
  18. {
  19. Member = 1,
  20. Members,
  21. Target,
  22. Leader,
  23. TotalLevels,
  24. AverageLevel,
  25. LootType,
  26. Looter,
  27. Looters,
  28. Locked,
  29. Invited,
  30. MainAssist,
  31. MasterLooter,
  32. MarkNPC,
  33. };
  34. enum class RaidMethods
  35. {
  36. };
  37. MQ2RaidType::MQ2RaidType()
  38. : MQ2Type("raid")
  39. {
  40. ScopedTypeMember(RaidMembers, Member);
  41. ScopedTypeMember(RaidMembers, Members);
  42. ScopedTypeMember(RaidMembers, Target);
  43. ScopedTypeMember(RaidMembers, Leader);
  44. ScopedTypeMember(RaidMembers, TotalLevels);
  45. ScopedTypeMember(RaidMembers, AverageLevel);
  46. ScopedTypeMember(RaidMembers, LootType);
  47. ScopedTypeMember(RaidMembers, Looter);
  48. ScopedTypeMember(RaidMembers, Looters);
  49. ScopedTypeMember(RaidMembers, Locked);
  50. ScopedTypeMember(RaidMembers, Invited);
  51. ScopedTypeMember(RaidMembers, MainAssist);
  52. ScopedTypeMember(RaidMembers, MasterLooter);
  53. ScopedTypeMember(RaidMembers, MarkNPC);
  54. }
  55. bool MQ2RaidType::GetMember(MQVarPtr VarPtr, const char* Member, char* Index, MQTypeVar& Dest)
  56. {
  57. if (!pLocalPC)
  58. return false;
  59. MQTypeMember* pMember = MQ2RaidType::FindMember(Member);
  60. if (!pMember)
  61. return false;
  62. switch (static_cast<RaidMembers>(pMember->ID))
  63. {
  64. case RaidMembers::Locked:
  65. Dest.Set(pRaid->Locked);
  66. Dest.Type = pBoolType;
  67. return true;
  68. case RaidMembers::Invited:
  69. Dest.Set(pRaid->Invited == 2);
  70. Dest.Type = pBoolType;
  71. return true;
  72. case RaidMembers::Member:
  73. Dest.DWord = 0;
  74. Dest.Type = pRaidMemberType;
  75. if (Index[0])
  76. {
  77. if (IsNumber(Index))
  78. {
  79. int Count = GetIntFromString(Index, 0);
  80. if (!Count || Count > pRaid->RaidMemberCount)
  81. return false;
  82. for (int nMember = 0; nMember < MAX_RAID_SIZE; nMember++)
  83. {
  84. if (pRaid->RaidMemberUsed[nMember])
  85. {
  86. Count--;
  87. if (!Count)
  88. {
  89. Dest.DWord = nMember + 1;
  90. return true;
  91. }
  92. }
  93. }
  94. }
  95. else
  96. {
  97. // by name
  98. for (int nMember = 0; nMember < MAX_RAID_SIZE; nMember++)
  99. {
  100. if (pRaid->RaidMemberUsed[nMember] && ci_equals(pRaid->RaidMember[nMember].Name, Index))
  101. {
  102. Dest.DWord = nMember + 1;
  103. return true;
  104. }
  105. }
  106. }
  107. }
  108. return false;
  109. case RaidMembers::Members:
  110. Dest.DWord = pRaid->RaidMemberCount;
  111. Dest.Type = pIntType;
  112. return true;
  113. case RaidMembers::Target:
  114. Dest.DWord = pRaid->RaidTarget + 1;
  115. Dest.Type = pRaidMemberType;
  116. return true;
  117. case RaidMembers::Leader:
  118. Dest.DWord = 0;
  119. Dest.Type = pRaidMemberType;
  120. for (int nMember = 0; nMember < MAX_RAID_SIZE; nMember++)
  121. {
  122. if (pRaid->RaidMemberUsed[nMember] && ci_equals(pRaid->RaidMember[nMember].Name, pRaid->RaidLeaderName))
  123. {
  124. Dest.DWord = nMember + 1;
  125. return true;
  126. }
  127. }
  128. return false;
  129. case RaidMembers::TotalLevels:
  130. Dest.DWord = pRaid->TotalRaidMemberLevels;
  131. Dest.Type = pIntType;
  132. return true;
  133. case RaidMembers::AverageLevel:
  134. Dest.Float = (float)pRaid->TotalRaidMemberLevels / (float)pRaid->RaidMemberCount;
  135. Dest.Type = pFloatType;
  136. return true;
  137. case RaidMembers::LootType:
  138. Dest.DWord = pRaid->LootType;
  139. Dest.Type = pIntType;
  140. return true;
  141. case RaidMembers::Looters:
  142. Dest.DWord = 0;
  143. Dest.Type = pIntType;
  144. for (auto& looter : pRaid->RaidLooters)
  145. {
  146. if (looter[0])
  147. Dest.DWord++;
  148. }
  149. return true;
  150. case RaidMembers::Looter:
  151. Dest.Type = pStringType;
  152. if (Index[0])
  153. {
  154. if (IsNumber(Index))
  155. {
  156. int Count = GetIntFromString(Index, 0);
  157. if (Count <= 0)
  158. return false;
  159. for (int nLooter = 0; nLooter < MAX_RAID_LOOTERS; nLooter++)
  160. {
  161. if (pRaid->RaidLooters[nLooter][0])
  162. {
  163. Count--;
  164. if (Count == 0)
  165. {
  166. strcpy_s(DataTypeTemp, pRaid->RaidLooters[nLooter]);
  167. Dest.Ptr = &DataTypeTemp[0];
  168. return true;
  169. }
  170. }
  171. }
  172. }
  173. // by name?
  174. }
  175. return false;
  176. case RaidMembers::MainAssist:
  177. Dest.DWord = 0;
  178. Dest.Type = pRaidMemberType;
  179. if (Index[0])
  180. {
  181. RaidData& rd = pLocalPC->raidData;
  182. if (IsNumber(Index))
  183. {
  184. // Look up Nth raid assist
  185. int maIndex = GetIntFromString(Index, 0);
  186. if (maIndex <= 0 || maIndex > MAX_RAID_ASSISTS)
  187. return false;
  188. // This matches what EQ says the RA at this index is.
  189. const char* raName = rd.MainAssistNames[maIndex - 1];
  190. if (raName[0] == 0)
  191. return false;
  192. for (int nMember = 0; nMember < MAX_RAID_SIZE; ++nMember)
  193. {
  194. if (!pRaid->RaidMemberUsed[nMember])
  195. continue;
  196. if (pRaid->RaidMember[nMember].RaidMainAssist)
  197. {
  198. if (strcmp(raName, pRaid->RaidMember[nMember].Name) == 0)
  199. {
  200. Dest.DWord = nMember + 1;
  201. return true;
  202. }
  203. }
  204. }
  205. }
  206. else
  207. {
  208. // Return raid member index if the specified name is a raid assist.
  209. for (int nMember = 0; nMember < MAX_RAID_SIZE; ++nMember)
  210. {
  211. if (!pRaid->RaidMemberUsed[nMember])
  212. continue;
  213. if (!pRaid->RaidMember[nMember].RaidMainAssist)
  214. continue;
  215. if (ci_equals(pRaid->RaidMember[nMember].Name, Index))
  216. {
  217. Dest.DWord = nMember + 1;
  218. return true;
  219. }
  220. }
  221. }
  222. }
  223. // just return the first raid assist that is found.
  224. for (int nMember = 0; nMember < MAX_RAID_SIZE; ++nMember)
  225. {
  226. if (!pRaid->RaidMemberUsed[nMember])
  227. continue;
  228. if (pRaid->RaidMember[nMember].RaidMainAssist)
  229. {
  230. Dest.DWord = nMember + 1;
  231. return true;
  232. }
  233. }
  234. return false;
  235. case RaidMembers::MasterLooter:
  236. Dest.DWord = 0;
  237. Dest.Type = pRaidMemberType;
  238. for (int i = 0; i < 72; i++)
  239. {
  240. if (pRaid->RaidMemberUsed[i] && pRaid->RaidMember[i].MasterLooter)
  241. {
  242. Dest.DWord = i + 1;
  243. return true;
  244. }
  245. }
  246. return false;
  247. case RaidMembers::MarkNPC:
  248. Dest.DWord = 0;
  249. Dest.Type = pRaidMemberType;
  250. if (Index[0])
  251. {
  252. if (IsNumber(Index))
  253. {
  254. // Look up Nth raid marker
  255. int count = GetIntFromString(Index, 0);
  256. if (count <= 0 || count > MAX_RAID_MARKERS)
  257. return false;
  258. for (int nMember = 0; nMember < MAX_RAID_SIZE; ++nMember)
  259. {
  260. if (!pRaid->RaidMemberUsed[nMember])
  261. continue;
  262. if (pRaid->RaidMember[nMember].RaidMarker)
  263. {
  264. if (--count == 0)
  265. {
  266. Dest.DWord = nMember + 1;
  267. return true;
  268. }
  269. }
  270. }
  271. }
  272. else
  273. {
  274. // by name
  275. for (int nMember = 0; nMember < MAX_RAID_SIZE; nMember++)
  276. {
  277. if (!pRaid->RaidMemberUsed[nMember])
  278. continue;
  279. if (pRaid->RaidMember[nMember].RaidMarker)
  280. {
  281. if (ci_equals(pRaid->RaidMember[nMember].Name, Index))
  282. {
  283. Dest.DWord = nMember + 1;
  284. return true;
  285. }
  286. }
  287. }
  288. }
  289. }
  290. else
  291. {
  292. // just return the first raid marker that is found.
  293. for (int nMember = 0; nMember < MAX_RAID_SIZE; ++nMember)
  294. {
  295. if (!pRaid->RaidMemberUsed[nMember])
  296. continue;
  297. if (pRaid->RaidMember[nMember].RaidMarker)
  298. {
  299. Dest.DWord = nMember + 1;
  300. return true;
  301. }
  302. }
  303. }
  304. return false;
  305. }
  306. return false;
  307. }
  308. bool MQ2RaidType::ToString(MQVarPtr VarPtr, char* Destination)
  309. {
  310. return false;
  311. }
  312. bool MQ2RaidType::dataRaid(const char* szIndex, MQTypeVar& Ret)
  313. {
  314. Ret.DWord = 0;
  315. Ret.Type = pRaidType;
  316. return true;
  317. }
  318. enum class RaidMemberMembers
  319. {
  320. Name = 1,
  321. Group,
  322. GroupLeader,
  323. RaidLeader,
  324. Spawn,
  325. Looter,
  326. Class,
  327. Level,
  328. };
  329. MQ2RaidMemberType::MQ2RaidMemberType() : MQ2Type("raidmember")
  330. {
  331. ScopedTypeMember(RaidMemberMembers, Name);
  332. ScopedTypeMember(RaidMemberMembers, Group);
  333. ScopedTypeMember(RaidMemberMembers, GroupLeader);
  334. ScopedTypeMember(RaidMemberMembers, RaidLeader);
  335. ScopedTypeMember(RaidMemberMembers, Spawn);
  336. ScopedTypeMember(RaidMemberMembers, Looter);
  337. ScopedTypeMember(RaidMemberMembers, Class);
  338. ScopedTypeMember(RaidMemberMembers, Level);
  339. }
  340. bool MQ2RaidMemberType::GetMember(MQVarPtr VarPtr, const char* Member, char* Index, MQTypeVar& Dest)
  341. {
  342. int nRaidMember = VarPtr.Int - 1;
  343. if (nRaidMember < 0 || nRaidMember >= MAX_RAID_SIZE)
  344. return false;
  345. if (!pRaid->RaidMemberUsed[nRaidMember])
  346. return false;
  347. RaidMember& raidMember = pRaid->RaidMember[nRaidMember];
  348. MQTypeMember* pMember = MQ2RaidMemberType::FindMember(Member);
  349. if (!pMember)
  350. {
  351. return pSpawnType->GetMember(GetSpawnByName(raidMember.Name), Member, Index, Dest);
  352. }
  353. switch (static_cast<RaidMemberMembers>(pMember->ID))
  354. {
  355. case RaidMemberMembers::Name:
  356. strcpy_s(DataTypeTemp, raidMember.Name);
  357. Dest.Ptr = &DataTypeTemp[0];
  358. Dest.Type = pStringType;
  359. return true;
  360. case RaidMemberMembers::Group:
  361. Dest.DWord = raidMember.GroupNumber + 1;
  362. Dest.Type = pIntType;
  363. return true;
  364. case RaidMemberMembers::GroupLeader:
  365. Dest.Set(raidMember.GroupLeader);
  366. Dest.Type = pBoolType;
  367. return true;
  368. case RaidMemberMembers::RaidLeader:
  369. Dest.Set(raidMember.RaidLeader);
  370. Dest.Type = pBoolType;
  371. return true;
  372. case RaidMemberMembers::Looter:
  373. Dest.Set(false);
  374. Dest.Type = pBoolType;
  375. if (raidMember.RaidLeader)
  376. {
  377. Dest.Set(true);
  378. return true;
  379. }
  380. if (pRaid->LootType == RaidLootLeaderAndGroupLeader)
  381. {
  382. Dest.Set(raidMember.GroupLeader);
  383. return true;
  384. }
  385. if (pRaid->LootType == RaidLootAssignments)
  386. {
  387. for (auto& RaidLooter : pRaid->RaidLooters)
  388. {
  389. if (ci_equals(RaidLooter, raidMember.Name))
  390. {
  391. Dest.Set(true);
  392. return true;
  393. }
  394. }
  395. }
  396. return true;
  397. case RaidMemberMembers::Spawn:
  398. Dest = pSpawnType->MakeTypeVar(GetSpawnByName(raidMember.Name));
  399. return true;
  400. case RaidMemberMembers::Level:
  401. Dest.DWord = raidMember.nLevel;
  402. Dest.Type = pIntType;
  403. return true;
  404. case RaidMemberMembers::Class:
  405. Dest.DWord = raidMember.nClass;
  406. Dest.Type = pClassType;
  407. return true;
  408. default: break;
  409. }
  410. return false;
  411. }
  412. bool MQ2RaidMemberType::ToString(MQVarPtr VarPtr, char* Destination)
  413. {
  414. int nRaidMember = VarPtr.Int - 1;
  415. if (nRaidMember >= MAX_RAID_SIZE || nRaidMember < 0)
  416. return false;
  417. if (!pRaid->RaidMemberUsed[nRaidMember])
  418. return false;
  419. strcpy_s(Destination, MAX_STRING, pRaid->RaidMember[nRaidMember].Name);
  420. return true;
  421. }
  422. bool MQ2RaidMemberType::FromData(MQVarPtr& VarPtr, const MQTypeVar& Source)
  423. {
  424. if (Source.Type != pRaidMemberType)
  425. return false;
  426. VarPtr = Source;
  427. return true;
  428. }
  429. bool MQ2RaidMemberType::Downcast(const MQVarPtr& fromVar, MQVarPtr& toVar, MQ2Type* toType)
  430. {
  431. if (toType == pSpawnType)
  432. {
  433. int nRaidMember = fromVar.Int - 1;
  434. if (nRaidMember >= MAX_RAID_SIZE || nRaidMember < 0)
  435. return false;
  436. if (!pRaid->RaidMemberUsed[nRaidMember])
  437. return false;
  438. toVar = pSpawnType->MakeVarPtr(GetSpawnByName(pRaid->RaidMember[nRaidMember].Name));
  439. return true;
  440. }
  441. return false;
  442. }
  443. } // namespace mq::datatypes