kolton / d2bot-with-kolbot

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

Javazon attack config #1002

Open thatguy692 opened 5 years ago

thatguy692 commented 5 years ago

I'm trying to run a javazon but i find it's running in a strange manner, here's my attack config:

Config.AttackSkill[0] = -1; // Preattack skill.
Config.AttackSkill[1] = 24; // Primary skill to bosses.
Config.AttackSkill[2] = 24; // Primary untimed skill to bosses. Keep at -1 if Config.AttackSkill[1] is untimed skill.
Config.AttackSkill[3] = 35; // Primary skill to others.
Config.AttackSkill[4] = 24; // Primary untimed skill to others. Keep at -1 if Config.AttackSkill[3] is untimed skill.
Config.AttackSkill[5] = -1; // Secondary skill if monster is immune to primary.
Config.AttackSkill[6] = -1; // Secondary untimed skill if monster is immune to primary untimed.
Config.LightningFuryDelay = 1; // Lightning fury interval in seconds. LF is treated as timed skill.

it should use LF every second and inbetween use CS, the problem is that sometimes it uses CS in the air in front of monsters, thats's annoying

anyone can maybe share their attack config?

Learningslow commented 5 years ago

that is a common problem ive seen, it will get stuck in a CS stabbing loop if the monster gets out of range. I found no fix hopefully someone else has a fix

redeyedjesus commented 5 years ago

Im trying to find a solution to this as well

Izaal87 commented 5 years ago

Anyone find a solution for javazon bot? I’m having problems with the skills config also.

redeyedjesus commented 5 years ago

Best I've been able to come up with is setting pre attack to fury and reducing the fury delay to 3 seconds and not just using cs. And using strokes instead of titans. I've asked a few people I know who are great at this like laz and haven't gotten much useful back. I'm honestly at a bit of a loss. I've even been through the Amazon attack trying to find a delay on checking monsters distances. It just wants to keep trying to FC once the monster becomes out of range.

On Wed, Feb 13, 2019, 10:41 AM Izaal87 notifications@github.com wrote:

Anyone find a solution for javazon bot? I’m having problems with the skills config also.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/kolton/d2bot-with-kolbot/issues/1002#issuecomment-463247440, or mute the thread https://github.com/notifications/unsubscribe-auth/ATvdjG8SmMa9lINXao4t6Q5ZhQ2dkZM8ks5vNDIVgaJpZM4Z8qxh .

artashur commented 5 years ago

since attack.js only Judge AttackSkill[1] and AttackSkill[3]'s attack range. so if you use LF as AttackSkill[1] or AttackSkill[3], it will CS stabbing sometimes.

if (gidAttack[i].attacks > 0 && gidAttack[i].attacks % ((target.spectype & 0x7) ? 5 : 15) === 0 && Skill.getRange(Config.AttackSkill[(target.spectype & 0x7) ? 1 : 3]) < 4)

so the simple soulution is not set LF as AttackSkill[1] or AttackSkill[3]

Config.AttackSkill[0] = 35; Config.AttackSkill[1] = 24; Config.AttackSkill[2] = 24; Config.AttackSkill[3] = 24; Config.AttackSkill[4] = 24;

try this. or add some code in attack.js.

Mexxtexer commented 4 years ago

This is perhaps a little late, but I've been using this thread at first, until I solved the problem, so I would like to contribute.

What I do is count monsters nearby, and then switch between LF/CS based on that. And of course set the LF delay low (0.25 or whatever)

So in Amazon.js I add this snippet, right after the line 'var needrepair....':

    if (this.monstersNearTarget(unit, 10) > 5) {  // 10 is the distance around the target to check, 5 is criteria for using LF.
        //print("MILL: Using LF!");
        Config.AttackSkill[0] = -1; // Preattack skill.
        Config.AttackSkill[1] = 35; // Primary skill to bosses.
        Config.AttackSkill[2] = 35; // Primary untimed skill to bosses. Keep at -1 if Config.AttackSkill[1] is untimed skill.
        Config.AttackSkill[3] = 35; // Primary skill to others.
        Config.AttackSkill[4] = 35; // Primary untimed skill to others. Keep at -1 if Config.AttackSkill[3] is untimed skill.
    }else{
        //print("MILL: Using CS!");
        Config.AttackSkill[0] = -1; // Preattack skill.
        Config.AttackSkill[1] = 24; // Primary skill to bosses.
        Config.AttackSkill[2] = 24; // Primary untimed skill to bosses. Keep at -1 if Config.AttackSkill[1] is untimed skill.
        Config.AttackSkill[3] = 24; // Primary skill to others.
        Config.AttackSkill[4] = 24; // Primary untimed skill to others. Keep at -1 if Config.AttackSkill[3] is untimed skill.
    }

and then define the counting function monstersNearTarget somewhere else to the variable ClassAttack:

monstersNearTarget: function (unit, radi) {
var count, monster = getUnit(1);    
count = 0;
if (monster) {
    do {
        if(Attack.checkMonster(monster)){
            if (getDistance(unit, monster) <= radi) {
                count += 1;
            }
        }
    } while (monster.getNext());
}   
return count;
}
123asdf321 commented 4 years ago

hi, where do I put this counting function exactly? mine is running errors

Mexxtexer commented 4 years ago

I notice now, that there are more than one file named Amazon.js.

I put it in the amazon.js file under libs\common\attacks\amazon.js

My amazon.js looks like this: (with danish comments)

/**
*   @filename   Amazon.js
*   @author     kolton
*   @desc       Amazon attack sequence
*/

