From b7013761e81b912097d7c5be9579a26f4b989f13 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 19 Nov 2025 12:58:39 +0000 Subject: [PATCH 1/2] Initial plan From 854954f00c0da94cdc346448a14896b051e488ef Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 19 Nov 2025 13:06:33 +0000 Subject: [PATCH 2/2] Implement party slot-based targeting for Arcane Mimicry Co-authored-by: Ewoog <72410352+Ewoog@users.noreply.github.com> --- HeroAI/combat.py | 19 +++++++++++++++++++ HeroAI/custom_skill_src/mesmer.py | 2 +- Py4GWCoreLib/GlobalCache/SharedMemory.py | 2 ++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/HeroAI/combat.py b/HeroAI/combat.py index 5d0eb13c5..886848400 100644 --- a/HeroAI/combat.py +++ b/HeroAI/combat.py @@ -104,6 +104,7 @@ def __init__(self): self.comfort_animal = GLOBAL_CACHE.Skill.GetID("Comfort_Animal") self.heal_as_one = GLOBAL_CACHE.Skill.GetID("Heal_as_One") self.heroic_refrain = GLOBAL_CACHE.Skill.GetID("Heroic_Refrain") + self.arcane_mimicry = GLOBAL_CACHE.Skill.GetID("Arcane_Mimicry") self.natures_blessing = GLOBAL_CACHE.Skill.GetID("Natures_Blessing") self.relentless_assault = GLOBAL_CACHE.Skill.GetID("Relentless_Assault") #junundu @@ -343,6 +344,24 @@ def GetAppropiateTarget(self, slot): if not self.HasEffect(GLOBAL_CACHE.Player.GetAgentID(), self.heroic_refrain): return GLOBAL_CACHE.Player.GetAgentID() + # Special handling for Arcane Mimicry - target based on party slot + if self.skills[slot].skill_id == self.arcane_mimicry: + # Get the configured target slot from HeroAI options + own_party_number = GLOBAL_CACHE.Party.GetOwnPartyNumber() + if own_party_number != -1: + hero_ai_options = GLOBAL_CACHE.ShMem.GetHeroAIOptions(GLOBAL_CACHE.Agent.GetEmail(GLOBAL_CACHE.Player.GetAgentID())) + if hero_ai_options is not None: + target_slot = hero_ai_options.ArcaneMimicryTargetSlot + # Get the agent ID for the target party slot + players = GLOBAL_CACHE.Party.GetPlayers() + if 0 <= target_slot < len(players): + target_agent_id = GLOBAL_CACHE.Party.Players.GetAgentIDByLoginNumber(players[target_slot].login_number) + # Verify the target is alive and in range + if target_agent_id != 0 and GLOBAL_CACHE.Agent.IsAlive(target_agent_id): + # Make sure we're not targeting ourselves + if target_agent_id != GLOBAL_CACHE.Player.GetAgentID(): + return target_agent_id + if target_allegiance == Skilltarget.Enemy: v_target = self.GetPartyTarget() if v_target == 0: diff --git a/HeroAI/custom_skill_src/mesmer.py b/HeroAI/custom_skill_src/mesmer.py index 0189a9a3b..edd6d1d83 100644 --- a/HeroAI/custom_skill_src/mesmer.py +++ b/HeroAI/custom_skill_src/mesmer.py @@ -973,7 +973,7 @@ def __init__(self, skill_data): skill.SkillType = SkillType.Spell.value skill.TargetAllegiance = Skilltarget.OtherAlly.value skill.Nature = SkillNature.Buff.value - skill.Conditions.TargetingStrict = True + skill.Conditions.TargetingStrict = False # Allow fallback targeting skill_data[skill.SkillID] = skill skill = CustomSkill() diff --git a/Py4GWCoreLib/GlobalCache/SharedMemory.py b/Py4GWCoreLib/GlobalCache/SharedMemory.py index 940961391..583a95f73 100644 --- a/Py4GWCoreLib/GlobalCache/SharedMemory.py +++ b/Py4GWCoreLib/GlobalCache/SharedMemory.py @@ -83,6 +83,7 @@ class HeroAIOptionStruct(Structure): ("FlagPosX", c_float), ("FlagPosY", c_float), ("FlagFacingAngle", c_float), + ("ArcaneMimicryTargetSlot", c_int), # Party slot to target for Arcane Mimicry (0-based) ] class AllAccounts(Structure): @@ -218,6 +219,7 @@ def ResetHeroAIData(self, index): option.FlagPosX = 0.0 option.FlagPosY = 0.0 option.FlagFacingAngle = 0.0 + option.ArcaneMimicryTargetSlot = 0 # Default to party slot 0 (party leader) def FindAccount(self, account_email: str) -> int: