-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgame_object.lua
More file actions
452 lines (443 loc) · 26.5 KB
/
Copy pathgame_object.lua
File metadata and controls
452 lines (443 loc) · 26.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
---@class threat_table
---@field is_tanking boolean
---@field status integer -- 0, 1, 2, 3
---@field threat_percent number -- 0 to 100
--- A single aura on a unit, as game_object:get_buffs() and get_debuffs() report it.
---
--- WHY impl AND buff_index ARE DOCUMENTED 2026-08-11: this class is not read-only. It is also the
--- argument type of core.input.cancel_buff, and the C++ side of that call (check_buff in
--- lua_type_buff.cpp) does a luaL_checkinteger on BOTH of these two fields. A table built by hand
--- from the seven fields this class used to list therefore throws inside cancel_buff, and the class
--- was the only place a caller could have learned otherwise. They arrived together with the call
--- that needs them, "add input.cancel_buff" (f6a71c33 in wow_core, 2025-03-09).
---
--- The rule that follows: pass back the SAME table get_buffs() handed you. Do not synthesize one,
--- and do not carry one across ticks, because impl is a native address whose aura may be gone.
---@class buff
---@field buff_name string
---@field buff_id integer
---@field count number
---@field expire_time number
---@field duration number
---@field type integer
---@field caster game_object
---@field impl integer Opaque native handle for the aura. Do NOT interpret it or do arithmetic on it; its only supported use is being passed straight back in core.input.cancel_buff.
---@field buff_index integer The aura's slot on the unit. Reused as soon as an aura fades, so it identifies the aura only within the tick that read it. Also required by core.input.cancel_buff.
---@field points number[] -- variable values from aura data (e.g. absorb remaining for shields)
---@class loss_of_control_info
---@field valid boolean
---@field spell_id integer
---@field start_time integer
---@field end_time integer
---@field duration integer
---@field type integer
---@field lockout_school schools_flag
--- One row from any container enumeration: core.inventory.get_items_in_bag,
--- game_object:get_equipped_items and game_object:get_item_at_inventory_slot all return this
--- shape and nothing else.
---
--- THERE IS NO item_id FIELD, and that omission has caused a real, long-lived bug. Code that
--- reads `row.item_id` gets nil on every row of every build, silently, forever. The core builds
--- these rows in lua_push_item_table (lua_bindings_inventory.cpp and lua_type_game_object.cpp)
--- and sets exactly the two fields below. Read the id off the object:
---
--- local id = row.object and row.object:get_item_id()
---
--- Empty slots are never emitted, so #list is an item count and never a slot count, and the
--- list cannot be indexed by slot. Walk it and read slot_id off each row.
---@class item_slot_info
---@field object game_object The item itself. Never nil in practice, since the core only emits a
--- row once find_object_by_guid resolved the slot, but it is pushed through
--- push_game_object_or_nill, so guard it if you are being careful.
---@field slot_id integer 1-BASED index into the container, always the native index plus one.
--- For bags 1 to 4 this is the slot within that bag. For the player container (bag 0, and both
--- game_object enumerations) it is a position in the whole player array: 1 to 19 worn gear,
--- 20 to 23 the bag objects, 24 and up the backpack, on the classic clients. NOT a
--- core.input.use_container_item slot, see common/utility/inventory_helper.lua.
---@class unit_ranged_damage_data
---@field speed number
---@field min_damage number
---@field max_damage number
---@field pos_buff integer
---@field neg_buff integer
---@field percent number
--- The four armor values game_object:get_armor() returns, straight from WoW's UnitArmor(unit).
---
--- Every field is an integer and every field is always present. The binding zero-initializes all
--- four and only overwrites the ones UnitArmor actually answered, so a unit the call could not
--- resolve reads as four zeros rather than nil, and there is no separate failure signal. Treat
--- effective_armor of 0 on a live unit as "not answered", not as "no armor".
---
--- UnitArmor returns baseArmor, effectiveArmor, armor, posBuff, negBuff. The core reads the first
--- four and DISCARDS negBuff, which is why bonus_armor is the positive component only and a
--- debuffed unit's reduction shows up in effective_armor without a field of its own.
---@class armor_data
---@field base integer Armor before buffs and debuffs.
---@field effective_armor integer Armor actually applied to damage taken. This is the one mitigation math wants.
---@field armor integer The client's displayed armor value.
---@field bonus_armor integer The positive buff component only. UnitArmor's negBuff is not read by the core.
---@class nameplate_info
---@field is_shown boolean Whether the nameplate frame is currently shown on screen.
---@field left number The x coordinate of the nameplate's bottom-left corner, in scaled screen pixels.
---@field bottom number The y coordinate of the nameplate's bottom-left corner, in scaled screen pixels.
---@field width number The nameplate width in scaled screen pixels.
---@field height number The nameplate height in scaled screen pixels.
---@class game_object
---Returns whether the game_object is valid.
---@field is_valid fun(self: game_object): boolean
---Returns whether the game_object is visible.
---@field is_visible fun(self: game_object): boolean
---Returns the type of the game object.
---@field get_type fun(self: game_object): number
---Returns the object type as a string.
---@field get_object_type_string fun(self: game_object): string
---Returns the class of the game object.
---@field get_class fun(self: game_object): number
---Returns the spec_id of the game object.
---@field get_specialization_id fun(self: game_object): number
---Returns the npc_id of the game object.
---@field get_npc_id fun(self: game_object): number
---Returns the item_id of the game object.
---@field get_item_id fun(self: game_object): number
---Returns the level of the game object.
---@field get_level fun(self: game_object): number
---Returns the effective level of the game object.
---@field get_effective_level fun(self: game_object): number
---Returns the LOCAL PLAYER's money in copper. 0 on every other object, and 0 when the
---client has no answer. The name says "gold" and the unit is copper: divide by 10000.
---
---Only the local player has a purse the client knows about, so calling this on a target,
---a party member or an NPC answers 0 by design rather than guessing. Before 2026-09-20 it
---read a hardcoded offset and answered whatever had moved into that slot after a patch,
---which is how it spent six weeks returning 0 on retail 12.1.0; it now asks the client
---through GetMoney(), so it cannot go stale again.
---
---This is a Lua call into the game, not a memory read. Cheap, but cache it rather than
---polling it every frame.
---@field get_gold fun(self: game_object): number
---Returns the faction id of the game object.
---@field get_faction_id fun(self: game_object): number
---Returns the mark id of the game object.
--- 0 = No Icon
--- 1 = Yellow 4-point Star
--- 2 = Orange Circle
--- 3 = Purple Diamond
--- 4 = Green Triangle
--- 5 = White Crescent Moon
--- 6 = Blue Square
--- 7 = Red "X" Cross
--- 8 = White Skull
---@field get_target_marker_index fun(self: game_object): number
---Sets the target marker (raid icon) on the game object. Pass 0 to clear the icon.
---This is the icon that rides on the unit; the ground flares are core.world.place_raid_marker.
---@field set_target_marker_index fun(self: game_object, index: integer)
---Returns the race id of the game object.
---@field get_race_id fun(self: game_object): integer
---Returns the creature_type id of the game object.
-- 1 -> Beast
-- 2 -> Dragonkin
-- 3 -> Demon
-- 4 -> Elemental
-- 5 -> Giant
-- 6 -> Undead
-- 7 -> Humanoid
-- 8 -> Critter
-- 9 -> Mechanical
-- 10 -> Not specified
-- 11 -> Totem
-- 12 -> Non-combat Pet
-- 13 -> Gas Cloud
-- 14 -> Wild Pet
-- 15 -> Aberration
---@field get_creature_type fun(self: game_object): number
---Returns the classification id of the game object.
--- -1 = unknown
--- 0 = normal
--- 1 = elite
--- 2 = rareelite
--- 3 = worldboss
--- 4 = rare
--- 5 = trivial
--- 6 = minus
---@field get_classification fun(self: game_object): number
---Returns the group role of the game object.
--- "NONE" / unknown = -1
--- "TANK" = 0
--- "HEALER" = 1
--- "DAMAGER" = 2
---@field get_group_role fun(self: game_object): number
---Returns the bounding radius of the game object.
---@field get_bounding_radius fun(self: game_object): number
---Returns the combat reach of the game object. Only valid for units.
---@field get_combat_reach fun(self: game_object): number
---Returns the height of the game object.
---@field get_height fun(self: game_object): number
---Returns the scale of the game object.
---@field get_scale fun(self: game_object): number
---Returns the cooldown of the specified item.
---@field get_item_cooldown fun(self: game_object, item_id: integer): number
---Returns whether the game object is a party member.
---@field is_party_member fun(self: game_object): boolean
---Returns whether the game object has the specified item.
---@field has_item fun(self: game_object, item_id: integer): boolean
---Returns whether the game object is dead.
---@field is_dead fun(self: game_object): boolean
---Returns whether the game object is ghost.
---@field is_ghost fun(self: game_object): boolean
---Returns whether the game object is feigning death.
---@field is_feign_death fun(self: game_object): boolean
---Returns whether the game object is a basic object.
---@field is_basic_object fun(self: game_object): boolean
---Returns whether the game object is a player.
---@field is_player fun(self: game_object): boolean
---Returns whether the game object is a unit.
---@field is_unit fun(self: game_object): boolean
---Returns whether the game object is a boss.
---@field is_boss fun(self: game_object): boolean
---Returns whether the game object is a quest unit.
---@field is_quest_unit fun(self: game_object): boolean
---Returns whether the game object is an item.
---@field is_item fun(self: game_object): boolean
---Returns whether the game object is mounted.
---@field is_mounted fun(self: game_object): boolean
---Returns whether the game object is outdoors.
---@field is_outdoors fun(self: game_object): boolean
---Returns whether the game object is indoors.
---@field is_indoors fun(self: game_object): boolean
---Returns whether the game object is glowing.
---@field is_glow fun(self: game_object): boolean
---Sets the glowing state of the game object.
---@field set_glow fun(self: game_object, state: boolean): nil
---Returns whether the game object is in combat.
---@field is_in_combat fun(self: game_object): boolean
---Returns the position of the game object.
---@field get_position fun(self: game_object): vec3
---Returns the name of the game object.
---@field get_name fun(self: game_object): string
---Returns the object's globally-unique GUID string (e.g. "Player-1-000011A6",
---"Creature-0-1-0-0-3124-00000019EB", "Item-1-0-00000000000C4E5C", "GameObject-0-...").
---Since core commit "Fixed lua_get_object_from_guid" (2026-09-01) this is printed natively
---and answers for EVERY object type, not just units: items and game objects used to return
---"" because the old implementation asked the client's UnitGUID, which only names units.
---The string is byte-identical to UnitGUID's for the types the client prints (verified on
---wow_tbc_ps 2.5.3 and wow_vanilla_ps 1.14.2, sessions 01_09_2026_02_33_33_1066 and
---01_09_2026_03_02_57_176034), so it compares equal against combat-log guids and feeds
---core.object_manager.get_object_from_guid for a lossless round trip. "" still appears for
---the handful of guid types with no printable form (e.g. ClientActor).
---@field get_guid fun(self: game_object): string
---Returns the current health of the game object.
---@field get_health fun(self: game_object): number
---NOTE 2026-09-20: there is no get_money and there never has been, on any build. A
---`get_money?` field used to sit here; it was added to satisfy a call site in
---test_barney rather than because the core registered anything, which is exactly what
---CORE_WOW.md forbids, and every caller of it got nil. Use get_gold above, or
---core.inventory.get_gold. Do not re-add it without a matching luaL_Reg row in
---lua_type_game_object.cpp.
---Returns the maximum health of the game object.
---@field get_max_health fun(self: game_object): number
---Returns the max health modifier of the game object.
---@field get_max_health_modifier fun(self: game_object): number
---Returns the current power of the game object for the specified power type.
--- Note: https://wowpedia.fandom.com/wiki/Enum.PowerType
---@field get_power fun(self: game_object, power_type: number): number
---Returns the maximum power of the game object for the specified power type.
--- Note: https://wowpedia.fandom.com/wiki/Enum.PowerType
---@field get_max_power fun(self: game_object, power_type: number): number
---Returns the experience points (XP) of the game object.
---@field get_xp fun(self: game_object): number
---Returns the maximum experience points (XP) of the game object.
---@field get_max_xp fun(self: game_object): number
---Returns the total absorb shield of the game object.
---@field get_total_shield fun(self: game_object): number
---Returns the total incoming heals of the game object.
---@field get_incoming_heals fun(self: game_object): number
---Returns the incoming heals of the game object from an specific game_object.
---@field get_incoming_heals_from fun(self: game_object): number
---Returns whether the game object can attack the specified game object.
---@field can_attack fun(self: game_object, other_game_object: game_object): boolean
---Returns whether the game object is an enemy with the specified game object.
---@field is_enemy_with fun(self: game_object, other_game_object: game_object): boolean
---Returns whether the game object is a friend with the specified game object.
---@field is_friend_with fun(self: game_object, other_game_object: game_object): boolean
---Returns whether the game object is moving.
---@field is_moving fun(self: game_object): boolean
---Returns whether the game object is dashing.
---@field is_dashing fun(self: game_object): boolean
---Returns whether the game object is flying.
---@field is_flying fun(self: game_object): boolean
---Returns the current movement speed of the game object.
---@field get_movement_speed fun(self: game_object): number
---Returns the maximum movement speed of the game object.
---@field get_movement_speed_max fun(self: game_object): number
---Returns the maximum swim speed of the game object.
---@field get_swim_speed_max fun(self: game_object): number
---Returns the maximum flight speed of the game object.
---@field get_flight_speed_max fun(self: game_object): number
---Returns the glide speed of the game object.
---@field get_glide_speed fun(self: game_object): number
---Returns the auto attack swing speed of the game object.
---@field get_attack_speed fun(self: game_object): number
---Returns the rotation of the game object.
---@field get_rotation fun(self: game_object): number
---Returns the direction of the game object.
---@field get_direction fun(self: game_object): vec3
---Returns the direction of the game object movement manager.
---@field get_movement_direction fun(self: game_object): vec3
---Returns whether the game object is a pet.
---@field is_pet fun(self: game_object): boolean
---Returns whether the game object is a minion (alt pets).
---@field is_minion fun(self: game_object): boolean
---Returns whether the game object is a bag type item.
---@field is_item_bag fun(self: game_object): boolean
---Returns the stack count of the item in our bag.
---@field get_item_stack_count fun(self: game_object): number
---Returns the owner of the game object.
---@field get_owner fun(self: game_object): game_object
---Returns the pet of the game object.
---@field get_pet fun(self: game_object): game_object
---Returns the target of the game object.
---@field get_target fun(self: game_object): game_object
---Returns the target of the active spell being cast by the game object.
---@field get_active_spell_target fun(self: game_object): game_object
---Returns whether the game object is casting a spell.
---@field is_casting_spell fun(self: game_object): boolean
---Returns the ID of the active spell being cast by the game object.
---@field get_active_spell_id fun(self: game_object): number
---Returns the start time of the active spell being cast by the game object.
---@field get_active_spell_cast_start_time fun(self: game_object): number
---Returns the end time of the active spell being cast by the game object.
---@field get_active_spell_cast_end_time fun(self: game_object): number
---Returns whether the active spell being cast by the game object can be interrupted.
---@field is_active_spell_interruptable fun(self: game_object): boolean
---Returns whether the game object is currently channeling a spell.
---@field is_channelling_spell fun(self: game_object): boolean
---Returns the ID of the active channel spell being cast by the game object.
---@field get_active_channel_spell_id fun(self: game_object): number
---Returns the start time of the active channel spell being cast by the game object.
---@field get_active_channel_cast_start_time fun(self: game_object): number
---Returns the end time of the active channel spell being cast by the game object.
---@field get_active_channel_cast_end_time fun(self: game_object): number
---Returns the threat situation from the game_object to another game_object.
---@field get_threat_situation fun(self: game_object, obj: game_object): threat_table
---Returns resolved buff data for the specified aura spec (cached).
---@field get_buff_data fun(self: game_object, spec: buff_db | number[]): buff_manager_data|nil
---Returns resolved debuff data for the specified aura spec (cached).
---@field get_debuff_data fun(self: game_object, spec: buff_db | number[]): buff_manager_data|nil
---Returns resolved aura data for the specified aura spec (cached).
---@field get_aura_data fun(self: game_object, spec: buff_db | number[]): buff_manager_data|nil
---Returns a table containing the auras applied to the game object.
---@field get_auras fun(self: game_object): buff_table
---Returns a table containing the buffs applied to the game object.
---@field get_buffs fun(self: game_object): buff_table
---Returns a table containing the debuffs applied to the game object.
---@field get_debuffs fun(self: game_object): buff_table
---Returns a list of equipped items (item_slot_info) of the game object, the format comes in we call item_slot_info, a table that contains game_object ptr of the item and item_slot.
---
---IT RETURNS MORE THAN EQUIPPED ITEMS ON THE CLASSIC CLIENTS, and the overshoot is a fixed
---number of backpack rows rather than an occasional one. Documented 2026-08-31.
---
---The binding walks the player's whole item array, the same buffer core.inventory
---.get_items_in_bag(0) returns, and trims it with a single hardcoded cutoff in
---lua_type_game_object.cpp: `if (slot <= 35)`, commented "bags 31..35, after this slot it starts
---enumerating your bag contents". That 35 is a RETAIL layout number. It is not derived from the
---build, so every client gets it:
---
--- retail family slot_id 1..30 worn, 31..35 the bag objects, backpack from 36. Cutoff correct,
--- though the four or five bag OBJECTS are still included as "equipped".
--- classic family slot_id 1..19 worn, 20..23 the bag objects, backpack from 24. The cutoff
--- admits slot_id 24 through 35, so up to TWELVE BACKPACK ITEMS arrive labelled
--- as equipment.
---
---So on wow_tbc_ps, wow_vanilla_ps and the Blizzard classic targets alike, filter by slot_id
---yourself: worn gear is slot_id 1 to 19 and nothing else. Do not treat the list length as an
---equipped-item count and do not feed it to anything that assumes an INVSLOT.
---
---This is a core-side defect, tracked rather than worked around in the SDK because the fix is a
---per-build constant next to o_player_inventory. Reported with the bag 0 write-up, see
---claude_md/GLOBAL/CORE_WOW.md under "Bag 0 is the whole player container".
---@field get_equipped_items fun(self: game_object): item_slot_info_table
---Returns a table with the item game_object ptr and the slot_id where the item is on the game object equipped items.
---
---THE SLOT IS 1-BASED, an INVSLOT_* id, not a 0-based index. The binding subtracts one before it
---indexes the player array, so 1 is the head and 19 is the tabard. Passing 0 underflows to an
---unsigned 0xFFFFFFFF, fails the capacity check and returns a row whose .object is nil, which
---looks exactly like an empty slot and is why a `for slot = 0, 18` loop silently reads head
---through ranged and never sees the tabard.
---
---The full 1-based map on the classic clients: 1 head, 2 neck, 3 shoulder, 4 shirt, 5 chest,
---6 waist, 7 legs, 8 feet, 9 wrist, 10 hands, 11 finger1, 12 finger2, 13 trinket1, 14 trinket2,
---15 back, 16 main hand, 17 off hand, 18 ranged, 19 tabard. Above that it keeps indexing the
---same array, so 20 to 23 are the bag objects and 24 and up is the backpack.
---
---The returned row always exists; an empty or out-of-range slot gives .object == nil rather than
---nil itself, so test the field, not the return value.
---@field get_item_at_inventory_slot fun(self: game_object, slot:number): item_slot_info
--- Returns whether the game object can be looted.
---@field can_be_looted fun(self: game_object): boolean
--- Returns whether the game object contains loot.
---@field has_loot fun(self: game_object): boolean
--- Returns whether the game object can be used.
---@field can_be_used fun(self: game_object): boolean
--- Returns whether the game object can be skinned.
---@field can_be_skinned fun(self: game_object): boolean
--- Returns whether the game object has skin to harvest.
---@field has_skin fun(self: game_object): boolean
--- Returns the game object creator.
---@field get_creator_object fun(self: game_object): game_object
---Returns a table containing the loss of control info for the game object.
---@field get_loss_of_control_info fun(self: game_object): loss_of_control_info
---Returns the phase reason for this unit relative to the local player.
--- -1 = same phase (no reason / equivalent to UnitPhaseReason returning nil)
--- 0 = Phasing (different phase)
--- 1 = Sharding (different shard)
--- 2 = WarMode (different war mode)
--- 3 = ChromieTime (Timewalking Campaign)
--- 4 = TimerunningHwt
---@field get_unit_phase fun(self: game_object): number
---Returns whether the item in the specified slot has an enchant.
---@field item_has_enchant fun(self: game_object): boolean
---Returns the expiration time (in seconds) of the enchant on the item in the specified slot.
---@field item_enchant_expiration fun(self: game_object): number
---Returns the number of remaining charges of the enchant on the item in the specified slot.
---@field item_enchant_charges fun(self: game_object): integer
---Returns the enchant ID of the item in the specified slot.
---@field item_enchant_id fun(self: game_object): integer
---Returns the current spell haste percentage of the game object.
---A value of 8 means 8% haste.
---@field get_spell_haste fun(self: game_object): number
---Returns the duration (in seconds) of a specific empower stage for the currently cast empower spell by the game object.
---@field get_empower_stage_duration fun(self: game_object, index:number): number
---Returns the maximum empower stage of the spell being cast by the game object.
---@field get_empower_max_stage fun(self: game_object): number
---Returns the game object that currently holds the combo points generated by this game object.
---@field get_combo_points_target fun(self: game_object): game_object
---Returns the total amount of healing that is being absorbed on this game object (i.e., cannot be healed until the absorb is removed).
---@field get_total_heal_absorbs fun(self: game_object): number
---Returns whether the game object currently has auto attack toggled on.
---@field is_auto_attacking fun(self: game_object): boolean
---Returns whether the game object constains fish to loot.
---@field does_bobber_have_fish fun(self: game_object): boolean
---Returns the current empower stage of the spell being cast by the game object.
---Returns -1 if not currently casting an empower spell.
---@field get_empower_current_stage fun(self: game_object): number
---Returns the unit's ranged damage information including speed, damage range, buffs, and percentage modifier.
---@field get_unit_ranged_damage fun(self: game_object): unit_ranged_damage_data
---Returns the game object's armor as a TABLE of four integers, not a single value.
---This stub said `number` from the day the binding landed ("Added get_armor to lua", 085e19ed in
---wow_core, 2026-03-16) until 2026-08-11, so anything written against it was doing arithmetic on a
---table. lua_game_object_get_armor builds the table with lua_newtable and four lua_pushinteger
---calls; there is no scalar return path anywhere in it. See armor_data for which field to use.
---@field get_armor fun(self: game_object): armor_data
---Returns the current state flags bitfield of the game object.
---@field get_state_flags fun(self: game_object): integer
---Returns whatever the npc is tap denied for the localplayer (grey healthbar)
---@field is_tap_denied fun(self: game_object): number
---Returns this unit's nameplate visibility and on-screen rectangle (bottom-left
---origin, in scaled screen pixels), or nil when the unit has no nameplate frame
---(out of range, nameplates disabled, or the C_NamePlate API is unavailable on
---older clients).
---@field get_nameplate fun(self: game_object): nameplate_info|nil
---Returns the world position of the unit's name attachment point (the anchor above the model where the name/nameplate text sits, roughly the top of the head). Returns a zero vector when the model is not loaded.
---@field get_attachment_name_position fun(self: game_object): vec3
---Returns the world position of a specific model attachment point, identified by its numeric id (e.g. hands, chest, base, overhead). Returns a zero vector when the model is not loaded or does not have the requested attachment.
---@field get_attachment_position fun(self: game_object, attachment_id: integer): vec3