var ClassAttack = {
    bowCheck: false,
    lightFuryTick: 0,

    monstersNearTarget: function (unit, radi) {

        var count, 
            monster = getUnit(1);

        count = 0;

        if (monster) {

            do {
                if(Attack.checkMonster(monster)){
                    if (getDistance(unit, monster) <= radi) {
                        count += 1;
                    }
                }

            } while (monster.getNext());
        }   

        print("MILL: Der er "+count+" mobs indenfor "+radi+" enheder!");

        return count;

    },

    doAttack: function (unit, preattack) {
        var needRepair = Town.needRepair();

        // MILL sætter lf til baseret på antal mobs omkring
        if (this.monstersNearTarget(unit, 12) > 4) {
            //print("MILL: Bruger LF!");
            Config.AttackSkill[0] = -1; // Preattack skill.
            Config.AttackSkill[1] = 35; // Primary skill to bosses.
            Config.AttackSkill[2] = 35; // Primary untimed skill to bosses. Keep at -1 if Config.AttackSkill[1] is untimed skill.
            Config.AttackSkill[3] = 35; // Primary skill to others.
            Config.AttackSkill[4] = 35; // Primary untimed skill to others. Keep at -1 if Config.AttackSkill[3] is untimed skill.
        }else{
            //print("MILL: Bruger CS!");
            Config.AttackSkill[0] = -1; // Preattack skill.
            Config.AttackSkill[1] = 24; // Primary skill to bosses.
            Config.AttackSkill[2] = 24; // Primary untimed skill to bosses. Keep at -1 if Config.AttackSkill[1] is untimed skill.
            Config.AttackSkill[3] = 24; // Primary skill to others.
            Config.AttackSkill[4] = 24; // Primary untimed skill to others. Keep at -1 if Config.AttackSkill[3] is untimed skill.
        }

        if ((Config.MercWatch && Town.needMerc()) || needRepair.length > 0) {
            Town.visitTown(!!needRepair.length);
        }

        if (preattack && Config.AttackSkill[0] > 0 && Attack.checkResist(unit, Config.AttackSkill[0]) && (!me.getState(121) || !Skill.isTimed(Config.AttackSkill[0]))) {
            if (Math.round(getDistance(me, unit)) > Skill.getRange(Config.AttackSkill[0]) || checkCollision(me, unit, 0x4)) {
                if (!Attack.getIntoPosition(unit, Skill.getRange(Config.AttackSkill[0]), 0x4)) {
                    return 0;
                }
            }

            Skill.cast(Config.AttackSkill[0], Skill.getHand(Config.AttackSkill[0]), unit);
            if(Config.AttackSkill[0] == 35) {
                // Light fury
                print("MILL: Gentager lf!");
                if(!unit.dead){
                    Skill.cast(Config.AttackSkill[0], Skill.getHand(Config.AttackSkill[0]), unit);  
                }
                if(!unit.dead){
                    Skill.cast(Config.AttackSkill[0], Skill.getHand(Config.AttackSkill[0]), unit);  
                }
                if(!unit.dead){
                    Skill.cast(Config.AttackSkill[0], Skill.getHand(Config.AttackSkill[0]), unit);  
                }
                if(!unit.dead){
                    Skill.cast(Config.AttackSkill[0], Skill.getHand(Config.AttackSkill[0]), unit);  
                }
            }

            return 1;
        }

        var index, checkSkill, result,
            mercRevive = 0,
            timedSkill = -1,
            untimedSkill = -1;

        index = ((unit.spectype & 0x7) || unit.type === 0) ? 1 : 3;

        // Get timed skill
        if (Attack.getCustomAttack(unit)) {
            checkSkill = Attack.getCustomAttack(unit)[0];
        } else {
            checkSkill = Config.AttackSkill[index];
        }

        if (Attack.checkResist(unit, checkSkill)) {
            timedSkill = checkSkill;
        } else if (Config.AttackSkill[5] > -1 && Attack.checkResist(unit, Config.AttackSkill[5]) && ([56, 59].indexOf(Config.AttackSkill[5]) === -1 || Attack.validSpot(unit.x, unit.y))) {
            timedSkill = Config.AttackSkill[5];
        }

        // Get untimed skill
        if (Attack.getCustomAttack(unit)) {
            checkSkill = Attack.getCustomAttack(unit)[1];
        } else {
            checkSkill = Config.AttackSkill[index + 1];
        }

        if (Attack.checkResist(unit, checkSkill)) {
            untimedSkill = checkSkill;
        } else if (Config.AttackSkill[6] > -1 && Attack.checkResist(unit, Config.AttackSkill[6]) && ([56, 59].indexOf(Config.AttackSkill[6]) === -1 || Attack.validSpot(unit.x, unit.y))) {
            untimedSkill = Config.AttackSkill[6];
        }

        // Low mana timed skill
        if (Config.LowManaSkill[0] > -1 && Skill.getManaCost(timedSkill) > me.mp && Attack.checkResist(unit, Config.LowManaSkill[0])) {
            timedSkill = Config.LowManaSkill[0];
        }

        // Low mana untimed skill
        if (Config.LowManaSkill[1] > -1 && Skill.getManaCost(untimedSkill) > me.mp && Attack.checkResist(unit, Config.LowManaSkill[1])) {
            untimedSkill = Config.LowManaSkill[1];
        }

        result = this.doCast(unit, timedSkill, untimedSkill);

        if (result === 2 && Config.TeleStomp && Attack.checkResist(unit, "physical") && !!me.getMerc()) {
            while (Attack.checkMonster(unit)) {
                if (Town.needMerc()) {
                    if (Config.MercWatch && mercRevive++ < 1) {
                        Town.visitTown();
                    } else {
                        return 2;
                    }
                }

                if (getDistance(me, unit) > 3) {
                    Pather.moveToUnit(unit);
                }

                this.doCast(unit, Config.AttackSkill[1], Config.AttackSkill[2]);
            }

            return 1;
        }

        return result;
    },

    afterAttack: function () {
        var needRepair;

        Misc.unShift();
        Precast.doPrecast(false);

        needRepair = Town.needRepair();

        if (needRepair && needRepair.length > 0) { // Repair check, mainly to restock arrows
            Town.visitTown(true);
        }

        this.lightFuryTick = 0;
    },

    // Returns: 0 - fail, 1 - success, 2 - no valid attack skills
    doCast: function (unit, timedSkill, untimedSkill) {
        var i, walk;

        // No valid skills can be found
        if (timedSkill < 0 && untimedSkill < 0) {
            return 2;
        }

        // Arrow/bolt check
        if (this.bowCheck) {
            switch (this.bowCheck) {
            case "bow":
                if (!me.getItem("aqv", 1)) {
                    Town.visitTown();
                }

                break;
            case "crossbow":
                if (!me.getItem("cqv", 1)) {
                    Town.visitTown();
                }

                break;
            }
        }

        if (timedSkill > -1 && (!me.getState(121) || !Skill.isTimed(timedSkill))) {
            switch (timedSkill) {
            case 35:
                if (!this.lightFuryTick || getTickCount() - this.lightFuryTick > Config.LightningFuryDelay * 1000) {
                    if (Math.round(getDistance(me, unit)) > Skill.getRange(timedSkill) || checkCollision(me, unit, 0x4)) {
                        if (!Attack.getIntoPosition(unit, Skill.getRange(timedSkill), 0x4)) {
                            return 0;
                        }
                    }

                    if (!unit.dead && Skill.cast(timedSkill, Skill.getHand(timedSkill), unit)) {
                        this.lightFuryTick = getTickCount();
                    }

                    return 1;
                }

                break;
            default:
                if (Skill.getRange(timedSkill) < 4 && !Attack.validSpot(unit.x, unit.y)) {
                    return 0;
                }

                if (Math.round(getDistance(me, unit)) > Skill.getRange(timedSkill) || checkCollision(me, unit, 0x4)) {
                    // Allow short-distance walking for melee skills
                    walk = Skill.getRange(timedSkill) < 4 && getDistance(me, unit) < 10 && !checkCollision(me, unit, 0x1);

                    if (!Attack.getIntoPosition(unit, Skill.getRange(timedSkill), 0x4, walk)) {
                        return 0;
                    }
                }

                if (!unit.dead) {
                    Skill.cast(timedSkill, Skill.getHand(timedSkill), unit);
                }

                return 1;
            }
        }

        if (untimedSkill > -1) {
            if (Skill.getRange(untimedSkill) < 4 && !Attack.validSpot(unit.x, unit.y)) {
                return 0;
            }

            if (Math.round(getDistance(me, unit)) > Skill.getRange(untimedSkill) || checkCollision(me, unit, 0x4)) {
                // Allow short-distance walking for melee skills
                walk = Skill.getRange(untimedSkill) < 4 && getDistance(me, unit) < 10 && !checkCollision(me, unit, 0x1);

                if (!Attack.getIntoPosition(unit, Skill.getRange(untimedSkill), 0x4, walk)) {
                    return 0;
                }
            }

            if (!unit.dead) {
                Skill.cast(untimedSkill, Skill.getHand(untimedSkill), unit);
            }

            return 1;
        }

        for (i = 0; i < 25; i += 1) {
            if (!me.getState(121)) {
                break;
            }

            delay(40);
        }

        // Wait for Lightning Fury timeout
        while (this.lightFuryTick && getTickCount() - this.lightFuryTick < Config.LightningFuryDelay * 1000) {
            delay(40);
        }

        return 1;
    }
};
UltaMist commented 4 years ago

