Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: updates to blizzard sorc #707

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

jasorello
Copy link

@jasorello jasorello commented Feb 27, 2025

I had accidentally polluted my commits in #695 with bad line endings, this is a cleaned PR with just the blizzard sorc changes

This PR attempts:

  1. Better static field usage, porting the more complicated logic over from the nova sorceress character, as well as moving the distance logic to the common config so it can be more easily referenced across all other sorceress builds
  2. Moved blizzard-specific configurations to a function within the struct, keeping the same ease of configuration but without polluting the rest of the character package with consts (i also fixed some other cross-character references that were caught up in this)
  3. I did some optimization of the blizzard attack loop. The problem I'm trying to fix here is that on a faster machine, we're iterating through this loop much faster than the bot can actually perform any of the attacks. We can hit 200+ attack loops on a boss after just performing 6 or 7 actual attacks within the game. I think the issues here may also be present in other characters, but I'll wait for someone smarter than me to weigh in.

I also included the switch from sorceress to blizzardsorceress that was suggested in #691

…onst; optimization of attackloop to minimize wasted iterations
useMerc: true
stashToShared: false
useTeleport: true # If set to false, bot will not use teleport skill and will walk to the destination

sorceress: # generic sorceress configurations
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

common configuration that can be leveraged via s.Data.CharacterCfg.Character.Sorceress.StaticFieldMinDist

type BlizzardSorceress struct {
BaseCharacter
}

func (s BlizzardSorceress) attackConfig() map[string]int {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed there were issues in the builds with accidental references across the characters which might have unintended results. I thought this might be a better pattern to make it more clear which settings are relevant for each character. Is there a better way?

@@ -53,6 +58,46 @@ func (s BlizzardSorceress) CheckKeyBindings() []skill.ID {
return missingKeybindings
}

func (s BlizzardSorceress) killMonsterWithStatic(bossID npc.ID, monsterType data.MonsterType) error {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is mostly stolen from the nova sorceress

// Pull target threshold from config based on difficulty
var targetThreshold int
switch s.Data.CharacterCfg.Game.Difficulty {
case difficulty.Normal:
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These values have a bit of a buffer over the bare minimum for the difficulty to minimize wasted casts

@@ -77,7 +128,8 @@ func (s BlizzardSorceress) KillMonsterSequence(
return nil
}

if completedAttackLoops >= sorceressMaxAttacksLoop {
if completedAttackLoops >= s.attackConfig()["maxAttacksLoop"] {
s.Logger.Error("Exceeded MaxAttacksLoop", slog.String("completedAttackLoops", fmt.Sprintf("%v", completedAttackLoops)))
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've noticed a few people in Help noting that their character is bailing early but not knowing why. I think many of them are from hitting this loop in their respective character. This log message should help identify those cases better.

@@ -86,39 +138,34 @@ func (s BlizzardSorceress) KillMonsterSequence(
s.Logger.Info("Monster not found", slog.String("monster", fmt.Sprintf("%v", monster)))
return nil
}
if monster.Stats[stat.Life] <= 0 {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This avoids unnecessary attackloop iterations for bosses with an extended death animation like andariel

Copy link
Contributor

@elobo91 elobo91 Feb 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello . Thats a good catch. There isnt any character using this yet but maybe it could be useful in that case?
IMG_2060

could use npcmode 0 and 12 instead of life stat to determine if its dead if its problematic.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I've been testing with this after every attack in KillMonsterSequence, seems to work:

				if s.Data.PlayerUnit.Mode == mode.CastingSkill {
					attackSuccess = true
				}

Then at the bottom:

if attackSuccess {
			s.Logger.Debug("Completed attack loop", slog.Int("completedAttackLoops", completedAttackLoops))
			completedAttackLoops++
		}

Copy link
Contributor

@elobo91 elobo91 Feb 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant using mode dead and death . Dead is when it just died, death is when its extremely dead ( after animation) or i inverted

return nil
}

for s.Data.PlayerUnit.States.HasState(state.Cooldown) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

switched this to cast our leftskill until we're out of cooldown instead of just a single time. This should better leverage our activity during blizzard cooldown without resulting in a new attack loop.

I've pulled it ahead of the blizzard self-cast because otherwise we were usually hitting the self-cast block while blizzard was on cooldown.

New behavior should be:

while on cooldown:
	cast leftskill
	
if timeToCastSelfBlizzard:
	cast selfBlizzard
else
	cast regularBlizzard:

previousUnitID = int(id)
}
}

func (s BlizzardSorceress) killMonster(npc npc.ID, t data.MonsterType) error {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function was no longer being called

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants