From 45850c5aa911da12fc2584ccdda164f76089a7b2 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Sat, 21 Mar 2026 01:58:03 -0700 Subject: [PATCH] feat: add targeting Lua API functions for addon and macro support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement 8 targeting functions commonly used by unit frame addons, targeting macros, and click-casting addons: - TargetUnit(unitId) / ClearTarget() - FocusUnit(unitId) / ClearFocus() - AssistUnit(unitId) — target the given unit's target - TargetLastTarget() — return to previous target - TargetNearestEnemy() / TargetNearestFriend() — tab-targeting --- src/addons/lua_engine.cpp | 82 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/src/addons/lua_engine.cpp b/src/addons/lua_engine.cpp index 1b9067c0..7160576e 100644 --- a/src/addons/lua_engine.cpp +++ b/src/addons/lua_engine.cpp @@ -582,6 +582,80 @@ static int lua_HasTarget(lua_State* L) { return 1; } +// TargetUnit(unitId) — set current target +static int lua_TargetUnit(lua_State* L) { + auto* gh = getGameHandler(L); + if (!gh) return 0; + const char* uid = luaL_checkstring(L, 1); + std::string uidStr(uid); + for (char& c : uidStr) c = static_cast(std::tolower(static_cast(c))); + uint64_t guid = resolveUnitGuid(gh, uidStr); + if (guid != 0) gh->setTarget(guid); + return 0; +} + +// ClearTarget() — clear current target +static int lua_ClearTarget(lua_State* L) { + auto* gh = getGameHandler(L); + if (gh) gh->clearTarget(); + return 0; +} + +// FocusUnit(unitId) — set focus target +static int lua_FocusUnit(lua_State* L) { + auto* gh = getGameHandler(L); + if (!gh) return 0; + const char* uid = luaL_optstring(L, 1, nullptr); + if (!uid || !*uid) return 0; + std::string uidStr(uid); + for (char& c : uidStr) c = static_cast(std::tolower(static_cast(c))); + uint64_t guid = resolveUnitGuid(gh, uidStr); + if (guid != 0) gh->setFocus(guid); + return 0; +} + +// ClearFocus() — clear focus target +static int lua_ClearFocus(lua_State* L) { + auto* gh = getGameHandler(L); + if (gh) gh->clearFocus(); + return 0; +} + +// AssistUnit(unitId) — target whatever the given unit is targeting +static int lua_AssistUnit(lua_State* L) { + auto* gh = getGameHandler(L); + if (!gh) return 0; + const char* uid = luaL_optstring(L, 1, "target"); + std::string uidStr(uid); + for (char& c : uidStr) c = static_cast(std::tolower(static_cast(c))); + uint64_t guid = resolveUnitGuid(gh, uidStr); + if (guid == 0) return 0; + uint64_t theirTarget = getEntityTargetGuid(gh, guid); + if (theirTarget != 0) gh->setTarget(theirTarget); + return 0; +} + +// TargetLastTarget() — re-target previous target +static int lua_TargetLastTarget(lua_State* L) { + auto* gh = getGameHandler(L); + if (gh) gh->targetLastTarget(); + return 0; +} + +// TargetNearestEnemy() — tab-target nearest enemy +static int lua_TargetNearestEnemy(lua_State* L) { + auto* gh = getGameHandler(L); + if (gh) gh->targetEnemy(false); + return 0; +} + +// TargetNearestFriend() — target nearest friendly unit +static int lua_TargetNearestFriend(lua_State* L) { + auto* gh = getGameHandler(L); + if (gh) gh->targetFriend(false); + return 0; +} + // --- GetSpellInfo / GetSpellTexture --- // GetSpellInfo(spellIdOrName) -> name, rank, icon, castTime, minRange, maxRange, spellId static int lua_GetSpellInfo(lua_State* L) { @@ -2214,6 +2288,14 @@ void LuaEngine::registerCoreAPI() { {"IsSpellKnown", lua_IsSpellKnown}, {"GetSpellCooldown", lua_GetSpellCooldown}, {"HasTarget", lua_HasTarget}, + {"TargetUnit", lua_TargetUnit}, + {"ClearTarget", lua_ClearTarget}, + {"FocusUnit", lua_FocusUnit}, + {"ClearFocus", lua_ClearFocus}, + {"AssistUnit", lua_AssistUnit}, + {"TargetLastTarget", lua_TargetLastTarget}, + {"TargetNearestEnemy", lua_TargetNearestEnemy}, + {"TargetNearestFriend", lua_TargetNearestFriend}, {"UnitRace", lua_UnitRace}, {"UnitPowerType", lua_UnitPowerType}, {"GetNumGroupMembers", lua_GetNumGroupMembers},