Mexxtexer That script helped a lot, thanks! Eth Titans don't ever run dry! <3

Amphetamemes commented 4 years ago

Mexxtexer That script is great, thanks a lot.

SimonGrass commented 4 years ago

Mexxtexer That script is great, thanks a lot.

Hey could you explain how did you do it? once you modify Amazon.js you have to create a new user to import those mods into script created for bot?.

When u run it for the first time a file is created which has the name of your bot.js and there has Config.AttackSkill[0] = -1; Config.AttackSkill[1] = -1; Config.AttackSkill[2] = -1; Config.AttackSkill[3] = -1; Config.AttackSkill[4] = -1;

But that file is different from the Amazon.js thats why im getting confused.

Thanks!

Mexxtexer commented 4 years ago

Mexxtexer That script is great, thanks a lot.

Hey could you explain how did you do it? once you modify Amazon.js you have to create a new user to import those mods into script created for bot?.

When u run it for the first time a file is created which has the name of your bot.js and there has Config.AttackSkill[0] = -1; Config.AttackSkill[1] = -1; Config.AttackSkill[2] = -1; Config.AttackSkill[3] = -1; Config.AttackSkill[4] = -1;

But that file is different from the Amazon.js thats why im getting confused.

Thanks!

Hi,

The bot uses the file Amazon.js after having read name of your bot.js, so whatever Config.attackSkill is set to in name of your bot.js automatically gets overwritten.

I.e., you just need to modify Amazon.js

SimonGrass commented 4 years ago

Mexxtexer That script is great, thanks a lot.

Hey could you explain how did you do it? once you modify Amazon.js you have to create a new user to import those mods into script created for bot?. When u run it for the first time a file is created which has the name of your bot.js and there has Config.AttackSkill[0] = -1; Config.AttackSkill[1] = -1; Config.AttackSkill[2] = -1; Config.AttackSkill[3] = -1; Config.AttackSkill[4] = -1; But that file is different from the Amazon.js thats why im getting confused. Thanks!

Hi,

The bot uses the file Amazon.js after having read name of your bot.js, so whatever Config.attackSkill is set to in name of your bot.js automatically gets overwritten.

I.e., you just need to modify Amazon.js

Thanks so much for the early response! I made it work!

Do you have any tips to make it so my zon doesn´t tele right in the middle of a pack? she does it ocasionally and setting the Dodge to true explicitly asks not to use it when you can use "short range attacks". Should I set it to true and put a low distance or something?

Again, thanks for the response!

d2botter commented 3 years ago

Just modify the following lines

https://github.com/kolton/d2bot-with-kolbot/blob/0ba87a25ef5e9432920e20d93082b936b318e148/d2bs/kolbot/libs/common/Attack.js#L1549-L1551

to:

if (getDistance(me, unit) > distance || checkCollision(me, unit, coll)) {
    Pather.walkTo(unit.x, unit.y, distance);
}

It works perfectly, it walks everytime to the correct distance and CS never fails. No more deaths because you're hitting the air

Invictus-101 commented 3 years ago

Just wanted to thank Mexxtexer for the excellent monster counting function. I adapted it to use on my lightning sorc as well to determine when to use chain lightning. Also, instead of adding the if else statement changing your whole attack config you can just go down to (line 35 in my amazon.js file) where you see the line:

index = ((unit.spectype & 0x7) || unit.type === 0) ? 1 : 3;

Then you can just add the if/else statement like so:

if (this.monstersNearTarget(unit, 12) > 4) {
    index = unit.type === 0 ? 1 : 3
}else {
    index = 1
}

Assuming you have Config.AttackSkill[1] set to CS and Config.AttackSkill[3] set to LF, this will tell the zon to use fury on regular mobs when there are more than 4 within 12y, and CS on stragglers and bosses. I was actually toying with the idea of setting AttackSkill[4] to lightning strike and having it use CS for < 4 monsters, lightning strike for 4-8 monsters and fury for > 8 or something like that. I may code that in the next couple days and see how it works.

flippyfloppyflappy commented 3 years ago

hey so I adopted Mexxtexer's program on amazon.js , but my zon kept running into cow packs so I changed the distance 8,3 to distance, distance on the attack.js like d2botter showed. But I'm still not sure what the attack config on the Amazon.name.js script should be (the one where u pick where to farm and stuff, not the if, then program), I have:

Config.AttackSkill[0] = 35; // Preattack skill. Config.AttackSkill[1] = 24; // Primary skill to bosses. Config.AttackSkill[2] = 24; // Primary untimed skill to bosses. Keep at -1 if Config.AttackSkill[1] is untimed skill. Config.AttackSkill[3] = 35; // Primary skill to others. Config.AttackSkill[4] = 35; // Primary untimed skill to others. Keep at -1 if Config.AttackSkill[3] is untimed skill. Config.AttackSkill[5] = -1; // Secondary skill if monster is immune to primary. Config.AttackSkill[6] = -1; // Secondary untimed skill if monster is immune to primary untimed.

