Dinosaurrxd

LegendaryActionTracker

Oct 29th, 2024
41
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.24 KB | None | 0 0
  1. on("ready", () => {
  2. let legendaryActionTracker = {}; // Changed from const to let
  3. const legendaryActionSetupComplete = new Set();
  4. let ownerId = null;
  5.  
  6. on("change:campaign:turnorder", () => {
  7. const turnOrder = JSON.parse(Campaign().get("turnorder") || "[]");
  8.  
  9. if (turnOrder.length > 0) {
  10. const currentTurn = turnOrder[0];
  11. const tokenId = currentTurn.id;
  12. const token = getObj("graphic", tokenId);
  13.  
  14. if (token && token.get("represents")) {
  15. const characterId = token.get("represents");
  16. const character = getObj("character", characterId);
  17.  
  18. if (!character) return;
  19.  
  20. if (!legendaryActionSetupComplete.has(tokenId)) {
  21. setupLegendaryActions(tokenId, characterId);
  22. legendaryActionSetupComplete.add(tokenId);
  23. }
  24.  
  25. if (ownerId && ownerId !== tokenId && legendaryActionTracker[ownerId]?.remaining > 0) {
  26. displayLegendaryActions(ownerId);
  27. }
  28.  
  29. if (tokenId === ownerId) refreshLegendaryActions(ownerId);
  30. }
  31. }
  32. });
  33.  
  34. function setupLegendaryActions(tokenId, characterId) {
  35. const legendaryActions = findObjs({
  36. _type: "ability",
  37. _characterid: characterId
  38. }).filter(ability => ability.get("name").startsWith("L-"));
  39.  
  40. if (legendaryActions.length > 0) {
  41. legendaryActionTracker[tokenId] = {
  42. max: legendaryActions.length,
  43. remaining: legendaryActions.length,
  44. actions: {}
  45. };
  46.  
  47. legendaryActions.forEach(action => {
  48. let actionName = action.get("name").replace(/^L-/, "").replace(/-\([\w-]*\d+a\)$/i, "").trim();
  49. const cost = parseCostFromAbilityName(action.get("name"));
  50. legendaryActionTracker[tokenId].actions[action.id] = {
  51. name: capitalizeFirstLetter(actionName),
  52. cost: cost,
  53. abilityId: action.id
  54. };
  55. });
  56. ownerId = tokenId;
  57. }
  58. }
  59.  
  60. function parseCostFromAbilityName(name) {
  61. const match = name.match(/-\((?:\w*-)?(\d+)a\)/i);
  62. return match ? parseInt(match[1]) : 1;
  63. }
  64.  
  65. function refreshLegendaryActions(tokenId) {
  66. if (legendaryActionTracker[tokenId]) {
  67. legendaryActionTracker[tokenId].remaining = legendaryActionTracker[tokenId].max;
  68. }
  69. }
  70.  
  71. function displayLegendaryActions(tokenId) {
  72. const characterId = getObj("graphic", tokenId)?.get("represents");
  73. const character = getObj("character", characterId);
  74. if (!character) return;
  75.  
  76. const characterName = character.get("name");
  77. const remainingActions = legendaryActionTracker[tokenId].remaining;
  78. let message = `&{template:default} {{name=${characterName} Legendary Actions}} {{Remaining=${remainingActions}}}`;
  79.  
  80. for (const actionId in legendaryActionTracker[tokenId].actions) {
  81. const action = legendaryActionTracker[tokenId].actions[actionId];
  82. if (action.cost <= remainingActions) {
  83. message += ` {{${action.name} (Cost: ${action.cost})=[Use](~${character.id}|${action.abilityId})}}`;
  84. }
  85. }
  86.  
  87. sendChat("Legendary Action Tracker", `/w gm ${message}`);
  88. }
  89.  
  90. on("chat:message", (msg) => {
  91. if (msg.type === "general" && ownerId) {
  92. detectAbilityUsageFromChat(msg.content, ownerId);
  93. } else if (msg.type === "api" && msg.content.toLowerCase() === "!endcombat") {
  94. resetCombat();
  95. }
  96. });
  97.  
  98. function detectAbilityUsageFromChat(content, tokenId) {
  99. const cleanedContent = content.replace(/<[^>]*>/g, "").replace(/\s+/g, " ").trim().toLowerCase();
  100. const tracker = legendaryActionTracker[tokenId];
  101.  
  102. if (!tracker) return;
  103.  
  104. const characterId = getObj("graphic", tokenId)?.get("represents");
  105. const legendaryActions = tracker.actions;
  106.  
  107. for (const actionId in legendaryActions) {
  108. const action = legendaryActions[actionId];
  109. const actionName = action.name.toLowerCase();
  110.  
  111. if (cleanedContent.includes(actionName) && tracker.remaining >= action.cost) {
  112. tracker.remaining -= action.cost; // Deduct full action cost
  113. sendRemainingActionsPrompt(getObj("character", characterId), tokenId);
  114. break;
  115. }
  116. }
  117. }
  118.  
  119. function sendRemainingActionsPrompt(character, tokenId) {
  120. const remainingActions = legendaryActionTracker[tokenId].remaining;
  121. const message = `&{template:default} {{name=${character.get("name")} Legendary Actions}} {{Remaining=${remainingActions}}}`;
  122. sendChat("Legendary Action Tracker", `/w gm ${message}`);
  123. }
  124.  
  125. function capitalizeFirstLetter(string) {
  126. return string.charAt(0).toUpperCase() + string.slice(1);
  127. }
  128.  
  129. function resetCombat() {
  130. for (let key in legendaryActionTracker) delete legendaryActionTracker[key];
  131. legendaryActionSetupComplete.clear();
  132. ownerId = null;
  133. }
  134. });
  135.  
Add Comment
Please, Sign In to add comment