├── .vscode
└── settings.json
├── README.md
├── ashita
├── _ashita.lua
├── _enums.lua
├── ability.lua
├── chat.lua
├── item.lua
├── menu.lua
├── mob.lua
├── packets.lua
├── party.lua
├── player.lua
├── spell.lua
└── weaponskill.lua
├── columns
├── !column.lua
├── accuracy.lua
├── attack_speed.lua
├── catalog.lua
├── damage.lua
├── defense.lua
├── general.lua
├── healing.lua
├── proc.lua
├── spell.lua
├── string.lua
└── util.lua
├── commands.lua
├── database
├── _database.lua
├── _enum.lua
├── accuracy.lua
├── attack_speed.lua
├── catalog.lua
├── data.lua
├── dps.lua
├── lists.lua
├── pet_catalog.lua
├── pet_data.lua
└── widgets.lua
├── file.lua
├── handlers
├── _handler.lua
├── abilities.lua
├── deaths.lua
├── items.lua
├── melee.lua
├── melee_def.lua
├── ranged.lua
├── spells.lua
├── spells_def.lua
├── tp_action.lua
└── tp_action_def.lua
├── initialization.lua
├── metrics.lua
├── modules
├── battle log
│ ├── _battle_log.lua
│ ├── columns.lua
│ ├── config.lua
│ ├── entries.lua
│ └── widgets.lua
├── config
│ └── _config.lua
├── debug
│ ├── !debug.lua
│ ├── performance.lua
│ ├── screens
│ │ ├── data_viewer.lua
│ │ ├── error_log.lua
│ │ ├── mob_viewer.lua
│ │ └── packet_viewer.lua
│ └── unit_tests
│ │ ├── _tests.lua
│ │ ├── abilities.lua
│ │ ├── defense.lua
│ │ ├── melee.lua
│ │ ├── ranged.lua
│ │ ├── spells.lua
│ │ └── tp_action.lua
├── exp
│ ├── _exp.lua
│ ├── chains.lua
│ ├── columns.lua
│ ├── config.lua
│ ├── dedication.lua
│ └── tracking.lua
├── focus
│ ├── _focus.lua
│ ├── abilities.lua
│ ├── cataloged.lua
│ ├── config.lua
│ ├── defense.lua
│ ├── magic.lua
│ ├── melee.lua
│ ├── overview.lua
│ ├── pets.lua
│ ├── ranged.lua
│ └── weaponskills.lua
├── hub
│ ├── !hub.lua
│ └── config.lua
├── overview
│ ├── _overview.lua
│ ├── config.lua
│ ├── focus.lua
│ └── parse.lua
├── parse
│ ├── _parse.lua
│ ├── config.lua
│ ├── display_full.lua
│ ├── display_mini.lua
│ ├── display_nano.lua
│ ├── enum.lua
│ └── widgets.lua
└── report
│ ├── _report.lua
│ ├── config.lua
│ ├── publishing.lua
│ └── widgets.lua
├── packets
├── _bitreader.lua
└── _parser.lua
├── resources
├── _resource.lua
├── abilities.lua
├── avatars.lua
├── buffs.lua
├── colors.lua
├── game.lua
├── items.lua
├── jobs.lua
├── monster_abilities.lua
├── monster_abilities_curated.lua
├── pets.lua
├── spells.lua
├── spells_curated.lua
├── themes.lua
├── weapon_skills.lua
└── weapon_skills_curated.lua
├── throttling.lua
├── timers.lua
└── windows
├── !manager.lua
├── !window.lua
├── config.lua
├── themes.lua
└── widgets.lua
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Lua.diagnostics.globals": [
3 | "windower",
4 | "_addon",
5 | "addon",
6 | "AshitaCore",
7 | "ashita",
8 | "ImGuiWindowFlags_NoDecoration",
9 | "ImGuiWindowFlags_AlwaysAutoResize",
10 | "ImGuiWindowFlags_NoSavedSettings",
11 | "ImGuiWindowFlags_NoFocusOnAppearing",
12 | "ImGuiWindowFlags_NoNav",
13 | "ImGuiTableFlags_SizingFixedFit",
14 | "ImGuiTableFlags_None",
15 | "ImGuiTableFlags_Borders",
16 | "bit",
17 | "ImGuiTableColumnFlags_WidthFixed",
18 | "ImGuiWindowFlags_None",
19 | "ImGuiTableFlags_SizingStretchProp",
20 | "ImGuiTableColumnFlags_None",
21 | "ImGuiCond_Always",
22 | "ImGuiStyleVar_CellPadding",
23 | "ImGuiTableFlags_PadOuterX",
24 | "ImGuiStyleVar_WindowPadding",
25 | "ImGuiTabBarFlags_None",
26 | "ImGuiComboFlags_None",
27 | "ImGuiTreeNodeFlags_None",
28 | "GetPlayerEntity",
29 | "ImGuiStyleVar_ItemSpacing",
30 | "ImGuiStyleVar_ItemInnerSpacing",
31 | "ImGuiStyleVar_Alpha",
32 | "ImGuiTableColumnFlags_WidthStretch",
33 | "ImGuiTableFlags_Resizable",
34 | "ImGuiTableFlags_SizingStretchSame",
35 | "ImGuiTableFlags_NoSavedSettings",
36 | "ImGuiWindowFlags_HorizontalScrollbar",
37 | "ImGuiCol_TableHeaderBg",
38 | "ImGuiSliderFlags_None",
39 | "ImGuiInputTextFlags_CharsDecimal",
40 | "ImGuiTableFlags_Reorderable",
41 | "ImGuiTableFlags_Sortable",
42 | "ImGuiTableColumnFlags_DefaultSort",
43 | "ImGuiTableFlags_ScrollY",
44 | "ImGuiStyleVar_IndentSpacing",
45 | "ImGuiTableFlags_NoHostExtendX",
46 | "T",
47 | "ImGuiCol_Text",
48 | "ImGuiCol_TextDisabled",
49 | "ImGuiCol_WindowBg",
50 | "ImGuiCol_ChildBg",
51 | "ImGuiCol_PopupBg",
52 | "ImGuiCol_Border",
53 | "ImGuiCol_BorderShadow",
54 | "ImGuiCol_FrameBg",
55 | "ImGuiCol_FrameBgHovered",
56 | "ImGuiCol_FrameBgActive",
57 | "ImGuiCol_TitleBg",
58 | "ImGuiCol_TitleBgActive",
59 | "ImGuiCol_TitleBgCollapsed",
60 | "ImGuiCol_MenuBarBg",
61 | "ImGuiCol_ScrollbarBg",
62 | "ImGuiCol_ScrollbarGrab",
63 | "ImGuiCol_ScrollbarGrabHovered",
64 | "ImGuiCol_ScrollbarGrabActive",
65 | "ImGuiCol_CheckMark",
66 | "ImGuiCol_SliderGrab",
67 | "ImGuiCol_SliderGrabActive",
68 | "ImGuiCol_Button",
69 | "ImGuiCol_ButtonHovered",
70 | "ImGuiCol_ButtonActive",
71 | "ImGuiCol_Header",
72 | "ImGuiCol_HeaderHovered",
73 | "ImGuiCol_HeaderActive",
74 | "ImGuiCol_Separator",
75 | "ImGuiCol_SeparatorHovered",
76 | "ImGuiCol_SeparatorActive",
77 | "ImGuiCol_ResizeGrip",
78 | "ImGuiCol_ResizeGripHovered",
79 | "ImGuiCol_ResizeGripActive",
80 | "ImGuiCol_Tab",
81 | "ImGuiCol_TabHovered",
82 | "ImGuiCol_TabActive",
83 | "ImGuiCol_TabUnfocused",
84 | "ImGuiCol_TabUnfocusedActive",
85 | "ImGuiCol_PlotLines",
86 | "ImGuiCol_PlotLinesHovered",
87 | "ImGuiCol_PlotHistogram",
88 | "ImGuiCol_PlotHistogramHovered",
89 | "ImGuiCol_TableBorderStrong",
90 | "ImGuiCol_TableBorderLight",
91 | "ImGuiCol_TableRowBg",
92 | "ImGuiCol_TableRowBgAlt",
93 | "ImGuiCol_TextSelectedBg",
94 | "ImGuiCol_DragDropTarget",
95 | "ImGuiCol_NavHighlight",
96 | "ImGuiCol_NavWindowingHighlight",
97 | "ImGuiCol_NavWindowingDimBg",
98 | "ImGuiCol_ModalWindowDimBg",
99 | "ImGuiTreeNodeFlags_SpanAvailWidth",
100 | "ImGuiWindowFlags_NoTitleBar",
101 | "breader",
102 | "switch",
103 | "GetEntity",
104 | "ImGuiTabItemFlags_SetSelected",
105 | "ImGuiWindowFlags_NoBackground",
106 | "ImGuiTableBgTarget_CellBg",
107 | "ImGuiTableBgTarget_RowBg0",
108 | "ImGuiCond_Once",
109 | "ImGuiTableFlags_RowBg",
110 | "ImGuiInputTextFlags_AutoSelectAll"
111 | ],
112 | "Lua.diagnostics.disable": [
113 | "undefined-field"
114 | ]
115 | }
--------------------------------------------------------------------------------
/ashita/_ashita.lua:
--------------------------------------------------------------------------------
1 | Ashita = T{}
2 |
3 | -- ------------------------------------------------------------------------------------------------------
4 | -- https://github.com/AshitaXI/Ashita-v4beta/blob/main/plugins/sdk/Ashita.h
5 | -- Memory Manager Functions
6 | -- IAutoFollow* GetAutoFollow(void)
7 | -- ICastBar* GetCastBar(void)
8 | -- IEntity* GetEntity(void)
9 | -- IInventory* GetInventory(void)
10 | -- IParty* GetParty(void)
11 | -- IPlayer* GetPlayer(void)
12 | -- IRecast* GetRecast(void)
13 | -- ITarget* GetTarget(void)
14 | -- ------------------------------------------------------------------------------------------------------
15 | -- TO DO
16 | -- 1. Finish the pet portion in a.Mob.Get_Mob_By_Target
17 | -- ------------------------------------------------------------------------------------------------------
18 |
19 | Ashita.States = {
20 | Zoning = false,
21 | }
22 |
23 | require("ashita._enums")
24 | require("ashita.mob") -- Getting data related to mobs.
25 | require("ashita.player") -- Getting data related to the player.
26 | require("ashita.party") -- Getting data related to the party.
27 | require("ashita.ability") -- Getting data related to abilities.
28 | require("ashita.spell") -- Getting data related to spells.
29 | require("ashita.weaponskill") -- Getting data related to weaponskills.
30 | require("ashita.item") -- Getting data related to items.
31 | require("ashita.chat") -- Chat functions.
32 | require("ashita.packets") -- Packet functions.
33 | require("ashita.menu") -- Memory and Menus.
--------------------------------------------------------------------------------
/ashita/_enums.lua:
--------------------------------------------------------------------------------
1 | Ashita.Enum = T{}
2 |
3 | Ashita.Enum.Chat = T{
4 | PARTY = 1,
5 | LINKSHELL = 2,
6 | LINKSHELL2 = 3,
7 | SAY = 4,
8 | }
9 |
10 | Ashita.Enum.Player_Attributes = T{
11 | TP = "TP",
12 | PET_TP = "Pet TP",
13 | ISZONING = "IsZoning",
14 | }
15 |
16 | Ashita.Enum.Targets = T{
17 | ME = "me",
18 | TARGET = "t",
19 | PET = "pet",
20 | }
21 |
22 | Ashita.Enum.Spawn_Flags = T{
23 | MAINPLAYER = 525,
24 | OTHERPLAYER = 1,
25 | NPC = 2,
26 | IN_PARTY = 13,
27 | IN_ALLIANCE = 9,
28 | MOB = 16,
29 | TRUST = 4366,
30 | PET = 258,
31 | }
32 |
33 | Ashita.Enum.Ability = T{
34 | NORMAL = 1, -- Type: Normal Ability
35 | PETLOGISTICS = 2, -- Type: Fight, Heel, Stay, etc.
36 | BLOODPACTRAGE = 6, -- Type:
37 | BLOODPACTWARD = 10, -- Type:
38 | PETABILITY = 18, -- Type: Offensive BST/SMN ability.
39 | }
40 |
41 | -- Animation IDs from incoming packet 0x028 (Action Packet).
42 | Ashita.Enum.Animation = T{
43 | MELEE_MAIN = 0,
44 | MELEE_OFFHAND = 1,
45 | MELEE_KICK = 2,
46 | MELEE_KICK2 = 3,
47 | DAKEN = 4,
48 | }
49 |
50 | Ashita.Enum.Reaction = T{
51 | GUARD = 2,
52 | SHIELD_BLOCK = 4,
53 | }
54 |
55 | Ashita.Enum.Effect_Animation = T{
56 | FIRE = 1,
57 | ICE = 2,
58 | WIND = 3,
59 | EARTH = 4,
60 | THUNDER = 5,
61 | WATER = 6,
62 | LIGHT = 7,
63 | DARK = 8,
64 | SLEEP = 9,
65 | POISON = 10,
66 | PARALYZE = 11,
67 | BLIND = 12,
68 | SILENCE = 13,
69 | STUN = 16,
70 | CURSE = 17,
71 | DEF_DOWN = 18,
72 | DRAIN = 21,
73 | ASPIR = 22,
74 | HASTE = 23,
75 | }
76 |
77 | -- Message IDs from incoming packet 0x029 (Action Message).
78 | Ashita.Enum.Message = T{
79 | HIT = 1,
80 | MOBHEAL3 = 3,
81 | MOB_KILL = 6,
82 | MOBHEAL373 = 373,
83 | MISS = 15,
84 | DEATH_FALL = 20,
85 | SHADOWS = 31,
86 | DODGE = 32,
87 | COUNTER = 33,
88 | SPIKE_DMG = 44,
89 | CRIT = 67,
90 | PARRY = 70,
91 | NO_EFFECT = 75,
92 | RESIST = 85,
93 | DEATH = 97,
94 | EFFECT_FAIL = 114,
95 | ENDEBUFF = 160,
96 | ENDRAIN = 161,
97 | ENASPIR = 162,
98 | ENDAMAGE = 163,
99 | RANGEPUP = 185,
100 | MISS_TP = 188,
101 | ENSPELL = 229,
102 | ENF_LAND = 236,
103 | ENF_LAND_2 = 237,
104 | BURST = 252,
105 | ENF_BURST = 271,
106 | RESIST_2 = 284,
107 | ABSORB_STR = 329,
108 | ABSORB_DEX = 330,
109 | ABSORB_VIT = 331,
110 | ABSORB_AGI = 332,
111 | ABSORB_INT = 333,
112 | ABSORB_MND = 334,
113 | ABSORB_CHR = 335,
114 | MAGIC_ERASE = 341,
115 | RANGEHIT = 352,
116 | RANGECRIT = 353,
117 | RANGEMISS = 354,
118 | COR_BUST = 426,
119 | ABSORB_TP = 454,
120 | ABSORB_ACC = 533,
121 | SQUARE = 576,
122 | TRUE = 577,
123 | COMP_RESIST = 655,
124 | OVERLOAD = 799,
125 | }
--------------------------------------------------------------------------------
/ashita/ability.lua:
--------------------------------------------------------------------------------
1 | Ashita.Ability = T{}
2 |
3 | -- ------------------------------------------------------------------------------------------------------
4 | -- Get ability data.
5 | -- https://wiki.ashitaxi.com/doku.php?id=addons:adk:iresourcemanager
6 | -- Type 1 = Special Ability (2-hour), Third Eye,
7 | -- Type 6 = SMN using BloodPactRage
8 | -- Type 10 = BloodPactWard
9 | -- Type 18 = BloodPactRage
10 | -- Offsets
11 | -- WS have zero offset.
12 | -- Abilities have 512 offset.
13 | -- ------------------------------------------------------------------------------------------------------
14 | ---@param id number
15 | ---@return table
16 | -- ------------------------------------------------------------------------------------------------------
17 | Ashita.Ability.Get_By_ID = function(id)
18 | return AshitaCore:GetResourceManager():GetAbilityById(id)
19 | end
20 |
21 | -- ------------------------------------------------------------------------------------------------------
22 | -- Get the name of an ability.
23 | -- If we already have the ability data then we don't need to get it again.
24 | -- ------------------------------------------------------------------------------------------------------
25 | ---@param id number ability ID.
26 | ---@param data? table ability table if we already have it.
27 | ---@return string
28 | -- ------------------------------------------------------------------------------------------------------
29 | Ashita.Ability.Name = function(id, data)
30 | local ability = data
31 | if not ability then
32 | ability = Ashita.Ability.Get_By_ID(id)
33 | end
34 | if not ability then return "Error" end
35 | return ability.Name[1]
36 | end
37 |
38 | -- ------------------------------------------------------------------------------------------------------
39 | -- Get the current recast time for an ability by the abilities ID.
40 | -- ------------------------------------------------------------------------------------------------------
41 | ---@param id number ability ID.
42 | ---@return number
43 | -- ------------------------------------------------------------------------------------------------------
44 | Ashita.Ability.Recast_ID = function(id)
45 | local ability_id
46 | local recast = 0
47 | local found = false
48 | for i = 0, 31 do
49 | if not found then
50 | ability_id = AshitaCore:GetMemoryManager():GetRecast():GetAbilityTimerId(i)
51 | if ability_id == id then
52 | recast = math.floor(AshitaCore:GetMemoryManager():GetRecast():GetAbilityTimer(i) / 60)
53 | found = true
54 | end
55 | end
56 | end
57 | return recast
58 | end
--------------------------------------------------------------------------------
/ashita/chat.lua:
--------------------------------------------------------------------------------
1 | Ashita.Chat = T{}
2 |
3 | Ashita.Chat.Selection = T{
4 | Title = "Chat Mode",
5 | Width = 150,
6 | }
7 |
8 | Ashita.Chat.Modes = {
9 | [1] = {Name = "Party", Prefix = "/p"},
10 | [2] = {Name = "Linkshell 1", Prefix = "/l"},
11 | [3] = {Name = "Linkshell 2", Prefix = "/l2"},
12 | [4] = {Name = "Say", Prefix = "/s"},
13 | }
14 |
15 | -- ------------------------------------------------------------------------------------------------------
16 | -- Adds a message in game chat. Doesn't actually send anything to other people.
17 | -- ------------------------------------------------------------------------------------------------------
18 | ---@param message string
19 | -- ------------------------------------------------------------------------------------------------------
20 | Ashita.Chat.Message = function(message)
21 | print("METRICS: " .. message)
22 | end
23 |
24 | -- ------------------------------------------------------------------------------------------------------
25 | -- Adds a message in game chat. This is meant to be viewed by other people.
26 | -- ------------------------------------------------------------------------------------------------------
27 | ---@param message string
28 | -- ------------------------------------------------------------------------------------------------------
29 | Ashita.Chat.Add_To_Chat = function(type, message)
30 | AshitaCore:GetChatManager():QueueCommand(1, tostring(type) .. " " .. tostring(message))
31 | end
--------------------------------------------------------------------------------
/ashita/item.lua:
--------------------------------------------------------------------------------
1 | Ashita.Item = T{}
2 |
3 | -- ------------------------------------------------------------------------------------------------------
4 | -- Checks a piece of gear's level.
5 | -- ------------------------------------------------------------------------------------------------------
6 | ---@param item_name string
7 | ---@return number
8 | -- ------------------------------------------------------------------------------------------------------
9 | Ashita.Item.Get_Item_Level = function(item_name)
10 | local item = AshitaCore:GetResourceManager():GetItemByName(item_name, 0)
11 | local item_level = item.Level
12 | if not item_level then return 0 end
13 | return item_level
14 | end
--------------------------------------------------------------------------------
/ashita/menu.lua:
--------------------------------------------------------------------------------
1 | Ashita.Menu = T{}
2 |
3 | Ashita.Menu.Module = "FFXiMain.dll"
4 | Ashita.Menu.Pattern = "8B480C85C974??8B510885D274??3B05"
5 |
6 | Ashita.Menu.Types = T{
7 | fulllog = true, -- Expanded chat log
8 | equip = true, -- Equipment menu
9 | inventor = true, -- Inventory
10 | mnstorag = true, -- Equip inventory selection
11 | iuse = true, -- Use item
12 | map0 = true, -- Regular map
13 | maplist = true, -- Selecting a map from within the regular map
14 | mapframe = true, -- Temporary map state while transitioning between maps
15 | scanlist = true, -- Widescan
16 | cnqframe = true, -- Conquest, Beseiged, Campaign, etc. map
17 | conf2win = true, -- Gameplay
18 | cfilter = true, -- Chat Filters
19 | textcol1 = true, -- Font Colors -> Chat, For Self, For Others, System
20 | confyn = true, -- Font Colors -> Default
21 | conf5m = true, -- Windows
22 | conf5win = true, -- Windows -> Shared
23 | conf5w1 = true, -- Windows -> Window 1
24 | conf5w2 = true, -- Windows -> Window 2
25 | conf11m = true, -- Log
26 | conf11l = true, -- Log -> Window 1/2
27 | conf11s = true, -- Log -> Window 1/2 -> Chat, For Self, For Others, System
28 | conf3win = true, -- Misc
29 | conf6win = true, -- Misc 2
30 | conf12wi = true, -- Misc 3
31 | conf13wi = true, -- Misc 4
32 | fxfilter = true, -- Effects
33 | conf7 = true, -- Mouse/Cam
34 | conf4 = true, -- Global
35 | link5 = true, -- Linkshell
36 | link12 = true, -- Linkshell list
37 | link13 = true, -- Linkshell -> Unequiped linkshell
38 | link3 = true, -- Linkshell -> Equipped linkshell
39 | scresult = true, -- Search results
40 | evitem = true, -- Curencies
41 | statcom2 = true, -- Combat skills
42 | auc1 = true, -- AH Bid/Sell
43 | moneyctr = true, -- AH Window
44 | shopsell = true, -- Sell prompt
45 | comyn = true, -- AH confirm sell
46 | auclist = true, -- AH Sales Status
47 | auchisto = true, -- AH History
48 | auc4 = true, -- AH Stop Sale
49 | post1 = true, -- Delivery Box
50 | post2 = true, -- Delivery Box Confirm
51 | stringdl = true, -- Delivery Box Send Recipient
52 | delivery = true, -- Delivery Box Sending
53 | mcr1edlo = true, -- Macro editing row 1
54 | mcr2edlo = true, -- Macro editing row 2
55 | mcrbedit = true, -- Hitting + to edit macros
56 | mcresed = true, -- Equipset editing
57 | bank = true, -- Mog Satchel
58 | handover = true, -- Trade Menu
59 | itmsortw = true, -- Item Sort Menu
60 | sortyn = true, -- Item Sort Yes/No
61 | itemctrl = true, -- Choosing the number of items to select for transfer in inventory
62 | loot = true, -- Treasure Pool
63 | lootope = true, -- Cast Lot
64 | meritcat = true, -- Merit Categories
65 | merit1 = true, -- Merit Categories/Mode Switch
66 | merit2 = true, -- Merit EXP/Limit Points
67 | merit3 = true, -- Merit Raise/Lower
68 | merityn = true, -- Yes/No on the merit upgrades
69 | shop = true, -- Setting bazaar prices
70 | automato = true, -- Automaton equipment menu
71 | bluinven = true, -- Automaton equipment selection
72 | bluequip = true, -- BLU magic spell equip menu
73 | quest00 = true, -- Quest menu
74 | quest01 = true, -- Quest selection menu
75 | miss00 = true, -- Mission submenu
76 | faqsub = true, -- Help Desk
77 | cmbhlst = true, -- Synthesis History
78 | }
79 |
80 | -- ------------------------------------------------------------------------------------------------------
81 | -- Gets the name of the upper most menu.
82 | -- Copied from PetMe which got it from XITools.
83 | -- https://github.com/mousseng/xitools
84 | -- https://github.com/m4thmatic/PetMe
85 | -- ------------------------------------------------------------------------------------------------------
86 | ---@return string, integer
87 | -- ------------------------------------------------------------------------------------------------------
88 | function Ashita.Menu.Get_Menu_Name()
89 | local menu = ashita.memory.find(Ashita.Menu.Module, 0, Ashita.Menu.Pattern, 16, 0)
90 | local pointer = ashita.memory.read_uint32(menu)
91 | local pointer_value = ashita.memory.read_uint32(pointer)
92 | if pointer_value == 0 then return "", 0 end
93 | local menu_header = ashita.memory.read_uint32(pointer_value + 4)
94 | local menu_name = ashita.memory.read_string(menu_header + 0x46, 16)
95 | return string.gsub(menu_name, "\x00", "")
96 | end
97 |
98 | -- ------------------------------------------------------------------------------------------------------
99 | -- Checks whether a menu is up that we should hide Metrics for.
100 | -- ------------------------------------------------------------------------------------------------------
101 | ---@return boolean
102 | -- ------------------------------------------------------------------------------------------------------
103 | function Ashita.Menu.Hide()
104 | local menu_name = Ashita.Menu.Get_Menu_Name()
105 | if not menu_name then return true end
106 |
107 | -- Get rid of prefix junk and clip off trailing spaces.
108 | menu_name = string.sub(menu_name, 9)
109 | menu_name = string.gsub(menu_name, " ", "")
110 |
111 | return Ashita.Menu.Types[menu_name]
112 | end
--------------------------------------------------------------------------------
/ashita/spell.lua:
--------------------------------------------------------------------------------
1 | Ashita.Spell = T{}
2 |
3 | -- ------------------------------------------------------------------------------------------------------
4 | -- Get spell data.
5 | -- https://wiki.ashitaxi.com/doku.php?id=addons:adk:iresourcemanager
6 | -- ------------------------------------------------------------------------------------------------------
7 | ---@param id number spell ID.
8 | ---@return table
9 | -- ------------------------------------------------------------------------------------------------------
10 | Ashita.Spell.Get_By_ID = function(id)
11 | return AshitaCore:GetResourceManager():GetSpellById(id)
12 | end
13 |
14 | -- ------------------------------------------------------------------------------------------------------
15 | -- Get the name of a spell.
16 | -- If we already have the spell data then we don't need to get it again.
17 | -- ------------------------------------------------------------------------------------------------------
18 | ---@param id number spell ID.
19 | ---@param data? table spell table if we already have it.
20 | ---@return string
21 | -- ------------------------------------------------------------------------------------------------------
22 | Ashita.Spell.Name = function(id, data)
23 | local spell = data
24 | if not spell then
25 | spell = Ashita.Spell.Get_By_ID(id)
26 | end
27 | if not spell then return "Error" end
28 | return spell.Name[1]
29 | end
30 |
31 | -- ------------------------------------------------------------------------------------------------------
32 | -- Get the MP cost of a spell.
33 | -- If we already have the spell data then we don't need to get it again.
34 | -- ------------------------------------------------------------------------------------------------------
35 | ---@param id number spell ID.
36 | ---@param data? table spell table if we already have it.
37 | ---@return number
38 | -- ------------------------------------------------------------------------------------------------------
39 | Ashita.Spell.MP = function(id, data)
40 | local spell = data
41 | if not spell then
42 | spell = Ashita.Spell.Get_By_ID(id)
43 | end
44 | if not spell then return 0 end
45 | return spell.ManaCost
46 | end
--------------------------------------------------------------------------------
/ashita/weaponskill.lua:
--------------------------------------------------------------------------------
1 | Ashita.WS = T{}
2 |
3 | -- ------------------------------------------------------------------------------------------------------
4 | -- Gets properties for a WS.
5 | -- The resource file used to do this is from Windower.
6 | -- Some things are treated as weaponskills, but aren't actually. Those can be missing from the WS file.
7 | -- For those I keep track of them in Missing_WS define in the lists.lua
8 | -- ------------------------------------------------------------------------------------------------------
9 | ---@param id number weaponskill ID.
10 | ---@return table
11 | -- ------------------------------------------------------------------------------------------------------
12 | Ashita.WS.Get_By_ID = function(id)
13 | local ws = Res.WS.Get_Full_List(id)
14 | if not ws then ws = Res.WS.Get_Missing(id) end
15 | return ws
16 | end
--------------------------------------------------------------------------------
/columns/!column.lua:
--------------------------------------------------------------------------------
1 | Column = T{}
2 |
3 | Column.Flags = T{
4 | None = bit.bor(ImGuiTableColumnFlags_None),
5 | Expandable = bit.bor(ImGuiTableColumnFlags_WidthStretch),
6 | }
7 |
8 | Column.Widths = T{
9 | Name = 150,
10 | Parse = 60,
11 | Percent = 60,
12 | Single = 40,
13 | Standard = 75,
14 | Settings = 175,
15 | Report = 110,
16 | Catalog = 65,
17 | }
18 |
19 | Column.Mode = DB.Enum.Mode
20 | Column.Trackable = DB.Enum.Trackable
21 | Column.Metric = DB.Enum.Metric
22 |
23 | -- Load dependencies
24 | require("columns.string")
25 | require("columns.damage")
26 | require("columns.attack_speed")
27 | require("columns.defense")
28 | require("columns.healing")
29 | require("columns.accuracy")
30 | require("columns.proc")
31 | require("columns.spell")
32 | require("columns.catalog")
33 | require("columns.util")
34 | require("columns.general")
--------------------------------------------------------------------------------
/columns/accuracy.lua:
--------------------------------------------------------------------------------
1 | Column.Acc = T{}
2 |
3 | ------------------------------------------------------------------------------------------------------
4 | -- Grabs an entities accuracy for a specific trackable.
5 | -- Accuracy can be broken up into type--like melee and ranged--or melee and ranged combined.
6 | ------------------------------------------------------------------------------------------------------
7 | ---@param player_name string
8 | ---@param acc_type string a trackable from the model.
9 | ---@param justify? boolean whether or not to right justify the text
10 | ---@param count_type? string used for getting ranged square and truestrike rates.
11 | ---@param raw? boolean true: just output the raw value; false: output a column to a table.
12 | ---@return string
13 | ------------------------------------------------------------------------------------------------------
14 | Column.Acc.By_Type = function(player_name, acc_type, justify, count_type, raw)
15 | local hits, attempts
16 | if not count_type then count_type = Column.Metric.HIT_COUNT end
17 | if acc_type == DB.Enum.Values.COMBINED then
18 | local melee_hits = DB.Data.Get(player_name, Column.Trackable.MELEE, Column.Metric.HIT_COUNT)
19 | local melee_attempts = DB.Data.Get(player_name, Column.Trackable.MELEE, Column.Metric.COUNT)
20 | local ranged_hits = DB.Data.Get(player_name, Column.Trackable.RANGED, Column.Metric.HIT_COUNT)
21 | local ranged_attempts = DB.Data.Get(player_name, Column.Trackable.RANGED, Column.Metric.COUNT)
22 | hits = melee_hits + ranged_hits
23 | attempts = melee_attempts + ranged_attempts
24 | else
25 | hits = DB.Data.Get(player_name, acc_type, count_type)
26 | attempts = DB.Data.Get(player_name, acc_type, Column.Metric.COUNT)
27 | end
28 |
29 | local color = Res.Colors.Basic.WHITE
30 | local percent = Column.String.Raw_Percent(hits, attempts)
31 | if percent == 0 then
32 | color = Res.Colors.Basic.DIM
33 | elseif percent <= DB.Settings.Accuracy_Warning then
34 | color = Res.Colors.Basic.RED
35 | end
36 |
37 | if raw then return Column.String.Format_Percent(hits, attempts) end
38 | return UI.TextColored(color, Column.String.Format_Percent(hits, attempts, justify))
39 | end
40 |
41 | ------------------------------------------------------------------------------------------------------
42 | -- Grabs the accuracy of a certain trackable that the entity's pet has done.
43 | ------------------------------------------------------------------------------------------------------
44 | ---@param player_name string the entity that owns the pet.
45 | ---@param pet_name string the pet that we want the damage for.
46 | ---@param acc_type string a trackable from the model.
47 | ---@param justify? boolean whether or not to right justify the text
48 | ---@param count_type? string used for getting ranged square and truestrike rates.
49 | ---@return string
50 | ------------------------------------------------------------------------------------------------------
51 | Column.Acc.Pet_By_Type = function(player_name, pet_name, acc_type, justify, count_type)
52 | if not count_type then count_type = Column.Metric.HIT_COUNT end
53 | local hits = DB.Pet_Data.Get(player_name, pet_name, acc_type, count_type)
54 | local attempts = DB.Pet_Data.Get(player_name, pet_name, acc_type, Column.Metric.COUNT)
55 |
56 | local color = Res.Colors.Basic.WHITE
57 | local percent = Column.String.Raw_Percent(hits, attempts)
58 | if percent == 0 then
59 | color = Res.Colors.Basic.DIM
60 | elseif percent <= DB.Settings.Accuracy_Warning then
61 | color = Res.Colors.Basic.RED
62 | end
63 |
64 | return UI.TextColored(color, Column.String.Format_Percent(hits, attempts, justify))
65 | end
66 |
67 |
68 | ------------------------------------------------------------------------------------------------------
69 | -- Grabs an entity's accuracy for last {X} amount of attempts. Includes melee and ranged combined.
70 | -- {X} is defined in the model's settings.
71 | ------------------------------------------------------------------------------------------------------
72 | ---@param player_name string
73 | ---@param justify? boolean
74 | ---@return string
75 | ------------------------------------------------------------------------------------------------------
76 | Column.Acc.Running = function(player_name, justify)
77 | local accuracy = DB.Accuracy.Get(player_name)
78 | local color = Res.Colors.Basic.WHITE
79 | local percent = Column.String.Raw_Percent(accuracy[1], accuracy[2])
80 |
81 | if percent == 0 then
82 | color = Res.Colors.Basic.DIM
83 | elseif percent <= DB.Settings.Accuracy_Warning then
84 | color = Res.Colors.Basic.RED
85 | end
86 |
87 | return UI.TextColored(color, Column.String.Format_Percent(accuracy[1], accuracy[2], justify))
88 | end
--------------------------------------------------------------------------------
/columns/attack_speed.lua:
--------------------------------------------------------------------------------
1 | Column.Attack_Speed = T{}
2 |
3 | ------------------------------------------------------------------------------------------------------
4 | -- Gets a player's attack speed.
5 | ------------------------------------------------------------------------------------------------------
6 | ---@param player_name string
7 | ---@param justify? boolean whether or not to right justify the text
8 | ---@param raw? boolean true: just output the raw value; false: output a column to a table.
9 | ---@return string
10 | ------------------------------------------------------------------------------------------------------
11 | Column.Attack_Speed.Get = function(player_name, justify, raw)
12 | local speed = DB.Attack_Speed.Get(player_name)
13 |
14 | local color = Res.Colors.Basic.WHITE
15 | if speed == 0 then color = Res.Colors.Basic.DIM end
16 |
17 | if raw then return Column.String.Format_Decimal(speed, justify) end
18 | return UI.TextColored(color, Column.String.Format_Decimal(speed, justify))
19 | end
--------------------------------------------------------------------------------
/columns/defense.lua:
--------------------------------------------------------------------------------
1 | Column.Defense = T{}
2 |
3 | ------------------------------------------------------------------------------------------------------
4 | -- Grabs the damage of a certain trackable that the entity has taken.
5 | ------------------------------------------------------------------------------------------------------
6 | ---@param player_name string
7 | ---@param damage_type string a trackable from the model.
8 | ---@param percent? boolean whether or not the damage should be raw or percent.
9 | ---@param justify? boolean whether or not to right justify the text
10 | ---@param raw? boolean true: just output the raw value; false: output a column to a table.
11 | ---@return string
12 | ------------------------------------------------------------------------------------------------------
13 | Column.Defense.Damage_Taken_By_Type = function(player_name, damage_type, percent, justify, raw)
14 | local total = DB.Data.Get(player_name, damage_type, Column.Metric.TOTAL)
15 | local color = Column.String.Color_Zero(total)
16 | if percent then
17 | local total_damage = DB.Data.Get(player_name, Column.Trackable.DAMAGE_TAKEN_TOTAL, Column.Metric.TOTAL)
18 | if raw then return Column.String.Format_Percent(total, total_damage) end
19 | return UI.TextColored(color, Column.String.Format_Percent(total, total_damage, justify))
20 | end
21 | if raw then return Column.String.Format_Number(total) end
22 | return UI.TextColored(color, Column.String.Format_Number(total, justify))
23 | end
24 |
25 | ------------------------------------------------------------------------------------------------------
26 | -- Grabs the proc rate of certain defensive actions.
27 | ------------------------------------------------------------------------------------------------------
28 | ---@param player_name string
29 | ---@param damage_type string a trackable from the model.
30 | ---@param justify? boolean whether or not to right justify the text
31 | ---@param raw? boolean true: just output the raw value; false: output a column to a table.
32 | ---@return string
33 | ------------------------------------------------------------------------------------------------------
34 | Column.Defense.Proc_Rate_By_Type = function(player_name, damage_type, justify, raw)
35 | local proc_count = DB.Data.Get(player_name, damage_type, Column.Metric.HIT_COUNT)
36 | local color = Column.String.Color_Zero(proc_count)
37 | local attack_count = DB.Data.Get(player_name, damage_type, Column.Metric.COUNT)
38 | if raw then return Column.String.Format_Percent(proc_count, attack_count) end
39 | return UI.TextColored(color, Column.String.Format_Percent(proc_count, attack_count, justify))
40 | end
41 |
42 | ------------------------------------------------------------------------------------------------------
43 | -- Approximates how much damage has been potentially mitigated by the given mitigation type.
44 | ------------------------------------------------------------------------------------------------------
45 | ---@param player_name string
46 | ---@param mitigation_type string a trackable from the model.
47 | ---@param justify? boolean whether or not to right justify the text
48 | ---@return string
49 | ------------------------------------------------------------------------------------------------------
50 | Column.Defense.Damage_Mitigation = function(player_name, mitigation_type, justify)
51 | local mitigation_proc = DB.Data.Get(player_name, mitigation_type, Column.Metric.HIT_COUNT)
52 | local color = Column.String.Color_Zero(mitigation_proc)
53 | if mitigation_proc == 0 then return UI.TextColored(color, Column.String.Format_Number(mitigation_proc)) end
54 |
55 | local average_melee = Column.Defense.Average_Damage_By_Type(player_name, Column.Trackable.DEF_UNMITIGATED, false, true)
56 | color = Column.String.Color_Zero(average_melee)
57 | if average_melee == 0 then return UI.TextColored(color, "...") end
58 |
59 | local average_reduced_damage = Column.Defense.Average_Damage_By_Type(player_name, mitigation_type, false, true)
60 | if mitigation_type == DB.Enum.Trackable.DEF_COUNTER then average_reduced_damage = 0 end -- Counter reduces damage 100%, but stores counter damage done.
61 | local damage_mitigated = mitigation_proc * (average_melee - average_reduced_damage)
62 | if damage_mitigated < 0 then damage_mitigated = 0 end
63 | color = Column.String.Color_Zero(damage_mitigated)
64 | return UI.TextColored(color, Column.String.Format_Number(damage_mitigated, justify))
65 | end
66 |
67 | ------------------------------------------------------------------------------------------------------
68 | -- Gets the average amount of damage taken per damage type.
69 | ------------------------------------------------------------------------------------------------------
70 | ---@param player_name string
71 | ---@param damage_type string a trackable from the model.
72 | ---@param justify? boolean whether or not to right justify the text
73 | ---@param raw? boolean true: just output the raw value; false: output a column to a table.
74 | ---@return integer
75 | ------------------------------------------------------------------------------------------------------
76 | Column.Defense.Average_Damage_By_Type = function(player_name, damage_type, justify, raw)
77 | local count = DB.Data.Get(player_name, damage_type, Column.Metric.HIT_COUNT)
78 | local color = Column.String.Color_Zero(count)
79 | if count == 0 then
80 | if raw then return 0 end
81 | return UI.TextColored(color, "...", justify)
82 | end
83 |
84 | local damage = DB.Data.Get(player_name, damage_type, Column.Metric.TOTAL)
85 | color = Column.String.Color_Zero(damage)
86 | local average_damage = math.floor(damage / count)
87 | if raw then return average_damage end
88 | return UI.TextColored(color, Column.String.Format_Percent(damage, count, justify, true))
89 | end
90 |
91 | ------------------------------------------------------------------------------------------------------
92 | -- Calculates how what the DT% is for a given mitigation type.
93 | ------------------------------------------------------------------------------------------------------
94 | ---@param player_name string
95 | ---@param mitigation_type string a trackable from the model.
96 | ---@param justify? boolean whether or not to right justify the text
97 | ---@return string
98 | ------------------------------------------------------------------------------------------------------
99 | Column.Defense.Damage_Reduction = function(player_name, mitigation_type, justify)
100 | local average_melee = Column.Defense.Average_Damage_By_Type(player_name, Column.Trackable.DEF_UNMITIGATED, false, true)
101 | local color = Column.String.Color_Zero(average_melee)
102 | if average_melee == 0 then return UI.TextColored(color, "...") end
103 |
104 | local average_reduced_damage = Column.Defense.Average_Damage_By_Type(player_name, mitigation_type, false, true)
105 | color = Column.String.Color_Zero(average_reduced_damage)
106 |
107 | return UI.TextColored(color, Column.String.Format_Percent(average_melee - average_reduced_damage, average_melee, justify))
108 | end
--------------------------------------------------------------------------------
/columns/general.lua:
--------------------------------------------------------------------------------
1 | Column.General = T{}
2 |
3 | ------------------------------------------------------------------------------------------------------
4 | -- Takes one metric and divides it by another metric.
5 | ------------------------------------------------------------------------------------------------------
6 | ---@param player_name string
7 | ---@param trackable string a trackable from the model.
8 | ---@param metric_numerator string a metric from the model.
9 | ---@param metric_denominator string metric from the model to be used as a denominator in a percent calculation.
10 | ---@param justify? boolean whether or not to right justify the text
11 | ---@param raw? boolean true: just output the raw value; false: output a column to a table.
12 | ---@param no_scaling? boolean do not scale the fraction by 100.
13 | ---@return string
14 | ------------------------------------------------------------------------------------------------------
15 | Column.General.Fraction = function(player_name, trackable, metric_numerator, metric_denominator, justify, raw, no_scaling)
16 | local numerator = DB.Data.Get(player_name, trackable, metric_numerator)
17 | local color = Column.String.Color_Zero(numerator)
18 | local denominator = DB.Data.Get(player_name, trackable, metric_denominator)
19 | if not denominator or denominator <= 0 then return UI.TextColored(color, Column.String.Format_Percent(0, 0, justify)) end
20 | if raw then return Column.String.Format_Percent(numerator, denominator) end
21 | return UI.TextColored(color, Column.String.Format_Percent(numerator, denominator, justify, no_scaling))
22 | end
23 |
24 | ------------------------------------------------------------------------------------------------------
25 | -- Takes the total metric from a trackable and divides by how much of the trackable the party has done.
26 | ------------------------------------------------------------------------------------------------------
27 | ---@param player_name string
28 | ---@param trackable string a trackable from the model.
29 | ---@param justify? boolean whether or not to right justify the text
30 | ---@param raw? boolean true: just output the raw value; false: output a column to a table.
31 | ---@return string
32 | ------------------------------------------------------------------------------------------------------
33 | Column.General.Percent_Party_Total = function(player_name, trackable, justify, raw)
34 | local player_total = DB.Data.Get(player_name, trackable, Column.Metric.TOTAL)
35 | local color = Column.String.Color_Zero(player_total)
36 | local party_total = 0
37 | for name, _ in pairs(DB.Tracking.Initialized_Players) do
38 | party_total = party_total + DB.Data.Get(name, trackable, Column.Metric.TOTAL)
39 | end
40 | if raw then return Column.String.Format_Percent(player_total, party_total) end
41 | return UI.TextColored(color, Column.String.Format_Percent(player_total, party_total, justify))
42 | end
43 |
44 | ------------------------------------------------------------------------------------------------------
45 | -- This is for cataloged actions.
46 | -- Grabs the total amount of damage a cataloged action has done for a given trackable and metric.
47 | ------------------------------------------------------------------------------------------------------
48 | ---@param player_name string
49 | ---@param action_name string
50 | ---@param trackable string a trackable from the model.
51 | ---@param raw? boolean true: just output the raw value; false: output a column to a table.
52 | ---@return string
53 | ------------------------------------------------------------------------------------------------------
54 | Column.General.Percent_Party_Total_Action = function(player_name, action_name, trackable, raw)
55 | local action_total = DB.Catalog.Get(player_name, trackable, action_name, Column.Metric.TOTAL)
56 | local color = Column.String.Color_Zero(action_total)
57 | local party_total = 0
58 | for name, _ in pairs(DB.Tracking.Initialized_Players) do
59 | party_total = party_total + DB.Data.Get(name, trackable, Column.Metric.TOTAL)
60 | end
61 | if raw then return Column.String.Format_Percent(action_total, party_total) end
62 | return UI.TextColored(color, Column.String.Format_Percent(action_total, party_total))
63 | end
64 |
65 | ------------------------------------------------------------------------------------------------------
66 | -- Takes the total metric from a pet specific trackable and divides by how much of the trackable the party has done.
67 | ------------------------------------------------------------------------------------------------------
68 | ---@param player_name string
69 | ---@param pet_name string
70 | ---@param trackable string a trackable from the model.
71 | ---@param justify? boolean whether or not to right justify the text
72 | ---@param raw? boolean true: just output the raw value; false: output a column to a table.
73 | ---@return string
74 | ------------------------------------------------------------------------------------------------------
75 | Column.General.Percent_Party_Total_Pet = function(player_name, pet_name, trackable, justify, raw)
76 | local pet_total = DB.Pet_Data.Get(player_name, pet_name, trackable, Column.Metric.TOTAL)
77 | local color = Column.String.Color_Zero(pet_total)
78 | local party_total = 0
79 | for name, _ in pairs(DB.Tracking.Initialized_Players) do
80 | party_total = party_total + DB.Data.Get(name, trackable, Column.Metric.TOTAL)
81 | end
82 | if raw then return Column.String.Format_Percent(pet_total, party_total) end
83 | return UI.TextColored(color, Column.String.Format_Percent(pet_total, party_total, justify))
84 | end
85 |
--------------------------------------------------------------------------------
/columns/healing.lua:
--------------------------------------------------------------------------------
1 | Column.Healing = T{}
2 |
3 | ------------------------------------------------------------------------------------------------------
4 | -- Grabs the damage of a certain trackable that the entity has done.
5 | ------------------------------------------------------------------------------------------------------
6 | ---@param player_name string
7 | ---@param percent? boolean whether or not the damage should be raw or percent.
8 | ---@param justify? boolean whether or not to right justify the text
9 | ---@param raw? boolean true: just output the raw value; false: output a column to a table.
10 | ---@return string
11 | ------------------------------------------------------------------------------------------------------
12 | Column.Healing.Total = function(player_name, percent, justify, raw)
13 | local spell_healing = DB.Data.Get(player_name, DB.Enum.Trackable.HEALING, Column.Metric.TOTAL)
14 | local ability_healing = DB.Data.Get(player_name, DB.Enum.Trackable.ABILITY_HEALING, Column.Metric.TOTAL)
15 | local total_healing = spell_healing + ability_healing
16 | local color = Column.String.Color_Zero(total_healing)
17 | if percent then
18 | local total_damage = Column.Damage.Raw_Total_Player_Damage(player_name)
19 | if raw then return Column.String.Format_Percent(total_healing, total_damage) end
20 | return UI.TextColored(color, Column.String.Format_Percent(total_healing, total_damage, justify))
21 | end
22 | if raw then return Column.String.Format_Number(total_healing) end
23 | return UI.TextColored(color, Column.String.Format_Number(total_healing, justify))
24 | end
25 |
26 | ------------------------------------------------------------------------------------------------------
27 | -- Grabs the overcure amount for the player.
28 | ------------------------------------------------------------------------------------------------------
29 | ---@param player_name string
30 | ---@param justify? boolean whether or not to right justify the text
31 | ---@return string
32 | ------------------------------------------------------------------------------------------------------
33 | Column.Healing.Overcure = function(player_name, justify)
34 | local overcure = DB.Data.Get(player_name, Column.Trackable.HEALING, Column.Metric.OVERCURE)
35 | local color = Column.String.Color_Zero(overcure)
36 | return UI.TextColored(color, Column.String.Format_Number(overcure, justify))
37 | end
--------------------------------------------------------------------------------
/columns/spell.lua:
--------------------------------------------------------------------------------
1 | Column.Spell = T{}
2 |
3 | ------------------------------------------------------------------------------------------------------
4 | -- Shows MP a player has used.
5 | ------------------------------------------------------------------------------------------------------
6 | ---@param player_name string
7 | ---@param magic_type string
8 | ---@param justify? boolean whether or not to right justify the text
9 | ---@return string
10 | ------------------------------------------------------------------------------------------------------
11 | Column.Spell.MP = function(player_name, magic_type, justify)
12 | if not magic_type then magic_type = Column.Trackable.MAGIC end
13 | local mp = 0
14 | if magic_type == "Other" then
15 | local total = DB.Data.Get(player_name, Column.Trackable.MAGIC, Column.Metric.MP_SPENT)
16 | local healing = DB.Data.Get(player_name, Column.Trackable.HEALING, Column.Metric.MP_SPENT)
17 | local nuke = DB.Data.Get(player_name, Column.Trackable.NUKE, Column.Metric.MP_SPENT)
18 | local enfeeble = DB.Data.Get(player_name, Column.Trackable.ENFEEBLE, Column.Metric.MP_SPENT)
19 | local enspell = DB.Data.Get(player_name, Column.Trackable.ENSPELL, Column.Metric.MP_SPENT)
20 | local mp_drain = DB.Data.Get(player_name, Column.Trackable.MP_DRAIN, Column.Metric.MP_SPENT)
21 | mp = total - healing - nuke - enfeeble - enspell - mp_drain
22 | else
23 | mp = DB.Data.Get(player_name, magic_type, Column.Metric.MP_SPENT)
24 | end
25 | local color = Column.String.Color_Zero(mp)
26 | return UI.TextColored(color, Column.String.Format_Number(mp, justify))
27 | end
28 |
29 | ------------------------------------------------------------------------------------------------------
30 | -- Shows many much MP is used per damage or healing done.
31 | ------------------------------------------------------------------------------------------------------
32 | ---@param player_name string
33 | ---@param magic_type string
34 | ---@return string
35 | ------------------------------------------------------------------------------------------------------
36 | Column.Spell.Unit_Per_MP = function(player_name, magic_type)
37 | local mp = DB.Data.Get(player_name, magic_type, Column.Metric.MP_SPENT)
38 | local unit = DB.Data.Get(player_name, magic_type, Column.Metric.TOTAL)
39 | local color = Column.String.Color_Zero(unit)
40 | return UI.TextColored(color, Column.String.Format_Percent(unit, mp, false, true))
41 | end
--------------------------------------------------------------------------------
/columns/util.lua:
--------------------------------------------------------------------------------
1 | Column.Util = T{}
2 |
3 | ------------------------------------------------------------------------------------------------------
4 | -- Switches to a player in the player filter based on partial matching.
5 | ------------------------------------------------------------------------------------------------------
6 | ---@param player_name string
7 | ------------------------------------------------------------------------------------------------------
8 | Column.Util.Focus = function(player_name)
9 | if not player_name then return nil end
10 | local focus_check = player_name
11 | player_name = string.lower(player_name)
12 | UI.PushID(player_name)
13 | if UI.SmallButton(" F ") then
14 | -- Default to the Overview tab when jumping from this column.
15 | Focus.Tabs.Switch[Focus.Tabs.Names.OVERVIEW] = ImGuiTabItemFlags_SetSelected
16 |
17 | -- If in multi-window mode toggle open and closing if the focus is already the given player.
18 | -- Always jump to Focus if in non-Window mode.
19 | if focus_check ~= DB.Widgets.Util.Get_Player_Focus() or not Metrics.Window.Multi_Window then
20 | DB.Widgets.Util.Player_Switch(player_name)
21 | Window_Manager.Switch_Module(Focus.Name)
22 | Focus.Window.Show()
23 | else
24 | Focus.Window.Toggle_Visibility()
25 | end
26 | end
27 | UI.PopID()
28 | end
--------------------------------------------------------------------------------
/commands.lua:
--------------------------------------------------------------------------------
1 | ------------------------------------------------------------------------------------------------------
2 | -- Subscribe to addon commands.
3 | -- Influenced by HXUI: https://github.com/tirem/HXUI
4 | ------------------------------------------------------------------------------------------------------
5 | ashita.events.register('command', 'command_cb', function (e)
6 | local command_args = e.command:lower():args()
7 | ---@diagnostic disable-next-line: undefined-field
8 | if table.contains({"/metrics"}, command_args[1]) or table.contains({"/met"}, command_args[1]) then
9 | local arg = command_args[2]
10 | local sub_command = command_args[3]
11 |
12 | -- Help Text
13 | if not arg then
14 | if Config.Settings_Mode ~= Config.Enum.File.CONFIG and Config.Window.Is_Visible() then
15 | Config.Settings_Mode = Config.Enum.File.CONFIG
16 | elseif Config.Settings_Mode ~= Config.Enum.File.CONFIG and not Config.Window.Is_Visible() then
17 | Config.Settings_Mode = Config.Enum.File.CONFIG
18 | Config.Window.Show()
19 | elseif Config.Settings_Mode == Config.Enum.File.CONFIG then
20 | Config.Window.Toggle_Visibility()
21 | end
22 |
23 | -- General Settings
24 | elseif arg == "show" or arg == "s" then
25 | Window_Manager.Toggle_Mask()
26 | elseif arg == "hub" then
27 | Hub.Window.Toggle_Visibility()
28 | elseif arg == "debug" then
29 | Debug.Toggle()
30 | elseif arg == "nano" or arg == "n" then
31 | Parse.Nano.Toggle()
32 | elseif arg == "mini" or arg == "m" then
33 | Parse.Mini.Toggle()
34 | elseif arg == "reset" or arg == "r" then
35 | DB.Initialize(true)
36 | elseif arg == "full" or arg == "f" then
37 | Parse.Full.Enable()
38 | elseif (arg == "pet" or arg == "p") then
39 | Parse.Config.Toggle_Pet()
40 | elseif arg == "clock" or arg == "c" then
41 | Parse.Config.Toggle_Clock()
42 | elseif arg == "percent" then
43 | Focus.Config.Percent_Toggle()
44 | elseif arg == "dps" then
45 | Metrics.Parse.DPS = not Metrics.Parse.DPS
46 | Parse.Util.Calculate_Column_Flags()
47 | elseif arg == "speed" then
48 | Metrics.Parse.Attack_Speed = not Metrics.Parse.Attack_Speed
49 | Parse.Util.Calculate_Column_Flags()
50 | elseif arg == "throttle" then
51 | Throttle.Toggle()
52 | elseif arg == "lurk" then
53 | Metrics.Parse.Lurk_Mode = not Metrics.Parse.Lurk_Mode
54 | elseif arg == "mouse" then
55 | Window_Manager.Toggle_Mouse()
56 |
57 | -- XP
58 | elseif arg == "xp" and sub_command then
59 | if sub_command == "mini" then
60 | Metrics.XP.XP_Mini = not Metrics.XP.XP_Mini
61 | end
62 |
63 | -- General reports.
64 | elseif arg == "report" or arg == "rep" then
65 | local report_type = command_args[3]
66 | if report_type == "total" then
67 | Report.Publishing.Total_Damage()
68 | elseif report_type == "acc" then
69 | Report.Publishing.Accuracy()
70 | elseif report_type == "melee" then
71 | Report.Publishing.Damage_By_Type(DB.Enum.Trackable.MELEE)
72 | elseif report_type == "ws" then
73 | Report.Publishing.Damage_By_Type(DB.Enum.Trackable.WS)
74 | elseif report_type == "healing" then
75 | Report.Publishing.Damage_By_Type(DB.Enum.Trackable.HEALING)
76 | end
77 |
78 | -- Primary module switching.
79 | elseif arg == "team" or arg == "parse" then Parse.Window.Make_Active()
80 | elseif arg == "focus" then Focus.Window.Make_Active()
81 | elseif arg == "log" or arg == "bl" then Blog.Window.Make_Active()
82 | elseif arg == "xp" then XP.Window.Make_Active()
83 | elseif arg == "report" or arg == "rep" then Report.Window.Make_Active()
84 |
85 | -- Player selection
86 | elseif arg == "player" or arg == "pl" then
87 | local player_string = command_args[3]
88 | Debug.Error.Add("Metrics Command: " .. tostring(arg) .. " " .. tostring(command_args[3]))
89 | if player_string then
90 | DB.Widgets.Util.Player_Switch(player_string)
91 | end
92 |
93 | -- Focus tab switching.
94 | elseif arg == "melee" then
95 | Focus.Tabs.Switch[Focus.Tabs.Names.MELEE] = ImGuiTabItemFlags_SetSelected
96 | elseif arg == "ranged" then
97 | Focus.Tabs.Switch[Focus.Tabs.Names.RANGED] = ImGuiTabItemFlags_SetSelected
98 | elseif arg == "ws" or arg == "weaponskill" then
99 | Focus.Tabs.Switch[Focus.Tabs.Names.WS] = ImGuiTabItemFlags_SetSelected
100 | elseif arg == "magic" then
101 | Focus.Tabs.Switch[Focus.Tabs.Names.MAGIC] = ImGuiTabItemFlags_SetSelected
102 | elseif arg == "ability" or arg == "abil" then
103 | Focus.Tabs.Switch[Focus.Tabs.Names.ABILITIES] = ImGuiTabItemFlags_SetSelected
104 | elseif (arg == "pet" or arg == "p") and Window_Manager.Tabs.Active == Focus.Name then
105 | Focus.Tabs.Switch[Focus.Tabs.Names.PETS] = ImGuiTabItemFlags_SetSelected
106 | elseif arg == "defense" or arg == "def" then
107 | Focus.Tabs.Switch[Focus.Tabs.Names.DEFENSE] = ImGuiTabItemFlags_SetSelected
108 | end
109 | end
110 | end)
--------------------------------------------------------------------------------
/database/_database.lua:
--------------------------------------------------------------------------------
1 | DB = T{}
2 |
3 | -- Primary Database
4 | DB.Parse = T{} -- [index][trackable][metric]
5 | -- [index][trackable][m.Enum.Node.CATALOG][action_name][metric]
6 | DB.Pet_Parse = T{} -- [index][pet][trackable][metric]
7 | -- [index][pet][trackable][m.Enum.Node.CATALOG][action_name][metric]
8 |
9 | -- Secondary Tracking Tables
10 | DB.Tracking = T{}
11 | DB.Tracking.Trackable = T{} -- [trackable][player_name]
12 | DB.Tracking.Pet_Trackable = T{} -- [trackable][player_name][pet_name]
13 | DB.Tracking.Initialized_Players = T{} -- [player_name]
14 | DB.Tracking.Initialized_Pets = T{} -- [player_name][pet_name]
15 | DB.Tracking.Initialized_Mobs = T{} -- [mob_name]
16 | DB.Tracking.Running_Accuracy = T{} -- [player_name]
17 | DB.Tracking.Running_Attack_Speed = T{} -- [player_name]
18 | DB.Tracking.Running_Damage = T{} -- [player_name]
19 | DB.Tracking.Multi_Attack = T{} -- [player_name][multi-rank]
20 | DB.Tracking.Defeated_Mobs = T{} -- [mob_name]
21 |
22 | -- Used to hold column data for performance improvements.
23 | DB.Cache = T{} -- [player_name][trackable][metric]
24 |
25 | DB.Settings = T{}
26 | DB.Settings.Accuracy_Warning = 0.80
27 |
28 | -- These are used for user saved settings.
29 | DB.Defaults = T{
30 | Running_Accuracy_Limit = 25
31 | }
32 |
33 | require("database._enum")
34 | require("database.accuracy")
35 | require("database.dps")
36 | require("database.attack_speed")
37 | require("database.catalog")
38 | require("database.data")
39 | require("database.lists")
40 | require("database.pet_catalog")
41 | require("database.pet_data")
42 | require("database.widgets")
43 |
44 | ------------------------------------------------------------------------------------------------------
45 | -- Resets the parsing data and clears the battle log.
46 | ------------------------------------------------------------------------------------------------------
47 | ---@param reset? boolean true: manual reset; false: normal initialization
48 | ------------------------------------------------------------------------------------------------------
49 | DB.Initialize = function(reset)
50 | if Metrics.Report.Auto_Save and reset then
51 | File.Save_Data()
52 | File.Save_Catalog()
53 | File.Save_Battlelog()
54 | end
55 |
56 | DB.Parse = T{}
57 | DB.Pet_Parse = T{}
58 |
59 | DB.Tracking.Trackable = T{}
60 | DB.Tracking.Pet_Trackable = T{}
61 | DB.Tracking.Initialized_Players = T{}
62 | DB.Tracking.Initialized_Pets = T{}
63 | DB.Tracking.Initialized_Mobs = T{[DB.Widgets.Dropdown.Enum.NONE] = true}
64 | DB.Tracking.Running_Accuracy = T{}
65 | DB.Tracking.Running_Damage = T{}
66 | DB.Tracking.Multi_Attack = T{}
67 | DB.Tracking.Defeated_Mobs = T{}
68 |
69 | DB.Sorted.Players = T{[1] = DB.Widgets.Dropdown.Enum.NONE}
70 | DB.Sorted.Mobs = T{[1] = DB.Widgets.Dropdown.Enum.NONE}
71 | DB.Sorted.Total_Damage = T{}
72 | DB.Sorted.Catalog_Damage = T{}
73 |
74 | DB.Healing_Max = {}
75 | DB.Widgets.Dropdown.Player.Focus = DB.Widgets.Dropdown.Enum.NONE
76 | DB.Widgets.Dropdown.Player.Index = 1
77 | DB.Widgets.Dropdown.Mob.Focus = DB.Widgets.Dropdown.Enum.NONE
78 | DB.Widgets.Dropdown.Mob.Index = 1
79 | for spell, threshold in pairs(DB.Enum.HEALING) do
80 | DB.Healing_Max[spell] = threshold
81 | end
82 | Blog.Reset_Log()
83 | DB.Attack_Speed.Reset()
84 | Timers.Reset(Timers.Enum.Names.PARSE)
85 | end
86 |
87 | ------------------------------------------------------------------------------------------------------
88 | -- Calculates the total damage from everyone currently on the Parse display.
89 | ------------------------------------------------------------------------------------------------------
90 | ---@return number
91 | ------------------------------------------------------------------------------------------------------
92 | DB.Team_Damage = function()
93 | local total = 0
94 | DB.Lists.Sort.Total_Damage()
95 | for _, data in ipairs(DB.Sorted.Total_Damage) do
96 | local player_name = data[1]
97 | if Parse.Config.Include_SC_Damage() then
98 | total = total + DB.Data.Get(player_name, DB.Enum.Trackable.TOTAL, DB.Enum.Metric.TOTAL)
99 | else
100 | total = total + DB.Data.Get(player_name, DB.Enum.Trackable.TOTAL_NO_SC, DB.Enum.Metric.TOTAL)
101 | end
102 | end
103 | return total
104 | end
105 |
106 | ------------------------------------------------------------------------------------------------------
107 | -- Calculates the total damage by type from everyone currently on the Parse display.
108 | ------------------------------------------------------------------------------------------------------
109 | ---@return number
110 | ------------------------------------------------------------------------------------------------------
111 | DB.Team_Damage_By_Type = function(damage_type)
112 | local total = 0
113 | DB.Lists.Sort.Total_Damage()
114 | for rank, data in ipairs(DB.Sorted.Total_Damage) do
115 | if rank <= Parse.Config.Rank_Cutoff() then
116 | local player_name = data[1]
117 | total = total + DB.Data.Get(player_name, damage_type, DB.Enum.Metric.TOTAL)
118 | end
119 | end
120 | return total
121 | end
122 |
123 | ------------------------------------------------------------------------------------------------------
124 | -- Keeps track of how many mobs have been defeated.
125 | ------------------------------------------------------------------------------------------------------
126 | ---@param mob_name string
127 | ------------------------------------------------------------------------------------------------------
128 | DB.Defeated_Mob = function(mob_name)
129 | if not DB.Tracking.Defeated_Mobs[mob_name] then DB.Tracking.Defeated_Mobs[mob_name] = 0 end
130 | DB.Tracking.Defeated_Mobs[mob_name] = DB.Tracking.Defeated_Mobs[mob_name] + 1
131 | end
--------------------------------------------------------------------------------
/database/_enum.lua:
--------------------------------------------------------------------------------
1 | DB.Enum = T{}
2 |
3 | DB.Enum.Mode = T{
4 | INC = "inc",
5 | SET = "set",
6 | }
7 |
8 | DB.Enum.Trackable = T{
9 | TOTAL = "Total",
10 | TOTAL_NO_SC = "No SC Total",
11 | MELEE = "Melee", -- Melee
12 | MELEE_MAIN = "Melee Mainhand",
13 | MELEE_OFFHAND = "Melee Offhand",
14 | MELEE_KICK = "Melee Kicks",
15 | PET_MELEE = "Pet Melee",
16 | PET_MELEE_DISCRETE = "Pet Melee Discrete",
17 | MELEE_COUNTERED = "Countered",
18 | RANGED = "Ranged", -- Ranged
19 | RANGED_SQUARE = "Ranged Square Hit",
20 | RANGED_TRUE = "Ranged True Strike",
21 | PET_RANGED = "Pet Ranged",
22 | THROWING = "Throwing",
23 | WS = "Weaponskills", -- TP Action
24 | PET_WS = "Pet Weaponskills",
25 | SC = "Skillchains",
26 | ABILITY = "Abilities", -- Ability
27 | ABILITY_DAMAGING = "Damaging Abilities",
28 | ABILITY_HEALING = "Healing Abilities",
29 | ABILITY_MP_RECOVERY = "MP Recovery Abilities",
30 | ABILITY_GENERAL = "General Ability",
31 | MANEUVER = "Maneuver",
32 | PHANTOM_ROLL = "Corsair Roll",
33 | PET = "Pet", -- Pets
34 | PET_ABILITY = "Pet Ability",
35 | PET_HEAL = "Pet Healing",
36 | PET_NUKE = "Pet Nuking",
37 | PET_ENFEEBLING = "Pet Enfeebling",
38 | PET_MP_DRAIN = "Pet MP Drain",
39 | PET_MAGIC = "Pet Magic",
40 | MAGIC = "Spells", -- Magic
41 | ENSPELL = "Enspell",
42 | ENDAMAGE = "Melee Endamage",
43 | ENDAMAGE_R = "Ranged Endamage",
44 | ENDRAIN = "Melee Endrain",
45 | ENDRAIN_R = "Ranged Endrain",
46 | ENASPIR = "Melee Enaspir",
47 | ENASPIR_R = "Ranged Enaspir",
48 | ENDEBUFF = "Melee Debuff",
49 | ENDEBUFF_R = "Ranged Debuff",
50 | NUKE = "Nuking",
51 | HEALING = "Healing",
52 | ALL_HEAL = "Combined Healing",
53 | ENFEEBLE = "Enfeebling",
54 | BUFF_SONG = "BRD Buff Song",
55 | DEBUFF_REMOVAL = "Debuff Removal",
56 | BUFF_SPELL = "Buff Spell",
57 | MP_DRAIN = "MP Drain",
58 | OUTGOING_SPIKE_DMG = "Outgoing Spike Damage",
59 | HEALING_RECEIVED = "Healing Received",
60 | DAMAGE_TAKEN_TOTAL = "Total Damage Taken", -- Defense
61 | DMG_TAKEN_TOTAL_PET = "Total Pet Damage Taken",
62 | MELEE_DMG_TAKEN = "Melee Damage Taken",
63 | MELEE_PET_DMG_TAKEN = "Melee Pet Damage Taken",
64 | DEF_EVASION = "Evasion",
65 | DEF_PARRY = "Parry",
66 | DEF_SHADOWS = "Shadow Absorption",
67 | DEF_COUNTER = "Counter",
68 | DEF_GUARD = "Guard",
69 | DEF_BLOCK = "Shield Block",
70 | DEF_CRIT = "Crits Taken",
71 | DEF_UNMITIGATED = "Unmitigated Melee Damage Taken",
72 | INCOMING_SPIKE_DMG = "Incoming Spike Damage",
73 | SPELL_DMG_TAKEN = "Spell Damage Taken",
74 | SPELL_PET_DMG_TAKEN = "Spell Pet Damage Taken",
75 | DEF_NO_DMG_SPELLS = "No Damage Spells",
76 | DEF_MP_DRAIN = "Player MP Drained",
77 | DEF_ENFEEBLE = "Player Enfeebled",
78 | -- SPELL_ENF_RESIST = "Enfeeble Resist"
79 | TP_DMG_TAKEN = "TP Move Damage Taken",
80 | PET_TP_DMG_TAKEN = "Pet TP Move Damage Taken",
81 | DEATH = "Death", -- Misc
82 | DEFAULT = "Default",
83 | }
84 |
85 | DB.Enum.Metric = T{
86 | TOTAL = "Total",
87 | COUNT = "Attempts",
88 | AOE_COUNT = "AOE Targets Hit",
89 | CYCLE = "Melee Cycles", -- How many times a melee cycle occurred.
90 | ROUNDS = "Attack Rounds", -- Used in multi-attacks
91 | MULTI_TOTAL = "Multi-Attack",
92 | MULT_ATK_1 = "Single",
93 | MULT_ATK_2 = "Double",
94 | MULT_ATK_3 = "Triple",
95 | MULT_ATK_4 = "Quad",
96 | MULT_ATK_5 = "Mult. V",
97 | MULT_ATK_6 = "Mult. VI",
98 | MULT_ATK_7 = "Mult. VII",
99 | MULT_ATK_8 = "Mult. VIII",
100 | GUARD = "Guard",
101 | HIT_COUNT = "Hits",
102 | SHOT_DISTANCE = "Shot Distance",
103 | CRIT_COUNT = "Crit Count",
104 | CRIT_DAMAGE = "Crit Damage",
105 | SHADOWS = "Shadow Absorption",
106 | MOB_HEAL = "Mob Heal",
107 | MIN = "Min",
108 | MAX = "Max",
109 | BURST_COUNT = "Burst Count",
110 | BURST_DAMAGE = "Burst Damage",
111 | OVERCURE = "Overcure",
112 | MP_SPENT = "MP Spent",
113 | TP_SPENT = "TP Spent",
114 | SC_OPENED = "Skillchains Opened",
115 | SC_CLOSED = "Skillchains Closed",
116 | OVERLOAD = "Maneuver Overload",
117 | PHANTOM_ROLL_FIRST_ROLL = "Phantom Roll First Rolls",
118 | PHANTOM_ROLL_REROLL = "Phantom Roll Rerolls",
119 | BUST_COUNT = "COR Roll Bust Count",
120 | LUCKY_COUNT = "COR Roll Lucky Count",
121 | UNLUCKY_COUNT = "COR Roll Unlucky Count",
122 | LUCKY_11_COUNT = "COR Roll Lucky 11 Count",
123 | }
124 |
125 | DB.Enum.Pet_Single_Trackable = T{
126 | PET_WS = DB.Enum.Trackable.PET_WS,
127 | PET_ABILITY = DB.Enum.Trackable.PET_ABILITY,
128 | PET_HEAL = DB.Enum.Trackable.PET_HEAL,
129 | PET_NUKE = DB.Enum.Trackable.PET_NUKE,
130 | PET_ENFEEBLING = DB.Enum.Trackable.PET_ENFEEBLING,
131 | PET_MP_DRAIN = DB.Enum.Trackable.PET_MP_DRAIN,
132 | PET_MAGIC = DB.Enum.Trackable.PET_MAGIC,
133 | }
134 |
135 | DB.Enum.Values = T{
136 | CATALOG = "catalog",
137 | PET_CATALOG = "pet_catalog",
138 | DEBUG = "Debug",
139 | IGNORE = 'ignore',
140 | COMBINED = 'combined',
141 | MAX_DAMAGE = 100000,
142 | }
143 |
144 | DB.Enum.HEALING = T{
145 | ["Cure"] = 50, -- 35
146 | ["Cure II"] = 150, -- 102
147 | ["Cure III"] = 250, -- 212
148 | ["Cure IV"] = 500, -- 430
149 | ["Cure V"] = 1300,
150 | ["Cure VI"] = 1500,
151 | ["Curaga"] = 150, -- 102
152 | ["Curaga II"] = 300, -- 213
153 | ["Curaga III"] = 400,
154 | ["Curaga IV"] = 500,
155 | ["Curaga V"] = 800,
156 | }
157 |
158 | DB.Healing_Max = T{
159 | ["Cure"] = 50,
160 | ["Cure II"] = 150,
161 | ["Cure III"] = 250,
162 | ["Cure IV"] = 500,
163 | ["Cure V"] = 1300,
164 | ["Cure VI"] = 1500,
165 | ["Curaga"] = 150,
166 | ["Curaga II"] = 300,
167 | ["Curaga III"] = 400,
168 | ["Curaga IV"] = 500,
169 | ["Curaga V"] = 800,
170 | }
--------------------------------------------------------------------------------
/database/accuracy.lua:
--------------------------------------------------------------------------------
1 | DB.Accuracy = T{}
2 |
3 | ------------------------------------------------------------------------------------------------------
4 | -- Keeps a tally of the last running accuracy limit amount of hit attempts.
5 | -- This is called by the action handling functions.
6 | ------------------------------------------------------------------------------------------------------
7 | ---@param player_name string primary index for the Running_Accuracy_Data table
8 | ---@param hit boolean if true then there was a hit; miss otherwise
9 | ---@return boolean
10 | ------------------------------------------------------------------------------------------------------
11 | DB.Accuracy.Update = function(player_name, hit)
12 | if not DB.Tracking.Running_Accuracy[player_name] then
13 | Debug.Error.Add("Update.Running_Accuracy: {" .. tostring(player_name) .. "} is missing in Data.Running_Accuracy.")
14 | return false
15 | end
16 | local max = #DB.Tracking.Running_Accuracy[player_name]
17 | if max >= Metrics.Model.Running_Accuracy_Limit then table.remove(DB.Tracking.Running_Accuracy[player_name], Metrics.Model.Running_Accuracy_Limit) end
18 | table.insert(DB.Tracking.Running_Accuracy[player_name], 1, hit)
19 | return true
20 | end
21 |
22 | ------------------------------------------------------------------------------------------------------
23 | -- Returns the players accuracy for the last running accuracy limit amount of attempts.
24 | ------------------------------------------------------------------------------------------------------
25 | ---@param player_name string primary index for the Running_Accuracy_Data table
26 | ---@return table {hits, count}
27 | ------------------------------------------------------------------------------------------------------
28 | DB.Accuracy.Get = function(player_name)
29 | -- This error can occur in mini mode when trying to load data before the player has been initialized. Not a big deal.
30 | if not DB.Tracking.Running_Accuracy[player_name] then
31 | Debug.Error.Add("Get.Running_Accuracy: Attempt to get {" .. tostring(player_name) .. "} running accuracy, but it didn't exist.")
32 | return {0, 0}
33 | end
34 | local hits = 0
35 | local count = 0
36 |
37 | -- Tally how hits the player had in the last {running accuracy limit} amount of attempts.
38 | for _, value in pairs(DB.Tracking.Running_Accuracy[player_name]) do
39 | if value then hits = hits + 1 end
40 | count = count + 1
41 | end
42 |
43 | return {hits, count}
44 | end
--------------------------------------------------------------------------------
/database/attack_speed.lua:
--------------------------------------------------------------------------------
1 | DB.Attack_Speed = T{}
2 |
3 | DB.Attack_Speed.Players = T{}
4 | DB.Attack_Speed.Timestamp = T{}
5 | DB.Attack_Speed.Max_Windows = 3
6 | DB.Attack_Speed.Timeout = 15 -- Treshold in seconds to throw away a value (in between pulls or something).
7 |
8 | ------------------------------------------------------------------------------------------------------
9 | -- Resets the attack speed globals.
10 | ------------------------------------------------------------------------------------------------------
11 | DB.Attack_Speed.Reset = function()
12 | DB.Attack_Speed.Players = T{}
13 | DB.Attack_Speed.Timestamp = T{}
14 | end
15 |
16 | ------------------------------------------------------------------------------------------------------
17 | -- Keeps a tally of the player's attack speed.
18 | ------------------------------------------------------------------------------------------------------
19 | ---@param player_name string
20 | ------------------------------------------------------------------------------------------------------
21 | DB.Attack_Speed.Update = function(player_name)
22 | if not DB.Tracking.Running_Attack_Speed[player_name] then
23 | Debug.Error.Add("Attack_Speed.Update: {" .. tostring(player_name) .. "} is missing in Tracking.Attack_Speed.")
24 | return false
25 | end
26 |
27 | -- Capture the rate.
28 | local rate = 0
29 | local skip = false
30 | local timestamp = DB.Attack_Speed.Timestamp[player_name]
31 | if timestamp then
32 | rate = Socket.gettime() - timestamp
33 | if rate > DB.Attack_Speed.Timeout then skip = true end
34 | else
35 | skip = true
36 | end
37 | timestamp = Socket.gettime()
38 | DB.Attack_Speed.Timestamp[player_name] = timestamp
39 | if skip then return false end
40 |
41 | -- Add the new speed to the attack speed tracking buckets.
42 | local size = #DB.Tracking.Running_Attack_Speed[player_name]
43 | if size >= DB.Attack_Speed.Max_Windows then table.remove(DB.Tracking.Running_Attack_Speed[player_name], DB.Attack_Speed.Max_Windows) end
44 | table.insert(DB.Tracking.Running_Attack_Speed[player_name], 1, rate)
45 | local new_size = #DB.Tracking.Running_Attack_Speed[player_name]
46 |
47 | -- Average the attack speed.
48 | local total = 0
49 | for _, attack_speed in pairs(DB.Tracking.Running_Attack_Speed[player_name]) do
50 | total = total + attack_speed
51 | end
52 | local average = total / new_size
53 | DB.Attack_Speed.Players[player_name] = average
54 |
55 | return true
56 | end
57 |
58 | ------------------------------------------------------------------------------------------------------
59 | -- Retrieves a player's attack speed.
60 | ------------------------------------------------------------------------------------------------------
61 | ---@param player_name string
62 | ------------------------------------------------------------------------------------------------------
63 | DB.Attack_Speed.Get = function(player_name)
64 | local speed = DB.Attack_Speed.Players[player_name]
65 | if not speed then speed = 0 end
66 | return speed
67 | end
--------------------------------------------------------------------------------
/database/pet_data.lua:
--------------------------------------------------------------------------------
1 | DB.Pet_Data = T{}
2 |
3 | ------------------------------------------------------------------------------------------------------
4 | -- Initializes an [actor:target][pet_name] combination in the primary data node and catalog nodes.
5 | -- Also initializes separate tracking globals for Running Accuracy.
6 | -- If the "actor:target" combo has already been initialized then this will quit out early.
7 | -- CALLED BY: Init.Data
8 | ------------------------------------------------------------------------------------------------------
9 | ---@param index string "actor_name:target_name"
10 | ---@param player_name? string used for maintaining various player indexed tables. In the case of pets this will be the owner.
11 | ---@param pet_name string used for maintaining various pet indexed tables.
12 | ------------------------------------------------------------------------------------------------------
13 | DB.Pet_Data.Init = function(index, player_name, pet_name)
14 | if not index or not pet_name then
15 | Debug.Error.Add("Pet_Data.Init: {" .. tostring(player_name) .. " {" .. tostring(pet_name) .. "} nil index passed in." )
16 | return false
17 | end
18 |
19 | if not DB.Pet_Parse[index] then DB.Pet_Parse[index] = {} end
20 | if DB.Pet_Parse[index][pet_name] then return false end
21 |
22 | DB.Pet_Parse[index][pet_name] = {}
23 |
24 | -- Initialize data nodes
25 | for _, trackable in pairs(DB.Enum.Trackable) do
26 | DB.Pet_Parse[index][pet_name][trackable] = {}
27 | DB.Pet_Parse[index][pet_name][trackable][DB.Enum.Values.CATALOG] = {}
28 | for _, metric in pairs(DB.Enum.Metric) do
29 | DB.Pet_Data.Set(0, index, pet_name, trackable, metric)
30 | end
31 | end
32 |
33 | -- Need to set minimum high manually to capture accurate minimums.
34 | DB.Pet_Data.Set(DB.Enum.Values.MAX_DAMAGE, index, pet_name, DB.Enum.Trackable.PET_WS, DB.Enum.Metric.MIN)
35 | DB.Pet_Data.Set(DB.Enum.Values.MAX_DAMAGE, index, pet_name, DB.Enum.Trackable.PET_ABILITY, DB.Enum.Metric.MIN)
36 | DB.Pet_Data.Set(DB.Enum.Values.MAX_DAMAGE, index, pet_name, DB.Enum.Trackable.PET_HEAL, DB.Enum.Metric.MIN)
37 | DB.Pet_Data.Set(DB.Enum.Values.MAX_DAMAGE, index, pet_name, DB.Enum.Trackable.PET_NUKE, DB.Enum.Metric.MIN)
38 | DB.Pet_Data.Set(DB.Enum.Values.MAX_DAMAGE, index, pet_name, DB.Enum.Trackable.MELEE_PET_DMG_TAKEN, DB.Enum.Metric.MIN)
39 | DB.Pet_Data.Set(DB.Enum.Values.MAX_DAMAGE, index, pet_name, DB.Enum.Trackable.SPELL_PET_DMG_TAKEN, DB.Enum.Metric.MIN)
40 | DB.Pet_Data.Set(DB.Enum.Values.MAX_DAMAGE, index, pet_name, DB.Enum.Trackable.PET_TP_DMG_TAKEN, DB.Enum.Metric.MIN)
41 |
42 | -- Initialize pet tracking tables.
43 | if player_name and not DB.Tracking.Initialized_Pets[player_name] then
44 | DB.Tracking.Initialized_Pets[player_name] = {}
45 | end
46 | if player_name and not DB.Tracking.Initialized_Pets[player_name][pet_name] then
47 | DB.Tracking.Initialized_Pets[player_name][pet_name] = true
48 | end
49 | end
50 |
51 | ------------------------------------------------------------------------------------------------------
52 | -- Directly sets a pet's trackables metric to a specified value.
53 | ------------------------------------------------------------------------------------------------------
54 | ---@param value number the value to set the node to.
55 | ---@param index string "actor_name:target_name".
56 | ---@param pet_name string
57 | ---@param trackable string a tracked item from the trackable list.
58 | ---@param metric string a trackable's metric from the metric
59 | ---@return boolean
60 | ------------------------------------------------------------------------------------------------------
61 | DB.Pet_Data.Set = function(value, index, pet_name, trackable, metric)
62 | if not value or not index or not pet_name or not trackable or not metric then
63 | Debug.Error.Add("Set.Pet_Data: {" .. tostring(index) .. "} {" .. tostring(trackable) .. "} nil required parameter passed in." )
64 | return false
65 | end
66 | DB.Pet_Parse[index][pet_name][trackable][metric] = value
67 | return true
68 | end
69 |
70 | ------------------------------------------------------------------------------------------------------
71 | -- Increments a pet's trackables metric by a specified amount.
72 | ------------------------------------------------------------------------------------------------------
73 | ---@param value number the value to increment the node by.
74 | ---@param index string "player_name:mob_name"
75 | ---@param pet_name string
76 | ---@param trackable string a tracked item from the trackable list.
77 | ---@param metric string a trackable's metric from the metric list.
78 | ---@return boolean
79 | ------------------------------------------------------------------------------------------------------
80 | DB.Pet_Data.Inc = function(value, index, pet_name, trackable, metric)
81 | if not value or not index or not pet_name or not trackable or not metric then
82 | Debug.Error.Add("Inc.Pet_Data: {" .. tostring(index) .. "} {" .. tostring(pet_name) .. "} {" .. tostring(trackable) .. "} nil required parameter passed in." )
83 | return false
84 | end
85 | DB.Pet_Parse[index][pet_name][trackable][metric] = DB.Pet_Parse[index][pet_name][trackable][metric] + value
86 | return true
87 | end
88 |
89 | ------------------------------------------------------------------------------------------------------
90 | -- Gets data from a pet's trackable metric.
91 | -- If the mob filter is set then only actions towards that mob are counted.
92 | -- Consider that not every player:mob index will have a pet node.
93 | ------------------------------------------------------------------------------------------------------
94 | ---@param player_name string the player or entity name to search data for.
95 | ---@param pet_name string
96 | ---@param trackable string a tracked item from the trackable list.
97 | ---@param metric string a trackable's metric from the metric list.
98 | ---@return number
99 | ------------------------------------------------------------------------------------------------------
100 | DB.Pet_Data.Get = function(player_name, pet_name, trackable, metric)
101 | local total = 0
102 | local mob_focus = DB.Widgets.Util.Get_Mob_Focus()
103 | for index, _ in pairs(DB.Pet_Parse) do
104 | if mob_focus == DB.Widgets.Dropdown.Enum.NONE then
105 | if string.find(index, player_name .. ":") then
106 | if DB.Pet_Parse[index][pet_name] then
107 | total = total + DB.Pet_Parse[index][pet_name][trackable][metric]
108 | end
109 | end
110 | else
111 | if string.find(index, player_name .. ":" .. mob_focus) then
112 | if DB.Pet_Parse[index][pet_name] then
113 | total = total + DB.Pet_Parse[index][pet_name][trackable][metric]
114 | end
115 | end
116 | end
117 | end
118 | return total
119 | end
--------------------------------------------------------------------------------
/database/widgets.lua:
--------------------------------------------------------------------------------
1 | DB.Widgets = T{}
2 |
3 | DB.Widgets.Util = T{}
4 |
5 | DB.Widgets.Dropdown = T{}
6 | DB.Widgets.Dropdown.Enum = T{
7 | MOB = "Mob Filter",
8 | FOCUS = "Player",
9 | NONE = "!NONE",
10 | }
11 | DB.Widgets.Dropdown.Width = 150
12 | DB.Widgets.Dropdown.Flags = ImGuiComboFlags_None
13 | DB.Widgets.Dropdown.Player = T{}
14 | DB.Widgets.Dropdown.Player.Focus = DB.Widgets.Dropdown.Enum.NONE
15 | DB.Widgets.Dropdown.Player.Index = 1
16 | DB.Widgets.Dropdown.Mob = T{}
17 | DB.Widgets.Dropdown.Mob.Focus = DB.Widgets.Dropdown.Enum.NONE
18 | DB.Widgets.Dropdown.Mob.Index = 1
19 |
20 | ------------------------------------------------------------------------------------------------------
21 | -- Creates a dropdown menu to show only damage done to a certain mob.
22 | ------------------------------------------------------------------------------------------------------
23 | DB.Widgets.Mob_Filter = function()
24 | local list = DB.Lists.Get.Mob()
25 | local flags = DB.Widgets.Dropdown.Flags
26 | if list[1] then
27 | UI.SetNextItemWidth(DB.Widgets.Dropdown.Width)
28 | if UI.BeginCombo(DB.Widgets.Dropdown.Enum.MOB, list[DB.Widgets.Dropdown.Mob.Index], flags) then
29 | for n = 1, #list, 1 do
30 | local is_selected = DB.Widgets.Dropdown.Mob.Index == n
31 | if UI.Selectable(list[n], is_selected) then
32 | DB.Widgets.Dropdown.Mob.Index = n
33 | DB.Widgets.Dropdown.Mob.Focus = list[n]
34 | end
35 | if is_selected then
36 | UI.SetItemDefaultFocus()
37 | end
38 | end
39 | UI.EndCombo()
40 | end
41 | else
42 | if UI.BeginCombo(DB.Widgets.Dropdown.Enum.MOB, DB.Widgets.Dropdown.Enum.NONE, flags) then
43 | UI.EndCombo()
44 | end
45 | end
46 | DB.Widgets.Mob_Filter_Help_Text()
47 | end
48 |
49 | ------------------------------------------------------------------------------------------------------
50 | -- Shows the help text for the mob filter.
51 | ------------------------------------------------------------------------------------------------------
52 | DB.Widgets.Mob_Filter_Help_Text = function()
53 | UI.SameLine() Window_Manager.Widgets.HelpMarker("You can filter to show only data for actions taken against mobs with a specific name.\n"
54 | .. "Notes:\n"
55 | .. "1. The filter may not be for individual mobs. It is for mobs with that name collectively.\n"
56 | .. "2. If the mob has a unique name (like an NM) then the data will be mob specific.\n"
57 | .. "3. The filter only affects actions taken against mobs with that name.\n"
58 | .. "4. The filter does not work for healing because those actions are taken on other players.\n"
59 | .. "5. The filter does not work for abilities that are used on yourself or other players.\n")
60 | end
61 |
62 | ------------------------------------------------------------------------------------------------------
63 | -- Utility function for accessing the name of the currently focused mob.
64 | ------------------------------------------------------------------------------------------------------
65 | DB.Widgets.Util.Get_Mob_Focus = function()
66 | return DB.Widgets.Dropdown.Mob.Focus
67 | end
68 |
69 | ------------------------------------------------------------------------------------------------------
70 | -- Creates a dropdown menu to show only damage done by a certain entity.
71 | ------------------------------------------------------------------------------------------------------
72 | DB.Widgets.Player_Filter = function()
73 | local list = DB.Lists.Get.Players()
74 | local flags = DB.Widgets.Dropdown.Flags
75 | if list[1] then
76 | UI.SetNextItemWidth(DB.Widgets.Dropdown.Width)
77 | if UI.BeginCombo(DB.Widgets.Dropdown.Enum.FOCUS, list[DB.Widgets.Dropdown.Player.Index], flags) then
78 | for n = 1, #list, 1 do
79 | local is_selected = DB.Widgets.Dropdown.Player.Index == n
80 | if UI.Selectable(list[n], is_selected) then
81 | DB.Widgets.Dropdown.Player.Index = n
82 | DB.Widgets.Dropdown.Player.Focus = list[n]
83 | end
84 | if is_selected then
85 | UI.SetItemDefaultFocus()
86 | end
87 | end
88 | UI.EndCombo()
89 | end
90 | else
91 | if UI.BeginCombo(DB.Widgets.Dropdown.Enum.FOCUS, DB.Widgets.Dropdown.Enum.NONE, flags) then
92 | UI.EndCombo()
93 | end
94 | end
95 | DB.Widgets.Player_Filter_Help_Text()
96 | end
97 |
98 | ------------------------------------------------------------------------------------------------------
99 | -- Shows the help text for the player filter.
100 | ------------------------------------------------------------------------------------------------------
101 | DB.Widgets.Player_Filter_Help_Text = function()
102 | UI.SameLine() Window_Manager.Widgets.HelpMarker("Pick a player that you would like to see more detailed stats for.\n")
103 | end
104 |
105 | ------------------------------------------------------------------------------------------------------
106 | -- Utility function for accessing the name of the currently focused entity.
107 | ------------------------------------------------------------------------------------------------------
108 | DB.Widgets.Util.Get_Player_Focus = function()
109 | return DB.Widgets.Dropdown.Player.Focus
110 | end
111 |
112 | ------------------------------------------------------------------------------------------------------
113 | -- Switches to a player in the player filter based on partial matching.
114 | ------------------------------------------------------------------------------------------------------
115 | ---@param player_string string
116 | ------------------------------------------------------------------------------------------------------
117 | DB.Widgets.Util.Player_Switch = function(player_string)
118 | local list = DB.Lists.Get.Players()
119 | local found = false
120 | for n, player_name in pairs(list) do
121 | if not found then
122 | if string.find(string.lower(player_name), player_string) then
123 | DB.Widgets.Dropdown.Player.Index = n
124 | DB.Widgets.Dropdown.Player.Focus = list[n]
125 | found = true
126 | end
127 | end
128 | end
129 | end
--------------------------------------------------------------------------------
/handlers/_handler.lua:
--------------------------------------------------------------------------------
1 | H = {}
2 |
3 | H.Mode = DB.Enum.Mode
4 | H.Trackable = DB.Enum.Trackable
5 | H.Metric = DB.Enum.Metric
6 |
7 | H.Enum = {}
8 |
9 | H.Enum.Flags = {
10 | IGNORE = "ignore",
11 | }
12 |
13 | H.Enum.Offsets = {
14 | ABILITY = 512,
15 | PET = 512,
16 | }
17 |
18 | H.Enum.Text = {
19 | BLANK = "",
20 | }
21 |
22 | require("handlers.melee")
23 | require("handlers.melee_def")
24 | require("handlers.ranged")
25 | require("handlers.tp_action")
26 | require("handlers.tp_action_def")
27 | require("handlers.abilities")
28 | require("handlers.spells")
29 | require("handlers.spells_def")
30 | require("handlers.deaths")
31 | require("handlers.items")
--------------------------------------------------------------------------------
/handlers/deaths.lua:
--------------------------------------------------------------------------------
1 | H.Death = {}
2 |
3 | ------------------------------------------------------------------------------------------------------
4 | -- Parse the player death message.
5 | ------------------------------------------------------------------------------------------------------
6 | ---@param actor_mob table mob id of the entity performing the action
7 | ---@param target_mob table mob id of the entity receiving the action (this is the person dying)
8 | ------------------------------------------------------------------------------------------------------
9 | H.Death.Action = function(actor_mob, target_mob)
10 | if not actor_mob or not target_mob then return nil end
11 |
12 | local audits = {
13 | player_name = target_mob.name,
14 | target_name = actor_mob.name,
15 | }
16 |
17 | DB.Data.Update(H.Mode.INC, 1, audits, H.Trackable.DEATH, H.Metric.COUNT)
18 | DB.Data.Update(H.Mode.INC, 1, audits, H.Trackable.DEATH, H.Metric.TOTAL)
19 | Blog.Add(target_mob.name, nil, Blog.Enum.Types.DEATH, Blog.Enum.Text.PLAYER_DEATH, nil, actor_mob.name, DB.Enum.Trackable.DEATH)
20 | end
21 |
--------------------------------------------------------------------------------
/handlers/items.lua:
--------------------------------------------------------------------------------
1 | H.Item = T{}
2 |
3 | -- ------------------------------------------------------------------------------------------------------
4 | -- Parse the finish item use packet.
5 | -- ------------------------------------------------------------------------------------------------------
6 | ---@param action table action packet data.
7 | ---@param actor_mob table
8 | -- ------------------------------------------------------------------------------------------------------
9 | H.Item.Action = function(action, actor_mob)
10 | if not action then return nil end
11 | if not actor_mob then return nil end
12 | if not Ashita.Mob.Is_Me(actor_mob.name) then return nil end
13 | local item_id = action.param
14 | local dedication_item = Res.Items.Get_Dedication(item_id)
15 | if dedication_item then XP.Dedication.Set(dedication_item, true) end
16 | end
--------------------------------------------------------------------------------
/modules/battle log/columns.lua:
--------------------------------------------------------------------------------
1 | Blog.Columns = T{}
2 |
3 | ------------------------------------------------------------------------------------------------------
4 | -- Creates a name string for display in the battle log.
5 | ------------------------------------------------------------------------------------------------------
6 | ---@param player_name string
7 | ---@param pet_name string
8 | ---@return string
9 | ------------------------------------------------------------------------------------------------------
10 | Blog.Columns.Name = function(player_name, pet_name)
11 | if Metrics.Parse.Hide_Name then player_name = Blog.Columns.Job(player_name) end
12 | if pet_name ~= Blog.Enum.Text.NO_PET then
13 | local combined_string = player_name .. " (" .. pet_name .. ")"
14 | if string.len(combined_string) > Blog.Settings.Truncate_Length then
15 | local truncated_pet = Column.String.Truncate(pet_name, Blog.Settings.Pet_Name_Truncate_Length, true)
16 | local truncated_player = Column.String.Truncate(player_name, Blog.Settings.Player_Name_Truncate_Length)
17 | combined_string = truncated_player .. " (" .. truncated_pet .. ")"
18 | end
19 | return Column.String.Set_Length(combined_string, Blog.Settings.Truncate_Length)
20 | end
21 | player_name = Column.String.Set_Length(player_name, Blog.Settings.Truncate_Length)
22 | return player_name
23 | end
24 |
25 | ------------------------------------------------------------------------------------------------------
26 | -- Gets the player's job for name masking.
27 | -- Don't need the color because it gets saved when the entry is saved.
28 | ------------------------------------------------------------------------------------------------------
29 | ---@param player_name string
30 | ---@return string
31 | ------------------------------------------------------------------------------------------------------
32 | Blog.Columns.Job = function(player_name)
33 | local anon_string = "NON0/NON0"
34 | local hide_subjob = Metrics.Parse.Hide_Subjob
35 | if hide_subjob then anon_string = "NON0" end
36 | if not player_name or not Ashita.Party.Jobs[player_name] then return anon_string end
37 |
38 | local main = Res.Jobs.Get_Job(Ashita.Party.Jobs[player_name].main)
39 | local main_level = Ashita.Party.Jobs[player_name].main_level
40 | if not main then main = Res.Jobs.List[0] end
41 | local main_string = string.format("%s%02d", main.ens, main_level)
42 |
43 | local sub_string = ""
44 | if not hide_subjob then
45 | local sub = Res.Jobs.Get_Job(Ashita.Party.Jobs[player_name].sub)
46 | local sub_level = Ashita.Party.Jobs[player_name].sub_level
47 | if not sub then sub = Res.Jobs.List[0] end
48 | sub_string = "/" .. string.format("%s%02d", sub.ens, sub_level)
49 | end
50 |
51 | return main_string .. sub_string
52 | end
53 |
54 | ------------------------------------------------------------------------------------------------------
55 | -- Formats the damage string.
56 | ------------------------------------------------------------------------------------------------------
57 | ---@param damage string
58 | ---@return string
59 | ------------------------------------------------------------------------------------------------------
60 | Blog.Columns.Damage = function(damage)
61 | return Column.String.Set_Length(damage, Blog.Settings.Damage_Truncate_Length)
62 | end
63 |
64 | ------------------------------------------------------------------------------------------------------
65 | -- Formats the action name.
66 | ------------------------------------------------------------------------------------------------------
67 | ---@param action_name string
68 | ---@return string
69 | ------------------------------------------------------------------------------------------------------
70 | Blog.Columns.Action = function(action_name)
71 | action_name = Column.String.Truncate(action_name, Blog.Settings.Action_Truncate_Length)
72 | action_name = Column.String.Set_Length(action_name, Blog.Settings.Action_Truncate_Length)
73 | return action_name
74 | end
75 |
76 | ------------------------------------------------------------------------------------------------------
77 | -- Formats the note.
78 | ------------------------------------------------------------------------------------------------------
79 | ---@param note string
80 | ---@return string
81 | ------------------------------------------------------------------------------------------------------
82 | Blog.Columns.Notes = function(note)
83 | note = Column.String.Truncate(note, Blog.Settings.Action_Truncate_Length)
84 | note = Column.String.Set_Length(note, Blog.Settings.Action_Truncate_Length)
85 | return note
86 | end
87 |
--------------------------------------------------------------------------------
/modules/battle log/entries.lua:
--------------------------------------------------------------------------------
1 | Blog.Entries = T{}
2 |
3 | ------------------------------------------------------------------------------------------------------
4 | -- Format the player name component of the battle log.
5 | ------------------------------------------------------------------------------------------------------
6 | ---@param player_name string
7 | ---@param is_mob? boolean
8 | ---@return table {Name, Color}
9 | ------------------------------------------------------------------------------------------------------
10 | Blog.Entries.Name = function(player_name, is_mob)
11 | local color = Res.Colors.Basic.WHITE
12 | if is_mob then
13 | color = Res.Colors.Basic.MOB
14 | elseif Metrics.Parse.Name_Colors and Ashita.Party.Jobs[player_name] then
15 | local job = Res.Jobs.Get_Job(Ashita.Party.Jobs[player_name].main)
16 | if not job then job = Res.Jobs.List[0] end
17 | color = Res.Colors.Get_Job(job.id)
18 | end
19 | return {Value = tostring(player_name), Color = color}
20 | end
21 |
22 | ------------------------------------------------------------------------------------------------------
23 | -- Format the pet name component of the battle log.
24 | ------------------------------------------------------------------------------------------------------
25 | ---@param pet_name string
26 | ---@return table {Name, Color}
27 | ------------------------------------------------------------------------------------------------------
28 | Blog.Entries.Pet_Name = function(pet_name)
29 | local color = Res.Colors.Basic.WHITE
30 | if not pet_name then pet_name = Blog.Enum.Text.NO_PET end
31 | return {Value = pet_name, Color = color}
32 | end
33 |
34 | ------------------------------------------------------------------------------------------------------
35 | -- Format the damage component of the battle log.
36 | ------------------------------------------------------------------------------------------------------
37 | ---@param damage? number
38 | ---@param action_type? string a trackable from the data model.
39 | ---@param color? table
40 | ---@param is_mob? boolean
41 | ---@return table {Damage, Color}
42 | ------------------------------------------------------------------------------------------------------
43 | Blog.Entries.Damage = function(damage, action_type, color, is_mob)
44 | if action_type == Blog.Enum.Flags.IGNORE then return {Value = Blog.Enum.Text.NA, Color = Res.Colors.Basic.WHITE} end
45 |
46 | local default_color = Res.Colors.Basic.WHITE
47 | if color then default_color = color end
48 |
49 | -- Change the color of the text if the damage is over a certain threshold.
50 | local threshold = Blog.Entries.Damage_Threshold(action_type)
51 |
52 | -- Generate damage string.
53 | if not damage then
54 | return {Value = Blog.Enum.Text.NA, Color = Res.Colors.Basic.DIM}
55 | elseif is_mob then
56 | return {Value = Column.String.Format_Number(damage), Color = Res.Colors.Basic.MOB}
57 | elseif damage < 0 then -- Enfeeble
58 | return {Value = Blog.Enum.Text.NA, Color = Res.Colors.Basic.DIM}
59 | elseif damage == 0 then
60 | return {Value = Column.String.Format_Number(0), Color = default_color, Note = Blog.Enum.Text.MISS}
61 | elseif damage >= threshold then
62 | return {Value = Column.String.Format_Number(damage), Color = default_color, Note = Blog.Enum.Text.HIGH_DAMAGE}
63 | end
64 | return {Value = Column.String.Format_Number(damage), Color = default_color}
65 | end
66 |
67 | ------------------------------------------------------------------------------------------------------
68 | -- Helper function for calculating a damage threshold for highlighting.
69 | ------------------------------------------------------------------------------------------------------
70 | ---@param action_type? string a trackable from the data model.
71 | ---@return number
72 | ------------------------------------------------------------------------------------------------------
73 | Blog.Entries.Damage_Threshold = function(action_type)
74 | local threshold = DB.Enum.Values.MAX_DAMAGE
75 | if not action_type then
76 | return threshold
77 | elseif action_type == DB.Enum.Trackable.WS then
78 | return Metrics.Blog.WS_THRESHOLD
79 | elseif action_type == DB.Enum.Trackable.MAGIC then
80 | return Metrics.Blog.MAGIC_THRESHOLD
81 | else
82 | return threshold
83 | end
84 | end
85 |
86 | ------------------------------------------------------------------------------------------------------
87 | -- Format the action component of the battle log.
88 | ------------------------------------------------------------------------------------------------------
89 | ---@param action_name string
90 | ---@param color table
91 | ---@param is_mob? boolean
92 | ---@return table {Name, Color}
93 | ------------------------------------------------------------------------------------------------------
94 | Blog.Entries.Action = function(action_name, color, is_mob)
95 | if is_mob then color = Res.Colors.Basic.MOB end
96 | return {Value = action_name, Color = color}
97 | end
98 |
99 | ------------------------------------------------------------------------------------------------------
100 | -- Format the TP component of the battle log.
101 | -- Will also show if a spell cast is a magic burst.
102 | ------------------------------------------------------------------------------------------------------
103 | ---@param note? string|number how much TP was used by the weaponskill
104 | ---@param action_type? string a trackable from the data model.
105 | ---@param is_mob? boolean
106 | ---@return table
107 | ------------------------------------------------------------------------------------------------------
108 | Blog.Entries.Notes = function(note, action_type, is_mob)
109 | local color = Res.Colors.Basic.WHITE
110 | if is_mob then color = Res.Colors.Basic.MOB end
111 |
112 | local final_note = {Value = " ", Color = color}
113 | if not note or note == "" then return final_note end
114 |
115 | -- A note should be passed in with these actions. Just use that.
116 | if action_type == DB.Enum.Trackable.MAGIC or action_type == DB.Enum.Trackable.HEALING
117 | or action_type == DB.Enum.Trackable.TP_DMG_TAKEN or action_type == Blog.Enum.Flags.IGNORE
118 | or action_type == DB.Enum.Trackable.ENFEEBLE or action_type == DB.Enum.Trackable.BUFF_SONG
119 | or action_type == DB.Enum.Trackable.PET_ABILITY or action_type == DB.Enum.Trackable.PHANTOM_ROLL
120 | or action_type == DB.Enum.Trackable.DEBUFF_REMOVAL or action_type == DB.Enum.Trackable.DEATH then
121 | final_note.Value = tostring(note)
122 |
123 | -- If the player died then show who killed them.
124 | elseif action_type == DB.Enum.Trackable.DEATH then
125 | if note then final_note.Value = "by " .. tostring(note) end
126 |
127 | -- Show the TP of the weaponskill.
128 | elseif action_type == DB.Enum.Trackable.WS then
129 | ---@diagnostic disable-next-line: param-type-mismatch
130 | if note then final_note.Value = "TP: " .. Column.String.Format_Number(note) .. " " end
131 |
132 | -- We passed in a note, but didn't handle it above.
133 | else
134 | Debug.Error.Add("Entries.Notes: Unhandled battle log note. Note: {" .. tostring(note) .. "} Type: {" .. tostring(action_type) .. "} Mob {" .. tostring(is_mob) .. "}.")
135 | final_note.Value = " "
136 | end
137 |
138 | return final_note
139 | end
--------------------------------------------------------------------------------
/modules/debug/!debug.lua:
--------------------------------------------------------------------------------
1 | Debug = {}
2 | Debug.Enabled = false
3 | Debug.Show_Demo = false
4 |
5 | Debug.Name = "Debug"
6 | Debug.Title = "Metrics - Debug"
7 | Debug.Module = "Debug"
8 | Debug.Window = Window:New({
9 | Name = Debug.Name,
10 | Title = Debug.Title,
11 | Module = Debug.Module,
12 | Visible = {false},
13 | Show_Title = true,
14 | })
15 |
16 | Debug.Modes = T{
17 | MOB_VIEWER = "Mob Viewer ",
18 | ACTION_PACKET = "Action Packet ",
19 | MESSAGE_PACKET = "Message Packet",
20 | ERROR_LOG = "Error Log ",
21 | DATA_VIEWER = "Data Viewer ",
22 | JOB_COLORS = "Job Colors ",
23 | UNIT_TESTS = "Unit Tests ",
24 | DEMO = "Demo Window ",
25 | }
26 | Debug.Active_Mode = Debug.Modes.MOB_VIEWER
27 |
28 | require("modules.debug.performance")
29 | require("modules.debug.screens.mob_viewer")
30 | require("modules.debug.screens.packet_viewer")
31 | require("modules.debug.screens.error_log")
32 | require("modules.debug.screens.data_viewer")
33 | require("modules.debug.unit_tests._tests")
34 | require("modules.debug.unit_tests.melee")
35 | require("modules.debug.unit_tests.ranged")
36 | require("modules.debug.unit_tests.tp_action")
37 | require("modules.debug.unit_tests.abilities")
38 | require("modules.debug.unit_tests.spells")
39 | require("modules.debug.unit_tests.defense")
40 |
41 | ------------------------------------------------------------------------------------------------------
42 | -- Is debug mode enabled.
43 | ------------------------------------------------------------------------------------------------------
44 | ---@return boolean
45 | ------------------------------------------------------------------------------------------------------
46 | Debug.Is_Enabled = function()
47 | return Debug.Enabled
48 | end
49 |
50 | ------------------------------------------------------------------------------------------------------
51 | -- Toggles debug mode.
52 | ------------------------------------------------------------------------------------------------------
53 | Debug.Toggle = function()
54 | Debug.Enabled = not Debug.Enabled
55 | if Debug.Enabled then Debug.Window.Show() else Debug.Window.Hide() end
56 | end
57 |
58 | -- ------------------------------------------------------------------------------------------------------
59 | -- Adds a message in game chat if the debug mode is enabled.
60 | -- ------------------------------------------------------------------------------------------------------
61 | ---@param message string
62 | -- ------------------------------------------------------------------------------------------------------
63 | Debug.Message = function(message)
64 | if Debug.Enabled then print("METRICS DEBUG: " .. message) end
65 | end
66 |
67 | ------------------------------------------------------------------------------------------------------
68 | -- Poplates the debug screen to show debug tools.
69 | ------------------------------------------------------------------------------------------------------
70 | Debug.Content = function()
71 | local col_flags = Column.Flags.None
72 | local width = 150
73 |
74 | if UI.BeginTable("Debug Functions", 3, Window_Manager.Table.Flags.None) then
75 | UI.TableSetupColumn("Col 1", col_flags, width)
76 | UI.TableSetupColumn("Col 2", col_flags, width)
77 | UI.TableSetupColumn("Col 3", col_flags, width)
78 |
79 | UI.TableNextColumn() if UI.Button(Debug.Modes.MOB_VIEWER) then Debug.Active_Mode = Debug.Modes.MOB_VIEWER end
80 | UI.TableNextColumn() if UI.Button(Debug.Modes.ACTION_PACKET) then Debug.Active_Mode = Debug.Modes.ACTION_PACKET end
81 | UI.TableNextColumn() if UI.Button(Debug.Modes.MESSAGE_PACKET) then Debug.Active_Mode = Debug.Modes.MESSAGE_PACKET end
82 | UI.TableNextColumn() if UI.Button(Debug.Modes.ERROR_LOG) then Debug.Active_Mode = Debug.Modes.ERROR_LOG end
83 | UI.TableNextColumn() if UI.Button(Debug.Modes.DATA_VIEWER) then Debug.Active_Mode = Debug.Modes.DATA_VIEWER end
84 | UI.TableNextColumn() if UI.Button(Debug.Modes.JOB_COLORS) then Debug.Active_Mode = Debug.Modes.JOB_COLORS end
85 | UI.TableNextColumn() if UI.Button(Debug.Modes.UNIT_TESTS) then
86 | Debug.Active_Mode = Debug.Modes.UNIT_TESTS
87 | Debug.Unit.Results = T{}
88 | Debug.Unit.Run_Tests()
89 | end
90 | UI.TableNextColumn() if UI.Button(Debug.Modes.DEMO) then Debug.Show_Demo = not Debug.Show_Demo end
91 |
92 | UI.EndTable()
93 | end
94 |
95 | if Debug.Active_Mode == Debug.Modes.MOB_VIEWER then Debug.Mob.Populate(Ashita.Mob.Get_Mob_By_Target(Ashita.Enum.Targets.TARGET))
96 | elseif Debug.Active_Mode == Debug.Modes.ACTION_PACKET then Debug.Packet.Populate_Action()
97 | elseif Debug.Active_Mode == Debug.Modes.MESSAGE_PACKET then Debug.Packet.Populate_Message()
98 | elseif Debug.Active_Mode == Debug.Modes.ERROR_LOG then Debug.Error.Populate()
99 | elseif Debug.Active_Mode == Debug.Modes.DATA_VIEWER then Debug.Data_View.Populate()
100 | elseif Debug.Active_Mode == Debug.Modes.JOB_COLORS then
101 | UI.TextColored(Res.Colors.Get_Job(1), "Warrior")
102 | UI.TextColored(Res.Colors.Get_Job(2), "Monk")
103 | UI.TextColored(Res.Colors.Get_Job(3), "White Mage")
104 | UI.TextColored(Res.Colors.Get_Job(4), "Black Mage")
105 | UI.TextColored(Res.Colors.Get_Job(5), "Red Mage")
106 | UI.TextColored(Res.Colors.Get_Job(6), "Thief")
107 | UI.TextColored(Res.Colors.Get_Job(7), "Paladin")
108 | UI.TextColored(Res.Colors.Get_Job(8), "Dark Knight")
109 | UI.TextColored(Res.Colors.Get_Job(9), "Beastmaster")
110 | UI.TextColored(Res.Colors.Get_Job(10), "Bard")
111 | UI.TextColored(Res.Colors.Get_Job(11), "Ranger")
112 | UI.TextColored(Res.Colors.Get_Job(12), "Samurai")
113 | UI.TextColored(Res.Colors.Get_Job(13), "Ninja")
114 | UI.TextColored(Res.Colors.Get_Job(14), "Dragoon")
115 | UI.TextColored(Res.Colors.Get_Job(15), "Summoner")
116 | UI.TextColored(Res.Colors.Get_Job(16), "Blue Mage")
117 | UI.TextColored(Res.Colors.Get_Job(17), "Corsair")
118 | UI.TextColored(Res.Colors.Get_Job(18), "Puppetmaster")
119 | elseif Debug.Active_Mode == Debug.Modes.UNIT_TESTS then
120 | Debug.Unit.Populate()
121 | else
122 | UI.Text("Select a tool.")
123 | end
124 | end
--------------------------------------------------------------------------------
/modules/debug/performance.lua:
--------------------------------------------------------------------------------
1 | Debug.Perf = T{}
2 |
3 | Debug.Perf.Players = T{
4 | "Player1",
5 | "Player2",
6 | "Player3",
7 | "Player4",
8 | "Player5",
9 | "Player6",
10 | "Player7",
11 | "Player8",
12 | "Player9",
13 | "Player10",
14 | "Player11",
15 | "Player12",
16 | "Player13",
17 | "Player14",
18 | "Player15",
19 | "Player16",
20 | "Player17",
21 | "Player18",
22 | }
23 |
24 | Debug.Perf.Mobs = T{
25 | "Mob1",
26 | "Mob2",
27 | "Mob3",
28 | "Mob4",
29 | "Mob5",
30 | "Mob6",
31 | "Mob7",
32 | "Mob8",
33 | "Mob9",
34 | "Mob10",
35 | "Mob11",
36 | "Mob12",
37 | "Mob13",
38 | }
39 |
40 | ------------------------------------------------------------------------------------------------------
41 | -- Adds a lot of players and mobs that need to be sorted through to test performance.
42 | ------------------------------------------------------------------------------------------------------
43 | Debug.Perf.Add_Load = function()
44 | for _, player in pairs(Debug.Perf.Players) do
45 | for _, mob in pairs(Debug.Perf.Mobs) do
46 | DB.Data.Update("inc", 25, {player_name = player, target_name = mob}, "No SC Total", "Total")
47 | end
48 | end
49 | end
--------------------------------------------------------------------------------
/modules/debug/screens/data_viewer.lua:
--------------------------------------------------------------------------------
1 | Debug.Data_View = {}
2 |
3 | ------------------------------------------------------------------------------------------------------
4 | -- Populates the data viewer tab.
5 | ------------------------------------------------------------------------------------------------------
6 | Debug.Data_View.Populate = function()
7 | local stack = T{}
8 | if UI.TreeNode("Model.Data") then
9 | for index, value in pairs(DB.Parse) do
10 | if UI.TreeNode(tostring(index)) then
11 | Debug.Data_View.Node(stack, value)
12 | UI.TreePop()
13 | end
14 | end
15 | UI.TreePop()
16 | end
17 |
18 | if UI.TreeNode("Party List") then
19 | for player_name, party_number in pairs(Ashita.Party.List) do
20 | UI.Text(tostring(player_name) .. ": " .. tostring(party_number))
21 | end
22 | UI.TreePop()
23 | end
24 | end
25 |
26 | ------------------------------------------------------------------------------------------------------
27 | -- Recursively go through the data nodes.
28 | ------------------------------------------------------------------------------------------------------
29 | ---@param stack table
30 | ---@param data table
31 | ------------------------------------------------------------------------------------------------------
32 | Debug.Data_View.Node = function(stack, data)
33 | for index, value in pairs(data) do
34 | if type(value) == "table" then
35 | if index ~= DB.Enum.Values.CATALOG then
36 | table.insert(stack, index)
37 | Debug.Data_View.Node(stack, value)
38 | table.remove(stack)
39 | end
40 | else
41 | if value and value > 0 then
42 | if not (index == DB.Enum.Metric.MIN and value == DB.Enum.Values.MAX_DAMAGE) then
43 | for _, v in ipairs(stack) do UI.Text(tostring(v)) UI.SameLine() UI.Text(" ") UI.SameLine() end
44 | UI.Text(tostring(index) .. ": " .. tostring(value))
45 | end
46 | end
47 | end
48 | end
49 | end
--------------------------------------------------------------------------------
/modules/debug/screens/error_log.lua:
--------------------------------------------------------------------------------
1 | Debug.Error = {}
2 | Debug.Error.Log = {} -- Error, Count
3 | Debug.Error.Count = 0
4 | Debug.Error.Util = {}
5 |
6 | ------------------------------------------------------------------------------------------------------
7 | -- Adds an entry to the error log.
8 | -- Example Call: _Debug.Error.Add("Function: Error")
9 | ------------------------------------------------------------------------------------------------------
10 | ---@param error string error string and index to the error log.
11 | ---@return boolean whether or not this is a new error.
12 | ------------------------------------------------------------------------------------------------------
13 | Debug.Error.Add = function(error)
14 | Debug.Error.Count = Debug.Error.Count + 1
15 | if not Debug.Error.Log[error] then
16 | Debug.Error.Log[error] = {
17 | Error = error,
18 | Count = 1,
19 | }
20 | return true
21 | end
22 | Debug.Error.Log[error].Count = Debug.Error.Log[error].Count + 1
23 | return false
24 | end
25 |
26 | ------------------------------------------------------------------------------------------------------
27 | -- Resets the error log.
28 | ------------------------------------------------------------------------------------------------------
29 | Debug.Error.Reset = function()
30 | Debug.Error.Log = {}
31 | Debug.Error.Count = 0
32 | end
33 |
34 | ------------------------------------------------------------------------------------------------------
35 | -- Populates the error log tab.
36 | ------------------------------------------------------------------------------------------------------
37 | Debug.Error.Populate = function()
38 | if UI.BeginTable("Error Log", 2, Window_Manager.Table.Flags.Borders) then
39 | Debug.Error.Headers()
40 | for _, data in pairs(Debug.Error.Log) do
41 | Debug.Error.Rows(data)
42 | end
43 | UI.EndTable()
44 | end
45 | end
46 |
47 | ------------------------------------------------------------------------------------------------------
48 | -- Handles setting up the headers for the error log.
49 | ------------------------------------------------------------------------------------------------------
50 | Debug.Error.Headers = function()
51 | local flags = Column.Flags.None
52 | UI.TableSetupColumn("Count", flags)
53 | UI.TableSetupColumn("Error", flags)
54 | UI.TableHeadersRow()
55 | end
56 |
57 | ------------------------------------------------------------------------------------------------------
58 | -- Creates the rows of the error log.
59 | ------------------------------------------------------------------------------------------------------
60 | ---@param entry table
61 | ------------------------------------------------------------------------------------------------------
62 | Debug.Error.Rows = function(entry)
63 | UI.TableNextRow()
64 | UI.TableNextColumn() UI.Text(tostring(entry.Count))
65 | UI.TableNextColumn() UI.Text(tostring(entry.Error))
66 | end
67 |
68 | ------------------------------------------------------------------------------------------------------
69 | -- Returns how many errors are currently in the error log.
70 | ------------------------------------------------------------------------------------------------------
71 | Debug.Error.Util.Error_Count = function()
72 | return Debug.Error.Count
73 | end
--------------------------------------------------------------------------------
/modules/debug/screens/mob_viewer.lua:
--------------------------------------------------------------------------------
1 | Debug.Mob = {}
2 |
3 | ------------------------------------------------------------------------------------------------------
4 | -- Populates the Mob Viewer tab.
5 | ------------------------------------------------------------------------------------------------------
6 | Debug.Mob.Populate = function(mob)
7 | if mob then
8 | if UI.BeginTable("table1", 2, Window_Manager.Table.Flags.Team) then
9 | Debug.Mob.Headers()
10 | Debug.Mob.Rows(mob)
11 | UI.EndTable()
12 | end
13 | end
14 | end
15 |
16 | ------------------------------------------------------------------------------------------------------
17 | -- Handles setting up the headers for the mob viewer.
18 | ------------------------------------------------------------------------------------------------------
19 | Debug.Mob.Headers = function()
20 | local flags = Column.Flags.None
21 | UI.TableSetupColumn("Flag", flags)
22 | UI.TableSetupColumn("Data", flags)
23 | UI.TableHeadersRow()
24 | end
25 |
26 | ------------------------------------------------------------------------------------------------------
27 | -- Creates the rows of the mob viewer.
28 | ------------------------------------------------------------------------------------------------------
29 | Debug.Mob.Rows = function(mob)
30 | UI.TableNextRow()
31 | UI.TableNextColumn() UI.Text("name")
32 | UI.TableNextColumn() UI.Text(tostring(mob.name))
33 | UI.TableNextRow()
34 | UI.TableNextColumn() UI.Text("id")
35 | UI.TableNextColumn() UI.Text(tostring(mob.id_num))
36 | UI.TableNextRow()
37 | UI.TableNextColumn() UI.Text("index")
38 | UI.TableNextColumn() UI.Text(tostring(mob.index))
39 | UI.TableNextRow()
40 | UI.TableNextColumn() UI.Text("entity_type")
41 | UI.TableNextColumn() UI.Text(tostring(mob.entity_type))
42 | UI.TableNextRow()
43 | UI.TableNextColumn() UI.Text("status")
44 | UI.TableNextColumn() UI.Text(tostring(mob.status))
45 | UI.TableNextRow()
46 | UI.TableNextColumn() UI.Text("distance")
47 | UI.TableNextColumn() UI.Text(string.format("%.1f",(Ashita.Mob.Distance(Ashita.Mob.Get_Mob_By_Target(Ashita.Enum.Targets.ME), mob))))
48 | UI.TableNextRow()
49 | UI.TableNextColumn() UI.Text("hpp")
50 | UI.TableNextColumn() UI.Text(tostring(mob.hpp))
51 | UI.TableNextRow()
52 | UI.TableNextColumn() UI.Text("x")
53 | UI.TableNextColumn() UI.Text(Column.String.Format_Number(mob.x))
54 | UI.TableNextRow()
55 | UI.TableNextColumn() UI.Text("y")
56 | UI.TableNextColumn() UI.Text(Column.String.Format_Number(mob.y))
57 | UI.TableNextRow()
58 | UI.TableNextColumn() UI.Text("z")
59 | UI.TableNextColumn() UI.Text(Column.String.Format_Number(mob.z))
60 | UI.TableNextRow()
61 | UI.TableNextColumn() UI.Text("target_index")
62 | UI.TableNextColumn() UI.Text(tostring(mob.target_index))
63 | UI.TableNextRow()
64 | UI.TableNextColumn() UI.Text("pet_index")
65 | UI.TableNextColumn() UI.Text(tostring(mob.pet_index))
66 | UI.TableNextRow()
67 | UI.TableNextColumn() UI.Text("claim_id")
68 | UI.TableNextColumn() UI.Text(tostring(mob.claim_id))
69 | UI.TableNextRow()
70 | UI.TableNextColumn() UI.Text("spawn_flags")
71 | UI.TableNextColumn() UI.Text(tostring(mob.spawn_flags))
72 | UI.TableNextRow()
73 | UI.TableNextColumn() UI.Text("in_party")
74 | UI.TableNextColumn() UI.Text(tostring(mob.in_party))
75 | UI.TableNextRow()
76 | UI.TableNextColumn() UI.Text("in_alliance")
77 | UI.TableNextColumn() UI.Text(tostring(mob.in_alliance))
78 | end
--------------------------------------------------------------------------------
/modules/exp/chains.lua:
--------------------------------------------------------------------------------
1 | XP.Chains = T{}
2 |
3 | -- Adapted from Points and ASB.
4 | -- https://github.com/Shinzaku/Points
5 | XP.Chains.Max_Times = T{
6 | {level=10, maxtime={80, 80, 60, 40, 30, 15}},
7 | {level=20, maxtime={130, 130, 110, 80, 60, 25}},
8 | {level=30, maxtime={160, 150, 120, 90, 60, 30}},
9 | {level=40, maxtime={200, 200, 170, 130, 80, 40}},
10 | {level=50, maxtime={290, 290, 230, 170, 110, 50}},
11 | {level=99, maxtime={300, 300, 240, 180, 120, 60}},
12 | }
13 |
14 | XP.Chains.Is_Active = false
15 | XP.Chains.Start_Time = 0
16 | XP.Chains.Duration = 0
17 | XP.Chains.Current = -1
18 | XP.Chains.Max = 0
19 |
20 | -- ------------------------------------------------------------------------------------------------------
21 | -- Sets appropriate data for the start or continuation of a chain.
22 | -- ------------------------------------------------------------------------------------------------------
23 | ---@param chain integer
24 | -- ------------------------------------------------------------------------------------------------------
25 | XP.Chains.Start = function(chain)
26 | if chain > XP.Chains.Current then
27 | XP.Chains.Is_Active = true
28 | XP.Chains.Start_Time = os.time()
29 | XP.Chains.Metrics(chain)
30 | XP.Chains.Set_Duration()
31 | end
32 | end
33 |
34 | -- ------------------------------------------------------------------------------------------------------
35 | -- Ends the chain.
36 | -- ------------------------------------------------------------------------------------------------------
37 | XP.Chains.End = function()
38 | XP.Chains.Current = -1
39 | XP.Chains.Duration = 999
40 | XP.Chains.Start_Time = 0
41 | XP.Chains.Is_Active = false
42 | end
43 |
44 | -- ------------------------------------------------------------------------------------------------------
45 | -- Handles chain metrics.
46 | -- ------------------------------------------------------------------------------------------------------
47 | ---@param chain integer
48 | -- ------------------------------------------------------------------------------------------------------
49 | XP.Chains.Metrics = function(chain)
50 | if not chain then chain = 0 end
51 | if chain > XP.Metric.Max_Chain then XP.Metric.Max_Chain = chain end
52 | XP.Chains.Current = chain
53 | end
54 |
55 | -- ------------------------------------------------------------------------------------------------------
56 | -- Gets the amount of time left in the current chain.
57 | -- ------------------------------------------------------------------------------------------------------
58 | XP.Chains.Set_Duration = function()
59 | local player = Ashita.Player.Get()
60 | if not player then return nil end
61 | local level = player:GetMainJobLevel()
62 | local chain = XP.Chains.Current
63 | if not chain or chain <= 0 then XP.Chains.Duration = 999 end
64 | chain = chain + 1 -- Chain we are going for is the next chain.
65 | if chain > 6 then chain = 6 end
66 | for _, bucket in ipairs(XP.Chains.Max_Times) do
67 | if level <= bucket.level then
68 | if bucket.maxtime[chain] then
69 | XP.Chains.Duration = bucket.maxtime[chain]
70 | break
71 | end
72 | end
73 | end
74 | end
75 |
76 | -- ------------------------------------------------------------------------------------------------------
77 | -- Handles the chain countdown.
78 | -- ------------------------------------------------------------------------------------------------------
79 | XP.Chains.Timer = function()
80 | local color = Res.Colors.Basic.WHITE
81 | if not XP.Chains.Is_Active then return UI.TextColored(color, "--:--") end
82 | local now = os.time()
83 | local elapsed_time = now - XP.Chains.Start_Time
84 | local time_remaining = XP.Chains.Duration - elapsed_time
85 | if time_remaining <=0 then
86 | color = Res.Colors.Basic.RED
87 | XP.Chains.End()
88 | elseif time_remaining <= 10 then
89 | color = Res.Colors.Basic.RED
90 | elseif time_remaining <= 30 then
91 | color = Res.Colors.Basic.YELLOW
92 | else
93 | color = Res.Colors.Basic.WHITE
94 | end
95 | UI.TextColored(color, Timers.Format(time_remaining, true))
96 | end
--------------------------------------------------------------------------------
/modules/exp/dedication.lua:
--------------------------------------------------------------------------------
1 | XP.Dedication = T{}
2 |
3 | XP.Dedication.Is_Active = true
4 | XP.Dedication.Need_Defaulting = false
5 | XP.Dedication.Need_Clear = false
6 | XP.Dedication.Zone_Delay = 10
7 |
8 | -- ------------------------------------------------------------------------------------------------------
9 | -- Checks if dedication is active.
10 | -- ------------------------------------------------------------------------------------------------------
11 | XP.Dedication.Check = function()
12 | XP.Dedication.Is_Active = Ashita.Player.Has_Buff(Ashita.Player.Buffs.DEDICATION)
13 |
14 | if not XP.Dedication.Is_Active and not Ashita.States.Zoning and XP.Dedication.Need_Clear
15 | and Timers.Get_Duration(Timers.Enum.Names.ZONE) > XP.Dedication.Zone_Delay then
16 | XP.Dedication.Clear()
17 |
18 | elseif XP.Dedication.Is_Active and XP.Dedication.Need_Defaulting then
19 | local default_item = Res.Items.Get_Dedication(0)
20 | if Metrics.XP.Boost_Default then
21 | local default_item_id = Res.Items.Get_Dedication_ID_From_Name(Metrics.XP.Boost_Item_Default_Name)
22 | default_item = Res.Items.Get_Dedication(default_item_id)
23 | end
24 | XP.Dedication.Set(default_item)
25 |
26 | elseif XP.Dedication.Is_Active then
27 | XP.Dedication.Need_Clear = true
28 |
29 | end
30 | end
31 |
32 | -- ------------------------------------------------------------------------------------------------------
33 | -- Checks dedication progress.
34 | -- ------------------------------------------------------------------------------------------------------
35 | ---@return number
36 | -- ------------------------------------------------------------------------------------------------------
37 | XP.Dedication.Progress = function()
38 | if not XP.Dedication.Is_Active then return 0 end
39 | local bonus_xp = Metrics.XP.Boost_EXP
40 | local max_xp = Metrics.XP.Boost_Item_Max
41 | if not max_xp or max_xp == 0 then max_xp = 1 end
42 | return bonus_xp / max_xp
43 | end
44 |
45 | -- ------------------------------------------------------------------------------------------------------
46 | -- Sets dedication flags.
47 | -- ------------------------------------------------------------------------------------------------------
48 | ---@param item? table
49 | ---@param from_packet? boolean if the call comes from a packet then a real item was used.
50 | -- ------------------------------------------------------------------------------------------------------
51 | XP.Dedication.Set = function(item, from_packet)
52 | if item and item.name then
53 | XP.Dedication.Is_Active = true -- Need to set manually when item is used.
54 | Metrics.XP.Boost_Item_Name = item.name
55 | Metrics.XP.Boost_Item_Rate = item.boost
56 | Metrics.XP.Boost_Item_Max = item.max
57 | if from_packet then XP.Dedication.Need_Defaulting = false end
58 | end
59 | end
60 |
61 | -- ------------------------------------------------------------------------------------------------------
62 | -- Clears dedication flags.
63 | -- ------------------------------------------------------------------------------------------------------
64 | XP.Dedication.Clear = function()
65 | Metrics.XP.Boost_Item_Name = "None"
66 | Metrics.XP.Boost_Item_Rate = 0
67 | Metrics.XP.Boost_Item_Max = 0
68 | Metrics.XP.Boost_EXP = 0
69 | XP.Dedication.Need_Defaulting = true
70 | XP.Dedication.Need_Clear = false
71 | Window_Manager.Set_Bar_Delay()
72 | end
--------------------------------------------------------------------------------
/modules/focus/abilities.lua:
--------------------------------------------------------------------------------
1 | Focus.Abilities = T{}
2 |
3 | ------------------------------------------------------------------------------------------------------
4 | -- Loads data to the ability drop down inside the focus window.
5 | ------------------------------------------------------------------------------------------------------
6 | ---@param player_name string
7 | ---@param hide_publish? boolean
8 | ------------------------------------------------------------------------------------------------------
9 | Focus.Abilities.Display = function(player_name, hide_publish)
10 | local ability_total = DB.Data.Get(player_name, DB.Enum.Trackable.ABILITY_DAMAGING, DB.Enum.Metric.COUNT)
11 | local healing_total = DB.Data.Get(player_name, DB.Enum.Trackable.ABILITY_HEALING, DB.Enum.Metric.COUNT)
12 | local mp_recovery = DB.Data.Get(player_name, DB.Enum.Trackable.ABILITY_MP_RECOVERY, DB.Enum.Metric.COUNT)
13 | local maneuvers = DB.Data.Get(player_name, DB.Enum.Trackable.MANEUVER, DB.Enum.Metric.COUNT)
14 | local rolls = DB.Data.Get(player_name, DB.Enum.Trackable.PHANTOM_ROLL, DB.Enum.Metric.COUNT)
15 | local misc_count = DB.Data.Get(player_name, DB.Enum.Trackable.ABILITY, DB.Enum.Metric.COUNT)
16 |
17 | Focus.Abilities.Total(player_name)
18 | UI.Separator()
19 |
20 | if rolls > 0 then Focus.Overview.Phantom_Roll(player_name, true) end
21 | if maneuvers > 0 then
22 | Focus.Overview.Overload(player_name)
23 | Focus.Overview.Maneuvers(player_name)
24 | end
25 | if ability_total > 0 then Focus.Catalog.Abilities(player_name, DB.Enum.Trackable.ABILITY_DAMAGING, "Damaging") end
26 | if healing_total > 0 then Focus.Catalog.Abilities(player_name, DB.Enum.Trackable.ABILITY_HEALING, "Healing") end
27 | if mp_recovery > 0 then Focus.Catalog.Abilities(player_name, DB.Enum.Trackable.ABILITY_MP_RECOVERY, "MP Recover") end
28 | if misc_count > 0 and Metrics.Focus.Show_Misc_Actions then Focus.Catalog.Abilities_General(player_name) end
29 |
30 | if not hide_publish then Focus.Abilities.Publish(player_name, ability_total, healing_total) end
31 | end
32 |
33 | ------------------------------------------------------------------------------------------------------
34 | -- Loads data to the ability table inside the focus window.
35 | ------------------------------------------------------------------------------------------------------
36 | ---@param player_name string
37 | ------------------------------------------------------------------------------------------------------
38 | Focus.Abilities.Total = function(player_name)
39 | local col_flags = Focus.Column_Flags
40 | local table_flags = Focus.Table_Flags
41 | local name_width = Column.Widths.Name
42 | local width = Column.Widths.Standard
43 |
44 | local row = 1
45 | if UI.BeginTable("Ability", 2, table_flags) then
46 | UI.TableSetupColumn("Type", col_flags, name_width)
47 | UI.TableSetupColumn("Total", col_flags, width)
48 | UI.TableHeadersRow()
49 |
50 | UI.TableNextRow()
51 | UI.TableNextColumn() UI.Text("Damaging")
52 | UI.TableNextColumn() Column.Damage.By_Type(player_name, DB.Enum.Trackable.ABILITY_DAMAGING)
53 | Window_Manager.Table_Row_Color(row)
54 | row = row + 1
55 |
56 | UI.TableNextRow()
57 | UI.TableNextColumn()UI.Text("Healing")
58 | UI.TableNextColumn() Column.Damage.By_Type(player_name, DB.Enum.Trackable.ABILITY_HEALING)
59 | Window_Manager.Table_Row_Color(row)
60 | row = row + 1
61 |
62 | UI.TableNextRow()
63 | UI.TableNextColumn()UI.Text("MP Recovery")
64 | UI.TableNextColumn() Column.Damage.By_Type(player_name, DB.Enum.Trackable.ABILITY_MP_RECOVERY)
65 | Window_Manager.Table_Row_Color(row)
66 | row = row + 1
67 |
68 | UI.EndTable()
69 | end
70 | end
71 |
72 | ------------------------------------------------------------------------------------------------------
73 | -- Sets up ability publishing buttons from within the focus window.
74 | ------------------------------------------------------------------------------------------------------
75 | ---@param player_name string
76 | ---@param ability_total number
77 | ---@param healing_total number
78 | ------------------------------------------------------------------------------------------------------
79 | Focus.Abilities.Publish = function(player_name, ability_total, healing_total)
80 | if ability_total > 0 then
81 | Report.Widgets.Button(player_name, DB.Enum.Trackable.ABILITY_DAMAGING, "Publish Abilities")
82 | end
83 | if healing_total > 0 then
84 | if ability_total > 0 then UI.SameLine() UI.Text(" ") UI.SameLine() end
85 | Report.Widgets.Button(player_name, DB.Enum.Trackable.ABILITY_HEALING, "Publish Healing")
86 | end
87 | end
--------------------------------------------------------------------------------
/modules/focus/config.lua:
--------------------------------------------------------------------------------
1 | Focus.Config = T{}
2 |
3 | Focus.Config.Defaults = T{
4 | X = 100,
5 | Y = 100,
6 | Visible = {true},
7 | Show_Mitigation_Details = false,
8 | Show_Misc_Actions = false,
9 | }
10 |
11 | Focus.Config.Show_Percent_Details = false
12 | Focus.Config.Column_Flags = Column.Flags.None
13 | Focus.Config.Column_Width = Column.Widths.Settings
14 |
15 | ------------------------------------------------------------------------------------------------------
16 | -- Shows settings that affect the focus screens.
17 | ------------------------------------------------------------------------------------------------------
18 | Focus.Config.Display = function()
19 | local col_flags = Focus.Config.Column_Flags
20 |
21 | if UI.BeginTable("Focus General", 2) then
22 | UI.TableSetupColumn("Col 1", col_flags)
23 | UI.TableSetupColumn("Col 2", col_flags)
24 |
25 | -- Row 1
26 | UI.TableNextColumn()
27 | if UI.Checkbox("Misc Actions", {Metrics.Focus.Show_Misc_Actions}) then
28 | Metrics.Focus.Show_Misc_Actions = not Metrics.Focus.Show_Misc_Actions
29 | end
30 | UI.SameLine() Window_Manager.Widgets.HelpMarker("Shows uncategorized actions in the catalog lists. "
31 | .."Sometimes these lists can get quite long and take up a lot of space. "
32 | .."Turn this off if you aren't interested in seeing those.")
33 |
34 | UI.EndTable()
35 | end
36 | end
37 |
38 | ------------------------------------------------------------------------------------------------------
39 | -- Toggles the settings showing for the battle log.
40 | ------------------------------------------------------------------------------------------------------
41 | Focus.Config.Settings_Button = function()
42 | if UI.SmallButton("Settings") then
43 | Config.Button_Toggle(Config.Enum.File.FOCUS)
44 | end
45 | end
46 |
47 | ------------------------------------------------------------------------------------------------------
48 | -- Shows percent details checkbox.
49 | ------------------------------------------------------------------------------------------------------
50 | Focus.Config.Percent_Details = function()
51 | if UI.SmallButton("% Details") then
52 | Focus.Config.Percent_Toggle()
53 | end
54 | end
55 |
56 | ------------------------------------------------------------------------------------------------------
57 | -- Toggles the percent details setting.
58 | ------------------------------------------------------------------------------------------------------
59 | Focus.Config.Percent_Toggle = function()
60 | Focus.Config.Show_Percent_Details = not Focus.Config.Show_Percent_Details
61 | end
--------------------------------------------------------------------------------
/modules/focus/weaponskills.lua:
--------------------------------------------------------------------------------
1 | Focus.WS = T{}
2 |
3 | ------------------------------------------------------------------------------------------------------
4 | -- Loads data to the weaponskill and skillchain drop down inside the focus window.
5 | ------------------------------------------------------------------------------------------------------
6 | ---@param player_name string
7 | ---@param hide_publish? boolean
8 | ------------------------------------------------------------------------------------------------------
9 | Focus.WS.Display = function(player_name, hide_publish)
10 | local col_flags = Column.Flags.None
11 | local table_flags = Window_Manager.Table.Flags.Fixed_Borders
12 | local name_width = Column.Widths.Name
13 | local width = Column.Widths.Standard
14 |
15 | local trackable_ws = DB.Enum.Trackable.WS
16 | local trackable_sc = DB.Enum.Trackable.SC
17 |
18 | local row = 1
19 | if UI.BeginTable("WS and SC", 7, table_flags) then
20 | UI.TableSetupColumn("Type", col_flags, name_width)
21 | UI.TableSetupColumn("Damage", col_flags, width)
22 | UI.TableSetupColumn("%Player", col_flags, width)
23 | UI.TableSetupColumn("Average", col_flags, width)
24 | UI.TableSetupColumn("Accuracy", col_flags, width)
25 | UI.TableSetupColumn("~TP", col_flags, width)
26 | UI.TableSetupColumn("DMG/TP", col_flags, width)
27 | UI.TableHeadersRow()
28 |
29 | UI.TableNextRow()
30 | UI.TableNextColumn() UI.Text("Weaponskills")
31 | UI.TableNextColumn() Column.Damage.By_Type(player_name, trackable_ws)
32 | UI.TableNextColumn() Column.Damage.By_Type(player_name, trackable_ws, true)
33 | UI.TableNextColumn() Column.Damage.Average_By_Type(player_name, trackable_ws)
34 | UI.TableNextColumn() Column.Acc.By_Type(player_name, trackable_ws)
35 | UI.TableNextColumn() Column.Damage.Average_TP(player_name)
36 | UI.TableNextColumn() Column.General.Fraction(player_name, trackable_ws, DB.Enum.Metric.TOTAL, DB.Enum.Metric.TP_SPENT, false, false, true)
37 | Window_Manager.Table_Row_Color(row)
38 | row = row + 1
39 |
40 | UI.TableNextRow()
41 | UI.TableNextColumn() UI.Text("Skillchains")
42 | UI.TableNextColumn() Column.Damage.By_Type(player_name, trackable_sc)
43 | UI.TableNextColumn() Column.Damage.By_Type(player_name, trackable_sc, true)
44 | UI.TableNextColumn() Column.Damage.Average_By_Type(player_name, trackable_sc)
45 | UI.TableNextColumn() UI.TextColored(Res.Colors.Basic.DIM, "---")
46 | UI.TableNextColumn() UI.TextColored(Res.Colors.Basic.DIM, "---")
47 | UI.TableNextColumn() UI.TextColored(Res.Colors.Basic.DIM, "---")
48 | Window_Manager.Table_Row_Color(row)
49 | row = row + 1
50 |
51 | UI.EndTable()
52 | end
53 |
54 | Focus.Overview.Skillchains(player_name)
55 |
56 | -- Cataloged data
57 | local show_ws_publish = false
58 | local show_sc_publish = false
59 | if DB.Tracking.Trackable[DB.Enum.Trackable.WS] and DB.Tracking.Trackable[DB.Enum.Trackable.WS][player_name] then
60 | Focus.Catalog.Weaponskill(player_name, DB.Enum.Trackable.WS)
61 | show_ws_publish = true
62 | end
63 |
64 | if DB.Tracking.Trackable[DB.Enum.Trackable.SC] and DB.Tracking.Trackable[DB.Enum.Trackable.SC][player_name] then
65 | Focus.Catalog.Skillchains(player_name, DB.Enum.Trackable.SC)
66 | show_sc_publish = true
67 | end
68 |
69 | -- Publish buttons
70 | if not hide_publish then
71 | if show_ws_publish then
72 | Report.Widgets.Button(player_name, trackable_ws, "Publish Weaponskills")
73 | end
74 | if show_sc_publish then
75 | UI.SameLine() UI.Text(" ") UI.SameLine()
76 | Report.Widgets.Button(player_name, trackable_sc, "Publish Skillchains")
77 | end
78 | end
79 | end
--------------------------------------------------------------------------------
/modules/hub/config.lua:
--------------------------------------------------------------------------------
1 | Hub.Config = T{}
2 |
3 | Hub.Config.Defaults = T{
4 | X = 100,
5 | Y = 100,
6 | Visible = {true},
7 | }
--------------------------------------------------------------------------------
/modules/overview/_overview.lua:
--------------------------------------------------------------------------------
1 | Overview = T{}
2 |
3 | Overview.Name = "Overview"
4 | Overview.Title = "Metrics - Overview"
5 | Overview.Module = "Overview"
6 | Overview.Window = Window:New({
7 | Name = Overview.Name,
8 | Title = Overview.Title,
9 | Module = Overview.Module,
10 | Visible = {false},
11 | Show_Title = true,
12 | })
13 |
14 | Overview.Modes = T{
15 | PARSE = "Parse",
16 | FOCUS = "Focus",
17 | BLOG = "Battle Log",
18 | }
19 | Overview.Mode = Overview.Modes.PARSE
20 |
21 | require("modules.overview.config")
22 | require("modules.overview.parse")
23 | require("modules.overview.focus")
24 |
25 | ------------------------------------------------------------------------------------------------------
26 | -- Opens a new window to show all tabs as a vertical column.
27 | ------------------------------------------------------------------------------------------------------
28 | Overview.Content = function()
29 | if Overview.Mode == Overview.Modes.PARSE then
30 | Overview.Parse.Content()
31 | elseif Overview.Mode == Overview.Modes.FOCUS then
32 | local player_name = DB.Widgets.Util.Get_Player_Focus()
33 | if player_name == DB.Widgets.Dropdown.Enum.NONE then
34 | Focus.Screenshot_Mode[1] = false
35 | return nil
36 | end
37 | Overview.Focus.Content(player_name)
38 | else
39 | UI.Text("No content.")
40 | end
41 | end
42 |
43 | ------------------------------------------------------------------------------------------------------
44 | -- Button that opens the overview window with focus content.
45 | ------------------------------------------------------------------------------------------------------
46 | Overview.Screenshot_Button = function()
47 | if UI.SmallButton("Screenshot") then
48 | if Overview.Mode == Overview.Modes.FOCUS then
49 | Overview.Window.Toggle_Visibility()
50 | else
51 | Overview.Window.Show()
52 | Overview.Mode = Overview.Modes.FOCUS
53 | end
54 | end
55 | end
56 |
57 | ------------------------------------------------------------------------------------------------------
58 | -- Button that opens the overview window with parse content.
59 | ------------------------------------------------------------------------------------------------------
60 | Overview.Overview_Button = function()
61 | if UI.SmallButton("Overview") then
62 | if Overview.Mode == Overview.Modes.PARSE then
63 | Overview.Window.Toggle_Visibility()
64 | else
65 | Overview.Window.Show()
66 | Overview.Mode = Overview.Modes.PARSE
67 | end
68 | end
69 | end
--------------------------------------------------------------------------------
/modules/overview/config.lua:
--------------------------------------------------------------------------------
1 | Overview.Config = T{}
2 |
3 | Overview.Config.Defaults = T{
4 | X = 100,
5 | Y = 100,
6 | Visible = {false},
7 | Timer = true,
8 | Melee = false,
9 | Ranged = false,
10 | WS = false,
11 | Nuke = false,
12 | Pets = false,
13 | Healing = false,
14 | Defense = false,
15 | Mobs_Defeated = false,
16 | }
--------------------------------------------------------------------------------
/modules/overview/focus.lua:
--------------------------------------------------------------------------------
1 | Overview.Focus = T{}
2 |
3 | ------------------------------------------------------------------------------------------------------
4 | -- Content for the Focus screenshot window.
5 | ------------------------------------------------------------------------------------------------------
6 | ---@param player_name string
7 | ------------------------------------------------------------------------------------------------------
8 | Overview.Focus.Content = function(player_name)
9 | UI.Text("Overall") Focus.Overall(player_name)
10 | UI.Separator() UI.Text("Melee") Focus.Melee.Display(player_name)
11 | UI.Separator() UI.Text("Ranged") Focus.Ranged.Display(player_name)
12 | UI.Separator() UI.Text("Weaponskills") Focus.WS.Display(player_name, true)
13 | UI.Separator() UI.Text("Magic") Focus.Magic.Display(player_name, true)
14 | UI.Separator() UI.Text("Abilities") Focus.Abilities.Display(player_name, true)
15 | UI.Separator() UI.Text("Pets") Focus.Pets.Display(player_name)
16 | UI.Separator() UI.Text("Defense") Focus.Defense.Display(player_name)
17 | end
--------------------------------------------------------------------------------
/modules/parse/_parse.lua:
--------------------------------------------------------------------------------
1 | Parse = T{}
2 |
3 | Parse.Name = "Parse"
4 | Parse.Title = "Metrics - Parse"
5 | Parse.Module = "Parse"
6 | Parse.Window = Window:New({
7 | Name = Parse.Name,
8 | Title = Parse.Title,
9 | Module = Parse.Module,
10 | })
11 |
12 | -- Used to house general functions that I don't want immediately exposed.
13 | Parse.Util = {}
14 |
15 | -- Keeps track of how many columns should be shown on the screen in full mode.
16 | Parse.Columns = {
17 | Base = 3, -- Name, Total, %T
18 | Current = 5,
19 | Max = 32,
20 | }
21 |
22 | Parse.Confirmation = false
23 |
24 | -- Load dependencies
25 | require("modules.parse.enum")
26 | require("modules.parse.config")
27 | require("modules.parse.display_full")
28 | require("modules.parse.display_mini")
29 | require("modules.parse.display_nano")
30 | require("modules.parse.widgets")
31 |
32 | ------------------------------------------------------------------------------------------------------
33 | -- Initializes the Parse screen.
34 | ------------------------------------------------------------------------------------------------------
35 | Parse.Initialize = function()
36 | Parse.Util.Calculate_Column_Flags()
37 | end
38 |
39 | ------------------------------------------------------------------------------------------------------
40 | -- Parse window content.
41 | ------------------------------------------------------------------------------------------------------
42 | Parse.Content = function()
43 | if Parse.Nano.Is_Enabled() then
44 | Parse.Nano.Populate()
45 | elseif Parse.Mini.Is_Enabled() then
46 | Parse.Mini.Populate()
47 | else
48 | Parse.Full.Populate()
49 | end
50 | end
51 |
52 | ------------------------------------------------------------------------------------------------------
53 | -- Calculates how many columns should be shown on the Parse table based on column visibility flags.
54 | ------------------------------------------------------------------------------------------------------
55 | Parse.Util.Calculate_Column_Flags = function()
56 | local added_columns = 0
57 | if Metrics.Parse.Focus then added_columns = added_columns + 1 end
58 | if Metrics.Parse.Jobs then added_columns = added_columns + 1 end
59 | if Metrics.Parse.Attack_Speed then added_columns = added_columns + 1 end
60 | if Metrics.Parse.DPS then added_columns = added_columns + 1 end
61 | if Metrics.Parse.Running_Acc then added_columns = added_columns + 1 end
62 | if Metrics.Parse.Total_Acc then added_columns = added_columns + 1 end
63 | if Metrics.Parse.Crit then added_columns = added_columns + 1 end
64 | if Metrics.Parse.Melee then added_columns = added_columns + 1 end
65 | if Metrics.Parse.Melee_Acc then added_columns = added_columns + 1 end
66 | if Metrics.Parse.Melee_Crit then added_columns = added_columns + 1 end
67 | if Metrics.Parse.Weaponskill then added_columns = added_columns + 1 end
68 | if Metrics.Parse.Average_WS then added_columns = added_columns + 1 end
69 | if Metrics.Parse.WS_TP then added_columns = added_columns + 1 end
70 | if Metrics.Parse.WS_Accuracy then added_columns = added_columns + 1 end
71 | if Parse.Config.Include_SC_Damage() then added_columns = added_columns + 1 end
72 | if Metrics.Parse.Ranged then added_columns = added_columns + 1 end
73 | if Metrics.Parse.Ranged_Acc then added_columns = added_columns + 1 end
74 | if Metrics.Parse.Ranged_Crit then added_columns = added_columns + 1 end
75 | if Metrics.Parse.Ranged_Dist then added_columns = added_columns + 1 end
76 | if Metrics.Parse.Magic then added_columns = added_columns + 1 end
77 | if Metrics.Parse.Ability then added_columns = added_columns + 1 end
78 | if Metrics.Parse.Pet_Acc then added_columns = added_columns + 1 end
79 | if Metrics.Parse.Pet_Melee then added_columns = added_columns + 1 end
80 | if Metrics.Parse.Pet_Ranged then added_columns = added_columns + 1 end
81 | if Metrics.Parse.Pet_WS then added_columns = added_columns + 1 end
82 | if Metrics.Parse.Pet_Ability then added_columns = added_columns + 1 end
83 | if Metrics.Parse.Healing then added_columns = added_columns + 1 end
84 | if Metrics.Parse.Damage_Taken then added_columns = added_columns + 1 end
85 | if Metrics.Parse.Deaths then added_columns = added_columns + 1 end
86 |
87 | -- Apply new column count.
88 | Parse.Columns.Current = Parse.Columns.Base + added_columns
89 | if Parse.Columns.Current > Parse.Columns.Max then Parse.Columns.Current = Parse.Columns.Max end
90 | end
--------------------------------------------------------------------------------
/modules/parse/display_mini.lua:
--------------------------------------------------------------------------------
1 | Parse.Mini = T{}
2 |
3 | Parse.Mini.Column_Flags = Column.Flags.None
4 | Parse.Mini.Table_Flags = bit.bor(ImGuiTableFlags_Borders)
5 |
6 | ------------------------------------------------------------------------------------------------------
7 | -- Loads shows just the Team tab with just the player.
8 | ------------------------------------------------------------------------------------------------------
9 | Parse.Mini.Populate = function()
10 | local columns = 3
11 | if Parse.Config.Is_Pet_Column_Enabled() then columns = columns + 2 end
12 | if Metrics.Parse.Attack_Speed then columns = columns + 1 end
13 | if Metrics.Parse.DPS then columns = columns + 1 end
14 | if Metrics.Parse.Running_Acc then columns = columns + 1 end
15 | if Metrics.Parse.Lurk_Mode then UI.Text("Lurking...") end
16 | if UI.BeginTable("Team Mini", columns, Parse.Mini.Table_Flags) then
17 | Parse.Mini.Headers()
18 |
19 | local player = Ashita.Player.My_Mob()
20 | if not player then return nil end
21 |
22 | local player_name = "Debug"
23 | DB.Lists.Sort.Total_Damage()
24 | for rank, data in ipairs(DB.Sorted.Total_Damage) do
25 | if rank <= Parse.Config.Rank_Cutoff() then
26 | player_name = data[1]
27 | Parse.Mini.Rows(player_name)
28 | elseif data[1] == player.name then
29 | Parse.Mini.Rows(player.name)
30 | end
31 | end
32 | if Metrics.Parse.Grand_Totals and #DB.Sorted.Total_Damage > 0 then Parse.Mini.Total_Row() end
33 |
34 | UI.EndTable()
35 | end
36 | end
37 |
38 | ------------------------------------------------------------------------------------------------------
39 | -- Populate table headers for mini mode.
40 | ------------------------------------------------------------------------------------------------------
41 | Parse.Mini.Headers = function()
42 | local flags = Parse.Mini.Column_Flags
43 |
44 | UI.TableSetupColumn("Name", flags)
45 | UI.TableSetupColumn("Total", flags)
46 | UI.TableSetupColumn("%T", flags)
47 | if Metrics.Parse.Attack_Speed then UI.TableSetupColumn("Speed", flags) end
48 | if Metrics.Parse.DPS then UI.TableSetupColumn(DB.DPS.Column_Header(), flags) end
49 | if Metrics.Parse.Running_Acc then UI.TableSetupColumn("%A-" .. Metrics.Model.Running_Accuracy_Limit, flags) end
50 | if Parse.Config.Is_Pet_Column_Enabled() then
51 | UI.TableSetupColumn("Pet D.", flags)
52 | UI.TableSetupColumn("Pet A.", flags)
53 | end
54 | UI.TableHeadersRow()
55 | end
56 |
57 | ------------------------------------------------------------------------------------------------------
58 | -- Populate table rows for mini mode.
59 | ------------------------------------------------------------------------------------------------------
60 | ---@param player_name string
61 | ------------------------------------------------------------------------------------------------------
62 | Parse.Mini.Rows = function(player_name)
63 | UI.TableNextRow()
64 | UI.TableNextColumn() Column.String.Format_Name(player_name)
65 | UI.TableNextColumn() Column.Damage.Total(player_name, false, true)
66 | UI.TableNextColumn() Column.Damage.Total(player_name, true, true)
67 | if Metrics.Parse.Attack_Speed then UI.TableNextColumn() Column.Attack_Speed.Get(player_name, true) end
68 | if Metrics.Parse.DPS then UI.TableNextColumn() Column.Damage.DPS(player_name, true) end
69 | if Metrics.Parse.Running_Acc then UI.TableNextColumn() Column.Acc.Running(player_name, true) end
70 | if Parse.Config.Is_Pet_Column_Enabled() then
71 | UI.TableNextColumn() Column.Damage.By_Type(player_name, DB.Enum.Trackable.PET)
72 | UI.TableNextColumn() Column.Acc.By_Type(player_name, DB.Enum.Trackable.PET_MELEE_DISCRETE)
73 | end
74 | end
75 |
76 | ------------------------------------------------------------------------------------------------------
77 | -- Shows totals for each column.
78 | ------------------------------------------------------------------------------------------------------
79 | Parse.Mini.Total_Row = function()
80 | UI.TableNextRow()
81 | local x, y, z, w = UI.GetStyleColorVec4(ImGuiCol_TableHeaderBg)
82 | local row_bg_color = UI.GetColorU32({x, y, z, w})
83 | UI.TableSetBgColor(ImGuiTableBgTarget_RowBg0, row_bg_color)
84 |
85 | UI.TableNextColumn() UI.Text("Total")
86 | UI.TableNextColumn() Column.Damage.Parse_Total(true)
87 | if Metrics.Parse.Attack_Speed then UI.TableNextColumn() UI.Text(" ") end
88 | if Metrics.Parse.DPS then UI.TableNextColumn() Column.Damage.Parse_DPS(true) end
89 | if Metrics.Parse.Running_Acc then UI.TableNextColumn() UI.Text(" ") end
90 | UI.TableNextColumn() UI.Text(" ")
91 | if Parse.Config.Is_Pet_Column_Enabled() then
92 | UI.TableNextColumn() UI.Text(" ")
93 | UI.TableNextColumn() Column.Damage.Trackable_Total(DB.Enum.Trackable.PET, true)
94 | UI.TableNextColumn() UI.Text(" ")
95 | end
96 | end
97 |
98 | ------------------------------------------------------------------------------------------------------
99 | -- Returns whether mini mode is enabled.
100 | ------------------------------------------------------------------------------------------------------
101 | Parse.Mini.Is_Enabled = function()
102 | return Metrics.Parse.Display_Mode == Parse.Enum.Display_Mode.MINI
103 | end
104 |
105 | ------------------------------------------------------------------------------------------------------
106 | -- Toggles mini mode.
107 | ------------------------------------------------------------------------------------------------------
108 | Parse.Mini.Toggle = function()
109 | Metrics.Parse.Display_Mode = Parse.Enum.Display_Mode.MINI
110 | end
111 |
--------------------------------------------------------------------------------
/modules/parse/display_nano.lua:
--------------------------------------------------------------------------------
1 | Parse.Nano = T{}
2 |
3 | Parse.Nano.Table_Flags = bit.bor(ImGuiTableFlags_Borders)
4 |
5 | ------------------------------------------------------------------------------------------------------
6 | -- Loads shows just the Team tab with just the player.
7 | ------------------------------------------------------------------------------------------------------
8 | Parse.Nano.Populate = function()
9 | local flags = Column.Flags.None
10 | local player = Ashita.Mob.Get_Mob_By_Target(Ashita.Enum.Targets.ME)
11 | if not player then return nil end
12 | local player_name = player.name
13 |
14 | local columns = 1
15 | if Metrics.Parse.DPS then columns = columns + 1 end
16 | if Metrics.Parse.Running_Acc then columns = columns + 1 end
17 |
18 | if UI.BeginTable("Team Nano", columns, Parse.Nano.Table_Flags) then
19 | UI.TableSetupColumn("Total", flags)
20 | if Metrics.Parse.DPS then UI.TableSetupColumn(DB.DPS.Column_Header(), flags) end
21 | if Metrics.Parse.Running_Acc then UI.TableSetupColumn("%A-" .. Metrics.Model.Running_Accuracy_Limit, flags) end
22 | UI.TableHeadersRow()
23 |
24 | UI.TableNextRow()
25 | UI.TableNextColumn() Column.Damage.Total(player_name, false, true)
26 | if Metrics.Parse.DPS then UI.TableNextColumn() Column.Damage.DPS(player_name, true) end
27 | if Metrics.Parse.Running_Acc then UI.TableNextColumn() Column.Acc.Running(player_name, true) end
28 |
29 | UI.EndTable()
30 | end
31 | end
32 |
33 | ------------------------------------------------------------------------------------------------------
34 | -- Returns whether nano mode is enabled.
35 | ------------------------------------------------------------------------------------------------------
36 | Parse.Nano.Is_Enabled = function()
37 | return Metrics.Parse.Display_Mode == Parse.Enum.Display_Mode.NANO
38 | end
39 |
40 | ------------------------------------------------------------------------------------------------------
41 | -- Toggles nano mode.
42 | ------------------------------------------------------------------------------------------------------
43 | Parse.Nano.Toggle = function()
44 | Metrics.Parse.Display_Mode = Parse.Enum.Display_Mode.NANO
45 | end
--------------------------------------------------------------------------------
/modules/parse/enum.lua:
--------------------------------------------------------------------------------
1 | Parse.Enum = T{}
2 |
3 | Parse.Enum.Display_Mode = T{
4 | FULL = 1,
5 | MINI = 2,
6 | NANO = 3,
7 | }
--------------------------------------------------------------------------------
/modules/report/_report.lua:
--------------------------------------------------------------------------------
1 | Report = T{}
2 |
3 | Report.Name = "Report"
4 | Report.Title = "Metrics - Reporting"
5 | Report.Module = "Report"
6 | Report.Window = Window:New({
7 | Name = Report.Name,
8 | Title = Report.Title,
9 | Module = Report.Module,
10 | })
11 |
12 | Report.Section = T{}
13 |
14 | -- Load dependencies
15 | require("modules.report.config")
16 | require("modules.report.publishing")
17 | require("modules.report.widgets")
18 |
19 | ------------------------------------------------------------------------------------------------------
20 | -- Creates some buttons to publish various party metrics to chat.
21 | ------------------------------------------------------------------------------------------------------
22 | Report.Content = function()
23 | Report.Widgets.Settings_Button()
24 | UI.Separator() Report.Section.Chat_Reports()
25 | UI.Separator() Report.Section.File()
26 | end
27 |
28 | ------------------------------------------------------------------------------------------------------
29 | -- Builds the chat report section.
30 | ------------------------------------------------------------------------------------------------------
31 | Report.Section.Chat_Reports = function()
32 | local col_flags = Column.Flags.None
33 | local width = Column.Widths.Report
34 | UI.Text("Chat Reports")
35 | Report.Widgets.Chat_Mode()
36 | if UI.BeginTable("Chat Reports", 4, Window_Manager.Table.Flags.None) then
37 | UI.TableSetupColumn("Col 1", col_flags, width)
38 | UI.TableSetupColumn("Col 2", col_flags, width)
39 | UI.TableSetupColumn("Col 3", col_flags, width)
40 | UI.TableSetupColumn("Col 4", col_flags, width)
41 |
42 | UI.TableNextRow()
43 | UI.TableNextColumn()
44 | if UI.Button("Total Damage") then
45 | Report.Publishing.Total_Damage()
46 | return nil
47 | end
48 | UI.TableNextColumn()
49 | if UI.Button("Accuracy ") then
50 | Report.Publishing.Accuracy()
51 | return nil
52 | end
53 | UI.TableNextColumn()
54 | UI.TableNextColumn()
55 | --
56 | UI.TableNextColumn()
57 | if UI.Button("Melee ") then
58 | Report.Publishing.Damage_By_Type(DB.Enum.Trackable.MELEE)
59 | return nil
60 | end
61 | UI.TableNextColumn()
62 | if UI.Button("Weaponskills") then
63 | Report.Publishing.Damage_By_Type(DB.Enum.Trackable.WS)
64 | return nil
65 | end
66 | UI.TableNextColumn()
67 | if UI.Button("Magic ") then
68 | Report.Publishing.Damage_By_Type(DB.Enum.Trackable.MAGIC)
69 | return nil
70 | end
71 | UI.TableNextColumn()
72 | if UI.Button("Pet ") then
73 | Report.Publishing.Damage_By_Type(DB.Enum.Trackable.PET)
74 | return nil
75 | end
76 | --
77 | UI.TableNextColumn()
78 | if UI.Button("Abilities ") then
79 | Report.Publishing.Damage_By_Type(DB.Enum.Trackable.ABILITY_DAMAGING)
80 | return nil
81 | end
82 | UI.TableNextColumn()
83 | if UI.Button("Healing ") then
84 | Report.Publishing.Damage_By_Type(DB.Enum.Trackable.ALL_HEAL)
85 | return nil
86 | end
87 | UI.EndTable()
88 | end
89 | end
90 |
91 | ------------------------------------------------------------------------------------------------------
92 | -- Builds the file section.
93 | ------------------------------------------------------------------------------------------------------
94 | Report.Section.File = function()
95 | local col_flags = Column.Flags.None
96 | local width = Column.Widths.Report
97 | UI.Text("Create CSV File")
98 | UI.Text("Files can be found in: /config/Metrics/")
99 |
100 | local blog_length = #Blog.Log
101 | if blog_length >= 50000 then
102 | UI.Text("NOTICE: There are " .. tostring(blog_length) .. " entries in the battle log.")
103 | UI.Text(" You may notice a stagger when saving it.")
104 | end
105 |
106 | if UI.BeginTable("Save File", 4, Window_Manager.Table.Flags.None) then
107 | UI.TableSetupColumn("Col 1", col_flags, width)
108 | UI.TableSetupColumn("Col 2", col_flags, width)
109 | UI.TableSetupColumn("Col 3", col_flags, width)
110 | UI.TableSetupColumn("Col 3", col_flags, width)
111 |
112 | UI.TableNextRow()
113 | UI.TableNextColumn()
114 | if UI.Button("Database ") then
115 | File.Save_Data()
116 | File.Save_Catalog()
117 | return nil
118 | end
119 | UI.TableNextColumn()
120 | if UI.Button("Battle Log ") then
121 | File.Save_Battlelog()
122 | return nil
123 | end
124 | UI.EndTable()
125 | end
126 | end
--------------------------------------------------------------------------------
/modules/report/config.lua:
--------------------------------------------------------------------------------
1 | Report.Config = T{}
2 |
3 | Report.Config.Defaults = T{
4 | X = 100,
5 | Y = 100,
6 | Visible = {true},
7 | Damage_Threshold = 5, -- Controls what damage percent is needed for showing up in a cross-player chat report.
8 | Auto_Save = false,
9 | }
10 |
11 | Report.Config.Slider_Width = 100
12 |
13 | ------------------------------------------------------------------------------------------------------
14 | -- Resets report settings.
15 | ------------------------------------------------------------------------------------------------------
16 | Report.Config.Reset = function()
17 | for setting, value in pairs(Report.Config.Defaults) do
18 | Metrics.Report[setting] = value
19 | end
20 | end
21 |
22 | ------------------------------------------------------------------------------------------------------
23 | -- Shows settings that affect the Report tab.
24 | ------------------------------------------------------------------------------------------------------
25 | Report.Config.Display = function()
26 | if UI.Checkbox("Auto Save", {Metrics.Report.Auto_Save}) then
27 | Metrics.Report.Auto_Save = not Metrics.Report.Auto_Save
28 | end
29 | UI.SameLine() Window_Manager.Widgets.HelpMarker("Automatically save an export of the database as a CSV whenver you "
30 | .."reset the database or re/unload the addon (like shutting down).")
31 | UI.Separator()
32 | local damage_threshold = {[1] = Metrics.Report.Damage_Threshold}
33 | UI.Text("This does not affect the Publish button on the focus tab.")
34 | UI.SetNextItemWidth(Report.Config.Slider_Width)
35 | if UI.DragInt("Chat Report % Threshold", damage_threshold, 0.1, 0, 50, "%d", ImGuiSliderFlags_None) then
36 | Metrics.Report.Damage_Threshold = damage_threshold[1]
37 | end
38 | end
--------------------------------------------------------------------------------
/modules/report/widgets.lua:
--------------------------------------------------------------------------------
1 | Report.Widgets = T{}
2 |
3 | ------------------------------------------------------------------------------------------------------
4 | -- Toggles the settings showing for the battle log.
5 | ------------------------------------------------------------------------------------------------------
6 | Report.Widgets.Settings_Button = function()
7 | if UI.SmallButton("Settings") then
8 | Config.Button_Toggle(Config.Enum.File.REPORT)
9 | end
10 | end
11 |
12 | ------------------------------------------------------------------------------------------------------
13 | -- Creates a button to publish certain cataloged actions to the screen.
14 | ------------------------------------------------------------------------------------------------------
15 | ---@param player_name string
16 | ---@param focus_type string
17 | ---@param caption? string
18 | ------------------------------------------------------------------------------------------------------
19 | Report.Widgets.Button = function(player_name, focus_type, caption)
20 | if not caption then caption = "Publish" end
21 | if UI.Button(caption) then
22 | Report.Publishing.Catalog(player_name, focus_type)
23 | end
24 | end
25 |
26 | ------------------------------------------------------------------------------------------------------
27 | -- Creates a dropdown menu to chat mode options for publishing.
28 | ------------------------------------------------------------------------------------------------------
29 | Report.Widgets.Chat_Mode = function()
30 | local list = Ashita.Chat.Modes
31 | local flags = DB.Widgets.Dropdown.Flags
32 | if list[1] then
33 | UI.SetNextItemWidth(Ashita.Chat.Selection.Width)
34 | if UI.BeginCombo(Ashita.Chat.Selection.Title, list[Report.Publishing.Chat_Index].Name, flags) then
35 | for n = 1, #list, 1 do
36 | local is_selected = Ashita.Chat.Selection.Index == n
37 | if UI.Selectable(list[n].Name, is_selected) then
38 | Report.Publishing.Chat_Index = n
39 | Report.Publishing.Chat_Mode = list[n]
40 | end
41 | if is_selected then
42 | UI.SetItemDefaultFocus()
43 | end
44 | end
45 | UI.EndCombo()
46 | end
47 | else
48 | if UI.BeginCombo(Ashita.Chat.Selection.Title, Ashita.Enum.Chat.PARTY, flags) then
49 | UI.EndCombo()
50 | end
51 | end
52 | end
--------------------------------------------------------------------------------
/packets/_bitreader.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | * Addons - Copyright (c) 2023 Ashita Development Team
3 | * Contact: https://www.ashitaxi.com/
4 | * Contact: https://discord.gg/Ashita
5 | *
6 | * This file is part of Ashita.
7 | *
8 | * Ashita is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * Ashita is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with Ashita. If not, see .
20 | --]]
21 |
22 | require('common');
23 |
24 | local bitreader = T{
25 | data = nil,
26 | bit = 0,
27 | pos = 0,
28 | };
29 |
30 | --[[
31 | * Creates and returns a new bit reader instance.
32 | *
33 | * @param {table} o - The default object table, if provided.
34 | * @return {table} The bit reader instance.
35 | --]]
36 | function bitreader:new(o)
37 | o = o or T{};
38 |
39 | setmetatable(o, self);
40 | self.__index = self;
41 |
42 | return o;
43 | end
44 |
45 |
46 | --[[
47 | * Sets the current reader data.
48 | *
49 | * @param {string|table} data - The data to use with the reader. (Strings are converted to a byte table automatically.)
50 | --]]
51 | function bitreader:set_data(data)
52 | self.bit = 0;
53 | self.data = T{};
54 | self.pos = 0;
55 |
56 | switch(type(data), T{
57 | ['string'] = function ()
58 | data:tohex():replace(' ', ''):gsub('(%x%x)', function (x)
59 | return table.insert(self.data, tonumber(x, 16));
60 | end);
61 | end,
62 | ['table'] = function ()
63 | self.data = data;
64 | end,
65 | [switch.default] = function ()
66 | error('[BitReader] Invalid data type: ' .. type(data));
67 | end,
68 | });
69 | end
70 |
71 | --[[
72 | * Sets the current reader position.
73 | *
74 | * @param {number} pos - The byte position to set the reader to. (Resets the bit position.)
75 | --]]
76 | function bitreader:set_pos(pos)
77 | self.bit = 0;
78 | self.pos = pos;
79 | end
80 |
81 | --[[
82 | * Reads a packed value from the current data.
83 | *
84 | * @param {number} bits - The number of bits to read.
85 | * @return {number} The read value.
86 | --]]
87 | function bitreader:read(bits)
88 | local ret = 0;
89 |
90 | if (self.data == nil) then
91 | return ret;
92 | end
93 |
94 | for x = 0, bits - 1 do
95 | local val = bit.lshift(bit.band(self.data[self.pos + 1], 1), x);
96 | self.data[self.pos + 1] = bit.rshift(self.data[self.pos + 1], 1);
97 | ret = bit.bor(ret, val);
98 |
99 | self.bit = self.bit + 1;
100 | if (self.bit == 8) then
101 | self.bit = 0;
102 | self.pos = self.pos + 1;
103 | end
104 | end
105 |
106 | return ret;
107 | end
108 |
109 | -- Return the BitReader table..
110 | return bitreader;
--------------------------------------------------------------------------------
/packets/_parser.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | * Addons - Copyright (c) 2023 Ashita Development Team
3 | * Contact: https://www.ashitaxi.com/
4 | * Contact: https://discord.gg/Ashita
5 | *
6 | * This file is part of Ashita.
7 | *
8 | * Ashita is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * Ashita is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with Ashita. If not, see .
20 | --]]
21 |
22 | require('common');
23 | local breader = require('packets._bitreader');
24 |
25 | -- Action parser table..
26 | local parser = T{};
27 |
28 | --[[
29 | * Locates and returns the name of the actor of the given server id.
30 | *
31 | * @param {number} id - The server id of the actor to locate.
32 | * @return {string} The actor name.
33 | --]]
34 | local function get_actor_name(id)
35 | local ret = 'Unknown';
36 | for x = 0, 2302 do
37 | local e = GetEntity(x);
38 | if (e and e.ServerId == id) then
39 | return e.Name;
40 | end
41 | end
42 | return ret;
43 | end
44 |
45 | --[[
46 | * Parses the given action packet.
47 | *
48 | * @param {string} packet - The packet string to parse.
49 | * @return {table} The parsed action packet.
50 | --]]
51 | parser.parse = function (packet)
52 | local reader = breader:new();
53 | reader:set_data(packet);
54 | reader:set_pos(5);
55 |
56 | local action = T{};
57 | action.m_uID = reader:read(32);
58 | action.caster_name = get_actor_name(action.m_uID);
59 | action.trg_sum = reader:read(6);
60 | action.res_sum = reader:read(4);
61 | action.cmd_no = reader:read(4);
62 | action.cmd_arg = reader:read(32);
63 | action.info = reader:read(32);
64 | action.target = T{};
65 |
66 | for _ = 0, action.trg_sum - 1 do
67 | local target = T{};
68 | target.m_uID = reader:read(32);
69 | target.target_name = get_actor_name(target.m_uID);
70 | target.result_sum = reader:read(4);
71 | target.result = T{};
72 |
73 | for _ = 0, target.result_sum - 1 do
74 | local result = T{};
75 | result.miss = reader:read(3);
76 | result.kind = reader:read(2);
77 | result.sub_kind = reader:read(12);
78 | result.info = reader:read(5);
79 | result.scale = reader:read(5);
80 | result.value = reader:read(17);
81 | result.message = reader:read(10);
82 | result.bit = reader:read(31);
83 |
84 | if (reader:read(1) > 0) then
85 | result.has_proc = true;
86 | result.proc_kind = reader:read(6);
87 | result.proc_info = reader:read(4);
88 | result.proc_value = reader:read(17);
89 | result.proc_message = reader:read(10);
90 | else
91 | result.has_proc = false;
92 | result.proc_kind = 0;
93 | result.proc_info = 0;
94 | result.proc_value = 0;
95 | result.proc_message = 0;
96 | end
97 |
98 | if (reader:read(1) > 0) then
99 | result.has_react = true;
100 | result.react_kind = reader:read(6);
101 | result.react_info = reader:read(4);
102 | result.react_value = reader:read(14);
103 | result.react_message= reader:read(10);
104 | else
105 | result.has_react = false;
106 | result.react_kind = 0;
107 | result.react_info = 0;
108 | result.react_value = 0;
109 | result.react_message= 0;
110 | end
111 |
112 | table.insert(target.result, result);
113 | end
114 |
115 | table.insert(action.target, target);
116 | end
117 |
118 | return action;
119 | end
120 |
121 | --[[
122 | * Returns the name of the given action command number.
123 | *
124 | * @param {number} cmd_no - The action command number.
125 | * @return {string} The command name.
126 | *--]]
127 | parser.get_action_name = function (cmd_no)
128 | return switch(cmd_no, T{
129 | [ 0] = function () return 'None'; end, -- None.
130 | [ 1] = function () return 'Attack'; end, -- Basic Attack
131 | [ 2] = function () return 'R.Attack (F)'; end, -- Finish: Ranged Attack
132 | [ 3] = function () return 'WeaponSkill (F)'; end, -- Finish: Player Weapon Skills (Some job abilities use this such as Mug.)
133 | [ 4] = function () return 'Magic (F)'; end, -- Finish: Player and Monster Magic Casts
134 | [ 5] = function () return 'Item (F)'; end, -- Finish: Item Use
135 | [ 6] = function () return 'JobAbility (F)'; end, -- Finish: Player Job Abilities, DNC Reverse Flourish
136 | [ 7] = function () return 'Mon/WepSkill (S)'; end, -- Start: Monster Skill, Weapon Skill
137 | [ 8] = function () return 'Magic (S)'; end, -- Start: Player and Monster Magic Casts
138 | [ 9] = function () return 'Item (S)'; end, -- Start: Item Use
139 | [10] = function () return 'JobAbility (S)'; end, -- Start: Job Ability
140 | [11] = function () return 'MonSkill (F)'; end, -- Finish: Monster Skill
141 | [12] = function () return 'R.Attack (S)'; end, -- Start: Ranged Attack
142 | [14] = function () return 'Dancer'; end, -- Dancer Flourish, Samba, Step, Waltz
143 | [15] = function () return 'RuneFencer'; end, -- Rune Fencer Effusion, Ward
144 | [switch.default] = function()
145 | return ('%d:Unknown'):fmt(cmd_no);
146 | end,
147 | });
148 | end
149 |
150 | --[[
151 | * Returns the name of the given miss id.
152 | *
153 | * @param {number} id - The miss id.
154 | * @return {string} The miss name.
155 | *--]]
156 | parser.get_miss_name = function (id)
157 | return switch(id, T{
158 | [0] = function () return 'hit'; end, -- Hit
159 | [1] = function () return 'miss'; end, -- Miss
160 | [2] = function () return 'guard'; end, -- Guard
161 | [3] = function () return 'parry'; end, -- Parry
162 | [4] = function () return 'block'; end, -- Block
163 | [9] = function () return 'evade'; end, -- Evade
164 | [switch.default] = function()
165 | return ('%d:unknown'):fmt(id);
166 | end,
167 | });
168 | end
169 |
170 | -- Return the action parser table..
171 | return parser;
--------------------------------------------------------------------------------
/resources/avatars.lua:
--------------------------------------------------------------------------------
1 | Res.Avatar = T{}
2 |
3 | -- Based off of monster_abilities.lua from Windower.
4 | Res.Avatar.Rage = T{
5 | -- Fenrir
6 | [831] = {id=831,en="Moonlit Charge",ja="ムーンリットチャージ"},
7 | [832] = {id=832,en="Crescent Fang",ja="クレセントファング"},
8 | [836] = {id=836,en="Eclipse Bite",ja="エクリプスバイト"},
9 | [838] = {id=838,en="Howling Moon",ja="(ハウリングムーン)",skillchain_a="Darkness",skillchain_b="Distortion",skillchain_c=""},
10 | [839] = {id=839,en="Howling Moon",ja="ハウリングムーン",skillchain_a="Darkness",skillchain_b="Distortion",skillchain_c=""},
11 | -- Ifrit
12 | [840] = {id=840,en="Punch",ja="パンチ"},
13 | [841] = {id=841,en="Fire II",ja="ファイアII"},
14 | [842] = {id=842,en="Burning Strike",ja="バーニングストライク"},
15 | [843] = {id=843,en="Double Punch",ja="ダブルパンチ"},
16 | [845] = {id=845,en="Fire IV",ja="ファイアIV"},
17 | [846] = {id=846,en="Flaming Crush",ja="フレイムクラッシュ"},
18 | [847] = {id=847,en="Meteor Strike",ja="メテオストライク"},
19 | [848] = {id=848,en="Inferno",ja="インフェルノ"},
20 | -- Titan
21 | [849] = {id=849,en="Rock Throw",ja="ロックスロー"},
22 | [850] = {id=850,en="Stone II",ja="ストーンII"},
23 | [851] = {id=851,en="Rock Buster",ja="ロックバスター"},
24 | [852] = {id=852,en="Megalith Throw",ja="メガリススロー"},
25 | [854] = {id=854,en="Stone IV",ja="ストーンIV"},
26 | [855] = {id=855,en="Mountain Buster",ja="マウンテンバスター"},
27 | [856] = {id=856,en="Geocrush",ja="ジオクラッシュ"},
28 | [857] = {id=857,en="Earthen Fury",ja="アースフューリー"},
29 | -- Leviathan
30 | [858] = {id=858,en="Barracuda Dive",ja="バラクーダダイブ"},
31 | [859] = {id=859,en="Water II",ja="ウォータII"},
32 | [860] = {id=860,en="Tail Whip",ja="テールウィップ"},
33 | [863] = {id=863,en="Water IV",ja="ウォータIV"},
34 | [864] = {id=864,en="Spinning Dive",ja="スピニングダイブ"},
35 | [865] = {id=865,en="Grand Fall",ja="グランドフォール"},
36 | [866] = {id=866,en="Tidal Wave",ja="タイダルウェイブ"},
37 | -- Garuda
38 | [867] = {id=867,en="Claw",ja="クロー"},
39 | [868] = {id=868,en="Aero II",ja="エアロII"},
40 | [872] = {id=872,en="Aero IV",ja="エアロIV"},
41 | [873] = {id=873,en="Predator Claws",ja="プレデタークロー"},
42 | [874] = {id=874,en="Wind Blade",ja="ウインドブレード"},
43 | [875] = {id=875,en="Aerial Blast",ja="エリアルブラスト"},
44 | -- Shiva
45 | [876] = {id=876,en="Axe Kick",ja="アクスキック"},
46 | [877] = {id=877,en="Blizzard II",ja="ブリザドII"},
47 | [880] = {id=880,en="Double Slap",ja="ダブルスラップ"},
48 | [881] = {id=881,en="Blizzard IV",ja="ブリザドIV"},
49 | [882] = {id=882,en="Rush",ja="ラッシュ"},
50 | [883] = {id=883,en="Heavenly Strike",ja="ヘヴンリーストライク"},
51 | [884] = {id=884,en="Diamond Dust",ja="ダイヤモンドダスト"},
52 | -- Ramuh
53 | [885] = {id=885,en="Shock Strike",ja="ショックストライク"},
54 | [886] = {id=886,en="Thunder II",ja="サンダーII"},
55 | [888] = {id=888,en="Thunderspark",ja="サンダースパーク"},
56 | [890] = {id=890,en="Thunder IV",ja="サンダーIV"},
57 | [891] = {id=891,en="Chaotic Strike",ja="カオスストライク"},
58 | [892] = {id=892,en="Thunderstorm",ja="サンダーストーム"},
59 | [893] = {id=893,en="Judgment Bolt",ja="ジャッジボルト"},
60 | -- Carbuncle
61 | [907] = {id=907,en="Poison Nails",ja="ポイズンネイル"},
62 | [910] = {id=910,en="Meteorite",ja="プチメテオ"},
63 | [912] = {id=912,en="Searing Light",ja="シアリングライト"},
64 | -- Diabolos
65 | [1903] = {id=1903,en="Camisado",ja="カミサドー"},
66 | [1904] = {id=1904,en="Somnolence",ja="ソムノレンス"},
67 | [1909] = {id=1909,en="Cacodemonia",ja="カコデモニア"},
68 | [1910] = {id=1910,en="Nether Blast",ja="ネザーブラスト"},
69 | [1911] = {id=1911,en="Ruinous Omen",ja="ルイナスオーメン"},
70 | [3554] = {id=3554,en="Night Terror",ja="ナイトテラー"},
71 | [3555] = {id=3555,en="Ruinous Omen",ja="ルイナスオーメン"},
72 | }
73 |
74 | -- Based off of monster_abilities.lua from Windower.
75 | Res.Avatar.Ward = T{
76 | -- Fenrir
77 | [833] = {id=833,en="Lunar Cry",ja="ルナークライ"},
78 | [834] = {id=834,en="Ecliptic Growl",ja="上弦の唸り"},
79 | [835] = {id=835,en="Lunar Roar",ja="ルナーロア"},
80 | [837] = {id=837,en="Ecliptic Howl",ja="下弦の咆哮"},
81 | -- Ifrit
82 | [844] = {id=844,en="Crimson Roar",ja="紅蓮の咆哮"},
83 | -- Titan
84 | [853] = {id=853,en="Earthen Ward",ja="大地の守り"},
85 | -- Leviathan (Spring Water is Refresh on Horizon)
86 | [861] = {id=861,en="Spring Water",ja="湧水"},
87 | [862] = {id=862,en="Slowga",ja="スロウガ"},
88 | -- Garuda
89 | [869] = {id=869,en="Whispering Wind",ja="風の囁き"},
90 | [870] = {id=870,en="Hastega",ja="ヘイスガ"},
91 | [871] = {id=871,en="Aerial Armor",ja="真空の鎧"},
92 | -- Shiva
93 | [878] = {id=878,en="Frost Armor",ja="凍てつく鎧"},
94 | [879] = {id=879,en="Sleepga",ja="スリプガ"},
95 | -- Ramuh
96 | [887] = {id=887,en="Rolling Thunder",ja="雷鼓"},
97 | [889] = {id=889,en="Lightning Armor",ja="雷電の鎧"},
98 | -- Carbuncle
99 | [906] = {id=906,en="Healing Ruby",ja="ルビーの癒し"},
100 | [908] = {id=908,en="Shining Ruby",ja="ルビーの輝き"},
101 | [909] = {id=909,en="Glittering Ruby",ja="ルビーの煌き"},
102 | [911] = {id=911,en="Healing Ruby II",ja="ルビーの癒しII"},
103 | -- Diabolos
104 | [1905] = {id=1905,en="Noctoshield",ja="ノクトシールド"},
105 | [1906] = {id=1906,en="Ultimate Terror",ja="アルティメットテラー"},
106 | [1907] = {id=1907,en="Dream Shroud",ja="ドリームシュラウド"},
107 | [1908] = {id=1908,en="Nightmare",ja="ナイトメア"},
108 | }
109 |
110 | -- Based off of monster_abilities.lua from Windower.
111 | Res.Avatar.Healing = T{
112 | -- Garuda
113 | [869] = {id=869,en="Whispering Wind",ja="風の囁き"},
114 | -- Carbuncle
115 | [906] = {id=906,en="Healing Ruby",ja="ルビーの癒し"},
116 | [911] = {id=911,en="Healing Ruby II",ja="ルビーの癒しII"},
117 | }
118 |
--------------------------------------------------------------------------------
/resources/colors.lua:
--------------------------------------------------------------------------------
1 | Res.Colors = T{}
2 |
3 | Res.Colors.Basic = {
4 | -- Base Colors
5 | WHITE = {1.00, 1.00, 1.00, 1.0},
6 | RED = {1.00, 0.00, 0.00, 1.0},
7 | GREEN = {0.00, 1.00, 0.00, 1.0},
8 | BLUE = {0.00, 0.00, 1.00, 1.0},
9 | ORANGE = {0.90, 0.60, 0.00, 1.0},
10 | YELLOW = {0.90, 1.00, 0.00, 1.0},
11 | BR_GREEN = {0.20, 1.00, 0.00, 1.0},
12 | PURPLE = {0.70, 0.20, 1.00, 1.0},
13 | DIM = {0.50, 0.50, 0.50, 1.0},
14 | INACTIVE = {0.14, 0.14, 0.14, 1.0},
15 | MOB = {0.60, 0.60, 0.60, 1.0},
16 | -- Elements
17 | LIGHT = {1.0, 1.0, 1.0, 1.0},
18 | DARK = {0.9, 0.0, 1.0, 1.0},
19 | FIRE = {1.0, 0.0, 0.0, 1.0},
20 | ICE = {0.0, 0.7, 1.0, 1.0},
21 | WIND = {0.0, 1.0, 0.0, 1.0},
22 | EARTH = {0.7, 0.5, 0.0, 1.0},
23 | THUNDER = {0.7, 0.2, 1.0, 1.0},
24 | WATER = {0.3, 0.5, 0.8, 1.0},
25 | }
26 |
27 | Res.Colors.Elements = {
28 | [0] = Res.Colors.Basic.FIRE,
29 | [1] = Res.Colors.Basic.ICE,
30 | [2] = Res.Colors.Basic.WIND,
31 | [3] = Res.Colors.Basic.EARTH,
32 | [4] = Res.Colors.Basic.THUNDER,
33 | [5] = Res.Colors.Basic.WATER,
34 | [6] = Res.Colors.Basic.LIGHT,
35 | [7] = Res.Colors.Basic.DARK,
36 | }
37 |
38 | Res.Colors.Avatars = {
39 | Carbuncle = Res.Colors.Basic.LIGHT,
40 | Fenrir = Res.Colors.Basic.DARK,
41 | Diabolos = Res.Colors.Basic.DARK,
42 | Ifrit = Res.Colors.Basic.FIRE,
43 | Shiva = Res.Colors.Basic.ICE,
44 | Garuda = Res.Colors.Basic.WIND,
45 | Titan = Res.Colors.Basic.EARTH,
46 | Ramuh = Res.Colors.Basic.THUNDER,
47 | Leviathan = Res.Colors.Basic.WATER,
48 | }
49 |
50 | Res.Colors.Jobs = T{
51 | [0] = {0.40, 0.40, 0.40, 1.0}, -- NON
52 | [1] = {0.90, 0.00, 0.00, 1.0}, -- WAR
53 | [2] = {0.96, 0.77, 0.01, 1.0}, -- MNK
54 | [3] = {1.00, 1.00, 1.00, 1.0}, -- WHM
55 | [4] = {0.65, 0.52, 0.74, 1.0}, -- BLM
56 | [5] = {0.91, 0.39, 0.40, 1.0}, -- RDM
57 | [6] = {0.03, 0.76, 0.11, 1.0}, -- THF
58 | [7] = {0.90, 0.98, 0.09, 1.0}, -- PLD
59 | [8] = {0.90, 0.00, 1.00, 1.0}, -- DRK
60 | [9] = {0.80, 0.73, 0.47, 1.0}, -- BST
61 | [10] = {0.97, 0.64, 0.91, 1.0}, -- BRD
62 | [11] = {0.43, 0.77, 0.35, 1.0}, -- RNG
63 | [12] = {0.99, 0.43, 0.01, 1.0}, -- SAM
64 | [13] = {0.96, 0.19, 0.00, 1.0}, -- NIN
65 | [14] = {0.70, 0.29, 0.98, 1.0}, -- DRG
66 | [15] = {0.44, 0.99, 0.71, 1.0}, -- SMN
67 | [16] = {0.30, 0.56, 0.83, 1.0}, -- BLU
68 | [17] = {0.79, 0.46, 0.34, 1.0}, -- COR
69 | [18] = {0.51, 0.48, 0.67, 1.0}, -- PUP
70 | [19] = {0.00, 0.00, 0.00, 1.0}, -- DNC
71 | [20] = {0.00, 0.00, 0.00, 1.0}, -- SCH
72 | [21] = {0.00, 0.00, 0.00, 1.0}, -- GEO
73 | [22] = {0.00, 0.00, 0.00, 1.0}, -- RUN
74 | }
75 |
76 | Res.Colors.XP = T{
77 | [1] = {0.83, 0.65, 0.31, 1.0}, -- Experience
78 | [2] = {0.30, 0.56, 0.83, 1.0}, -- Limit
79 | }
--------------------------------------------------------------------------------
/resources/game.lua:
--------------------------------------------------------------------------------
1 | Res.Game = T{}
2 |
3 | Res.Game.Effect_Animation = T{
4 | [1] = "Fire",
5 | [2] = "Ice",
6 | [3] = "Wind",
7 | [4] = "Earth",
8 | [5] = "Lightning",
9 | [6] = "Water",
10 | [7] = "Light",
11 | [8] = "Dark",
12 | [9] = "Sleep",
13 | [10] = "Poison",
14 | [11] = "Paralyze",
15 | [12] = "Blind",
16 | [13] = "Silence",
17 | [16] = "Stun",
18 | [17] = "Curse",
19 | [18] = "Stat Down",
20 | [21] = "Drain",
21 | [22] = "Aspir",
22 | [23] = "Haste",
23 | }
--------------------------------------------------------------------------------
/resources/items.lua:
--------------------------------------------------------------------------------
1 | Res.Items = T{}
2 |
3 | Res.Items.Dedication = T{
4 | [0] = {name = "Unknown", boost = -1, max = -1},
5 | [8191] = {name = "Wandering Heroes", boost = 75, max = 10000},
6 | [15793] = {name = "Anniversary Ring", boost = 100, max = 3000},
7 | [15763] = {name = "Emperor Band", boost = 75, max = 2250},
8 | [15762] = {name = "Empress Band", boost = 50, max = 1000},
9 | [15761] = {name = "Chariot Band", boost = 100, max = 4000},
10 | }
11 |
12 | -- Used for item dropdown selection.
13 | Res.Items.Dedication_Selection = T{
14 | [1] = "Chariot Band", -- 15761
15 | [2] = "Emperor Band", -- 15763
16 | [3] = "Empress Band", -- 15762
17 | [4] = "Wandering Heroes", -- 8191
18 | [5] = "Anniversary Ring", -- 15793
19 | }
20 |
21 | Res.Items.Dedication_Name_To_ID = T{
22 | ["Chariot Band"] = 15761,
23 | ["Emperor Band"] = 15763,
24 | ["Empress Band"] = 15762,
25 | ["Wandering Heroes"] = 8191,
26 | ["Anniversary Ring"] = 15793,
27 | }
--------------------------------------------------------------------------------
/resources/jobs.lua:
--------------------------------------------------------------------------------
1 | Res.Jobs = T{}
2 |
3 | Res.Jobs.List = T{
4 | [0] = {id=0,en="None",ja="なし",ens="NON",jas=""},
5 | [1] = {id=1,en="Warrior",ja="戦士",ens="WAR",jas="戦"},
6 | [2] = {id=2,en="Monk",ja="モンク",ens="MNK",jas="モ"},
7 | [3] = {id=3,en="White Mage",ja="白魔道士",ens="WHM",jas="白"},
8 | [4] = {id=4,en="Black Mage",ja="黒魔道士",ens="BLM",jas="黒"},
9 | [5] = {id=5,en="Red Mage",ja="赤魔道士",ens="RDM",jas="赤"},
10 | [6] = {id=6,en="Thief",ja="シーフ",ens="THF",jas="シ"},
11 | [7] = {id=7,en="Paladin",ja="ナイト",ens="PLD",jas="ナ"},
12 | [8] = {id=8,en="Dark Knight",ja="暗黒騎士",ens="DRK",jas="暗"},
13 | [9] = {id=9,en="Beastmaster",ja="獣使い",ens="BST",jas="獣"},
14 | [10] = {id=10,en="Bard",ja="吟遊詩人",ens="BRD",jas="詩"},
15 | [11] = {id=11,en="Ranger",ja="狩人",ens="RNG",jas="狩"},
16 | [12] = {id=12,en="Samurai",ja="侍",ens="SAM",jas="侍"},
17 | [13] = {id=13,en="Ninja",ja="忍者",ens="NIN",jas="忍"},
18 | [14] = {id=14,en="Dragoon",ja="竜騎士",ens="DRG",jas="竜"},
19 | [15] = {id=15,en="Summoner",ja="召喚士",ens="SMN",jas="召"},
20 | [16] = {id=16,en="Blue Mage",ja="青魔道士",ens="BLU",jas="青"},
21 | [17] = {id=17,en="Corsair",ja="コルセア",ens="COR",jas="コ"},
22 | [18] = {id=18,en="Puppetmaster",ja="からくり士",ens="PUP",jas="か"},
23 | [19] = {id=19,en="Dancer",ja="踊り子",ens="DNC",jas="踊"},
24 | [20] = {id=20,en="Scholar",ja="学者",ens="SCH",jas="学"},
25 | [21] = {id=21,en="Geomancer",ja="風水士",ens="GEO",jas="風"},
26 | [22] = {id=22,en="Rune Fencer",ja="魔導剣士",ens="RUN",jas="剣"},
27 | [23] = {id=23,en="Monipulator",ja="モンストロス",ens="MON",jas="MON"},
28 | }
29 |
30 | --[[
31 | Copyright © 2013-2023, Windower
32 | All rights reserved.
33 |
34 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
35 |
36 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
37 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
38 | * Neither the name of Windower nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
39 |
40 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Windower BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 | ]]
42 |
--------------------------------------------------------------------------------
/resources/pets.lua:
--------------------------------------------------------------------------------
1 | Res.Pets = T{}
2 |
3 | -- Based off of monster_abilities.lua from Windower.
4 | Res.Pets.Damaging_Wyvern_Breath = T{
5 | [646] = {id=900,en="Flame Breath",ja="フレイムブレス"},
6 | [647] = {id=901,en="Frost Breath",ja="フロストブレス"},
7 | [648] = {id=902,en="Gust Breath",ja="ガストブレス"},
8 | [649] = {id=903,en="Sand Breath",ja="サンドブレス"},
9 | [650] = {id=904,en="Lightning Breath",ja="ライトニングブレス"},
10 | [651] = {id=905,en="Hydro Breath",ja="ハイドロブレス"},
11 | }
12 |
13 | Res.Pets.Healing_Wyvern_Breath = T{
14 | [639] = {id=639,en="Healing Breath IV"},
15 | [640] = {id=894,en="Healing Breath",ja="ヒールブレス"},
16 | [641] = {id=895,en="Healing Breath II",ja="ヒールブレスII"},
17 | [642] = {id=896,en="Healing Breath III",ja="ヒールブレスIII"},
18 | }
--------------------------------------------------------------------------------
/resources/themes.lua:
--------------------------------------------------------------------------------
1 | local themes = {}
2 |
3 | themes.Elements = {
4 | ImGuiCol_Text = 0;
5 | ImGuiCol_TextDisabled = 1;
6 | ImGuiCol_WindowBg = 2; -- Background of normal windows
7 | ImGuiCol_ChildBg = 3; -- Background of child windows
8 | ImGuiCol_PopupBg = 4; -- Background of popups, menus, tooltips windows
9 | ImGuiCol_Border = 5;
10 | ImGuiCol_BorderShadow = 6;
11 | ImGuiCol_FrameBg = 7; -- Background of checkbox, radio button, plot, slider, text input
12 | ImGuiCol_FrameBgHovered = 8;
13 | ImGuiCol_FrameBgActive = 9;
14 | ImGuiCol_TitleBg = 10;
15 | ImGuiCol_TitleBgActive = 11;
16 | ImGuiCol_TitleBgCollapsed = 12;
17 | ImGuiCol_MenuBarBg = 13;
18 | ImGuiCol_ScrollbarBg = 14;
19 | ImGuiCol_ScrollbarGrab = 15;
20 | ImGuiCol_ScrollbarGrabHovered = 16;
21 | ImGuiCol_ScrollbarGrabActive = 17;
22 | ImGuiCol_CheckMark = 18;
23 | ImGuiCol_SliderGrab = 19;
24 | ImGuiCol_SliderGrabActive = 20;
25 | ImGuiCol_Button = 21;
26 | ImGuiCol_ButtonHovered = 22;
27 | ImGuiCol_ButtonActive = 23;
28 | ImGuiCol_Header = 24; -- Header* colors are used for CollapsingHeader, TreeNode, Selectable, MenuItem
29 | ImGuiCol_HeaderHovered = 25;
30 | ImGuiCol_HeaderActive = 26;
31 | ImGuiCol_Separator = 27;
32 | ImGuiCol_SeparatorHovered = 28;
33 | ImGuiCol_SeparatorActive = 29;
34 | ImGuiCol_ResizeGrip = 30;
35 | ImGuiCol_ResizeGripHovered = 31;
36 | ImGuiCol_ResizeGripActive = 32;
37 | ImGuiCol_Tab = 33;
38 | ImGuiCol_TabHovered = 34;
39 | ImGuiCol_TabActive = 35;
40 | ImGuiCol_TabUnfocused = 36;
41 | ImGuiCol_TabUnfocusedActive = 37;
42 | ImGuiCol_PlotLines = 38;
43 | ImGuiCol_PlotLinesHovered = 39;
44 | ImGuiCol_PlotHistogram = 40;
45 | ImGuiCol_PlotHistogramHovered = 41;
46 | ImGuiCol_TableHeaderBg = 42; -- Table header background
47 | ImGuiCol_TableBorderStrong = 43; -- Table outer and header borders (prefer using Alpha=1.0 here)
48 | ImGuiCol_TableBorderLight = 44; -- Table inner borders (prefer using Alpha=1.0 here)
49 | ImGuiCol_TableRowBg = 45; -- Table row background (even rows)
50 | ImGuiCol_TableRowBgAlt = 46; -- Table row background (odd rows)
51 | ImGuiCol_TextSelectedBg = 47;
52 | ImGuiCol_DragDropTarget = 48;
53 | ImGuiCol_NavHighlight = 49; -- Gamepad/keyboard: current highlighted item
54 | ImGuiCol_NavWindowingHighlight = 50; -- Highlight window when using CTRL+TAB
55 | ImGuiCol_NavWindowingDimBg = 51; -- Darken/colorize entire screen behind the CTRL+TAB window list, when active
56 | ImGuiCol_ModalWindowDimBg = 52; -- Darken/colorize entire screen behind a modal window, when one is active
57 | }
58 |
59 | themes.Default = {
60 | ImGuiCol_Text = {0.94, 0.94, 0.94, 1.00},
61 | ImGuiCol_TextDisabled = {0.94, 0.94, 0.94, 0.29},
62 | ImGuiCol_WindowBg = {0.18, 0.20, 0.23, 0.96},
63 | ImGuiCol_ChildBg = {0.22, 0.24, 0.27, 0.96},
64 | ImGuiCol_PopupBg = {0.05, 0.05, 0.10, 0.90},
65 | ImGuiCol_Border = {0.05, 0.05, 0.10, 0.80},
66 | ImGuiCol_BorderShadow = {0.00, 0.00, 0.00, 0.00},
67 | ImGuiCol_FrameBg = {0.16, 0.17, 0.20, 1.00},
68 | ImGuiCol_FrameBgHovered = {0.14, 0.14, 0.14, 0.78},
69 | ImGuiCol_FrameBgActive = {0.12, 0.12, 0.12, 1.00},
70 | ImGuiCol_TitleBg = {0.83, 0.33, 0.28, 0.69},
71 | ImGuiCol_TitleBgActive = {0.83, 0.33, 0.28, 1.00},
72 | ImGuiCol_TitleBgCollapsed = {0.83, 0.33, 0.28, 0.50},
73 | ImGuiCol_MenuBarBg = {0.12, 0.13, 0.17, 1.00},
74 | ImGuiCol_ScrollbarBg = {0.12, 0.13, 0.17, 1.00},
75 | ImGuiCol_ScrollbarGrab = {0.83, 0.33, 0.28, 0.69},
76 | ImGuiCol_ScrollbarGrabHovered = {0.83, 0.33, 0.28, 1.00},
77 | ImGuiCol_ScrollbarGrabActive = {0.83, 0.33, 0.28, 1.00},
78 | ImGuiCol_CheckMark = {0.83, 0.33, 0.28, 1.00},
79 | ImGuiCol_SliderGrab = {0.83, 0.33, 0.28, 0.69},
80 | ImGuiCol_SliderGrabActive = {0.83, 0.33, 0.28, 1.00},
81 | ImGuiCol_Button = {0.83, 0.33, 0.28, 0.78},
82 | ImGuiCol_ButtonHovered = {0.83, 0.33, 0.28, 1.00},
83 | ImGuiCol_ButtonActive = {0.83, 0.33, 0.28, 1.00},
84 | ImGuiCol_Header = {0.83, 0.33, 0.28, 0.78},
85 | ImGuiCol_HeaderHovered = {0.83, 0.33, 0.28, 1.00},
86 | ImGuiCol_HeaderActive = {0.83, 0.33, 0.28, 1.00},
87 | ImGuiCol_Separator = {0.43, 0.43, 0.50, 0.50},
88 | ImGuiCol_SeparatorHovered = {0.10, 0.40, 0.75, 0.78},
89 | ImGuiCol_SeparatorActive = {0.10, 0.40, 0.75, 1.00},
90 | ImGuiCol_ResizeGrip = {0.05, 0.05, 0.05, 0.69},
91 | ImGuiCol_ResizeGripHovered = {0.83, 0.33, 0.28, 1.00},
92 | ImGuiCol_ResizeGripActive = {0.83, 0.33, 0.28, 1.00},
93 | ImGuiCol_Tab = {0.05, 0.05, 0.05, 0.69},
94 | ImGuiCol_TabHovered = {0.83, 0.33, 0.28, 1.00},
95 | ImGuiCol_TabActive = {0.83, 0.33, 0.28, 1.00},
96 | ImGuiCol_TabUnfocused = {0.07, 0.10, 0.15, 0.97},
97 | ImGuiCol_TabUnfocusedActive = {0.14, 0.26, 0.42, 1.00},
98 | ImGuiCol_PlotLines = {0.83, 0.33, 0.28, 1.00},
99 | ImGuiCol_PlotLinesHovered = {0.81, 0.81, 0.81, 1.00},
100 | ImGuiCol_PlotHistogram = {0.83, 0.33, 0.28, 1.00},
101 | ImGuiCol_PlotHistogramHovered = {0.81, 0.81, 0.81, 1.00},
102 | ImGuiCol_TableHeaderBg = {0.05, 0.05, 0.05, 0.69},
103 | ImGuiCol_TableBorderStrong = {0.10, 0.10, 0.10, 1.00},
104 | ImGuiCol_TableBorderLight = {0.15, 0.15, 0.15, 1.00},
105 | ImGuiCol_TableRowBg = {0.00, 0.00, 0.00, 0.00},
106 | ImGuiCol_TableRowBgAlt = {1.00, 1.00, 1.00, 0.06},
107 | ImGuiCol_TextSelectedBg = {0.83, 0.33, 0.28, 0.50},
108 | ImGuiCol_DragDropTarget = {1.00, 1.00, 0.00, 0.90},
109 | ImGuiCol_NavHighlight = {1.00, 1.00, 0.00, 1.00},
110 | ImGuiCol_NavWindowingHighlight = {0.83, 0.33, 0.28, 1.00},
111 | ImGuiCol_NavWindowingDimBg = {0.00, 0.00, 0.00, 0.60},
112 | ImGuiCol_ModalWindowDimBg = {0.05, 0.05, 0.05, 0.78},
113 | }
114 |
115 | return themes
--------------------------------------------------------------------------------
/resources/weapon_skills_curated.lua:
--------------------------------------------------------------------------------
1 | Res.WS = T{}
2 |
3 | -- Based off of weapons_skills.lua from Windower.
4 | Res.WS.Missing = T{
5 | [260] = {id = 260, english = "Spirit Jump"},
6 | [293] = {id = 293, english = "Soul Jump"},
7 | [329] = {id = 329, english = "Intervene"},
8 | [3502] = {id = 3502, english = "Nott"}
9 | }
10 |
11 | -- Based off of weapons_skills.lua from Windower.
12 | Res.WS.Abilities = T{
13 | [26] = {id = 26, english = "Eagle Eye Shot"},
14 | [41] = {id = 41, english = "Steal"},
15 | [45] = {id = 45, english = "Mug"},
16 | [46] = {id = 46, english = "Shield Bash"},
17 | [57] = {id = 57, english = "Shadowbind"},
18 | [66] = {id = 66, english = "Jump"},
19 | [67] = {id = 67, english = "High Jump"},
20 | [68] = {id = 68, english = "Super Jump"},
21 | [77] = {id = 77, english = "Weapon Bash"},
22 | [228] = {id = 228, english = "Despoil"},
23 | [260] = {id = 260, english = "Spirit Jump"},
24 | [293] = {id = 293, english = "Soul Jump"},
25 | [329] = {id = 329, english = "Intervene"},
26 | }
27 |
28 | -- Based off of weapons_skills.lua from Windower.
29 | Res.WS.MP_Drain = T{
30 | [21] = {id=21,en="Energy Steal",ja="エナジースティール",element=7,icon_id=596,prefix="/weaponskill",range=2,skill=2,skillchain_a="",skillchain_b="",skillchain_c="",targets=32},
31 | -- [22] = {id=22,en="Energy Drain",ja="エナジードレイン",element=7,icon_id=596,prefix="/weaponskill",range=2,skill=2,skillchain_a="",skillchain_b="",skillchain_c="",targets=32},
32 | [163] = {id=163,en="Starlight",ja="スターライト",element=6,icon_id=628,prefix="/weaponskill",range=2,skill=11,skillchain_a="",skillchain_b="",skillchain_c="",targets=1},
33 | [164] = {id=164,en="Moonlight",ja="ムーンライト",element=6,icon_id=628,prefix="/weaponskill",range=2,skill=11,skillchain_a="",skillchain_b="",skillchain_c="",targets=1},
34 | [183] = {id=183,en="Spirit Taker",ja="スピリットテーカー",element=6,icon_id=631,prefix="/weaponskill",range=2,skill=12,skillchain_a="",skillchain_b="",skillchain_c="",targets=32},
35 | }
36 |
37 | Res.WS.Skillchains = T{
38 | [229] = 'DRG Jump Effect',
39 | [288] = 'Light', [289] = 'Darkness',
40 | [290] = 'Gravitation', [291] = 'Fragmentation', [292] = 'Distortion', [293] = 'Fusion',
41 | [294] = 'Compression', [295] = 'Liquefaction', [296] = 'Induration', [297] = 'Reverberation',
42 | [298] = 'Transfixion', [299] = 'Scission', [300] = 'Detonation', [301] = 'Impaction',
43 | [385] = 'Light', [386] = 'Darkness',
44 | [767] = 'Radiance', [768] = 'Umbra'
45 | }
--------------------------------------------------------------------------------
/throttling.lua:
--------------------------------------------------------------------------------
1 | Throttle = T{}
2 | Throttle.Enabled = true
3 | Throttle.Mod = 10
4 | Throttle.Tick = 0
5 | Throttle.Need_Refresh = true
6 |
7 | ------------------------------------------------------------------------------------------------------
8 | -- Provides a gate to throttle performance intensive calculations.
9 | ------------------------------------------------------------------------------------------------------
10 | Throttle.Throttle = function()
11 | Throttle.Tick = (Throttle.Tick + 1) % Throttle.Mod
12 | if Throttle.Tick == 0 then Throttle.Need_Refresh = true end
13 | end
14 |
15 | ------------------------------------------------------------------------------------------------------
16 | -- Returns whether throttling is enabled or not.
17 | ------------------------------------------------------------------------------------------------------
18 | ---@return boolean
19 | ------------------------------------------------------------------------------------------------------
20 | Throttle.Is_Enabled = function()
21 | return Throttle.Enabled
22 | end
23 |
24 | ------------------------------------------------------------------------------------------------------
25 | -- Toggle whether throttling is turned on or off.
26 | ------------------------------------------------------------------------------------------------------
27 | Throttle.Toggle = function()
28 | Throttle.Enabled = not Throttle.Enabled
29 | end
30 |
31 | ------------------------------------------------------------------------------------------------------
32 | -- Returns whether the caller is permitted to perform its calculation or not.
33 | ------------------------------------------------------------------------------------------------------
34 | ---@return boolean
35 | ------------------------------------------------------------------------------------------------------
36 | Throttle.Allow_Calculation = function()
37 | return Throttle.Need_Refresh
38 | end
39 |
40 | ------------------------------------------------------------------------------------------------------
41 | -- Blocks calculation until the next throttle window opens up.
42 | ------------------------------------------------------------------------------------------------------
43 | Throttle.Block = function()
44 | Throttle.Need_Refresh = false
45 | end
--------------------------------------------------------------------------------
/timers.lua:
--------------------------------------------------------------------------------
1 | local timers = T{}
2 |
3 | timers.Timers = T{}
4 |
5 | timers.Enum = T{}
6 | timers.Enum.Names = T{
7 | METRICS = "Total Runtime",
8 | PARSE = "Active Time",
9 | AUTOPAUSE = "Auto-Pause",
10 | AUTOSAVE = "Auto-Save",
11 | DPS = "DPS",
12 | EXP = "EXP",
13 | CHAIN = "Chain",
14 | ZONE = "Zone",
15 | }
16 |
17 | timers.Tresholds = T{
18 | AUTOPAUSE = 5,
19 | }
20 |
21 | ------------------------------------------------------------------------------------------------------
22 | -- Start the timer.
23 | ------------------------------------------------------------------------------------------------------
24 | ---@param name string name of the timer to check.
25 | ------------------------------------------------------------------------------------------------------
26 | timers.Start = function(name)
27 | if not name then name = "Default" end
28 | if not timers.Timers[name] then
29 | timers.Timers[name] = T{
30 | Start = os.time(),
31 | Duration = 0,
32 | Paused = false
33 | }
34 | end
35 | end
36 |
37 | ------------------------------------------------------------------------------------------------------
38 | -- Pause the timer.
39 | ------------------------------------------------------------------------------------------------------
40 | ---@param name string name of the timer to check.
41 | ------------------------------------------------------------------------------------------------------
42 | timers.Pause = function(name)
43 | if timers.Timers[name] then
44 | if not timers.Timers[name].Paused then
45 | local new_duration = os.time() - timers.Timers[name].Start
46 | timers.Timers[name].Paused = true
47 | timers.Timers[name].Duration = timers.Timers[name].Duration + new_duration
48 | end
49 | end
50 | end
51 |
52 | ------------------------------------------------------------------------------------------------------
53 | -- Unpause the timer.
54 | ------------------------------------------------------------------------------------------------------
55 | ---@param name string name of the timer to check.
56 | ------------------------------------------------------------------------------------------------------
57 | timers.Unpause = function(name)
58 | if timers.Timers[name] then
59 | if timers.Timers[name].Paused then
60 | timers.Timers[name].Start = os.time()
61 | timers.Timers[name].Paused = false
62 | end
63 | end
64 | end
65 |
66 | ------------------------------------------------------------------------------------------------------
67 | -- Checks if a timer is paused.
68 | ------------------------------------------------------------------------------------------------------
69 | ---@param name string name of the timer to check.
70 | ---@return boolean
71 | ------------------------------------------------------------------------------------------------------
72 | timers.Is_Paused = function(name)
73 | if timers.Timers[name] then
74 | return timers.Timers[name].Paused
75 | end
76 | return false
77 | end
78 |
79 | ------------------------------------------------------------------------------------------------------
80 | -- Resets the timer.
81 | ------------------------------------------------------------------------------------------------------
82 | ---@param name string name of the timer to check.
83 | ------------------------------------------------------------------------------------------------------
84 | timers.Reset = function(name)
85 | timers.Timers[name] = nil
86 | timers.Start(name)
87 | end
88 |
89 | ------------------------------------------------------------------------------------------------------
90 | -- Gets the duration for a timer.
91 | ------------------------------------------------------------------------------------------------------
92 | ---@param name string name of the timer to check.
93 | ---@return number
94 | ------------------------------------------------------------------------------------------------------
95 | timers.Get_Duration = function(name)
96 | local duration = 0
97 | if timers.Timers[name] then
98 | duration = timers.Timers[name].Duration
99 | if not timers.Timers[name].Paused then
100 | local start = timers.Timers[name].Start
101 | local now = os.time()
102 | duration = duration + (now - start)
103 | end
104 | end
105 | return duration
106 | end
107 |
108 | ------------------------------------------------------------------------------------------------------
109 | -- Check the timer.
110 | ------------------------------------------------------------------------------------------------------
111 | ---@param name string name of the timer to check.
112 | ---@param countdown? boolean true: count down; false: count up
113 | ---@return string
114 | ------------------------------------------------------------------------------------------------------
115 | timers.Check = function(name, countdown)
116 | if timers.Timers[name] then
117 | local duration = timers.Get_Duration(name)
118 | if countdown then
119 | return timers.Format((countdown * 60) - duration)
120 | else
121 | return timers.Format(duration)
122 | end
123 | end
124 | return timers.Format()
125 | end
126 |
127 | ------------------------------------------------------------------------------------------------------
128 | -- Take an action when a timer passes its threshold.
129 | ------------------------------------------------------------------------------------------------------
130 | ---@param name string name of the timer to check.
131 | ------------------------------------------------------------------------------------------------------
132 | timers.Cycle = function(name)
133 | local duration = timers.Get_Duration(name)
134 | if name == Timers.Enum.Names.AUTOPAUSE then
135 | if duration > timers.Tresholds.AUTOPAUSE then
136 | timers.Pause(timers.Enum.Names.PARSE)
137 | end
138 | elseif name == Timers.Enum.Names.DPS then
139 | if duration > DB.DPS.Snapshot_Time then
140 | DB.DPS.Create_Snapshot()
141 | timers.Reset(Timers.Enum.Names.DPS)
142 | end
143 | elseif name == Timers.Enum.Names.EXP then
144 | if duration > XP.Local.Bucket_Length then
145 | XP.Local.Cycle_Window()
146 | timers.Reset(Timers.Enum.Names.EXP)
147 | end
148 | end
149 | end
150 |
151 | ------------------------------------------------------------------------------------------------------
152 | -- Formats the display timer.
153 | ------------------------------------------------------------------------------------------------------
154 | ---@param time? number duration in seconds.
155 | ---@param hide_hour? boolean
156 | ---@return string
157 | ------------------------------------------------------------------------------------------------------
158 | timers.Format = function(time, hide_hour)
159 | if not time then return '00:00' end
160 | local hour, minute, second
161 | hour = string.format("%02.f", math.floor(time / 3600))
162 | minute = string.format("%02.f", math.floor((time / 60) - (hour * 60)))
163 | second = string.format("%02.f", math.floor(time % 60))
164 | local formatted_time = minute .. ":" .. second
165 | if not hide_hour then formatted_time = hour .. ":" .. formatted_time end
166 | return formatted_time
167 | end
168 |
169 | return timers
--------------------------------------------------------------------------------
/windows/!window.lua:
--------------------------------------------------------------------------------
1 | Window = T{}
2 |
3 | function Window:New(settings)
4 |
5 | local self = T{}
6 | settings = settings or T{}
7 |
8 | local name = settings.Name or "Default"
9 | local title = settings.Title or "Default Title"
10 | local module = settings.Module or "Default"
11 | local x = settings.X or 100
12 | local y = settings.Y or 100
13 | local show_title = settings.Show_Title or false
14 | local show_bg = true
15 |
16 | local need_position_reset = true
17 | local scaling_set = false
18 | local visible = {false}
19 |
20 | local flags_default = bit.bor(
21 | ImGuiWindowFlags_AlwaysAutoResize, -- This prevents manual resizing, but without it things look messed up.
22 | ImGuiWindowFlags_NoSavedSettings,
23 | ImGuiWindowFlags_NoNav
24 | )
25 |
26 | ------------------------------------------------------------------------------------------------------
27 | -- Populates the window.
28 | ------------------------------------------------------------------------------------------------------
29 | ---@param content? function
30 | ------------------------------------------------------------------------------------------------------
31 | self.Populate = function(content)
32 | visible[1] = Window_Manager.Get_Visibility(module)
33 | if Ashita.Player.Is_Zoning() or not visible[1] then return nil end
34 |
35 | UI.PushStyleVar(ImGuiStyleVar_Alpha, Metrics.Window.Alpha)
36 | UI.PushStyleVar(ImGuiStyleVar_CellPadding, {10, 1})
37 | UI.PushStyleVar(ImGuiStyleVar_WindowPadding, {7, 3})
38 | UI.PushStyleVar(ImGuiStyleVar_ItemSpacing, {0, 5})
39 | UI.PushStyleVar(ImGuiStyleVar_ItemInnerSpacing, {5, 0})
40 |
41 | local flags = flags_default
42 | if not Metrics.Window.Show_Title and not show_title then flags = bit.bor(flags, ImGuiWindowFlags_NoTitleBar) end
43 | if not show_bg then flags = bit.bor(flags, ImGuiWindowFlags_NoBackground) end
44 | self.Check_Position()
45 |
46 | if UI.Begin(title, visible, flags) then
47 | self.Update_Settings()
48 | self.Set_Scaling()
49 | Window_Manager.Theme.Set()
50 | if content then content() end
51 | UI.End()
52 | end
53 |
54 | UI.PopStyleVar(5)
55 | end
56 |
57 | ------------------------------------------------------------------------------------------------------
58 | -- Checks if the position of the window needs to be reset ex: switching characters.
59 | ------------------------------------------------------------------------------------------------------
60 | self.Check_Position = function()
61 | if need_position_reset then
62 | UI.SetNextWindowPos(Window_Manager.Get_Position(module), ImGuiCond_Always)
63 | need_position_reset = false
64 | end
65 | end
66 |
67 | ------------------------------------------------------------------------------------------------------
68 | -- Updates the window position for the settings file.
69 | ------------------------------------------------------------------------------------------------------
70 | self.Update_Settings = function()
71 | x, y = UI.GetWindowPos()
72 | Window_Manager.Save_Position(module, x, y)
73 | Window_Manager.Save_Visibility(module, visible[1])
74 | end
75 |
76 | ------------------------------------------------------------------------------------------------------
77 | -- Checks whether the window is currently visible.
78 | ------------------------------------------------------------------------------------------------------
79 | self.Is_Visible = function()
80 | return visible[1]
81 | end
82 |
83 | ------------------------------------------------------------------------------------------------------
84 | -- Toggles window visibility.
85 | ------------------------------------------------------------------------------------------------------
86 | self.Toggle_Visibility = function()
87 | visible[1] = not visible[1]
88 | Window_Manager.Save_Visibility(module, visible[1])
89 | end
90 |
91 | ------------------------------------------------------------------------------------------------------
92 | -- Makes the window visible.
93 | ------------------------------------------------------------------------------------------------------
94 | self.Show = function()
95 | visible[1] = true
96 | Window_Manager.Save_Visibility(module, true)
97 | end
98 |
99 | ------------------------------------------------------------------------------------------------------
100 | -- Makes the window invisible.
101 | ------------------------------------------------------------------------------------------------------
102 | self.Hide = function()
103 | visible[1] = false
104 | Window_Manager.Save_Visibility(module, false)
105 | end
106 |
107 | ------------------------------------------------------------------------------------------------------
108 | -- Makes the window active either by switching to the tab or by toggling the window.
109 | ------------------------------------------------------------------------------------------------------
110 | self.Make_Active = function()
111 | Window_Manager.Switch_Module(name)
112 | self.Toggle_Visibility()
113 | end
114 |
115 | ------------------------------------------------------------------------------------------------------
116 | -- Forces the position to need a reset for cases like character switch.
117 | ------------------------------------------------------------------------------------------------------
118 | self.Settings_Reset = function()
119 | need_position_reset = true
120 | scaling_set = false
121 | end
122 |
123 | ------------------------------------------------------------------------------------------------------
124 | -- Sets the window scaling.
125 | ------------------------------------------------------------------------------------------------------
126 | self.Set_Scaling = function()
127 | if not scaling_set then
128 | UI.SetWindowFontScale(Window_Manager.Get_Scaling())
129 | scaling_set = true
130 | end
131 | end
132 |
133 | ------------------------------------------------------------------------------------------------------
134 | -- Forces the scaling flag to reset after toggling the scaling setting.
135 | ------------------------------------------------------------------------------------------------------
136 | self.Force_Scaling_Reset = function()
137 | scaling_set = false
138 | end
139 |
140 | ------------------------------------------------------------------------------------------------------
141 | -- Forces the scaling flag to reset after toggling the scaling setting.
142 | ------------------------------------------------------------------------------------------------------
143 | ---@param background boolean
144 | ------------------------------------------------------------------------------------------------------
145 | self.Set_Background = function(background)
146 | show_bg = background
147 | end
148 |
149 | Window_Manager.Add_Window(module, module, self)
150 | return self
151 | end
152 |
--------------------------------------------------------------------------------
/windows/config.lua:
--------------------------------------------------------------------------------
1 | Window_Manager.Config = T{}
2 |
3 | Window_Manager.Config.Defaults = T{
4 | Alpha = 1.0,
5 | Window_Scaling = 1.0,
6 | Style = 0,
7 | X_Pos = 100,
8 | Y_Pos = 100,
9 | Show_Title = false,
10 | Show_Mouse = false,
11 | Multi_Window = false,
12 | Active_Window = "Parse",
13 | Hub_X = 100,
14 | Hub_Y = 100,
15 | Screenshot_X = 100,
16 | Screenshot_Y = 100,
17 | Config_Window_Visible = {false},
18 | Config_X = 100,
19 | Config_Y = 100,
20 | }
21 |
22 | ------------------------------------------------------------------------------------------------------
23 | -- Resets visual settings in the window.
24 | ------------------------------------------------------------------------------------------------------
25 | Window_Manager.Config.Reset = function()
26 | Metrics.Window.Alpha = Window_Manager.Defaults.Alpha
27 | Metrics.Window.Window_Scaling = Window_Manager.Defaults.Window_Scaling
28 | Metrics.Window.Show_Title = Window_Manager.Defaults.Show_Title
29 | end
30 |
31 | ------------------------------------------------------------------------------------------------------
32 | -- Shows settings that affect the GUI.
33 | ------------------------------------------------------------------------------------------------------
34 | Window_Manager.Config.Display = function()
35 | if UI.BeginTable("GUI Setings", 2) then
36 | UI.TableNextColumn()
37 | if UI.Checkbox("Show Title Bar", {Metrics.Window.Show_Title}) then
38 | Metrics.Window.Show_Title = not Metrics.Window.Show_Title
39 | end
40 | UI.SameLine() Window_Manager.Widgets.HelpMarker("Enables a window header that allows you to collapse the window.")
41 |
42 | UI.TableNextColumn()
43 | if UI.Checkbox("Show Mouse", {Metrics.Window.Show_Mouse}) then
44 | Window_Manager.Toggle_Mouse()
45 | end
46 | UI.SameLine() Window_Manager.Widgets.HelpMarker("There are a lot of click targets in Metrics. If you can't see your mouse when hovering over " ..
47 | "the windows of ImGui based addons and would like to then give this a try. It will show your regular " ..
48 | "Windows mouse on top of your regular in game cursor.")
49 |
50 | UI.TableNextColumn()
51 | if UI.Checkbox("Multi Window", {Metrics.Window.Multi_Window}) then
52 | Metrics.Window.Multi_Window = not Metrics.Window.Multi_Window
53 | if Metrics.Window.Multi_Window then
54 | Metrics.Window.Active_Window = nil
55 | Config.Window.Show()
56 | else
57 | Metrics.Window.Active_Window = Config.Name
58 | Config.Window.Hide()
59 | end
60 | end
61 | UI.SameLine() Window_Manager.Widgets.HelpMarker("Have mutliple tabs open at once by enabling multiple windows. Be cautious running at " ..
62 | "higher FPS with multiple windows open. It may affect performance.")
63 | UI.EndTable()
64 | end
65 |
66 | UI.Separator() Window_Manager.Theme.Choose()
67 | UI.Separator() Window_Manager.Widgets.Alpha()
68 | Window_Manager.Widgets.Window_Scale()
69 | end
--------------------------------------------------------------------------------
/windows/themes.lua:
--------------------------------------------------------------------------------
1 | Window_Manager.Theme = T{}
2 |
3 | Window_Manager.Theme.Is_Set = false
4 | Window_Manager.Theme.Table_Row_Bg = {0.00, 0.00, 0.00, 0.00}
5 |
6 | ------------------------------------------------------------------------------------------------------
7 | -- Change the window themes.
8 | -- Modeled from the ImGui demo.
9 | -- https://github.com/ocornut/imgui/blob/master/imgui_demo.cpp
10 | ------------------------------------------------------------------------------------------------------
11 | Window_Manager.Theme.Choose = function()
12 | UI.Text("Theme (will affect other ImGui based addons)")
13 | if UI.RadioButton("Default ", {Metrics.Window.Style}, 0) then
14 | Metrics.Window.Style = 0
15 | Window_Manager.Theme.Is_Set = false
16 | end
17 | UI.SameLine()
18 | if UI.RadioButton("Dark ", {Metrics.Window.Style}, 1) then
19 | Metrics.Window.Style = 1
20 | Window_Manager.Theme.Is_Set = false
21 | end
22 | UI.SameLine()
23 | if UI.RadioButton("Classic ", {Metrics.Window.Style}, 3) then
24 | Metrics.Window.Style = 3
25 | Window_Manager.Theme.Is_Set = false
26 | end
27 | Window_Manager.Theme.Set()
28 | end
29 |
30 | ------------------------------------------------------------------------------------------------------
31 | -- Change the window themes.
32 | -- Modeled from the ImGui demo.
33 | -- https://github.com/ocornut/imgui/blob/master/imgui_demo.cpp
34 | ------------------------------------------------------------------------------------------------------
35 | Window_Manager.Theme.Set = function()
36 | if not Window_Manager.Theme.Is_Set then
37 | if Metrics.Window.Style == 0 then
38 | Window_Manager.Theme.Apply_Custom(Themes.Default)
39 | Window_Manager.Theme.Table_Row_Bg = {0.18, 0.20, 0.23, 1.00}
40 | elseif Metrics.Window.Style == 1 then
41 | UI.StyleColorsDark()
42 | Window_Manager.Theme.Table_Row_Bg = {0.06, 0.06, 0.06, 1.00}
43 | elseif Metrics.Window.Style == 2 then
44 | UI.StyleColorsLight()
45 | elseif Metrics.Window.Style == 3 then
46 | UI.StyleColorsClassic()
47 | Window_Manager.Theme.Table_Row_Bg = {0.00, 0.00, 0.00, 1.00}
48 | else
49 | Window_Manager.Theme.Apply_Custom(Themes.Default)
50 | end
51 | Window_Manager.Theme.Is_Set = true
52 | end
53 | end
54 |
55 | ------------------------------------------------------------------------------------------------------
56 | -- Applies a custom theme.
57 | ------------------------------------------------------------------------------------------------------
58 | ---@param theme table defined in resources.themes.
59 | ------------------------------------------------------------------------------------------------------
60 | Window_Manager.Theme.Apply_Custom = function(theme)
61 | for flag_name, flag_value in pairs(Themes.Elements) do
62 | if theme[flag_name] then
63 | UI.PushStyleColor(flag_value, theme[flag_name])
64 | end
65 | end
66 | end
--------------------------------------------------------------------------------
/windows/widgets.lua:
--------------------------------------------------------------------------------
1 | Window_Manager.Widgets = T{}
2 |
3 | Window_Manager.Widgets.Slider_Width = 100
4 |
5 | ------------------------------------------------------------------------------------------------------
6 | -- Creates a help text marker.
7 | ------------------------------------------------------------------------------------------------------
8 | Window_Manager.Widgets.HelpMarker = function(text)
9 | UI.TextDisabled("(?)")
10 | if UI.IsItemHovered() then
11 | UI.BeginTooltip()
12 | UI.PushTextWrapPos(UI.GetFontSize() * 25)
13 | UI.TextUnformatted(text)
14 | UI.PopTextWrapPos()
15 | UI.EndTooltip()
16 | end
17 | end
18 |
19 | ------------------------------------------------------------------------------------------------------
20 | -- Sets screen alpha.
21 | ------------------------------------------------------------------------------------------------------
22 | Window_Manager.Widgets.Alpha = function()
23 | local alpha = {[1] = Metrics.Window.Alpha}
24 | UI.SetNextItemWidth(Window_Manager.Widgets.Slider_Width)
25 | if UI.DragFloat("Window Transparency", alpha, 0.005, 0.2, 1, "%.2f", ImGuiSliderFlags_None) then
26 | if alpha[1] < 0.2 then alpha[1] = 0.2
27 | elseif alpha[1] > 1 then alpha[1] = 1 end
28 | Metrics.Window.Alpha = alpha[1]
29 | end
30 | UI.SameLine() Window_Manager.Widgets.HelpMarker("Window transparency.")
31 | end
32 |
33 | ------------------------------------------------------------------------------------------------------
34 | -- Sets window scaling.
35 | ------------------------------------------------------------------------------------------------------
36 | Window_Manager.Widgets.Window_Scale = function()
37 | local window_scale = {[1] = Metrics.Window.Window_Scaling}
38 | UI.SetNextItemWidth(Window_Manager.Widgets.Slider_Width)
39 | if UI.DragFloat("Window Scaling", window_scale, 0.005, 0.7, 3, "%.2f", ImGuiSliderFlags_None) then
40 | if window_scale[1] < 0.7 then window_scale[1] = 0.7
41 | elseif window_scale[1] > 3 then window_scale[1] = 3 end
42 | Metrics.Window.Window_Scaling = window_scale[1]
43 | Window_Manager.Reset_Scaling_Flags()
44 | end
45 | UI.SameLine() Window_Manager.Widgets.HelpMarker("Adjust window element size.")
46 | end
--------------------------------------------------------------------------------