right now with LF @ 1 sec, but the clear speed is incredibly slow. It's like a 10 min run with a lot of running around not killing anything. I'm also trying to get her to farm Dkeys but the comp is too stupid and keeps dying. I have my dodge range at 15 to try speeding up cows, but even at 30 she couldn't survive nih. Overall, this is rather underwhelming for such a fun build to play manually.

flippyfloppyflappy commented 3 years ago
if (this.monstersNearTarget(unit, 12) > 4) {
    index = unit.type === 0 ? 1 : 3
}else {
    index = 1
}

can u post this file so I can try it? I saved over with Maxx's, but I think Maxx's counting thing is taking way too long. Perhaps this will speed things up

ciompek commented 3 years ago

monstersNearTarget function can be optimized a lot - i will give it a try this week. key is to make it return true as soon as it gets a certain mobs in certain distance. It will then skip the unneeded iterations (eg 12) when you are in the middle of eg 20 mobs.

ciompek commented 3 years ago

here you go, works like a charm ;)

` /**

var ClassAttack = { bowCheck: false, lightFuryTick: 0,

monstersNearTarget: function (unit) {

    var count, radi
        monster = getUnit(1);

    count = 0;
radi = 8;
min = 3

    if (monster) {
        do {
            if(Attack.checkMonster(monster)){
                if (getDistance(unit, monster) <= radi) {
                    count += 1;
        if (count > min) {
          return 1;
        }
                }
            }
        } while (monster.getNext());
    }
},

doAttack: function (unit, preattack) {
    var needRepair = Town.needRepair();

    // MILL sætter lf til baseret på antal mobs omkring
    if (this.monstersNearTarget(unit)) {
        Config.AttackSkill[0] = -1; // Preattack skill.
        Config.AttackSkill[1] = 35; // Primary skill to bosses.
        Config.AttackSkill[2] = 35; // Primary untimed skill to bosses. Keep at -1 if Config.AttackSkill[1] is untimed skill.
        Config.AttackSkill[3] = 35; // Primary skill to others.
        Config.AttackSkill[4] = 35; // Primary untimed skill to others. Keep at -1 if Config.AttackSkill[3] is untimed skill.
    }else{
        Config.AttackSkill[0] = -1; // Preattack skill.
        Config.AttackSkill[1] = 24; // Primary skill to bosses.
        Config.AttackSkill[2] = 24; // Primary untimed skill to bosses. Keep at -1 if Config.AttackSkill[1] is untimed skill.
        Config.AttackSkill[3] = 24; // Primary skill to others.
        Config.AttackSkill[4] = 24; // Primary untimed skill to others. Keep at -1 if Config.AttackSkill[3] is untimed skill.
    }

    if ((Config.MercWatch && Town.needMerc()) || needRepair.length > 0) {
        Town.visitTown(!!needRepair.length);
    }

    if (preattack && Config.AttackSkill[0] > 0 && Attack.checkResist(unit, Config.AttackSkill[0]) && (!me.getState(121) || !Skill.isTimed(Config.AttackSkill[0]))) {
        if (Math.round(getDistance(me, unit)) > Skill.getRange(Config.AttackSkill[0]) || checkCollision(me, unit, 0x4)) {
            if (!Attack.getIntoPosition(unit, Skill.getRange(Config.AttackSkill[0]), 0x4)) {
                return 0;
            }
        }

        Skill.cast(Config.AttackSkill[0], Skill.getHand(Config.AttackSkill[0]), unit);
        if(Config.AttackSkill[0] == 35) {
            // Light fury
            //print("MILL: Gentager lf!");
            if(!unit.dead){
                Skill.cast(Config.AttackSkill[0], Skill.getHand(Config.AttackSkill[0]), unit);
            }
            if(!unit.dead){
                Skill.cast(Config.AttackSkill[0], Skill.getHand(Config.AttackSkill[0]), unit);
            }
            if(!unit.dead){
                Skill.cast(Config.AttackSkill[0], Skill.getHand(Config.AttackSkill[0]), unit);
            }
            if(!unit.dead){
                Skill.cast(Config.AttackSkill[0], Skill.getHand(Config.AttackSkill[0]), unit);
            }
        }

        return 1;
    }

    var index, checkSkill, result,
        mercRevive = 0,
        timedSkill = -1,
        untimedSkill = -1;

    index = ((unit.spectype & 0x7) || unit.type === 0) ? 1 : 3;

    // Get timed skill
    if (Attack.getCustomAttack(unit)) {
        checkSkill = Attack.getCustomAttack(unit)[0];
    } else {
        checkSkill = Config.AttackSkill[index];
    }

    if (Attack.checkResist(unit, checkSkill)) {
        timedSkill = checkSkill;
    } else if (Config.AttackSkill[5] > -1 && Attack.checkResist(unit, Config.AttackSkill[5]) && ([56, 59].indexOf(Config.AttackSkill[5]) === -1 || Attack.validSpot(unit.x, unit.y))) {
        timedSkill = Config.AttackSkill[5];
    }

    // Get untimed skill
    if (Attack.getCustomAttack(unit)) {
        checkSkill = Attack.getCustomAttack(unit)[1];
    } else {
        checkSkill = Config.AttackSkill[index + 1];
    }

    if (Attack.checkResist(unit, checkSkill)) {
        untimedSkill = checkSkill;
    } else if (Config.AttackSkill[6] > -1 && Attack.checkResist(unit, Config.AttackSkill[6]) && ([56, 59].indexOf(Config.AttackSkill[6]) === -1 || Attack.validSpot(unit.x, unit.y))) {
        untimedSkill = Config.AttackSkill[6];
    }

    // Low mana timed skill
    if (Config.LowManaSkill[0] > -1 && Skill.getManaCost(timedSkill) > me.mp && Attack.checkResist(unit, Config.LowManaSkill[0])) {
        timedSkill = Config.LowManaSkill[0];
    }

    // Low mana untimed skill
    if (Config.LowManaSkill[1] > -1 && Skill.getManaCost(untimedSkill) > me.mp && Attack.checkResist(unit, Config.LowManaSkill[1])) {
        untimedSkill = Config.LowManaSkill[1];
    }

    result = this.doCast(unit, timedSkill, untimedSkill);

    if (result === 2 && Config.TeleStomp && Attack.checkResist(unit, "physical") && !!me.getMerc()) {
        while (Attack.checkMonster(unit)) {
            if (Town.needMerc()) {
                if (Config.MercWatch && mercRevive++ < 1) {
                    Town.visitTown();
                } else {
                    return 2;
                }
            }

            if (getDistance(me, unit) > 3) {
                Pather.moveToUnit(unit);
            }

            this.doCast(unit, Config.AttackSkill[1], Config.AttackSkill[2]);
        }

        return 1;
    }

    return result;
},

afterAttack: function () {
    var needRepair;

    Misc.unShift();
    Precast.doPrecast(false);

    needRepair = Town.needRepair();

    if (needRepair && needRepair.length > 0) { // Repair check, mainly to restock arrows
        Town.visitTown(true);
    }

    this.lightFuryTick = 0;
},

// Returns: 0 - fail, 1 - success, 2 - no valid attack skills
doCast: function (unit, timedSkill, untimedSkill) {
    var i, walk;

    // No valid skills can be found
    if (timedSkill < 0 && untimedSkill < 0) {
        return 2;
    }

    // Arrow/bolt check
    if (this.bowCheck) {
        switch (this.bowCheck) {
        case "bow":
            if (!me.getItem("aqv", 1)) {
                Town.visitTown();
            }

            break;
        case "crossbow":
            if (!me.getItem("cqv", 1)) {
                Town.visitTown();
            }

            break;
        }
    }

    if (timedSkill > -1 && (!me.getState(121) || !Skill.isTimed(timedSkill))) {
        switch (timedSkill) {
        case 35:
            if (!this.lightFuryTick || getTickCount() - this.lightFuryTick > Config.LightningFuryDelay * 1000) {
                if (Math.round(getDistance(me, unit)) > Skill.getRange(timedSkill) || checkCollision(me, unit, 0x4)) {
                    if (!Attack.getIntoPosition(unit, Skill.getRange(timedSkill), 0x4)) {
                        return 0;
                    }
                }

                if (!unit.dead && Skill.cast(timedSkill, Skill.getHand(timedSkill), unit)) {
                    this.lightFuryTick = getTickCount();
                }

                return 1;
            }

            break;
        default:
            if (Skill.getRange(timedSkill) < 4 && !Attack.validSpot(unit.x, unit.y)) {
                return 0;
            }

            if (Math.round(getDistance(me, unit)) > Skill.getRange(timedSkill) || checkCollision(me, unit, 0x4)) {
                // Allow short-distance walking for melee skills
                walk = Skill.getRange(timedSkill) < 4 && getDistance(me, unit) < 10 && !checkCollision(me, unit, 0x1);

                if (!Attack.getIntoPosition(unit, Skill.getRange(timedSkill), 0x4, walk)) {
                    return 0;
                }
            }

            if (!unit.dead) {
                Skill.cast(timedSkill, Skill.getHand(timedSkill), unit);
            }

            return 1;
        }
    }

    if (untimedSkill > -1) {
        if (Skill.getRange(untimedSkill) < 4 && !Attack.validSpot(unit.x, unit.y)) {
            return 0;
        }

        if (Math.round(getDistance(me, unit)) > Skill.getRange(untimedSkill) || checkCollision(me, unit, 0x4)) {
            // Allow short-distance walking for melee skills
            walk = Skill.getRange(untimedSkill) < 4 && getDistance(me, unit) < 10 && !checkCollision(me, unit, 0x1);

            if (!Attack.getIntoPosition(unit, Skill.getRange(untimedSkill), 0x4, walk)) {
                return 0;
            }
        }

        if (!unit.dead) {
            Skill.cast(untimedSkill, Skill.getHand(untimedSkill), unit);
        }

        return 1;
    }

    for (i = 0; i < 25; i += 1) {
        if (!me.getState(121)) {
            break;
        }

        delay(40);
    }

    // Wait for Lightning Fury timeout
    while (this.lightFuryTick && getTickCount() - this.lightFuryTick < Config.LightningFuryDelay * 1000) {
        delay(40);
    }

    return 1;
}

};

`

