kolton / d2bot-with-kolbot

d2bot game manager by D3STROY3R with kolbot libs by kolton for d2bs
346 stars 334 forks source link

LightSorc Doesnt Clear Diablo Properly #2128

Open InterestingIndeed opened 4 years ago

InterestingIndeed commented 4 years ago

It seems like my Sorc is not clearing CS properly. In some games, Diablo doesnt appear, even though the seal are activated (I believe if you miss some/certain monsters while clearing, Diablo doesnt appear).

EDIT: After watching the bot for some runs, the problem seem to be the souls. If the spawn/move outside of the map, the bot cant kill them properly (light res ...). Normally, the Merc helps clearing, but outside of the map that doesn't work. Bot tps away, leaves mob behind, Diablo doesnt spawn ...

Is there a way to start a second clearing round or solve the issue in another way? I am using a light sorc until I can afford a pala, which should be able to clear more reliably, but I would love to see a way to do it with the sorc.

Fa-b commented 4 years ago

have you tried:

Config.TeleStomp = true;

I'm experiencing similar behaviour with my light sorc before. Using TeleStomp for getting closer to the immunes will not only help the merc get to them but also more likely trigger conviction aura in case your merc has infinity. In that case the immunity might drop and your sorc will be able to handle them even if the merc does not reach them.

But I agree, it would be nice to have some kind of redundant check on the seal bosses if diablo is not found in the first round..

InterestingIndeed commented 4 years ago

Tried TeleStomp, Sorc chickens out way to often for it to be better than some dia-skips ;)

Fa-b commented 4 years ago

Maybe try in combination with the doge settings above as well (See here). I have the feeling though, the activation of TeleStomp will avoid dodging in some occasions... Maybe look into the Diablo.js script and see if you can implement some sort of double check algorithm for the seal bosses yourself.. shouldn't be too difficult. TeleStomp works for me, what is the max life of your sorc?

Fa-b commented 4 years ago

Maybe this will work:

this.vizierSeal();
this.seisSeal();
Precast.doPrecast(true);
this.infectorSeal();

switch (me.classid) {
    case 1:
        Pather.moveTo(7792, 5294);

            break;
        default:
            Pather.moveTo(7788, 5292);

            break;
}

if (Config.PublicMode) {
    say(Config.Diablo.DiabloMsg);
}

if(!this.diabloPrep()) {
        this.vizierSeal();
    this.seisSeal();
    this.infectorSeal();
        switch (me.classid) {
            case 1:
                Pather.moveTo(7792, 5294);
                    break;
                default:
                    Pather.moveTo(7788, 5292);
                        break;
        }
        this.diabloPrep();
}

Attack.kill(243); // Diablo

basically just trying it all over again, if one of the bosses is still there, we have a second chance clearing them. Might work like this but is of course untested..

Edit: here a reference to what part to replace in Diablo.js.

InterestingIndeed commented 4 years ago

I also found a part where the bot checks if the area is cleared and clears strays (follow path and clear strays functions). This might be closer to the "root" of the problem. I will try your solution first tonight, adding code that runs seems to be better than changing existing code.

I also noticed, that my dodge range is lower than the 15 you linked above. I will try TeleStomp with higher dodge first, before I get into the code ;) Thanks for your help!

Fa-b commented 4 years ago

Actually this solution above is not so elegant after all. Sorry to post again, I have just checked a bit deeper and the only place that I find this could possibly skip monsters is here

in Attack.js when we try to clear the area there are two possibilities for the clearing to skip monsters without either logging or throwing an error. The first one (outer if) appears to check if the boss or target is out of range or for some reason not found. The second one (inner if) will occur when the attack failed due to bad position of the monster, this one will try for 3 times before it leads to skipping. I think it would be best to get some logging output for both cases to see what is actually the case here. This can be used to replace in the linked function 'clear' in Attack.js, and should not affect the existing code at all:

    } else {
        if (retry++ > 3) {
            print("ÿc1BadPosition " + target.name + " " + target.gid + " " + gidAttack[i].attacks);
            monsterList.shift();
            retry = 0;
        }

        Packet.flash(me.gid);
    }
} else {
    print("ÿc1OutOfRange " + target.name + " " + target.gid + " " + gidAttack[i].attacks);
    monsterList.shift();
}
InterestingIndeed commented 4 years ago

How can I get the logging output? do I have to change some settings or is it in the logfiles already?

Above the linked code you showed, there is

// Skip non-unique monsters after 15 attacks, except in Throne of Destruction

I might just set that number up as well.

Fa-b commented 4 years ago

Hmm.. only playing with kolbot since 2 days.. I think this will only log to the ingame console. Maybe setting that number higher makes it better, but then you won't know for sure whats going on. I think to print to the manager console you will have to use:

D2Bot.printToConsole(string);

instead of

print(string)
InterestingIndeed commented 4 years ago

In which part of the script can I find that specific print command?

Fa-b commented 4 years ago

Not sure what you refer to. If you ask for D2Bot.printToConsole(string);, you can find it being used for example here in the D2BotLead.dbj Starter.

Edit: I did some research. Here a reference how the data passed to printToConsole are prepared and sent to the D2BS in order to display them in the manager console. You can find it in d2bs/kolbot/libs/OOG.js:

