From be6f8057fffa69d442d24e59713bb2c9e647608c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Nov 2025 02:03:40 +0000 Subject: [PATCH 01/12] Initial plan From 49080ef0e40a7fe05b2f6d1ccd007f682212a0fb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Nov 2025 02:09:47 +0000 Subject: [PATCH 02/12] Add Nundu Bay Vial of Purified Water spam bot snippet Co-authored-by: Ewoog <72410352+Ewoog@users.noreply.github.com> --- Bots/Nundu_Bay_Vial_Spam.py | 239 ++++++++++++++++++++++++++++++++++++ 1 file changed, 239 insertions(+) create mode 100644 Bots/Nundu_Bay_Vial_Spam.py diff --git a/Bots/Nundu_Bay_Vial_Spam.py b/Bots/Nundu_Bay_Vial_Spam.py new file mode 100644 index 000000000..3bd8ce373 --- /dev/null +++ b/Bots/Nundu_Bay_Vial_Spam.py @@ -0,0 +1,239 @@ +""" +Nundu Bay Vial of Purified Water Spam Bot + +This bot snippet continuously targets a specific enemy in Nundu Bay mission +and spams the skill "Vial of Purified Water" on that target as soon as it's +off cooldown until the target dies. + +Usage: +1. Equip "Vial of Purified Water" skill on your skill bar +2. Enter Nundu Bay mission +3. Edit this script: + - Set TARGET_NAME to the name of the enemy you want to target + Example: TARGET_NAME = "Margonite Priest" + OR + - Set TARGET_PLAYER_NUMBER to the specific player number of the enemy + (Use this if multiple enemies have the same name) +4. Load this script in Py4GW +5. Start the bot + +The bot will: +- Find the target enemy by name or player number +- Continuously spam "Vial of Purified Water" on the target +- Use the skill as soon as it comes off cooldown +- Repeat on the next target with the same name when current target dies + +Note: Similar to Nightfall Leveler bot structure but simplified for single skill spam. +""" + +from __future__ import annotations +from typing import Generator, Any +from Py4GWCoreLib import (GLOBAL_CACHE, Routines, Py4GW, ConsoleLog, Botting) + + +# Initialize the bot +bot = Botting("Nundu Bay Vial Spam", + upkeep_birthday_cupcake_restock=0, + upkeep_honeycomb_restock=0, + upkeep_war_supplies_restock=0, + upkeep_auto_inventory_management_active=False, + upkeep_auto_combat_active=False, + upkeep_auto_loot_active=False) + + +def find_target_by_name(target_name: str) -> int: + """ + Find an enemy agent by its name. + + Args: + target_name: The name of the target enemy (case-insensitive, partial match) + + Returns: + agent_id of the target, or 0 if not found + """ + enemy_array = GLOBAL_CACHE.AgentArray.GetEnemyArray() + + for agent_id in enemy_array: + agent_name = GLOBAL_CACHE.Agent.GetName(agent_id) + if agent_name and target_name.lower() in agent_name.lower(): + if GLOBAL_CACHE.Agent.IsAlive(agent_id): + return agent_id + + return 0 + + +def find_target_by_player_number(player_number: int) -> int: + """ + Find an enemy agent by its player number. + + Args: + player_number: The player number of the target enemy + + Returns: + agent_id of the target, or 0 if not found + """ + enemy_array = GLOBAL_CACHE.AgentArray.GetEnemyArray() + + for agent_id in enemy_array: + if GLOBAL_CACHE.Agent.GetPlayerNumber(agent_id) == player_number: + if GLOBAL_CACHE.Agent.IsAlive(agent_id): + return agent_id + + return 0 + + +def get_vial_skill_slot() -> int: + """ + Find the skill slot containing "Vial of Purified Water". + + Returns: + Skill slot number (1-8), or 0 if not found + """ + vial_skill_id = GLOBAL_CACHE.Skill.GetID("Vial_of_Purified_Water") + + for slot in range(1, 9): + skill_id = GLOBAL_CACHE.SkillBar.GetSkillIDBySlot(slot) + if skill_id == vial_skill_id: + return slot + + return 0 + + +def spam_vial_on_target(target_agent_id: int, vial_slot: int) -> Generator[Any, None, None]: + """ + Continuously use Vial of Purified Water on the target. + + Args: + target_agent_id: The agent ID of the target + vial_slot: The skill slot number containing Vial of Purified Water + """ + while GLOBAL_CACHE.Agent.IsAlive(target_agent_id): + # Check if the skill is ready to use + if GLOBAL_CACHE.SkillBar.IsSkillReady(vial_slot): + # Change target to ensure we're targeting the right enemy + yield from Routines.Yield.Agents.ChangeTarget(target_agent_id) + yield from Routines.Yield.wait(100) + + # Use the skill + GLOBAL_CACHE.SkillBar.UseSkill(vial_slot, target_agent_id) + ConsoleLog("Vial Spam", f"Used Vial of Purified Water on target", + Py4GW.Console.MessageType.Info, log=True) + + # Wait a bit for the skill to cast + yield from Routines.Yield.wait(250) + else: + # Skill is on cooldown, wait a bit before checking again + yield from Routines.Yield.wait(100) + + yield + + +def create_bot_routine(bot: Botting) -> None: + """ + Main bot routine that finds the target and spams the skill. + """ + bot.States.AddHeader("Nundu Bay Vial of Purified Water Spam") + + # Configuration: Set either the target name OR player number + # Option 1: Find target by name (easier, recommended) + TARGET_NAME = "" # CHANGE THIS to the target's name (e.g., "Margonite" or "Priest") + + # Option 2: Find target by player number (more precise if multiple enemies have same name) + TARGET_PLAYER_NUMBER = 0 # Leave as 0 if using TARGET_NAME + + # Validate configuration + if not TARGET_NAME and TARGET_PLAYER_NUMBER == 0: + bot.States.AddHeader("ERROR: No Target Specified!") + ConsoleLog("Vial Spam", + "Please edit the script and set either TARGET_NAME or TARGET_PLAYER_NUMBER", + Py4GW.Console.MessageType.Error, log=True) + ConsoleLog("Vial Spam", + "Example: TARGET_NAME = 'Margonite' or TARGET_PLAYER_NUMBER = 12345", + Py4GW.Console.MessageType.Warning, log=True) + return + + # Find the Vial of Purified Water skill slot + def FindVialSlot() -> Generator[Any, None, int]: + vial_slot = get_vial_skill_slot() + + if vial_slot == 0: + ConsoleLog("Vial Spam", + "ERROR: Vial of Purified Water not found on skill bar!", + Py4GW.Console.MessageType.Error, log=True) + ConsoleLog("Vial Spam", + "Please equip the skill on your skill bar and restart the bot", + Py4GW.Console.MessageType.Warning, log=True) + return 0 + + ConsoleLog("Vial Spam", + f"Found Vial of Purified Water in slot {vial_slot}", + Py4GW.Console.MessageType.Info, log=True) + yield + return vial_slot + + # Get the skill slot + bot.States.AddCustomState(FindVialSlot, "Find Vial Skill Slot") + vial_slot = get_vial_skill_slot() + + if vial_slot == 0: + return + + # Main loop: Find target and spam skill + def MainSpamLoop() -> Generator[Any, None, None]: + if TARGET_NAME: + ConsoleLog("Vial Spam", f"Searching for target by name: '{TARGET_NAME}'", + Py4GW.Console.MessageType.Info, log=True) + else: + ConsoleLog("Vial Spam", f"Searching for target by player number: {TARGET_PLAYER_NUMBER}", + Py4GW.Console.MessageType.Info, log=True) + + while True: + # Find the target using the configured method + if TARGET_NAME: + target_id = find_target_by_name(TARGET_NAME) + else: + target_id = find_target_by_player_number(TARGET_PLAYER_NUMBER) + + if target_id == 0: + if TARGET_NAME: + ConsoleLog("Vial Spam", + f"Target '{TARGET_NAME}' not found. Waiting...", + Py4GW.Console.MessageType.Warning, log=True) + else: + ConsoleLog("Vial Spam", + f"Target with player number {TARGET_PLAYER_NUMBER} not found. Waiting...", + Py4GW.Console.MessageType.Warning, log=True) + yield from Routines.Yield.wait(1000) + continue + + # Log the target found + target_name = GLOBAL_CACHE.Agent.GetName(target_id) + ConsoleLog("Vial Spam", + f"Found target: {target_name} (Agent ID: {target_id}). Starting skill spam...", + Py4GW.Console.MessageType.Info, log=True) + + # Spam the skill on the target until it dies + yield from spam_vial_on_target(target_id, vial_slot) + + ConsoleLog("Vial Spam", + f"Target {target_name} is dead. Searching for next target...", + Py4GW.Console.MessageType.Info, log=True) + + # Wait a bit before searching for the next target + yield from Routines.Yield.wait(1000) + + bot.States.AddCustomState(MainSpamLoop, "Spam Vial on Target") + + +# Configure the bot +bot.SetMainRoutine(create_bot_routine) + + +def main(): + """Main update loop""" + bot.Update() + bot.UI.draw_window() + + +if __name__ == "__main__": + main() From 7baca818661fc95e2af92dafaff0c710f8eed510 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Nov 2025 02:10:46 +0000 Subject: [PATCH 03/12] Add comprehensive README for Nundu Bay bot Co-authored-by: Ewoog <72410352+Ewoog@users.noreply.github.com> --- Bots/Nundu_Bay_Vial_Spam_README.md | 119 +++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 Bots/Nundu_Bay_Vial_Spam_README.md diff --git a/Bots/Nundu_Bay_Vial_Spam_README.md b/Bots/Nundu_Bay_Vial_Spam_README.md new file mode 100644 index 000000000..2519fe6b7 --- /dev/null +++ b/Bots/Nundu_Bay_Vial_Spam_README.md @@ -0,0 +1,119 @@ +# Nundu Bay Vial of Purified Water Spam Bot + +## Overview + +This bot snippet is designed for the Nundu Bay mission in Guild Wars. It continuously targets a specific enemy and spams the skill "Vial of Purified Water" on that target as soon as it comes off cooldown, repeating the process until the target dies. + +## Features + +- **Simple Configuration**: Target enemies by name (e.g., "Margonite") or player number +- **Automatic Skill Detection**: Finds "Vial of Purified Water" on your skill bar automatically +- **Cooldown Management**: Uses the skill as soon as it's available (spam mode) +- **Auto Re-targeting**: Finds the next matching target when the current one dies +- **Informative Logging**: Provides clear console messages about what the bot is doing + +## Prerequisites + +1. **Py4GW Framework**: This bot requires the Py4GW framework to be installed and running +2. **Skill Required**: You must have "Vial of Purified Water" equipped on your skill bar +3. **Mission Access**: You need to be in or able to enter the Nundu Bay mission + +## Setup Instructions + +### Step 1: Equip the Skill + +Make sure "Vial of Purified Water" is equipped on your skill bar before entering the mission. + +### Step 2: Configure the Target + +Open `Nundu_Bay_Vial_Spam.py` and edit the configuration section (around line 139): + +**Option A: Target by Name (Recommended)** +```python +TARGET_NAME = "Margonite" # Change to your target's name +TARGET_PLAYER_NUMBER = 0 # Leave as 0 +``` + +**Option B: Target by Player Number (More Precise)** +```python +TARGET_NAME = "" # Leave empty +TARGET_PLAYER_NUMBER = 12345 # Change to actual player number +``` + +### Step 3: Load the Script + +1. Start Guild Wars and Py4GW +2. Load the script `Nundu_Bay_Vial_Spam.py` in Py4GW +3. Enter Nundu Bay mission + +### Step 4: Start the Bot + +1. In the Py4GW interface, find the "Nundu Bay Vial Spam" bot window +2. Click "Start" to begin the bot +3. The bot will automatically: + - Find the "Vial of Purified Water" skill on your bar + - Locate the target enemy + - Spam the skill on the target until it dies + - Repeat on the next matching target + +## How It Works + +1. **Initialization**: The bot searches for "Vial of Purified Water" on your skill bar +2. **Target Acquisition**: Scans enemy agents for the configured target (by name or player number) +3. **Skill Spam Loop**: + - Changes target to the enemy + - Checks if "Vial of Purified Water" is off cooldown + - Uses the skill if ready + - Waits 100ms and checks again (spam mode) + - Continues until target dies +4. **Repeat**: Searches for the next matching target and repeats the process + +## Configuration Options + +### TARGET_NAME +- Set this to the name (or part of the name) of the enemy you want to target +- Case-insensitive partial matching (e.g., "Margonite" will match "Margonite Priest") +- Example: `TARGET_NAME = "Priest"` + +### TARGET_PLAYER_NUMBER +- Set this if you need to target a specific enemy when multiple have the same name +- Use a recorder script to find the player number +- Example: `TARGET_PLAYER_NUMBER = 12345` + +## Troubleshooting + +### "Vial of Purified Water not found on skill bar!" +- Make sure you have equipped the skill before starting the bot +- Check that the skill is actually named "Vial of Purified Water" in game + +### "Target not found. Waiting..." +- Verify the target name or player number is correct +- Make sure you're in the right area/mission where the enemy spawns +- Check that the enemy is alive and within range + +### Bot doesn't use the skill +- Ensure the skill is off cooldown +- Check that you have enough energy to cast the skill +- Verify you're not knocked down or interrupted + +## Tips + +- **Energy Management**: Make sure you have enough energy regeneration to keep spamming the skill +- **Safety**: This bot doesn't include movement or survival features - use with caution +- **Multiple Targets**: If using TARGET_NAME, the bot will target any enemy matching that name +- **Precision**: Use TARGET_PLAYER_NUMBER if you need to target a specific enemy among many with the same name + +## Based On + +This bot is modeled after the structure of the Nightfall Leveler bot, using the same Botting framework for consistency and reliability. + +## Support + +For issues or questions: +1. Check the console log messages for detailed error information +2. Verify all configuration settings are correct +3. Ensure you meet all prerequisites + +## License + +This bot snippet is part of the Py4GW project. Please refer to the main project license for usage terms. From 7c18a0bcaf11108bbcca44805e316391b37f8005 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Nov 2025 02:12:35 +0000 Subject: [PATCH 04/12] Add quick start guide for Nundu Bay bot Co-authored-by: Ewoog <72410352+Ewoog@users.noreply.github.com> --- Bots/Nundu_Bay_Vial_Spam_QUICKSTART.md | 89 ++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 Bots/Nundu_Bay_Vial_Spam_QUICKSTART.md diff --git a/Bots/Nundu_Bay_Vial_Spam_QUICKSTART.md b/Bots/Nundu_Bay_Vial_Spam_QUICKSTART.md new file mode 100644 index 000000000..7d3c22764 --- /dev/null +++ b/Bots/Nundu_Bay_Vial_Spam_QUICKSTART.md @@ -0,0 +1,89 @@ +# Quick Start Example: Nundu Bay Vial Spam Bot + +## Example Configuration + +Here's a quick example of how to configure the bot to target "Margonite Priests" in Nundu Bay: + +### Step 1: Edit the script + +Open `Nundu_Bay_Vial_Spam.py` and find line 139. Change this: + +```python +TARGET_NAME = "" # CHANGE THIS to the target's name +``` + +To this: + +```python +TARGET_NAME = "Margonite" # Targets any enemy with "Margonite" in their name +``` + +Or for more precision: + +```python +TARGET_NAME = "Margonite Priest" # Only targets Margonite Priests +``` + +### Step 2: Equip your skill + +Make sure "Vial of Purified Water" is on your skill bar before entering Nundu Bay. + +### Step 3: Run the bot + +1. Enter Nundu Bay mission +2. Load the script in Py4GW +3. Click "Start" in the bot window + +The bot will: +1. Find "Vial of Purified Water" on your skill bar +2. Search for enemies matching "Margonite" (or whatever you specified) +3. Target the first match found +4. Spam the skill on that target until it dies +5. Find the next matching enemy and repeat + +## Common Targets in Nundu Bay + +You might want to target: +- `"Margonite"` - Any Margonite enemy +- `"Priest"` - Margonite Priests specifically +- `"Anur"` - Anur enemies +- Or any other enemy name/partial name + +## Advanced: Using Player Number + +If you need to target a specific enemy (not just by name), you can use player number: + +```python +TARGET_NAME = "" # Leave empty when using player number +TARGET_PLAYER_NUMBER = 12345 # Use actual player number from recorder +``` + +To find the player number: +1. Use a recorder script (like SimpleEnemyModelIdRecorder.py) +2. Target the enemy in-game +3. The recorder will show the player number + +## Console Output Example + +When running, you'll see messages like: + +``` +[Vial Spam] Searching for target by name: 'Margonite' +[Vial Spam] Found target: Margonite Priest (Agent ID: 4567). Starting skill spam... +[Vial Spam] Used Vial of Purified Water on target +[Vial Spam] Used Vial of Purified Water on target +[Vial Spam] Used Vial of Purified Water on target +[Vial Spam] Target Margonite Priest is dead. Searching for next target... +[Vial Spam] Found target: Margonite Cleric (Agent ID: 4789). Starting skill spam... +``` + +## Tips + +- **Start Simple**: Use just part of the enemy name (e.g., "Margonite") to target all enemies of that type +- **Energy**: Make sure you have energy regeneration to keep spamming +- **Position**: Position yourself where you can see/reach your targets +- **Safety**: This bot only handles skill spamming - you're responsible for movement and survival + +## That's it! + +The bot is now ready to spam Vial of Purified Water on your targets in Nundu Bay. Happy farming! From 0dbda8045fbf7d119e54eb31cdf899db71e1f485 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Nov 2025 02:28:27 +0000 Subject: [PATCH 05/12] Add NunduBayVialSpam step to Nightfall_leveler Co-authored-by: Ewoog <72410352+Ewoog@users.noreply.github.com> --- Bots/Leveling/Nightfall/Nightfall_leveler.py | 31 +++ Bots/Nundu_Bay_Vial_Spam.py | 239 ------------------- Bots/Nundu_Bay_Vial_Spam_QUICKSTART.md | 89 ------- Bots/Nundu_Bay_Vial_Spam_README.md | 119 --------- 4 files changed, 31 insertions(+), 447 deletions(-) delete mode 100644 Bots/Nundu_Bay_Vial_Spam.py delete mode 100644 Bots/Nundu_Bay_Vial_Spam_QUICKSTART.md delete mode 100644 Bots/Nundu_Bay_Vial_Spam_README.md diff --git a/Bots/Leveling/Nightfall/Nightfall_leveler.py b/Bots/Leveling/Nightfall/Nightfall_leveler.py index ef31f80d4..a28518296 100644 --- a/Bots/Leveling/Nightfall/Nightfall_leveler.py +++ b/Bots/Leveling/Nightfall/Nightfall_leveler.py @@ -1504,6 +1504,37 @@ def UnlockMercenaryHeroes(bot: Botting) -> None: bot.Map.Travel(target_map_id=248) # GTOB bot.Move.XY(-4231.87, -8965.95) bot.Dialogs.WithModel(225, 0x800004) # Unlock Mercenary Heroes + +def NunduBayVialSpam(bot: Botting) -> None: + bot.Map.Travel(target_map_id=477) + + def SpamVialOnHarbinger(): + enemy_array = GLOBAL_CACHE.AgentArray.GetEnemyArray() + for agent_id in enemy_array: + player_num = GLOBAL_CACHE.Agent.GetPlayerNumber(agent_id) + if player_num in [5405, 5409]: + if GLOBAL_CACHE.Agent.IsAlive(agent_id): + vial_skill_id = GLOBAL_CACHE.Skill.GetID("Vial_of_Purified_Water") + vial_slot = 0 + for slot in range(1, 9): + if GLOBAL_CACHE.SkillBar.GetSkillIDBySlot(slot) == vial_skill_id: + vial_slot = slot + break + + if vial_slot > 0: + while GLOBAL_CACHE.Agent.IsAlive(agent_id): + if GLOBAL_CACHE.SkillBar.IsSkillReady(vial_slot): + yield from Routines.Yield.Agents.ChangeTarget(agent_id) + yield from Routines.Yield.wait(100) + GLOBAL_CACHE.SkillBar.UseSkill(vial_slot, agent_id) + yield from Routines.Yield.wait(250) + else: + yield from Routines.Yield.wait(100) + yield + return + yield from Routines.Yield.wait(1000) + + bot.States.AddCustomState(SpamVialOnHarbinger, "Spam Vial on Harbinger") #region MAIN selected_step = 0 filter_header_steps = True diff --git a/Bots/Nundu_Bay_Vial_Spam.py b/Bots/Nundu_Bay_Vial_Spam.py deleted file mode 100644 index 3bd8ce373..000000000 --- a/Bots/Nundu_Bay_Vial_Spam.py +++ /dev/null @@ -1,239 +0,0 @@ -""" -Nundu Bay Vial of Purified Water Spam Bot - -This bot snippet continuously targets a specific enemy in Nundu Bay mission -and spams the skill "Vial of Purified Water" on that target as soon as it's -off cooldown until the target dies. - -Usage: -1. Equip "Vial of Purified Water" skill on your skill bar -2. Enter Nundu Bay mission -3. Edit this script: - - Set TARGET_NAME to the name of the enemy you want to target - Example: TARGET_NAME = "Margonite Priest" - OR - - Set TARGET_PLAYER_NUMBER to the specific player number of the enemy - (Use this if multiple enemies have the same name) -4. Load this script in Py4GW -5. Start the bot - -The bot will: -- Find the target enemy by name or player number -- Continuously spam "Vial of Purified Water" on the target -- Use the skill as soon as it comes off cooldown -- Repeat on the next target with the same name when current target dies - -Note: Similar to Nightfall Leveler bot structure but simplified for single skill spam. -""" - -from __future__ import annotations -from typing import Generator, Any -from Py4GWCoreLib import (GLOBAL_CACHE, Routines, Py4GW, ConsoleLog, Botting) - - -# Initialize the bot -bot = Botting("Nundu Bay Vial Spam", - upkeep_birthday_cupcake_restock=0, - upkeep_honeycomb_restock=0, - upkeep_war_supplies_restock=0, - upkeep_auto_inventory_management_active=False, - upkeep_auto_combat_active=False, - upkeep_auto_loot_active=False) - - -def find_target_by_name(target_name: str) -> int: - """ - Find an enemy agent by its name. - - Args: - target_name: The name of the target enemy (case-insensitive, partial match) - - Returns: - agent_id of the target, or 0 if not found - """ - enemy_array = GLOBAL_CACHE.AgentArray.GetEnemyArray() - - for agent_id in enemy_array: - agent_name = GLOBAL_CACHE.Agent.GetName(agent_id) - if agent_name and target_name.lower() in agent_name.lower(): - if GLOBAL_CACHE.Agent.IsAlive(agent_id): - return agent_id - - return 0 - - -def find_target_by_player_number(player_number: int) -> int: - """ - Find an enemy agent by its player number. - - Args: - player_number: The player number of the target enemy - - Returns: - agent_id of the target, or 0 if not found - """ - enemy_array = GLOBAL_CACHE.AgentArray.GetEnemyArray() - - for agent_id in enemy_array: - if GLOBAL_CACHE.Agent.GetPlayerNumber(agent_id) == player_number: - if GLOBAL_CACHE.Agent.IsAlive(agent_id): - return agent_id - - return 0 - - -def get_vial_skill_slot() -> int: - """ - Find the skill slot containing "Vial of Purified Water". - - Returns: - Skill slot number (1-8), or 0 if not found - """ - vial_skill_id = GLOBAL_CACHE.Skill.GetID("Vial_of_Purified_Water") - - for slot in range(1, 9): - skill_id = GLOBAL_CACHE.SkillBar.GetSkillIDBySlot(slot) - if skill_id == vial_skill_id: - return slot - - return 0 - - -def spam_vial_on_target(target_agent_id: int, vial_slot: int) -> Generator[Any, None, None]: - """ - Continuously use Vial of Purified Water on the target. - - Args: - target_agent_id: The agent ID of the target - vial_slot: The skill slot number containing Vial of Purified Water - """ - while GLOBAL_CACHE.Agent.IsAlive(target_agent_id): - # Check if the skill is ready to use - if GLOBAL_CACHE.SkillBar.IsSkillReady(vial_slot): - # Change target to ensure we're targeting the right enemy - yield from Routines.Yield.Agents.ChangeTarget(target_agent_id) - yield from Routines.Yield.wait(100) - - # Use the skill - GLOBAL_CACHE.SkillBar.UseSkill(vial_slot, target_agent_id) - ConsoleLog("Vial Spam", f"Used Vial of Purified Water on target", - Py4GW.Console.MessageType.Info, log=True) - - # Wait a bit for the skill to cast - yield from Routines.Yield.wait(250) - else: - # Skill is on cooldown, wait a bit before checking again - yield from Routines.Yield.wait(100) - - yield - - -def create_bot_routine(bot: Botting) -> None: - """ - Main bot routine that finds the target and spams the skill. - """ - bot.States.AddHeader("Nundu Bay Vial of Purified Water Spam") - - # Configuration: Set either the target name OR player number - # Option 1: Find target by name (easier, recommended) - TARGET_NAME = "" # CHANGE THIS to the target's name (e.g., "Margonite" or "Priest") - - # Option 2: Find target by player number (more precise if multiple enemies have same name) - TARGET_PLAYER_NUMBER = 0 # Leave as 0 if using TARGET_NAME - - # Validate configuration - if not TARGET_NAME and TARGET_PLAYER_NUMBER == 0: - bot.States.AddHeader("ERROR: No Target Specified!") - ConsoleLog("Vial Spam", - "Please edit the script and set either TARGET_NAME or TARGET_PLAYER_NUMBER", - Py4GW.Console.MessageType.Error, log=True) - ConsoleLog("Vial Spam", - "Example: TARGET_NAME = 'Margonite' or TARGET_PLAYER_NUMBER = 12345", - Py4GW.Console.MessageType.Warning, log=True) - return - - # Find the Vial of Purified Water skill slot - def FindVialSlot() -> Generator[Any, None, int]: - vial_slot = get_vial_skill_slot() - - if vial_slot == 0: - ConsoleLog("Vial Spam", - "ERROR: Vial of Purified Water not found on skill bar!", - Py4GW.Console.MessageType.Error, log=True) - ConsoleLog("Vial Spam", - "Please equip the skill on your skill bar and restart the bot", - Py4GW.Console.MessageType.Warning, log=True) - return 0 - - ConsoleLog("Vial Spam", - f"Found Vial of Purified Water in slot {vial_slot}", - Py4GW.Console.MessageType.Info, log=True) - yield - return vial_slot - - # Get the skill slot - bot.States.AddCustomState(FindVialSlot, "Find Vial Skill Slot") - vial_slot = get_vial_skill_slot() - - if vial_slot == 0: - return - - # Main loop: Find target and spam skill - def MainSpamLoop() -> Generator[Any, None, None]: - if TARGET_NAME: - ConsoleLog("Vial Spam", f"Searching for target by name: '{TARGET_NAME}'", - Py4GW.Console.MessageType.Info, log=True) - else: - ConsoleLog("Vial Spam", f"Searching for target by player number: {TARGET_PLAYER_NUMBER}", - Py4GW.Console.MessageType.Info, log=True) - - while True: - # Find the target using the configured method - if TARGET_NAME: - target_id = find_target_by_name(TARGET_NAME) - else: - target_id = find_target_by_player_number(TARGET_PLAYER_NUMBER) - - if target_id == 0: - if TARGET_NAME: - ConsoleLog("Vial Spam", - f"Target '{TARGET_NAME}' not found. Waiting...", - Py4GW.Console.MessageType.Warning, log=True) - else: - ConsoleLog("Vial Spam", - f"Target with player number {TARGET_PLAYER_NUMBER} not found. Waiting...", - Py4GW.Console.MessageType.Warning, log=True) - yield from Routines.Yield.wait(1000) - continue - - # Log the target found - target_name = GLOBAL_CACHE.Agent.GetName(target_id) - ConsoleLog("Vial Spam", - f"Found target: {target_name} (Agent ID: {target_id}). Starting skill spam...", - Py4GW.Console.MessageType.Info, log=True) - - # Spam the skill on the target until it dies - yield from spam_vial_on_target(target_id, vial_slot) - - ConsoleLog("Vial Spam", - f"Target {target_name} is dead. Searching for next target...", - Py4GW.Console.MessageType.Info, log=True) - - # Wait a bit before searching for the next target - yield from Routines.Yield.wait(1000) - - bot.States.AddCustomState(MainSpamLoop, "Spam Vial on Target") - - -# Configure the bot -bot.SetMainRoutine(create_bot_routine) - - -def main(): - """Main update loop""" - bot.Update() - bot.UI.draw_window() - - -if __name__ == "__main__": - main() diff --git a/Bots/Nundu_Bay_Vial_Spam_QUICKSTART.md b/Bots/Nundu_Bay_Vial_Spam_QUICKSTART.md deleted file mode 100644 index 7d3c22764..000000000 --- a/Bots/Nundu_Bay_Vial_Spam_QUICKSTART.md +++ /dev/null @@ -1,89 +0,0 @@ -# Quick Start Example: Nundu Bay Vial Spam Bot - -## Example Configuration - -Here's a quick example of how to configure the bot to target "Margonite Priests" in Nundu Bay: - -### Step 1: Edit the script - -Open `Nundu_Bay_Vial_Spam.py` and find line 139. Change this: - -```python -TARGET_NAME = "" # CHANGE THIS to the target's name -``` - -To this: - -```python -TARGET_NAME = "Margonite" # Targets any enemy with "Margonite" in their name -``` - -Or for more precision: - -```python -TARGET_NAME = "Margonite Priest" # Only targets Margonite Priests -``` - -### Step 2: Equip your skill - -Make sure "Vial of Purified Water" is on your skill bar before entering Nundu Bay. - -### Step 3: Run the bot - -1. Enter Nundu Bay mission -2. Load the script in Py4GW -3. Click "Start" in the bot window - -The bot will: -1. Find "Vial of Purified Water" on your skill bar -2. Search for enemies matching "Margonite" (or whatever you specified) -3. Target the first match found -4. Spam the skill on that target until it dies -5. Find the next matching enemy and repeat - -## Common Targets in Nundu Bay - -You might want to target: -- `"Margonite"` - Any Margonite enemy -- `"Priest"` - Margonite Priests specifically -- `"Anur"` - Anur enemies -- Or any other enemy name/partial name - -## Advanced: Using Player Number - -If you need to target a specific enemy (not just by name), you can use player number: - -```python -TARGET_NAME = "" # Leave empty when using player number -TARGET_PLAYER_NUMBER = 12345 # Use actual player number from recorder -``` - -To find the player number: -1. Use a recorder script (like SimpleEnemyModelIdRecorder.py) -2. Target the enemy in-game -3. The recorder will show the player number - -## Console Output Example - -When running, you'll see messages like: - -``` -[Vial Spam] Searching for target by name: 'Margonite' -[Vial Spam] Found target: Margonite Priest (Agent ID: 4567). Starting skill spam... -[Vial Spam] Used Vial of Purified Water on target -[Vial Spam] Used Vial of Purified Water on target -[Vial Spam] Used Vial of Purified Water on target -[Vial Spam] Target Margonite Priest is dead. Searching for next target... -[Vial Spam] Found target: Margonite Cleric (Agent ID: 4789). Starting skill spam... -``` - -## Tips - -- **Start Simple**: Use just part of the enemy name (e.g., "Margonite") to target all enemies of that type -- **Energy**: Make sure you have energy regeneration to keep spamming -- **Position**: Position yourself where you can see/reach your targets -- **Safety**: This bot only handles skill spamming - you're responsible for movement and survival - -## That's it! - -The bot is now ready to spam Vial of Purified Water on your targets in Nundu Bay. Happy farming! diff --git a/Bots/Nundu_Bay_Vial_Spam_README.md b/Bots/Nundu_Bay_Vial_Spam_README.md deleted file mode 100644 index 2519fe6b7..000000000 --- a/Bots/Nundu_Bay_Vial_Spam_README.md +++ /dev/null @@ -1,119 +0,0 @@ -# Nundu Bay Vial of Purified Water Spam Bot - -## Overview - -This bot snippet is designed for the Nundu Bay mission in Guild Wars. It continuously targets a specific enemy and spams the skill "Vial of Purified Water" on that target as soon as it comes off cooldown, repeating the process until the target dies. - -## Features - -- **Simple Configuration**: Target enemies by name (e.g., "Margonite") or player number -- **Automatic Skill Detection**: Finds "Vial of Purified Water" on your skill bar automatically -- **Cooldown Management**: Uses the skill as soon as it's available (spam mode) -- **Auto Re-targeting**: Finds the next matching target when the current one dies -- **Informative Logging**: Provides clear console messages about what the bot is doing - -## Prerequisites - -1. **Py4GW Framework**: This bot requires the Py4GW framework to be installed and running -2. **Skill Required**: You must have "Vial of Purified Water" equipped on your skill bar -3. **Mission Access**: You need to be in or able to enter the Nundu Bay mission - -## Setup Instructions - -### Step 1: Equip the Skill - -Make sure "Vial of Purified Water" is equipped on your skill bar before entering the mission. - -### Step 2: Configure the Target - -Open `Nundu_Bay_Vial_Spam.py` and edit the configuration section (around line 139): - -**Option A: Target by Name (Recommended)** -```python -TARGET_NAME = "Margonite" # Change to your target's name -TARGET_PLAYER_NUMBER = 0 # Leave as 0 -``` - -**Option B: Target by Player Number (More Precise)** -```python -TARGET_NAME = "" # Leave empty -TARGET_PLAYER_NUMBER = 12345 # Change to actual player number -``` - -### Step 3: Load the Script - -1. Start Guild Wars and Py4GW -2. Load the script `Nundu_Bay_Vial_Spam.py` in Py4GW -3. Enter Nundu Bay mission - -### Step 4: Start the Bot - -1. In the Py4GW interface, find the "Nundu Bay Vial Spam" bot window -2. Click "Start" to begin the bot -3. The bot will automatically: - - Find the "Vial of Purified Water" skill on your bar - - Locate the target enemy - - Spam the skill on the target until it dies - - Repeat on the next matching target - -## How It Works - -1. **Initialization**: The bot searches for "Vial of Purified Water" on your skill bar -2. **Target Acquisition**: Scans enemy agents for the configured target (by name or player number) -3. **Skill Spam Loop**: - - Changes target to the enemy - - Checks if "Vial of Purified Water" is off cooldown - - Uses the skill if ready - - Waits 100ms and checks again (spam mode) - - Continues until target dies -4. **Repeat**: Searches for the next matching target and repeats the process - -## Configuration Options - -### TARGET_NAME -- Set this to the name (or part of the name) of the enemy you want to target -- Case-insensitive partial matching (e.g., "Margonite" will match "Margonite Priest") -- Example: `TARGET_NAME = "Priest"` - -### TARGET_PLAYER_NUMBER -- Set this if you need to target a specific enemy when multiple have the same name -- Use a recorder script to find the player number -- Example: `TARGET_PLAYER_NUMBER = 12345` - -## Troubleshooting - -### "Vial of Purified Water not found on skill bar!" -- Make sure you have equipped the skill before starting the bot -- Check that the skill is actually named "Vial of Purified Water" in game - -### "Target not found. Waiting..." -- Verify the target name or player number is correct -- Make sure you're in the right area/mission where the enemy spawns -- Check that the enemy is alive and within range - -### Bot doesn't use the skill -- Ensure the skill is off cooldown -- Check that you have enough energy to cast the skill -- Verify you're not knocked down or interrupted - -## Tips - -- **Energy Management**: Make sure you have enough energy regeneration to keep spamming the skill -- **Safety**: This bot doesn't include movement or survival features - use with caution -- **Multiple Targets**: If using TARGET_NAME, the bot will target any enemy matching that name -- **Precision**: Use TARGET_PLAYER_NUMBER if you need to target a specific enemy among many with the same name - -## Based On - -This bot is modeled after the structure of the Nightfall Leveler bot, using the same Botting framework for consistency and reliability. - -## Support - -For issues or questions: -1. Check the console log messages for detailed error information -2. Verify all configuration settings are correct -3. Ensure you meet all prerequisites - -## License - -This bot snippet is part of the Py4GW project. Please refer to the main project license for usage terms. From 1545a29236c3f994062d286ef2bd9dba936dc693 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Nov 2025 02:57:33 +0000 Subject: [PATCH 06/12] Fix: Use GetModelID instead of GetPlayerNumber for Harbinger Co-authored-by: Ewoog <72410352+Ewoog@users.noreply.github.com> --- Bots/Leveling/Nightfall/Nightfall_leveler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Bots/Leveling/Nightfall/Nightfall_leveler.py b/Bots/Leveling/Nightfall/Nightfall_leveler.py index a28518296..d465ad507 100644 --- a/Bots/Leveling/Nightfall/Nightfall_leveler.py +++ b/Bots/Leveling/Nightfall/Nightfall_leveler.py @@ -1511,8 +1511,8 @@ def NunduBayVialSpam(bot: Botting) -> None: def SpamVialOnHarbinger(): enemy_array = GLOBAL_CACHE.AgentArray.GetEnemyArray() for agent_id in enemy_array: - player_num = GLOBAL_CACHE.Agent.GetPlayerNumber(agent_id) - if player_num in [5405, 5409]: + model_id = GLOBAL_CACHE.Agent.GetModelID(agent_id) + if model_id in [5405, 5409]: if GLOBAL_CACHE.Agent.IsAlive(agent_id): vial_skill_id = GLOBAL_CACHE.Skill.GetID("Vial_of_Purified_Water") vial_slot = 0 From 19b267f0ad66b99ebd7ce4bd9df730e8ce58debc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Nov 2025 03:25:49 +0000 Subject: [PATCH 07/12] Fix: Add continuous loop to spam skill on multiple Harbingers Co-authored-by: Ewoog <72410352+Ewoog@users.noreply.github.com> --- Bots/Leveling/Nightfall/Nightfall_leveler.py | 33 ++++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/Bots/Leveling/Nightfall/Nightfall_leveler.py b/Bots/Leveling/Nightfall/Nightfall_leveler.py index d465ad507..0b6a90bf4 100644 --- a/Bots/Leveling/Nightfall/Nightfall_leveler.py +++ b/Bots/Leveling/Nightfall/Nightfall_leveler.py @@ -1509,17 +1509,21 @@ def NunduBayVialSpam(bot: Botting) -> None: bot.Map.Travel(target_map_id=477) def SpamVialOnHarbinger(): - enemy_array = GLOBAL_CACHE.AgentArray.GetEnemyArray() - for agent_id in enemy_array: - model_id = GLOBAL_CACHE.Agent.GetModelID(agent_id) - if model_id in [5405, 5409]: - if GLOBAL_CACHE.Agent.IsAlive(agent_id): - vial_skill_id = GLOBAL_CACHE.Skill.GetID("Vial_of_Purified_Water") - vial_slot = 0 - for slot in range(1, 9): - if GLOBAL_CACHE.SkillBar.GetSkillIDBySlot(slot) == vial_skill_id: - vial_slot = slot - break + vial_skill_id = GLOBAL_CACHE.Skill.GetID("Vial_of_Purified_Water") + vial_slot = 0 + for slot in range(1, 9): + if GLOBAL_CACHE.SkillBar.GetSkillIDBySlot(slot) == vial_skill_id: + vial_slot = slot + break + + while True: + enemy_array = GLOBAL_CACHE.AgentArray.GetEnemyArray() + target_found = False + + for agent_id in enemy_array: + model_id = GLOBAL_CACHE.Agent.GetModelID(agent_id) + if model_id in [5405, 5409] and GLOBAL_CACHE.Agent.IsAlive(agent_id): + target_found = True if vial_slot > 0: while GLOBAL_CACHE.Agent.IsAlive(agent_id): @@ -1531,8 +1535,11 @@ def SpamVialOnHarbinger(): else: yield from Routines.Yield.wait(100) yield - return - yield from Routines.Yield.wait(1000) + break + + if not target_found: + yield from Routines.Yield.wait(1000) + yield bot.States.AddCustomState(SpamVialOnHarbinger, "Spam Vial on Harbinger") #region MAIN From f0c9a523600dd95ea1e42fa70cb9dc61edb4f830 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Nov 2025 03:29:03 +0000 Subject: [PATCH 08/12] Simplify: Remove multi-target loop since only one Harbinger exists Co-authored-by: Ewoog <72410352+Ewoog@users.noreply.github.com> --- Bots/Leveling/Nightfall/Nightfall_leveler.py | 40 ++++++++------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/Bots/Leveling/Nightfall/Nightfall_leveler.py b/Bots/Leveling/Nightfall/Nightfall_leveler.py index 0b6a90bf4..a31207a7a 100644 --- a/Bots/Leveling/Nightfall/Nightfall_leveler.py +++ b/Bots/Leveling/Nightfall/Nightfall_leveler.py @@ -1516,30 +1516,22 @@ def SpamVialOnHarbinger(): vial_slot = slot break - while True: - enemy_array = GLOBAL_CACHE.AgentArray.GetEnemyArray() - target_found = False - - for agent_id in enemy_array: - model_id = GLOBAL_CACHE.Agent.GetModelID(agent_id) - if model_id in [5405, 5409] and GLOBAL_CACHE.Agent.IsAlive(agent_id): - target_found = True - - if vial_slot > 0: - while GLOBAL_CACHE.Agent.IsAlive(agent_id): - if GLOBAL_CACHE.SkillBar.IsSkillReady(vial_slot): - yield from Routines.Yield.Agents.ChangeTarget(agent_id) - yield from Routines.Yield.wait(100) - GLOBAL_CACHE.SkillBar.UseSkill(vial_slot, agent_id) - yield from Routines.Yield.wait(250) - else: - yield from Routines.Yield.wait(100) - yield - break - - if not target_found: - yield from Routines.Yield.wait(1000) - yield + enemy_array = GLOBAL_CACHE.AgentArray.GetEnemyArray() + for agent_id in enemy_array: + model_id = GLOBAL_CACHE.Agent.GetModelID(agent_id) + if model_id in [5405, 5409] and GLOBAL_CACHE.Agent.IsAlive(agent_id): + if vial_slot > 0: + while GLOBAL_CACHE.Agent.IsAlive(agent_id): + if GLOBAL_CACHE.SkillBar.IsSkillReady(vial_slot): + yield from Routines.Yield.Agents.ChangeTarget(agent_id) + yield from Routines.Yield.wait(100) + GLOBAL_CACHE.SkillBar.UseSkill(vial_slot, agent_id) + yield from Routines.Yield.wait(250) + else: + yield from Routines.Yield.wait(100) + yield + return + yield bot.States.AddCustomState(SpamVialOnHarbinger, "Spam Vial on Harbinger") #region MAIN From fb9e564c803e9d7c53ed57ecd2e97f0dfd2a8aa2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Nov 2025 03:37:59 +0000 Subject: [PATCH 09/12] Fix: Use GetSkillData().recharge instead of non-existent IsSkillReady Co-authored-by: Ewoog <72410352+Ewoog@users.noreply.github.com> --- Bots/Leveling/Nightfall/Nightfall_leveler.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Bots/Leveling/Nightfall/Nightfall_leveler.py b/Bots/Leveling/Nightfall/Nightfall_leveler.py index a31207a7a..1258f3d7f 100644 --- a/Bots/Leveling/Nightfall/Nightfall_leveler.py +++ b/Bots/Leveling/Nightfall/Nightfall_leveler.py @@ -1522,7 +1522,8 @@ def SpamVialOnHarbinger(): if model_id in [5405, 5409] and GLOBAL_CACHE.Agent.IsAlive(agent_id): if vial_slot > 0: while GLOBAL_CACHE.Agent.IsAlive(agent_id): - if GLOBAL_CACHE.SkillBar.IsSkillReady(vial_slot): + skill_data = GLOBAL_CACHE.SkillBar.GetSkillData(vial_slot) + if skill_data.recharge == 0: yield from Routines.Yield.Agents.ChangeTarget(agent_id) yield from Routines.Yield.wait(100) GLOBAL_CACHE.SkillBar.UseSkill(vial_slot, agent_id) From 51fc6ea9d4491b9302da5a0261da2021d534a4c5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Nov 2025 03:47:22 +0000 Subject: [PATCH 10/12] Add WaitForHarbinger function to wait until target is in range Co-authored-by: Ewoog <72410352+Ewoog@users.noreply.github.com> --- Bots/Leveling/Nightfall/Nightfall_leveler.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Bots/Leveling/Nightfall/Nightfall_leveler.py b/Bots/Leveling/Nightfall/Nightfall_leveler.py index 1258f3d7f..8c81aa89a 100644 --- a/Bots/Leveling/Nightfall/Nightfall_leveler.py +++ b/Bots/Leveling/Nightfall/Nightfall_leveler.py @@ -1508,6 +1508,20 @@ def UnlockMercenaryHeroes(bot: Botting) -> None: def NunduBayVialSpam(bot: Botting) -> None: bot.Map.Travel(target_map_id=477) + def WaitForHarbinger(): + while True: + enemy_array = GLOBAL_CACHE.AgentArray.GetEnemyArray() + for agent_id in enemy_array: + model_id = GLOBAL_CACHE.Agent.GetModelID(agent_id) + if model_id in [5405, 5409] and GLOBAL_CACHE.Agent.IsAlive(agent_id): + player_pos = GLOBAL_CACHE.Player.GetXY() + harbinger_pos = GLOBAL_CACHE.Agent.GetXY(agent_id) + from Py4GWCoreLib.Py4GWcorelib import Utils + distance = Utils.Distance(player_pos, harbinger_pos) + if distance <= Range.Spellcast.value: + return + yield from Routines.Yield.wait(500) + def SpamVialOnHarbinger(): vial_skill_id = GLOBAL_CACHE.Skill.GetID("Vial_of_Purified_Water") vial_slot = 0 @@ -1534,6 +1548,7 @@ def SpamVialOnHarbinger(): return yield + bot.States.AddCustomState(WaitForHarbinger, "Wait for Harbinger") bot.States.AddCustomState(SpamVialOnHarbinger, "Spam Vial on Harbinger") #region MAIN selected_step = 0 From 81ccdc3c60f3f68e447972f25ea988d538aac0ef Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Nov 2025 16:23:46 +0000 Subject: [PATCH 11/12] Add FollowElderJonah function to follow Elder Jonah until Harbinger in range Co-authored-by: Ewoog <72410352+Ewoog@users.noreply.github.com> --- Bots/Leveling/Nightfall/Nightfall_leveler.py | 32 ++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/Bots/Leveling/Nightfall/Nightfall_leveler.py b/Bots/Leveling/Nightfall/Nightfall_leveler.py index 8c81aa89a..6b6efc0ff 100644 --- a/Bots/Leveling/Nightfall/Nightfall_leveler.py +++ b/Bots/Leveling/Nightfall/Nightfall_leveler.py @@ -1508,6 +1508,37 @@ def UnlockMercenaryHeroes(bot: Botting) -> None: def NunduBayVialSpam(bot: Botting) -> None: bot.Map.Travel(target_map_id=477) + def FollowElderJonah(): + from Py4GWCoreLib.Py4GWcorelib import Utils + while True: + harbinger_id = 0 + enemy_array = GLOBAL_CACHE.AgentArray.GetEnemyArray() + for agent_id in enemy_array: + model_id = GLOBAL_CACHE.Agent.GetModelID(agent_id) + if model_id in [5405, 5409] and GLOBAL_CACHE.Agent.IsAlive(agent_id): + harbinger_id = agent_id + break + + if harbinger_id > 0: + player_pos = GLOBAL_CACHE.Player.GetXY() + harbinger_pos = GLOBAL_CACHE.Agent.GetXY(harbinger_id) + distance = Utils.Distance(player_pos, harbinger_pos) + if distance <= Range.Spirit.value: + return + + npc_array = GLOBAL_CACHE.AgentArray.GetNPCMinipetArray() + for agent_id in npc_array: + model_id = GLOBAL_CACHE.Agent.GetModelID(agent_id) + if model_id == 5286: + jonah_pos = GLOBAL_CACHE.Agent.GetXY(agent_id) + player_pos = GLOBAL_CACHE.Player.GetXY() + distance = Utils.Distance(player_pos, jonah_pos) + if distance > 200: + yield from Routines.Yield.Movement.Move(jonah_pos[0], jonah_pos[1]) + break + + yield from Routines.Yield.wait(500) + def WaitForHarbinger(): while True: enemy_array = GLOBAL_CACHE.AgentArray.GetEnemyArray() @@ -1548,6 +1579,7 @@ def SpamVialOnHarbinger(): return yield + bot.States.AddCustomState(FollowElderJonah, "Follow Elder Jonah") bot.States.AddCustomState(WaitForHarbinger, "Wait for Harbinger") bot.States.AddCustomState(SpamVialOnHarbinger, "Spam Vial on Harbinger") #region MAIN From d93cffdae247359061bbd0e6042768ef815a5e7d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Nov 2025 16:33:37 +0000 Subject: [PATCH 12/12] Simplify: Use bot.Move.FollowModel with exit condition instead of custom loop Co-authored-by: Ewoog <72410352+Ewoog@users.noreply.github.com> --- Bots/Leveling/Nightfall/Nightfall_leveler.py | 37 ++++++-------------- 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/Bots/Leveling/Nightfall/Nightfall_leveler.py b/Bots/Leveling/Nightfall/Nightfall_leveler.py index 6b6efc0ff..b09f715ec 100644 --- a/Bots/Leveling/Nightfall/Nightfall_leveler.py +++ b/Bots/Leveling/Nightfall/Nightfall_leveler.py @@ -1508,36 +1508,20 @@ def UnlockMercenaryHeroes(bot: Botting) -> None: def NunduBayVialSpam(bot: Botting) -> None: bot.Map.Travel(target_map_id=477) - def FollowElderJonah(): + def harbinger_in_spirit_range(): from Py4GWCoreLib.Py4GWcorelib import Utils - while True: - harbinger_id = 0 - enemy_array = GLOBAL_CACHE.AgentArray.GetEnemyArray() - for agent_id in enemy_array: - model_id = GLOBAL_CACHE.Agent.GetModelID(agent_id) - if model_id in [5405, 5409] and GLOBAL_CACHE.Agent.IsAlive(agent_id): - harbinger_id = agent_id - break - - if harbinger_id > 0: + enemy_array = GLOBAL_CACHE.AgentArray.GetEnemyArray() + for agent_id in enemy_array: + model_id = GLOBAL_CACHE.Agent.GetModelID(agent_id) + if model_id in [5405, 5409] and GLOBAL_CACHE.Agent.IsAlive(agent_id): player_pos = GLOBAL_CACHE.Player.GetXY() - harbinger_pos = GLOBAL_CACHE.Agent.GetXY(harbinger_id) + harbinger_pos = GLOBAL_CACHE.Agent.GetXY(agent_id) distance = Utils.Distance(player_pos, harbinger_pos) if distance <= Range.Spirit.value: - return - - npc_array = GLOBAL_CACHE.AgentArray.GetNPCMinipetArray() - for agent_id in npc_array: - model_id = GLOBAL_CACHE.Agent.GetModelID(agent_id) - if model_id == 5286: - jonah_pos = GLOBAL_CACHE.Agent.GetXY(agent_id) - player_pos = GLOBAL_CACHE.Player.GetXY() - distance = Utils.Distance(player_pos, jonah_pos) - if distance > 200: - yield from Routines.Yield.Movement.Move(jonah_pos[0], jonah_pos[1]) - break - - yield from Routines.Yield.wait(500) + return True + return False + + bot.Move.FollowModel(5286, 200, harbinger_in_spirit_range) def WaitForHarbinger(): while True: @@ -1579,7 +1563,6 @@ def SpamVialOnHarbinger(): return yield - bot.States.AddCustomState(FollowElderJonah, "Follow Elder Jonah") bot.States.AddCustomState(WaitForHarbinger, "Wait for Harbinger") bot.States.AddCustomState(SpamVialOnHarbinger, "Spam Vial on Harbinger") #region MAIN