flippyfloppyflappy commented 3 years ago

You’re amazing! Just curious for diagnostic purposes, what’s your cow run time with infinity and the basic endgame javazon gear?

On Sun, Jul 4, 2021 at 1:54 PM ciompek @.***> wrote:

here you go, works like a charm ;)

`/**

var ClassAttack = { bowCheck: false, lightFuryTick: 0,

monstersNearTarget: function (unit) {

var count, radi

  monster = getUnit(1);

count = 0;

radi = 8;

min = 3

if (monster) {

  do {

      if(Attack.checkMonster(monster)){

          if (getDistance(unit, monster) <= radi) {

              count += 1;

    if (count > min) {

      return 1;

    }

          }

      }

  } while (monster.getNext());

}

},

doAttack: function (unit, preattack) {

var needRepair = Town.needRepair();

// MILL sætter lf til baseret på antal mobs omkring

if (this.monstersNearTarget(unit)) {

  Config.AttackSkill[0] = -1; // Preattack skill.

  Config.AttackSkill[1] = 35; // Primary skill to bosses.

  Config.AttackSkill[2] = 35; // Primary untimed skill to bosses. Keep at -1 if Config.AttackSkill[1] is untimed skill.

  Config.AttackSkill[3] = 35; // Primary skill to others.

  Config.AttackSkill[4] = 35; // Primary untimed skill to others. Keep at -1 if Config.AttackSkill[3] is untimed skill.

}else{

  Config.AttackSkill[0] = -1; // Preattack skill.

  Config.AttackSkill[1] = 24; // Primary skill to bosses.

  Config.AttackSkill[2] = 24; // Primary untimed skill to bosses. Keep at -1 if Config.AttackSkill[1] is untimed skill.

  Config.AttackSkill[3] = 24; // Primary skill to others.

  Config.AttackSkill[4] = 24; // Primary untimed skill to others. Keep at -1 if Config.AttackSkill[3] is untimed skill.

}

if ((Config.MercWatch && Town.needMerc()) || needRepair.length > 0) {

  Town.visitTown(!!needRepair.length);

}

if (preattack && Config.AttackSkill[0] > 0 && Attack.checkResist(unit, Config.AttackSkill[0]) && (!me.getState(121) || !Skill.isTimed(Config.AttackSkill[0]))) {

  if (Math.round(getDistance(me, unit)) > Skill.getRange(Config.AttackSkill[0]) || checkCollision(me, unit, 0x4)) {

      if (!Attack.getIntoPosition(unit, Skill.getRange(Config.AttackSkill[0]), 0x4)) {

          return 0;

      }

  }

  Skill.cast(Config.AttackSkill[0], Skill.getHand(Config.AttackSkill[0]), unit);

  if(Config.AttackSkill[0] == 35) {

      // Light fury

      //print("MILL: Gentager lf!");

      if(!unit.dead){

          Skill.cast(Config.AttackSkill[0], Skill.getHand(Config.AttackSkill[0]), unit);

      }

      if(!unit.dead){

          Skill.cast(Config.AttackSkill[0], Skill.getHand(Config.AttackSkill[0]), unit);

      }

      if(!unit.dead){

          Skill.cast(Config.AttackSkill[0], Skill.getHand(Config.AttackSkill[0]), unit);

      }

      if(!unit.dead){

          Skill.cast(Config.AttackSkill[0], Skill.getHand(Config.AttackSkill[0]), unit);

      }

  }

  return 1;

}

var index, checkSkill, result,

  mercRevive = 0,

  timedSkill = -1,

  untimedSkill = -1;

index = ((unit.spectype & 0x7) || unit.type === 0) ? 1 : 3;

// Get timed skill

if (Attack.getCustomAttack(unit)) {

  checkSkill = Attack.getCustomAttack(unit)[0];

} else {

  checkSkill = Config.AttackSkill[index];

}

if (Attack.checkResist(unit, checkSkill)) {

  timedSkill = checkSkill;

} else if (Config.AttackSkill[5] > -1 && Attack.checkResist(unit, Config.AttackSkill[5]) && ([56, 59].indexOf(Config.AttackSkill[5]) === -1 || Attack.validSpot(unit.x, unit.y))) {

  timedSkill = Config.AttackSkill[5];

}

// Get untimed skill

if (Attack.getCustomAttack(unit)) {

  checkSkill = Attack.getCustomAttack(unit)[1];

} else {

  checkSkill = Config.AttackSkill[index + 1];

}

if (Attack.checkResist(unit, checkSkill)) {

  untimedSkill = checkSkill;

} else if (Config.AttackSkill[6] > -1 && Attack.checkResist(unit, Config.AttackSkill[6]) && ([56, 59].indexOf(Config.AttackSkill[6]) === -1 || Attack.validSpot(unit.x, unit.y))) {

  untimedSkill = Config.AttackSkill[6];

}

// Low mana timed skill

if (Config.LowManaSkill[0] > -1 && Skill.getManaCost(timedSkill) > me.mp && Attack.checkResist(unit, Config.LowManaSkill[0])) {

  timedSkill = Config.LowManaSkill[0];

}

// Low mana untimed skill

if (Config.LowManaSkill[1] > -1 && Skill.getManaCost(untimedSkill) > me.mp && Attack.checkResist(unit, Config.LowManaSkill[1])) {

  untimedSkill = Config.LowManaSkill[1];

}

result = this.doCast(unit, timedSkill, untimedSkill);

if (result === 2 && Config.TeleStomp && Attack.checkResist(unit, "physical") && !!me.getMerc()) {

  while (Attack.checkMonster(unit)) {

      if (Town.needMerc()) {

          if (Config.MercWatch && mercRevive++ < 1) {

              Town.visitTown();

          } else {

              return 2;

          }

      }

      if (getDistance(me, unit) > 3) {

          Pather.moveToUnit(unit);

      }

      this.doCast(unit, Config.AttackSkill[1], Config.AttackSkill[2]);

  }

  return 1;

}

return result;

},

afterAttack: function () {

var needRepair;

Misc.unShift();

Precast.doPrecast(false);

needRepair = Town.needRepair();

if (needRepair && needRepair.length > 0) { // Repair check, mainly to restock arrows

  Town.visitTown(true);

}

this.lightFuryTick = 0;

},

// Returns: 0 - fail, 1 - success, 2 - no valid attack skills

doCast: function (unit, timedSkill, untimedSkill) {

var i, walk;

// No valid skills can be found

if (timedSkill < 0 && untimedSkill < 0) {

  return 2;

}

// Arrow/bolt check

if (this.bowCheck) {

  switch (this.bowCheck) {

  case "bow":

      if (!me.getItem("aqv", 1)) {

          Town.visitTown();

      }

      break;

  case "crossbow":

      if (!me.getItem("cqv", 1)) {

          Town.visitTown();

      }

      break;

  }

}

if (timedSkill > -1 && (!me.getState(121) || !Skill.isTimed(timedSkill))) {

  switch (timedSkill) {

  case 35:

      if (!this.lightFuryTick || getTickCount() - this.lightFuryTick > Config.LightningFuryDelay * 1000) {

          if (Math.round(getDistance(me, unit)) > Skill.getRange(timedSkill) || checkCollision(me, unit, 0x4)) {

              if (!Attack.getIntoPosition(unit, Skill.getRange(timedSkill), 0x4)) {

                  return 0;

              }

          }

          if (!unit.dead && Skill.cast(timedSkill, Skill.getHand(timedSkill), unit)) {

              this.lightFuryTick = getTickCount();

          }

          return 1;

      }

      break;

  default:

      if (Skill.getRange(timedSkill) < 4 && !Attack.validSpot(unit.x, unit.y)) {

          return 0;

      }

      if (Math.round(getDistance(me, unit)) > Skill.getRange(timedSkill) || checkCollision(me, unit, 0x4)) {

          // Allow short-distance walking for melee skills

          walk = Skill.getRange(timedSkill) < 4 && getDistance(me, unit) < 10 && !checkCollision(me, unit, 0x1);

          if (!Attack.getIntoPosition(unit, Skill.getRange(timedSkill), 0x4, walk)) {

              return 0;

          }

      }

      if (!unit.dead) {

          Skill.cast(timedSkill, Skill.getHand(timedSkill), unit);

      }

      return 1;

  }

}

if (untimedSkill > -1) {

  if (Skill.getRange(untimedSkill) < 4 && !Attack.validSpot(unit.x, unit.y)) {

      return 0;

  }

  if (Math.round(getDistance(me, unit)) > Skill.getRange(untimedSkill) || checkCollision(me, unit, 0x4)) {

      // Allow short-distance walking for melee skills

      walk = Skill.getRange(untimedSkill) < 4 && getDistance(me, unit) < 10 && !checkCollision(me, unit, 0x1);

      if (!Attack.getIntoPosition(unit, Skill.getRange(untimedSkill), 0x4, walk)) {

          return 0;

      }

  }

  if (!unit.dead) {

      Skill.cast(untimedSkill, Skill.getHand(untimedSkill), unit);

  }

  return 1;

}

for (i = 0; i < 25; i += 1) {

  if (!me.getState(121)) {

      break;

  }

  delay(40);

}

// Wait for Lightning Fury timeout

while (this.lightFuryTick && getTickCount() - this.lightFuryTick < Config.LightningFuryDelay * 1000) {

  delay(40);

}

return 1;

}

}; `

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/kolton/d2bot-with-kolbot/issues/1002#issuecomment-873651390, or unsubscribe https://github.com/notifications/unsubscribe-auth/AUS6HD63OPP6SL4NKZS3Z23TWC363ANCNFSM4GPSVRQQ .

