Leveling fixes#698
Leveling fixes#698CarlPoppa1 wants to merge 41 commits intohectorgimenez:mainfrom CarlPoppa1:leveling
Conversation
IsFromQuest() doesn't work on equippable items
Moved from part of leveling to option in main runs
Also forced clear floors when leveling and low lvl
Useful when low on gold and has no other impact
Where possible. Also fixed bugs and improved logic
|
What do you mean by "Stat allocation (with struct to allow for stats to be defined more than once)"? Unsure what you mean by defined more than once. Is that to do with the autoequip? Some potential fixes on your more changes to come list below. Would like to help out where I can. Stat allocation and Skill allocation can use PR 674 #674 . It only changes leveling_tools.go so no impact on your changes. It also doesn't require any changes to the character scripts, so should be fine with your autoequip work? Assuming stat points will be amended in those scripts to meet strength requirements etc. Autostart without TP bound, I've tested a solution to this (or a workaround at least). Just need some time to amend it in this PR.. If it's easier for you to add or can improve on the workaround:
Other suggestion: There is lots of running through Act 1, so when traversing to new areas or even clearing areas I have been repurposing the Andy script section to buy Stamina Potions at the start of these functions (instead of antidote pots). Helps with speed and survivability. Especially running to Countess, 4 pots seemed sufficient if not clearing monsters. |
Now uses action.Waypoint and not MoveToArea
Current implementation uses a map with a key of stat.ID to assign stat points. That means we can only apply any single stat in one consecutive action or actions. In reality, we want to assign a few strength points at level 3, a few at level 12 etc to make sure that we can equip better items as we move through the acts. I've moved it to a struct where you input your target points, once that target has been reached it moves on to the next entry in the struct:
Yes, I've done exactly the same, I just haven't pushed the commit yet.
I've set it to be based on the amount of gold (in act 1 only but maybe it needs to be for all acts) - it get switched back on when we have enough gold and turned back off when we drop below a certain level.
Good idea, I'll do this, thanks for reviewing. |
|
Sounds like it's all getting there, appreciate the responses. Let me know if I can assist with anything, but happy to test/review when I can. Re: the stats allocation, is that not what it already does? The existing one below is from sorceress_leveling_lightning.go. I would change this to get strength earlier, but didn't think it was worth making a PR until autoequip would take advantage of it. But it's very clear for anyone editing what levels these start triggering. So just saying it's something that probably doesn't need an overhaul, and has a working PR if that's something you can save your time on. `statPoints := make(map[stat.ID]int) |
|
Current script isn't clearing tower floors, which is not ideal for leveling. The current countess.go on main does not have any action.ClearCurrentLevel. But we also need to make it a configurable, like you intended so a normal countess run isn't impacted by this. I believe if you add your local countess.go to this PR, it will fix the issue. |
|
Balance Update: Current script has us going to Countess at lvl 9. This is resulting in a lot of chickens. I recommend hitting countess at level 12. For a sorc, this allows for fireball, which is a decent power creep and allows for clearing countess much easier. Right now at lvl 9-10, I am chickening 100% of the time. If I wait until lvl 12, that lowers chicken rate significantly. Clearing Stoney until 12 just requires one parameter update in your code. We might be able to maximize this and just clear BlackMarsh until level 12, not sure what would be faster. I can test this if you want, but for now I am just going to settle with clearing stoney until 12. |
|
@Antizerg try running leveling as lightning. Firebolt with no AOE will be far less effective I imagine. @CarlPoppa1 I know you simplified the runs to match the existing boss runs but I think leveling will sometimes call for a different approach. i.e. Act 1 normal since we have to walk. |
|
The act 1 go script isn't saving cain properly. It will go into stoney after the scroll and immediately leave. It also doesn't right click on the scroll to activate the shrines. |
|
Some of the quest scripts no longer work, so den, cain etc. can be skipped or feel free to fix them too :) Andariel quest will never get completed by the way. This script triggers the main boss farming run instead of the leveling function. It needs that leveling function to go talk to Warriv and get to Act 2. #713 #718 |
Don't need to kill Summoner to kill Duriel & fix Jerhyn bug
Moved MoveTo coords closer to Tyrael & Tyrael hitbox adjustment
|
Based on latest files.
Act 3 Bug:
|
Now calls prepareStaff each time and runs Summoner if not completed
Won't find body parts unless needed and wait before clicking trav stairs
|
Act2 bug: I think the only way to solve this is to ensure the summoner quest is fully completed before running line 56: |
You're right. I've fixed it differently though. I've just moved the Duriel check to after the Summoner check. So it'll keep running Summoner until Summoner is killed. |
|
I've not tried this branch yet, but I appreciate your effort. Here's my fix for that specific case in case it is relevant and helpful: Another issue I encountered was in the Harem/Palace cellar area were there can be multiple transitions to the same area. The bot had problems interacting with the area transition in the cases where there were > 1. |
|
Found Issue when using ensureKeyBinding: true and legacy mode, bot is clicking on belt slot1 and gets stuck with potion in hand |
Respec at lvl 32
Allows non-consecutive stat allocation (str,vit,str etc)
Yeah I hadn't pushed my ensureKeyBinding changes. Please can you try again when you get chance? It should be fixed in legacy and normal graphics now. Thanks for testing. |
this fixed the legacy issue thx I also posted some related issues on #699 |
|
Another small suggestion i have, would be the following: Since you changed the logics for Andariel and Duriel to fit your leveling logic, its hard to merge this pr into other stuff, because you also changed some lines on the original logic. Like in duriel.go: action.Buff() before Bossfight is now only done if usethawing is active They way i fixed those merge issues was to make a copy of duriel.go, named it duriel_leveling.go and change the calls you now use twice to ....Leveling, in the long run this is maybe not the best idea, because we dont want to blowup the filescount thats getting used, but for PR testing i find this quite nice because we do not mess up the main logics that way and dont get major merge conflicts. And its also nice for debugging and readability, while testing. You can see it in action in my Custom Branch: Maybe you want to implement it like that for the moment, if not just ignore my wall of text :) |
|
|
||
| remainingPoints-- | ||
|
|
||
| updatedValue, _ := ctx.Data.PlayerUnit.BaseStats.FindStat(allocation.Stat, 0) |
There was a problem hiding this comment.
I think there's a slight false sense of success here. Since this value depends on being refreshed from the update loops it's possible this value won't be accurate. I think what makes it seem like it works is the delay due to clicking the button. However if the anything happens with the update this could lead to an incorrect result.
It might be easier just to rely on remainingPoints. The worst thing that could happen is a failed click and a point doesn't get assigned, this would just be reconciled next check for available points and the unspent point would be properly allocated.
There was a problem hiding this comment.
Yeah, I'll revert these commits and go with your implementation (although there are still conflicting PRs aiming to do the same thing)
| //Hacky way to find if we're lvling a sorc at clvl 1 | ||
| str, _ := ctx.Data.PlayerUnit.FindStat(stat.Strength, 0) |
There was a problem hiding this comment.
what's wrong with ctx.Data.PlayerUnit.Class?
There was a problem hiding this comment.
Nothing, dunno what I was thinking. I'll change it
| if !a.ctx.Data.CanTeleport() { | ||
| a.ctx.CharacterCfg.Game.Countess.ClearFloors = true | ||
| } |
There was a problem hiding this comment.
This would be made unnecessary with #713 finished and completed.
There was a problem hiding this comment.
Agreed. I've made progress with finishing that PR, just testing it on leveling runs and refining it
| running = true | ||
|
|
||
| // clear Blood Moor until level 3 | ||
| // Clear Den of Evil til level 3 - might need to run it in each difficulty if we need more than one respec |
There was a problem hiding this comment.
Curious why removing the trist runs after 6? It seems like this flow is also a bit more complex than it needs to be. So was the original flow but I did like the later level runs.
A combo of both would be great:
- Den when < 3 or den not completed
- Cold Plains < 6
- Cain Quest until complete
- Trist until 15 or nightmare though we're getting a bit bloated trying to make this a once size fits all, might be better to just make a leveling nightmare run or something.
- Countess until 18
- Andy until someone shuts off the bot and increases difficulty
There was a problem hiding this comment.
In my runs I was repeatedly chickening at Treehead Woodfist at the Inifuss Tree. I had much more success going straight to Tower and leveling there.
Countess to 18 is very slow. I think we should always aim to be within 5 levels of each area level, which means we should stop countess at level 12.
I don't understand step 6 in your list but I'm not a fan of a leveling script that needs manual intervention
| action.InteractNPC(npc.Warriv) | ||
| a.ctx.HID.KeySequence(win.VK_HOME, win.VK_DOWN, win.VK_RETURN) |
There was a problem hiding this comment.
this seems like it should be an option on the andy run like NewAndarial(continueToAct2 bool) or something
|
|
||
| if !staffAlreadyUsed { | ||
| a.prepareStaff() | ||
| a.ctx.CharacterCfg.Game.Duriel.UseThawing = true |
There was a problem hiding this comment.
if this is now a setting why override it?
There was a problem hiding this comment.
Because (in normal difficulty as a sorc) it's almost impossible to kill Duriel without being either twinked and/or over leveled because we can't kite like a player can. In my experience it's only remotely possible if we use thawing pots
| for _, itm := range ctx.Data.Inventory.ByLocation(item.LocationGround) { | ||
| // Skip itempickup on party leveling Maggot Lair, is too narrow and causes characters to get stuck | ||
| if isLevelingChar && !itm.IsFromQuest() && (ctx.Data.PlayerUnit.Area == area.MaggotLairLevel1 || | ||
| if isLevelingChar && itm.Name != "StaffOfKings" && (ctx.Data.PlayerUnit.Area == area.MaggotLairLevel1 || |
There was a problem hiding this comment.
probably out of scope here and not your code but why does it matter if this is a leveling character to pick up the staff?
Shouldn't any run that needs the staff pick it up?
There was a problem hiding this comment.
Yeah I guess but I think leveling is the only run that needs the staff, but I guess you're right that no other run will ever go to maggot lair so it's probably an unnecessary condition
| if _, found := ctx.Data.KeyBindings.KeyBindingForSkill(skill.FireBolt); !found { | ||
| ctx.Logger.Debug("Lvl 1 sorc found - forcing fire bolt bind") | ||
| if ctx.GameReader.LegacyGraphics() { | ||
| ctx.HID.MovePointer(1000, 530) | ||
| } else { | ||
| ctx.HID.MovePointer(685, 545) | ||
| } |
There was a problem hiding this comment.
I assume this is due to firebolt being a +skill on an item?
If so is there a way to make this reusable so it can be used in the future by other functions? I'm thinking lower res wands or teleport staff/amulet
There was a problem hiding this comment.
Yeah, I haven't bothered properly accounting for +skills or charges on the key binding script but you're right it would be helpful to do that and to move the key binding functions somewhere more generic to be used for non-leveling. It's not a priority for me at the moment though
| statPoints[stat.Energy] = 60 | ||
| statPoints[stat.Strength] = 50 | ||
| statPoints[stat.Vitality] = 9999 | ||
| func (s SorceressLevelingLightning) StatPoints() []context.StatAllocation { |
There was a problem hiding this comment.
I had a similar thought change by making it just an array of stat.ID returned, it looks more verbose than your implementation but has the same function.
Another feature that can be added following your approach is the ability to dynamically set certain stat levels. For example the amount of dexterity required to reach a certain block rate or amount of strength to wear all currently equipped gear (after a respec). Less important now since there's no autogearing but something that would be useful in the future.
| statPoints[stat.Energy] = 0 | ||
| // Define target totals (including base stats) | ||
| targets := []context.StatAllocation{ | ||
| {Stat: stat.Vitality, Points: 45}, // Base 25 + 20 |
There was a problem hiding this comment.
I think straight points to spend is more clear here than target totals. This of course would mean knowing the base stats of a character class but that's not hard to put together.
There was a problem hiding this comment.
I think your implementation is better so I'll reverse my commits relating to skill and stat point allocation

I've deliberately left out the changes I made to open doors more reliably. So this PR will only work smoothly once #697 has been merged. Both PRs will need to be tested together.
It also requires D2Go #91 to be merged in order to bind TP tome.
More changes to come...
Skill allocation
Stat allocation (with struct to allow for stats to be defined more than once)
Dodge
Autostart (don't need tome portal bound)
Option to set optimal settings