printToConsole: function (msg, color, tooltip, trigger) {
    var printObj = {
        msg: msg,
        color: color || 0,
        tooltip: tooltip || "",
        trigger: trigger || ""
    },

    obj = {
        profile: me.profile,
        func: "printToConsole",
        args: [JSON.stringify(printObj)]
    };

    sendCopyData(null, this.handle, 0, JSON.stringify(obj));
}

As you see, you can also specify some more arguments like color, tooltip and trigger. Can't tell you what trigger will do, maybe you can fire some onClick events when you click on the textline in the console. Tooltip will most probably show some text when you hover over the line and color is pretty selfexplanatory. For the colors I can only guess and hope the ones defined for kolbot are similar to the ones D2BS uses internally since I cant find a reference in the D2BS API: from NTItemAlias.dbl

InterestingIndeed commented 4 years ago

I mean: Where do I have to change the print command to be able to find the error in the logfile.

Fa-b commented 4 years ago

Ah I get it, let me do this for you.

go here and replace this:

    } else {
    if (retry++ > 3) {
        monsterList.shift();
            retry = 0;
    }

    Packet.flash(me.gid);
    }
} else {
    monsterList.shift();
}

with this:

    } else {
    if (retry++ > 3) {
            D2Bot.printToConsole("BadPosition " + target.name + " " + target.gid + " " + gidAttack[i].attacks);
        monsterList.shift();
        retry = 0;
    }

    Packet.flash(me.gid);
    }
} else {
    D2Bot.printToConsole("OutOfRange " + target.name + " " + target.gid + " " + gidAttack[i].attacks);
    monsterList.shift();
}

As far as I know, all D2Bot.printToConsole prints go to the logfile of d2bs. I'm unsure about how to log it differently to a file.. as I said, just started digging through the code.

Hope this helps

InterestingIndeed commented 4 years ago

Thank you very much, that clear up a lot. Will come back with results in an hour as soon as I get home!

InterestingIndeed commented 4 years ago

So, I watched my Bot a bit more. It seems that the clearing is indeed not done properly. There are instances where the bot clearly teleports away even there is monster on the screen right next to him. This means, neither TeleStomp nor the exception line will solve the issue. Also increasing the attacks on unkillable monsters wont do the trick.

I will try to include a second cs run next.

Fa-b commented 4 years ago

I have added this addition to my Attack.js as well to check this, because I'm also not 100% happy about the behaviour. What I found really fast is, that the Out of Range Message occurs reeeaally often (like 10 times a second), so I immediately deactivated that line:

D2Bot.printToConsole("OutOfRange " + target.name + " " + target.gid + " " + gidAttack[i].attacks);

The other one though happens rarely and in occasions where a monsters position (mostly a Stormtrooper) is really invalid. I can imagine that this is the right place to optimize the seal issues.

neither TeleStomp nor the exception line will solve the issue. Also increasing the attacks on unkillable monsters wont do the trick.

TeleStomp is only used for immune monsters, if a monster is really unreacheable (for whatever reason) increasing the attack attempts without getting the monster move won't neccessarily help, since the position of the monster remains invalid. What one would have to do is move and come back later, hoping the monster has moved. Maybe pushing these target.gid's to a new list to try again after the first list is handled. Have to try and see

InterestingIndeed commented 4 years ago

Some results from the latest runs: I introduced a second CS run, that checks the whole are again. It is almost identical to what Fa-b posted:

this.vizierSeal();
    this.seisSeal();
    Precast.doPrecast(true);
    this.infectorSeal();
    switch (me.classid) {
    case 1:
        Pather.moveTo(7792, 5294);
        break;
    default:
        Pather.moveTo(7788, 5292);
        break;
    }
    if (Config.PublicMode) {
        say(Config.Diablo.DiabloMsg);
    } 
        this.vizierSeal();
    this.seisSeal();
    this.infectorSeal();
        switch (me.classid) {
            case 1:
                Pather.moveTo(7792, 5294);
                    break;
                default:
                    Pather.moveTo(7788, 5292);
                        break;
        }
        this.diabloPrep();
    Attack.kill(243); // Diablo

This drastically reduces the number of times Diablo doesn't appear for me. From watching the bot, I assume that the times diablo doesnt appear, it is because the left-over monsters are boss monsters that the combination of my Sorc and Merc can't kill or it would take them forever. So far so good.

There is one thing left that bothers me a bit: On the second CS round, the Bot detects activated seals and gives out the public game warning ("Dont touch the seals!). To deactivate the message, go into the the character config and change the line:

    `Config.Diablo.SealWarning = "Dont touch the seals!";`

to

             `Config.Diablo.SealWarning = "";`
Fa-b commented 4 years ago

Well, if it works for your sorc and merc in the second round, it wouldn't have taken them forever in the first round either if nothing else went wrong.. This is at least how I would expect it. If you look into the single seals functions, there is no code implemented that skips the bosses intentionally and moves towards diablo! If a boss can't be found... See here as an example:

if (!this.getBoss(getLocaleString(2852))) {
    throw new Error("Failed to kill de Seis");
}

This error would be visible on your console.

And getBoss returns nothing but Attack.clear as soon as the boss is found. So what I checked for was all possibilities for Attack.clear to fail on an important monster without returning false, void or null basically.

Running the script a second time always just for the small chance of something missing is not very efficient. If it works for you right now.. OK...

My light sorc runs Chaos too btw. and I'm not experiencing this behaviour very often. I can see BadPosition beeing printed occasionally, but usually I think the sorc gets that monster on her way back. Maybe your issue is really just about the boss monster killing time or immunities...