ciompek commented 3 years ago

not doing cows to be honest :) shes doing cs & baal in a party. Whole run ~3,5 minute with 8 players

dakky221 commented 3 years ago

I'm getting error on that last edit of amazon.js from ciompek.. it says something about line 11, that anonymous function doesn't always return something and then whole game it keeps saying it cant afford repairs :D but shoots bolts and is fury :D

dakky221 commented 3 years ago

Ok guys I got it working without errors by just changing that

var count = 0, radi = 8, min = 3, monster = getUnit(1);

on the top, but: - when using Enigma, Java still teleports in the middle of the cow pack. While setting NoTele to true, it works slightly better, but still runs to the middle of the pack. Sometimes get them killed, sometimes chickens.

Is there a way to prevent running/tele to the middle of the pack? Looks to me sometimes the counting is wrong, ie. she goes to CS one cow while 2 yards away is the whole pack. She stabs that one while the whole pack approaches. Sometimes switches to LF, sometimes tries to run but again towards the middle of them.

master7720 commented 3 years ago

Mexxtexer that's fucking great bro

flippyfloppyflappy commented 3 years ago

Everyone say farewell to the coolest bot in d2. May we all get rich enough to afford her again in d2r in 2.5 weeks!

On Thu, Aug 5, 2021 at 12:15 PM PreparedSystem_32 @.***> wrote:

Anyone know why when I tele to a boss like andy or meph, upon arriving to them it instantly says in red letters "failed to kill" then it starts the next area?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/kolton/d2bot-with-kolbot/issues/1002#issuecomment-893678133, or unsubscribe https://github.com/notifications/unsubscribe-auth/AUS6HDZK5MXU467BJKUBKDDT3LIKJANCNFSM4GPSVRQQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&utm_campaign=notification-email .

shozkki commented 3 years ago

Just wanted to thank Mexxtexer for the excellent monster counting function. I adapted it to use on my lightning sorc as well to determine when to use chain lightning. Also, instead of adding the if else statement changing your whole attack config you can just go down to (line 35 in my amazon.js file) where you see the line:

index = ((unit.spectype & 0x7) || unit.type === 0) ? 1 : 3;

Then you can just add the if/else statement like so:

if (this.monstersNearTarget(unit, 12) > 4) {
    index = unit.type === 0 ? 1 : 3
}else {
    index = 1
}

Assuming you have Config.AttackSkill[1] set to CS and Config.AttackSkill[3] set to LF, this will tell the zon to use fury on regular mobs when there are more than 4 within 12y, and CS on stragglers and bosses. I was actually toying with the idea of setting AttackSkill[4] to lightning strike and having it use CS for < 4 monsters, lightning strike for 4-8 monsters and fury for > 8 or something like that. I may code that in the next couple days and see how it works

hey. anyone else got this working on a lightsorc with chain lightning?

Terredar1 commented 3 years ago

Just wanted to thank Mexxtexer for the excellent monster counting function. I adapted it to use on my lightning sorc as well to determine when to use chain lightning. Also, instead of adding the if else statement changing your whole attack config you can just go down to (line 35 in my amazon.js file) where you see the line:

index = ((unit.spectype & 0x7) || unit.type === 0) ? 1 : 3;

Then you can just add the if/else statement like so:

if (this.monstersNearTarget(unit, 12) > 4) {
    index = unit.type === 0 ? 1 : 3
}else {
    index = 1
}

Assuming you have Config.AttackSkill[1] set to CS and Config.AttackSkill[3] set to LF, this will tell the zon to use fury on regular mobs when there are more than 4 within 12y, and CS on stragglers and bosses. I was actually toying with the idea of setting AttackSkill[4] to lightning strike and having it use CS for < 4 monsters, lightning strike for 4-8 monsters and fury for > 8 or something like that. I may code that in the next couple days and see how it works

hey. anyone else got this working on a lightsorc with chain lightning?

Yes I just did it and it worked, I used the one from Mexxtexer and not the one from ciompek

/**
*   @filename   Sorceress.js
*   @author     kolton
*   @desc       Sorceress attack sequence
*   based on the javazon edit by Mexxtexer
*/

var ClassAttack = {

    monstersNearTarget: function (unit, radi) {

        var count, 
            monster = getUnit(1);

        count = 0;

        if (monster) {

            do {
                if(Attack.checkMonster(monster)){
                    if (getDistance(unit, monster) <= radi) {
                        count += 1;
                    }
                }

            } while (monster.getNext());
        }   

        //print("MILL: Der er "+count+" mobs indenfor "+radi+" enheder!");

        return count;

    },

    doAttack: function (unit, preattack) {
        if (this.monstersNearTarget(unit, 12) > 4) {
            Config.AttackSkill[0] = -1; // Preattack skill.
            Config.AttackSkill[1] = 53; // Primary skill to bosses.
            Config.AttackSkill[2] = 53; // Primary untimed skill to bosses. Keep at -1 if Config.AttackSkill[1] is untimed skill.
            Config.AttackSkill[3] = 53; // Primary skill to others.
            Config.AttackSkill[4] = 53; // Primary untimed skill to others. Keep at -1 if Config.AttackSkill[3] is untimed skill.
        }else{
            Config.AttackSkill[0] = -1; // Preattack skill.
            Config.AttackSkill[1] = 49; // Primary skill to bosses.
            Config.AttackSkill[2] = 49; // Primary untimed skill to bosses. Keep at -1 if Config.AttackSkill[1] is untimed skill.
            Config.AttackSkill[3] = 49; // Primary skill to others.
            Config.AttackSkill[4] = 49; // Primary untimed skill to others. Keep at -1 if Config.AttackSkill[3] is untimed skill.
        }

        if (Config.MercWatch && Town.needMerc()) {
            print("mercwatch");
            Town.visitTown();
        }

        if (!me.getState(30) && me.getSkill(58, 1)) {
            Skill.cast(58, 0);
        }

        if (preattack && Config.AttackSkill[0] > 0 && Attack.checkResist(unit, Config.AttackSkill[0]) && (!me.getState(121) || !Skill.isTimed(Config.AttackSkill[0]))) {
            if (Math.round(getDistance(me, unit)) > Skill.getRange(Config.AttackSkill[0]) || checkCollision(me, unit, 0x4)) {
                if (!Attack.getIntoPosition(unit, Skill.getRange(Config.AttackSkill[0]), 0x4)) {
                    return 0;
                }
            }

            Skill.cast(Config.AttackSkill[0], Skill.getHand(Config.AttackSkill[0]), unit);
            if(Config.AttackSkill[0] == 53) {
                // Charged Strike
                if(!unit.dead){
                    Skill.cast(Config.AttackSkill[0], Skill.getHand(Config.AttackSkill[0]), unit);  
                }
                if(!unit.dead){
                    Skill.cast(Config.AttackSkill[0], Skill.getHand(Config.AttackSkill[0]), unit);  
                }
                if(!unit.dead){
                    Skill.cast(Config.AttackSkill[0], Skill.getHand(Config.AttackSkill[0]), unit);  
                }
                if(!unit.dead){
                    Skill.cast(Config.AttackSkill[0], Skill.getHand(Config.AttackSkill[0]), unit);  
                }
            }
            return 1;
        }

        var index, staticRange, checkSkill, result,
            mercRevive = 0,
            timedSkill = -1,
            untimedSkill = -1;

        // Static
        if (Config.CastStatic < 100 && me.getSkill(42, 1) && Attack.checkResist(unit, "lightning") && Config.StaticList.some(
                function (id) {
                    if (unit) {
                        switch (typeof id) {
                        case "number":
                            if (unit.classid && unit.classid === id) {
                                return 1;
                            }

                            break;
                        case "string":
                            if (unit.name && unit.name.toLowerCase() === id.toLowerCase()) {
                                return 1;
                            }

                            break;
                        default:
                            throw new Error("Bad Config.StaticList settings.");
                        }
                    }

                    return 0;
                }
            ) && Math.round(unit.hp * 100 / unit.hpmax) > Config.CastStatic) {
            staticRange = Math.floor((me.getSkill(42, 1) + 4) * 2 / 3);

            while (!me.dead && Math.round(unit.hp * 100 / unit.hpmax) > Config.CastStatic && Attack.checkMonster(unit)) {
                if (getDistance(me, unit) > staticRange || checkCollision(me, unit, 0x4)) {
                    if (!Attack.getIntoPosition(unit, staticRange, 0x4)) {
                        return 0;
                    }
                }

                if (!Skill.cast(42, 0)) {
                    break;
                }
            }
        }

        index = ((unit.spectype & 0x7) || unit.type === 0) ? 1 : 3;

        // Get timed skill
        if (Attack.getCustomAttack(unit)) {
            checkSkill = Attack.getCustomAttack(unit)[0];
        } else {
            checkSkill = Config.AttackSkill[index];
        }

        if (Attack.checkResist(unit, checkSkill) && ([56, 59].indexOf(checkSkill) === -1 || Attack.validSpot(unit.x, unit.y))) {
            timedSkill = checkSkill;
        } else if (Config.AttackSkill[5] > -1 && Attack.checkResist(unit, Config.AttackSkill[5]) && ([56, 59].indexOf(Config.AttackSkill[5]) === -1 || Attack.validSpot(unit.x, unit.y))) {
            timedSkill = Config.AttackSkill[5];
        }

        // Get untimed skill
        if (Attack.getCustomAttack(unit)) {
            checkSkill = Attack.getCustomAttack(unit)[1];
        } else {
            checkSkill = Config.AttackSkill[index + 1];
        }

        if (Attack.checkResist(unit, checkSkill) && ([56, 59].indexOf(checkSkill) === -1 || Attack.validSpot(unit.x, unit.y))) {
            untimedSkill = checkSkill;
        } else if (Config.AttackSkill[6] > -1 && Attack.checkResist(unit, Config.AttackSkill[6]) && ([56, 59].indexOf(Config.AttackSkill[6]) === -1 || Attack.validSpot(unit.x, unit.y))) {
            untimedSkill = Config.AttackSkill[6];
        }

        // Low mana timed skill
        if (Config.LowManaSkill[0] > -1 && Skill.getManaCost(timedSkill) > me.mp && Attack.checkResist(unit, Config.LowManaSkill[0])) {
            timedSkill = Config.LowManaSkill[0];
        }

        // Low mana untimed skill
        if (Config.LowManaSkill[1] > -1 && Skill.getManaCost(untimedSkill) > me.mp && Attack.checkResist(unit, Config.LowManaSkill[1])) {
            untimedSkill = Config.LowManaSkill[1];
        }

        result = this.doCast(unit, timedSkill, untimedSkill);

        if (result === 2 && Config.TeleStomp && Attack.checkResist(unit, "physical") && !!me.getMerc() && Attack.validSpot(unit.x, unit.y)) {
            while (Attack.checkMonster(unit)) {
                if (Town.needMerc()) {
                    if (Config.MercWatch && mercRevive++ < 1) {
                        Town.visitTown();
                    } else {
                        return 2;
                    }
                }

                if (getDistance(me, unit) > 3) {
                    Pather.moveToUnit(unit);
                }

                this.doCast(unit, Config.AttackSkill[1], Config.AttackSkill[2]);
            }

            return 1;
        }

        return result;
    },

    afterAttack: function () {
        Precast.doPrecast(false);
    },

    // Returns: 0 - fail, 1 - success, 2 - no valid attack skills
    doCast: function (unit, timedSkill, untimedSkill) {
        var i, walk;

        // No valid skills can be found
        if (timedSkill < 0 && untimedSkill < 0) {
            return 2;
        }

        if (timedSkill > -1 && (!me.getState(121) || !Skill.isTimed(timedSkill))) {
            if (Skill.getRange(timedSkill) < 4 && !Attack.validSpot(unit.x, unit.y)) {
                return 0;
            }

            if (Math.round(getDistance(me, unit)) > Skill.getRange(timedSkill) || checkCollision(me, unit, 0x4)) {
                // Allow short-distance walking for melee skills
                walk = Skill.getRange(timedSkill) < 4 && getDistance(me, unit) < 10 && !checkCollision(me, unit, 0x1);

                if (!Attack.getIntoPosition(unit, Skill.getRange(timedSkill), 0x4, walk)) {
                    return 0;
                }
            }

            if (!unit.dead && !checkCollision(me, unit, 0x4)) {
                Skill.cast(timedSkill, Skill.getHand(timedSkill), unit);
            }

            return 1;
        }

        if (untimedSkill > -1) {
            if (Skill.getRange(untimedSkill) < 4 && !Attack.validSpot(unit.x, unit.y)) {
                return 0;
            }

            if (Math.round(getDistance(me, unit)) > Skill.getRange(untimedSkill) || checkCollision(me, unit, 0x4)) {
                // Allow short-distance walking for melee skills
                walk = Skill.getRange(untimedSkill) < 4 && getDistance(me, unit) < 10 && !checkCollision(me, unit, 0x1);

                if (!Attack.getIntoPosition(unit, Skill.getRange(untimedSkill), 0x4, walk)) {
                    return 0;
                }
            }

            if (!unit.dead) {
                Skill.cast(untimedSkill, Skill.getHand(untimedSkill), unit);
            }

            return 1;
        }

        for (i = 0; i < 25; i += 1) {
            if (!me.getState(121)) {
                break;
            }

            delay(40);
        }

        return 1;
    }
};
ilykere commented 2 years ago

image

I tried your code @ciompek . I copy/paste it to libs\common\Attacks\Amazon.js but it wont work as error shows above.