You are not logged in.

Applications: [GameMaster: OPEN] | [Volunteer Testers: OPEN]


This forum will be permanently shut down on Friday 13.07.2018
Please copy or save all important information from old forum before they will be deactivated
We have moved to new board. https://forum.runesofmagic.gameforge.com/Come join us.

1,541

Friday, July 1st 2011, 12:18am

Rogue/Druid????

Does anyone have a really nice combat engine for a Rogue/Druid?

Also if I am using this combat engine on a warrior that requires rage how do I set it up so that if a skill isn't available because of rage or whatever it skips that skill and goes to the next one? I like to use surprise attack on my warrior but for some reason the stupid skill gets stuck in red every once in a while and if it doesn't work it screws up the whole engine it won't go past that skill.

hangman04

Savage Warrior

Posts: 113

Location: Romania

Mood: Smile

  • Send private message

1,542

Friday, July 1st 2011, 10:41am

@Drake.
I know it's a filler skill. During Combo Shot cast none of the skills can interrupt it. But you can activate AS manually. DIYCE can't do that apparently. But it works great with AS second skill right after CS.
The interesting part is that in HoS i never had the chance of using wind arrow and shot :)). My mana pool hardly decreases and Disarmament is last skill used in the combo :P.

Drake1132

Beginner

Posts: 11

Location: Wait a minute... you mean I'm *not* a figment of your imagination?

  • Send private message

1,543

Friday, July 1st 2011, 11:56am

@effervescent:

I see a number of problems with your code...

First, you are making checks for energy, but the variable energy hasn't been defined. Instead, you have variables for focus and mana, but the way they are currently being used in your code, focus will actually track Energy for your Rogue and mana will track Focus for your Scout. So you'll need to fix that.

Second, you have several lines that have too many or too few parentheses. When you open a parenthesis "(", you have to close it again ")". So, for example, your line for premeditation opens a parenthesis 4 times, but only closes 3 of them, so you need to either delete the first opening one (which isn't necessary anyway), or close it by adding a new closing one at the end, just before the squiggly brace "}". You'll need to check and correct this same sort of problem for Vampire Arrows, Shadowstab, and your second instance of Low Blow (although you can skip the last one because of the next problem).

Lastly, you don't need the second instance of Low Blow. You are not listing skills in the specific order in which they will be used, you are providing a list of priorities that DIYCE will use to choose a skill for you. Every time you run your macro, DIYCE will start at the top of that list and will use the first skill it comes to whose use conditions evaluate to true. This is explained, quite specifically and explicitly, in detail, in the very first post of this thread... the post where the author explains what DIYCE is and a bit about how to use it. I hope that doesn't sound too harsh, I don't mean it to be taken personally, it's just that I've mentioned this same information a lot in the last few weeks and I'm getting frustrated. Anyway, because of this fact, your second line for Low Blow is unnecessary, because you already have it listed, with the exact same conditions, at a higher priority.

Anyway, try those fixes and see if it works.


@ItIsFinished22:

That code in the post you linked is more efficient from a programming stand point. It simply doesn't process certain functions more times than it needs to, like IsReady (what used to be the CD function) and ProcessAction (what used to be the MyCombat function), nor does it process more use conditions than it needs to. Because of the way it works, it also offers more flexibility for someone who knows what they're doing and can write custom Lua code to use within it. But an end user probably wouldn't notice any difference, because the speed improvement is one of mere fractions of a second. And if you look at that code, you'll notice that it also uses the cd == 0.4 tweak.

Also, it isn't *my* engine, not really. The original ideas for the code optimization came from Sixpax and Magual. I added in I think one additional idea, and I actually modified the code I had from DIYCE 1.4 into the code you see there, but it really is just my implementation of Sixpax and Magual's ideas.

If you choose to use that code, please note that some of the local variables I have in my class function template/example code only work with other code tweaks, which I did not include in that post, such as the calls to the DeBuffList function (which basically is a copy of the BuffList function, but with different check parameters to make things more intuitive for me). That means that if you choose to use the new methodology, you'll need to be careful about your class functions... you can't just copy and paste my template/example and have it work "out of the box", so to speak, so keep that in mind.


@GunnyDuke:

Like effervescent, your code has numerous problems.

First, your line for tbuffs needs to be fixed. It should call BuffList("target"), not BuffList("player").

Second, your line for Blind Spot checks "and (arg2 == "behind")" twice, and you only need it once. Also, since it checks for arg2 vs. a string value, you need to make sure that you pass a string for arg2 to the function when you call it in your macro.

Third, your line for Wound Attack has some odd parentheses issues, which is interesting, since your others are all just fine in that respect, and it is also missing a quotation mark. It should be as follows...

Source code

1
i=i+1; Skill[i] = { name = "Wound Attack", use = ((not friendly) and (energy >= 35) and not string.find(tbuffs, "Bleed") and string.find(tbuffs, "Grievous Wound")) }
Lastly, you need to remove "end" from the line between the line for Attack and the one for MyCombat.

Try those changes.


Drake

1,544

Friday, July 1st 2011, 1:36pm

ok...heres the changes i've made, but still getting an error message. sorry for being such a noob. Please help


function RogueKnight(arg1,arg2)

local Skill = {}
local i = 0
local energy = UnitMana("player")
local mana = UnitSkill("player")
local friendly = (notUnitCanAttack("player", "target")
local combat = GetPlayerCombatState()
local tspell,ttime,telapsed = UnitCastingTime("target")
local pbuffs = BuffList("player")
local tbuffs = BuffList("target")
local tDead = UnitIsDeadOrGhost ()
local LockedOn = UnitExists("target")

i=i+1; Skill = { name = "Blind Spot", use = ((not friendly) and (energy >= 25) and (arg2 == "behind") and (not string.find(tbuffs, "Bleed"))) }
i=i+1; Skill[i] = { name = "Shadowstab", use = ((not friendly) and (energy >= 35) and (not string.find(tbuffs, "Bleed"))) }
i=i+1; Skill[i] = { name = "Wound Attack", use = ((not friendly) and (energy >= 35) and not string.find(tbuffs, "Bleed") and string.find(tbuffs, "Grievous Wound")) }
i=i+1; Skill[i] = { name = "Low Blow", use = ((not friendly) and (energy >= 35) and string.find(tbuffs, "Bleed") and (not string.find(tbuffs, "Grievous Wound"))) }
i=i+1; Skill[i] = { name = "Disarmament", use = ((not friendly) and (mana >= 200) and (not string.find(tbuffs, "Disarmament I"))) }
i=i+1; Skill[i] = { name = "Shadowstab", use = ((not friendly) and (energy >= 35) and (not string.find(tbuffs, "Bleed"))) }
i=i+1; Skill[i] = { name = "Attack", use = (not friendly) }
 
MyCombat(Skill,arg1,arg2)

if (tDead) or (not LockedOn) or (not enemy) then
TargetNearestEnemy()

end

1,545

Friday, July 1st 2011, 7:22pm

Okay, I think I fixed the energy/focus check issue, and the parentheses...but it still isn't working :s. Weird thing is, the S/W function I had working perfectly the day before yesterday now isn't working...and I haven't done anything to it.

Anyway, maybe you can see if there's still something wrong with the code. I really don't understand much of this, so forgive me if I misunderstood something.

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function RogueScout(arg1)
    local Skill = {}
    local i = 0
    local combat = GetPlayerCombatState()
    local enemy = UnitCanAttack("player","target")
    local energy = UnitMana("player")
    local focus = UnitSkill("player")
    local tbuffs = BuffList("target")
    local pbuffs = BuffList("player")
    local front = UnitIsUnit("player", "targettarget")
    local tDead = UnitIsDeadOrGhost("target")
    local melee = GetActionUsable(3)
    local phealth = PctH("player")
    local thealth = PctH("target")
    local LockedOn = UnitExists("target")
    local ammo = (GetEquipSlotInfo(10) ~= nil)


    i=i+1; Skill[i] = { name = "Premeditation",  use = (not combat) and (not string.find(pbuffs,"Premeditation"))}
    i=i+1; Skill[i] = { name = "Vampire Arrows",       use = (enemy) and (focus >=20) }
    i=i+1; Skill[i] = { name = "Shadow Step",          use = (not front) and (enemy) and (not melee) }
    i=i+1; Skill[i] = { name = "Wound Attack",         use = (enemy) and (energy >=35) and string.find(tbuffs,"Bleed") and string.find(tbuffs,"Grievous Wound")}
    i=i+1; Skill[i] = { name = "Low Blow",             use = (enemy) and (energy >=30) and string.find(tbuffs,"Bleed") }
    i=i+1; Skill[i] = { name = "Shadowstab",           use = (enemy) and (energy >=20) and (not string.find(tbuffs,"Bleed"))  }
    i=i+1; Skill[i] = { name = "Shot"                  use = enemy }

 MyCombat(Skill,arg1)
end

Formerly Catorii, D/S/M of Faction.


Posts: 86

Location: Dominating in 3vs3, 6vs6 and siege.

Occupation: Network Administrator for a local NBC T.V. station.

  • Send private message

1,546

Friday, July 1st 2011, 7:30pm

I think you need a comma after "Shot" so it should look like this:

Source code

1
i=i+1; Skill[i] = { name = "Shot",                  use = enemy }

Drake1132

Beginner

Posts: 11

Location: Wait a minute... you mean I'm *not* a figment of your imagination?

  • Send private message

1,547

Saturday, July 2nd 2011, 2:09am

@GunnyDuke:

Your line for local friendly needs a space between "not" and "UnitCanAttack", otherwise the system will think that you are trying to run a function, "notUnitCanAttack", rather than get the opposite of the value returned by the function "UnitCanAttack". You also need an additional closing parenthesis at the end of that same line. Lua is very picky about such things, and a single incorrect, missing, or extra character can break your function. You *must* pay very close attention to detail (and even then you will probably miss something from time to time, as we all seem to).

Those are the only problems I see. But if you are getting an error message, then that error message should tell you exactly what the problem is, or at least what the first problem is (if you have more than one). It should tell the file name and line number where the problem exists, as well as at least some limited information about why there is a problem there, such as: ")" expected... (which would indicate a parenthesis problem somewhere on the given line), or call to function "notUnitCanAttack", a nil value (which would indicate that you have tried to make a call to a function, "norUnitCanAttack", that does not exist, and therefore cannot be called). If you learn to use the in-game error reporting system, then you will not need to post problems here, and wait for answers, quite as often. Learn to understand what the errors are telling you, so that you can use that information to fix issues right away, rather than having to wait for someone to help you.

Also, please get in the habit of surrounding your posted code segments in CODE tags. You can do this in either one of three possible ways. First, enter "

Source code

1
" before the segment and "
" after the segment, except using all CAPS instead of lower case letters for "code" (CODE, vs. code). My example uses lower case letters so that the forum system will not actually create code tags, but just simulate them. The second way is to click on the pound sign ("#") in the message editor toolbar (lower toolbar, toward the right-hand side). This will automatically create the code tags for you and all you have to do is place your cursor in between the two tags and paste your code at that cursor location. The third method would be to post the code segments first, then select the posted code (and only the posted code), and then click on the pound sign icon in the toolbar. This will automatically create the "

Source code

1
" tag at the beginning of the selection, and will also automatically create the "
" tag at the end of the selection, thus wrapping the code segments inside of the code tags. The result should look something like what effervescent posted.

The main reason for asking you to enclose code segments inside CODE tags is that it makes it easier to read, which in turn makes it easier to spot errors, and therefore makes it easier for us to help you.


@effervescent:

ItIsFinished22 is quite correct, you should have a comma after "Shot". I'm sorry I missed that when you first posted the code yesterday.

Also, while they aren't a problem, and won't break your function, you do not need the parentheses around "enemy" that you are using. For example, in your line for Vampire Arrows, you could use "enemy and (focus >= 20)" rather than your current "(enemy) and (focus >= 20)". Basically, the parentheses are used for function calls or to create grouping.

Grouping isn't always necessary unless you are trying to perform an operation on something. For example, focus >= 20 performs an operation which would then return a value of either true or false, so it needs to be enclosed in parentheses as (focus >= 20) or it will throw an error and break your function. Similarly, "not enemy" performs on operation on the value of enemy, reversing that value, and returning the reversed value, so that also would need to be enclosed as (not enemy).

For functions, the parentheses after the function name are always necessary. For example, with string.find, technically, string.find() is a function that is internal to the Lua string library. Because it is a function, it has to have parentheses at the end of the function name when you make a call to that function, and inside of those parentheses you pass the parameters, or arguments (a.k.a. args), that the function needs in order to work, namely in this case, the string to be searched and the substring to search for. Because of this, string.find(String, "substring") requires parentheses and parameters in order to work correctly, but otherwise does not need to be enclosed in parentheses entirely, such as "(string.find(String, "sunstring"))".

You can also use parenthesis grouping to create more complex conditionals, such as ((condition1 and condition2) or (condition3 and condition4)). That would return true if either both condition1 and condition2 are true, or if both condition3 and condition4 are true. So in that example, if condition1 is false, but the other three are all true, then the full group would return true, because both 3 and 4 are true. You could also use grouping to create negations of combinations, such as (not (condition1 and condition2)). If one of those conditions is true, but the other is not, or if neither are, then the conditions group will return false, and the not attachment will turn it into true and return a value of true, but if both conditions are true, then the conditions group will return true, and not will convert true into false and return false.

I hope I'm not confusing you with all of those examples. I just want you to understand the way the parentheses work. Basically, for your use conditions, you are defining a series of logical boolean operations, the combination of which will return a final result of either true or false, and that final result will be stored in the variable "Skill.use" for the current skill line.


Drake

1,548

Saturday, July 2nd 2011, 2:11am

Distance?

Is there a way to check for distance from the target? Such as using Surprise Attack on my warrior is there a way for me to check the distance and if the mob is too close then skip that skill and go to the next one?

Drake1132

Beginner

Posts: 11

Location: Wait a minute... you mean I'm *not* a figment of your imagination?

  • Send private message

1,549

Saturday, July 2nd 2011, 9:22am

Quoted from "MidgetSlap;438083"

Is there a way to check for distance from the target? Such as using Surprise Attack on my warrior is there a way for me to check the distance and if the mob is too close then skip that skill and go to the next one?



Sort of... There used to be a function, UnitDistance(), but it has been removed and cannot be used anymore, at least not by us (although the game client and server can both still make range checks internally). Right now, the closest thing we can do to making distance checks is to rely on GetActionUsable(), which has it's limitations. The reason we can do this is that even though we are no longer allowed to envoke direct range checks, skills still make range checks internally, and if a skill is out of range, it is made unavailable for use.

For example, if you want to know if you are within melee range, then you can place a spammable melee range skill, such as Joint Blow, or Shadowstab, or Power of the Wood Spirit, etc. onto an actionbar slot, say slot 31 for example. You can then set a local variable: "local inMeleeRange = GetActionUsable(31)". After that point, you can make checks against that variable... using inMeleeRange would indicate that your target is within the 50 unit range of such a skill, while (not inMeleeRange) would indicate that your target is farther away than that. If you have other skills with different ranges, you could check against such skills to make more complex checks as well, such as "closer than skill1, but further out than skill2". In that particular example you would have, say two variables, inSkill1Range and inSkill2Range, and the check would be: (inSkill1Range and (not inSkill2Range)).

The problem with doing it in this way is that GetActionUsable() will return false for reasons other than the target being out of range, such as if the skill is on cooldown (which is why you want to try and rely on spammable skills when possible), or because you do not have enough mana/rage/energy/focus to use the skill, or if you are under the effects of GCD. Under most circumstances, if you use a spammable skill, the other possibilities will be infrequent enough to not be a major issue, but the limitations are important to keep in mind. One other potentially significant limitation is that you must use skills that your character already knows, and this can sometimes cause its own limitations if you do not know a skill with the particular range you are interested in checking. For example, a Mage/Priest does not get any melee range skills, and therefore can never make a melee range check in this manner.

Now I've never played as a Warrior, so I'm not sure, but I believe that Surprise Attack will be unavailable for use when you are more than 150 in-game distance units away from your target, but that it is also made unavailable if your target is closer than the 60 unit minimum distance. If that is, in fact, the way the skill works, then all you would need to do is place Surprise Attack on an actionbar slot for which you know the slot number, then in your use conditions for the "Surprise Attack" skill line, include GetAtctionUsable(slot#) as one of the conditions. That way DIYCE will only ever attempt to use Surprise Attack if its associated actionbar slot indicates that it is usable.

Drake

1,550

Saturday, July 2nd 2011, 6:59pm

Quoted from "Drake1132;438213"

Sort of... There used to be a function, UnitDistance(), but it has been removed and cannot be used anymore, at least not by us (although the game client and server can both still make range checks internally). Right now, the closest thing we can do to making distance checks is to rely on GetActionUsable(), which has it's limitations. The reason we can do this is that even though we are no longer allowed to envoke direct range checks, skills still make range checks internally, and if a skill is out of range, it is made unavailable for use.

For example, if you want to know if you are within melee range, then you can place a spammable melee range skill, such as Joint Blow, or Shadowstab, or Power of the Wood Spirit, etc. onto an actionbar slot, say slot 31 for example. You can then set a local variable: "local inMeleeRange = GetActionUsable(31)". After that point, you can make checks against that variable... using inMeleeRange would indicate that your target is within the 50 unit range of such a skill, while (not inMeleeRange) would indicate that your target is farther away than that. If you have other skills with different ranges, you could check against such skills to make more complex checks as well, such as "closer than skill1, but further out than skill2". In that particular example you would have, say two variables, inSkill1Range and inSkill2Range, and the check would be: (inSkill1Range and (not inSkill2Range)).

The problem with doing it in this way is that GetActionUsable() will return false for reasons other than the target being out of range, such as if the skill is on cooldown (which is why you want to try and rely on spammable skills when possible), or because you do not have enough mana/rage/energy/focus to use the skill, or if you are under the effects of GCD. Under most circumstances, if you use a spammable skill, the other possibilities will be infrequent enough to not be a major issue, but the limitations are important to keep in mind. One other potentially significant limitation is that you must use skills that your character already knows, and this can sometimes cause its own limitations if you do not know a skill with the particular range you are interested in checking. For example, a Mage/Priest does not get any melee range skills, and therefore can never make a melee range check in this manner.

Now I've never played as a Warrior, so I'm not sure, but I believe that Surprise Attack will be unavailable for use when you are more than 150 in-game distance units away from your target, but that it is also made unavailable if your target is closer than the 60 unit minimum distance. If that is, in fact, the way the skill works, then all you would need to do is place Surprise Attack on an actionbar slot for which you know the slot number, then in your use conditions for the "Surprise Attack" skill line, include GetAtctionUsable(slot#) as one of the conditions. That way DIYCE will only ever attempt to use Surprise Attack if its associated actionbar slot indicates that it is usable.

Drake


Is there a list of for GetActionUsable where I know what numbers go on which bar? I use bottom bar and right side bar. I normally just put all my skills from 0-9 and I believe surprise attack is #1 slot so that would be set as GetActionUsable(1)? or if it's on #7 then GetActionUsable(7)?

All I really needed it to do is check if the target is too close. If it's too close then skip the skill. If it's too far my toon will just take off running when I click the skill till it's in range where it then uses the skill. So being too far is not a problem. I just need it to not use the skill if it's too close. If I'm too close to use the skill it screws up my whole engine. If it doesn't do that skill then it won't skip to the next skill. I then have to attack the target manually. I see it causing major problems later and ending up getting me killed if I couldn't find a solution but this one looks like a good one. Because it shows red when I'm too close so the skill is not available. Can you add it in here and show me where it needs to be located? I'm not very good with all this coding.

Might want to check and see if my coding is even good I took parts of many different ones and put them into one. Adjusting the skills around trying to find the best ones in order. I would love it to use a global and just skip a skill if it's already being used so it doesn't use the same skill twice that would be nice but I have yet to figure out the global variable thing so I took it out.

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function WarriorRogue(arg1)
    local Skill = {}
    local i = 0
    local friendly = (not UnitCanAttack("player", "target"))
    local rage = UnitMana("player")
    local energy = UnitSkill("player")
    local combat = GetPlayerCombatState()
    local tbuffs = BuffList("target")

    i=i+1; Skill[i] = { ['name'] = "Survival Instinct",  ['use'] = (PctH("player") < .25) }
    i=i+1; Skill[i] = { ['name'] = "Enraged",            ['use'] = (rage < 50) }
    i=i+1; Skill[i] = { ['name'] = "Surprise Attack",    ['use'] = (not friendly) }
    i=i+1; Skill[i] = { ['name'] = "Probing Attack",     ['use'] = ((not friendly) and (rage >= 20)) }
    i=i+1; Skill[i] = { ['name'] = "Blood Dance",        ['use'] = ((not friendly) and (PctH("player") >= 0.8)) }
    i=i+1; Skill[i] = { ['name'] = "Splitting Chop",     ['use'] = ((not friendly) and (rage >= 15) and (string.find(tbuffs,"Weakened"))) }
    i=i+1; Skill[i] = { ['name'] = "Open Flank",         ['use'] = ((not friendly) and (rage >= 10) and (string.find(tbuffs,"Vulnerable")) and CD("Splitting Chop")) }
    i=i+1; Skill[i] = { ['name'] = "Shadowstab",         ['use'] = (not friendly) }
    i=i+1; Skill[i] = { ['name'] = "Keen Attack",        ['use'] = ((not friendly) and (energy >= 20) and (string.find(tbuffs,"Vulnerable"))) }
    i=i+1; Skill[i] = { ['name'] = "Thunder",              ['use'] = ((not friendly) and (rage >= 15)) }
    i=i+1; Skill[i] = { ['name'] = "Slash",              ['use'] = ((not friendly) and (rage >= 40)) }

    MyCombat(Skill,arg1)
end


I really need to add some more buffs in such as Barserk, Frenzed Attack, and Aggressiveness but I am not sure how to set those up at the beginning of the code. I haven't been through every page of this forum yet to see if there are any warrior/rogue engines anyone has put together. There may be content for what I am looking for but I have yet to have time to go through all the pages yet and the search engine on the forums is not helpful as far as I have seen. Eventually I want to set it up to check if a target is a boss and do different attacks and buffs then when it's a normal target. Just trying to get one thing done at a time and make it better as I go along.

Peryl

Intermediate

Posts: 313

Location: Elsewhere

  • Send private message

1,551

Saturday, July 2nd 2011, 8:48pm

Action bars have the following numbers:

Main Action Bar: 1-20
Upper Bar: 21-40
Right Bar: 41-60
Left Bar: 61-80

Numbers go from left to right, top to bottom.
2013... The year from hell....

Drake1132

Beginner

Posts: 11

Location: Wait a minute... you mean I'm *not* a figment of your imagination?

  • Send private message

1,552

Saturday, July 2nd 2011, 10:35pm

@MidgetSlap:

OK, Peryl already gave you the actionbar slot id numbers (above). Those id numbers are used for any function that requires an actionbar slot number for an argument, such as GetActionInfo() and others, including GetActionUsable().

Now then, since you want to be able to use Surprise Attack even if you are too far away, but not use it if you are too close, you'll need to make a more complex range check. The best way to do this would be to check GetActionUsable for Surprise Attack and for another skill with a range of 150. Unfortunately, I don't think you get any other skills as a Warrior/Rogue that have such a range. So the closest I can suggest is this... If Surprise Attack is not usable, and Shadow Step is also not usable, then you theoretically are more than 150 away from the target (unless either skill is on cooldown or Shadow Step has insufficient Energy). If you were closer than 150, but further than the 100 max range for Shadow Step, then Shadow Step would not be usable, and Surprise Attack would be. On the other hand, if Shadow Step is usable, then you are at least within 100, and if Surprise Attack is not usable in such a case, then you should be within a range of 60 to your target.

To check that way, I would do the following:

Source code

1
local withinSurpriseAttackMinRange = GetActionUsable(shadowStepSlot) and (not GetActionUsable(surpriseAttackSlot))
You would need to replace "shadowStepSlot" and "surpriseAttackSlot" with the actual actionbar slot id numbers for Shadow Step and Surprise Attack respectively. You would then add the use condition to your line for Surprise Attack...

Source code

1
i=i+1; Skill[i] = { ['name'] = "Surprise Attack",    ['use'] = (not friendly) and (not withinSurpriseAttackMinRange) }
That is the closest I can think of to get you the sort of range check you are wanting. The limitations are a little more severe than with other range checks, although you can at least avoid problems with Shadow Step being unavailable due to cooldown simply by not ever using Shadow Step (Surprise Attack is the better skill anyways due to the larger range, shorter cooldown, and knockdown effect).

Another option would be to set Shadowstab on an actionbar slot, and use it to make a melee range check... "local inMeleeRange = GetActionUsable(shadowstabSlot)". You would then simply use "(not friendly) and (not inMeleeRange)" as your use conditions for Surprise Attack. This also has a limitation, because if the target is closer than range 60, but further than range 50, your rotation will still break. Personally, I think the Shadow Step check above is the better way to go, but it's up to you. Also, you could theoretically use Slash instead of Shadowstab, but that would require you to already have generated some Rage in order for the check to work, whereas Shadowstab simply requires you to not have used up all of your Energy (so it should always be available before opening combat).

Now, since you are wanting to later add in buffs, I would also recommend adding in the variable for pbuffs. This is done just like with tbuffs except that argument you pass is "player" instead of "target". So you could just add the line "local pbuffs = BuffList("player")" just below the line for tbuffs. Adding this in will alow you to make string.find checks to make sure you aren't already affected by the buff. In your particular case, since your buffs have a duration that is shorter than their cooldown, this isn't strictly necessary, as you should never be affected by the buff when it is available to be used. But it would be good practice for any other class functions you may decide to write later on.

As for adding in new lines, you just need to understand the basic structure and syntax for each individual skill line...

1. They always start with "i=i+1; Skill = { ['name'] = "
2. You then give it your skill name, enclosed in quotation marks, such as "Slash", and follow that with a comma and the declaration of your use variable. For example: ""Surprise Attack", ['use'] = "
3. You then add in your specific use conditions.
4. Lastly, you close the skill line with a closing squiggly bracket: "}"

All skill lines should follow this basic format. So let's say, for an example, that you wanted to add in Aggressiveness at the beginning of a fight, but only against Elite and Boss targets, and only after combat has already started. Your skill line would then be as follows (although you would need to add in the variable "local isBoss = (UnitSex("target") >= 2) in order to make the boss check)...

Source code

1
i=i+1; Skill[i] = { ['name'] = "Aggressiveness",     ['use'] = combat and isBoss }
You can insert such skill lines anywhere in your priority list that you want them, so, for example, you could list that line for Aggressiveness right at the very top, or just after Surprise Attack, or anywhere else that you feel is appropriate. Just remember that DIYCE *will always* try to use the *first* skill it comes to that has use conditions which evaluate to true, and every time you run your macro, DIYCE starts at the top of the list again.

Now as for your rotation itself, I can't really comment much on how good it may or may not be, because I've never played as a Warrior. Perhaps someone else can take a look at it, or perhaps you could ask about it in the Warrior forums. But as for finding other people's functions, this isn't actually that difficult to do. Go to the main Macro and Addon Crafting board, click on "Search this forum", enter a search string of "warriorrogue", and set it to return *posts* not threads. This should return a list of results, from most recent to oldest, most, if not all of which will contain a WarriorRogue class function.

You need to be cautious however, as often times those posts will be asking for help to fix a function that doesn't work, so check for that, and if that is the case, look at followup posts to see if anyone posted a fix for it before you try to use it. Also pay attention to what variables are used, as not everyone uses the same setup, and you might have to make adjustments to variable names, or to add in new variables that the other person used but you haven't included yet.

Other than that, your code looks good, from a syntax point of view. I might have missed something, but I don't see anything wrong with it. But from a functional point of view, I see a problem... Because Shadowstab is spammable and uses Energy, you should add an Energy check to your use conditions for it, so that DIYCE does not keep trying to use the skill if you have too little Energy. Also, because Shadowstab is spammable, and because you have it currently set to only check if your target is an enemy or not, you will never use any of the skills listed below it. That means that if you want to use those skills, you have to list them higher up in the priority list than any skills that could be spammed. This means that they most definitely need to be listed above Shadowstab at the least. Slash is one possible exception to this, as it is also spammable if you have enough Rage. Basically, you should compare the damage output for Shadowstab and Slash. List the most powerful one first, then the second most powerful.

Now just from looking at basic skill descriptions on runesdatabase.com (which might not be accurate), I would suggest the following skill order (not including buffs... you'll still need to figure out where you want to add in others), but this may not be as good as I think it is, so ask around to other Warrior/Rogue players...

1. Survival Instinct if HP is low
2. Enraged if Rage is low
3. Surprise Attack if not too close
4. Blind Stab if target is *not* "/Blind/"
5. Most powerful skill that causes Bleed if target is *not* yet bleeding
6. Second most powerful bleed skill if target is not yet bleeding.
7. Splitting Chop if target is Weakened and not already affected by the defense debuff
8. Thunder if target is Weakened
9. Open Flank if target is Vulnerable and is *not* Weakened (only used to Weaken)
10. Keen Attack if target is Vulnerable (spammable, slightly stronger than Open Flank)
11. Open flank if target is Vulnerable
12. Probing Attack if target is *not* Vulnerable
13. Blood Dance
14. Tactical attack if target is under a "Bleed" effect
15. Slash or Shadowstab (whichever is stronger)
16. Slash or Shadowstab (whichever is weaker)

You should also check for Energy or Rage for each skill, as appropriate. Now I could be wrong, and like I already said, you should check with other Warrior/Rogue players to verify the best rotation, but I *think* that rotation order should give you the best overall damage output. You'll debuff (Blind) and DoT (Bleed) the target first, and then use the most powerful damage skill that is available to be used at any given time (assuming I am correct about the amount of damage dealt by each skill, which I may not be). Your chances of reaching Blood Dance and below are rather low, but that's OK as long as the other skills used above them are more powerful.

Hope that all helps you work it out for what's best for your play style.

Drake

1,553

Sunday, July 3rd 2011, 1:07am

My code

This is what I came up with but the elite and boss part is not working it doesn't buff me up when I start using the engine on an elite and a boss. Any suggestions on what I'm doing wrong?

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function WarriorRogue(arg1)
    local Skill = {}
    local i = 0
    local friendly = (not UnitCanAttack("player", "target"))
    local rage = UnitMana("player")
    local energy = UnitSkill("player")
    local combat = GetPlayerCombatState()
    local tbuffs = BuffList("target")
    local pbuffs = BuffList("player")
    local isBoss = ((UnitSex("target") >= 2 or UnitSex("target")) == 2
    local withinSurpriseAttackMinRange = GetActionUsable(0) and (not GetActionUsable(9))

    i=i+1; Skill[i] = { ['name'] = "Frenzied Attack",    ['use'] = combat and isBoss and (string.find(pbuffs, "Frenzied Attack"))) }
    i=i+1; Skill[i] = { ['name'] = "Berserk",             ['use'] = combat and isBoss and (string.find(pbuffs, "Berserk"))) }
    i=i+1; Skill[i] = { ['name'] = "Aggressiveness",     ['use'] = combat and isBoss and (string.find(pbuffs, "Aggressiveness"))) }
    i=i+1; Skill[i] = { ['name'] = "Frenzy",             ['use'] = combat and isBoss and (string.find(pbuffs, "Frenzy"))) }
    i=i+1; Skill[i] = { ['name'] = "Survival Instinct",  ['use'] = (PctH("player") < .25) }
    i=i+1; Skill[i] = { ['name'] = "Enraged",            ['use'] = (rage < 50) }
    i=i+1; Skill[i] = { ['name'] = "Surprise Attack",    ['use'] = (not friendly) and (not withinSurpriseAttackMinRange) }
    i=i+1; Skill[i] = { ['name'] = "Blood Dance",        ['use'] = ((not friendly) and (PctH("player") >= 0.8)) }
    i=i+1; Skill[i] = { ['name'] = "Slash",              ['use'] = ((not friendly) and (rage >= 25)) }
    i=i+1; Skill[i] = { ['name'] = "Probing Attack",     ['use'] = ((not friendly) and (rage >= 20)) }
    i=i+1; Skill[i] = { ['name'] = "Splitting Chop",     ['use'] = ((not friendly) and (rage >= 15) and (string.find(tbuffs,"Weakened"))) }
    i=i+1; Skill[i] = { ['name'] = "Thunder",              ['use'] = ((not friendly) and (rage >= 15)) }
    i=i+1; Skill[i] = { ['name'] = "Open Flank",         ['use'] = ((not friendly) and (rage >= 10) and (string.find(tbuffs,"Vulnerable")) and CD("Splitting Chop")) }
    i=i+1; Skill[i] = { ['name'] = "Keen Attack",        ['use'] = ((not friendly) and (energy >= 20) and (string.find(tbuffs,"Vulnerable"))) }
    i=i+1; Skill[i] = { ['name'] = "Shadowstab",         ['use'] = ((not friendly) and (energy >= 20)) }

    MyCombat(Skill,arg1)
end

Drake1132

Beginner

Posts: 11

Location: Wait a minute... you mean I'm *not* a figment of your imagination?

  • Send private message

1,554

Sunday, July 3rd 2011, 6:48am

Quoted from "MidgetSlap;438511"

This is what I came up with but the elite and boss part is not working it doesn't buff me up when I start using the engine on an elite and a boss. Any suggestions on what I'm doing wrong?



Yeah, question... why are you trying to check if UnitSex() is greater than or equal to 2, and then also checking if it is equal to 2? The second check is superfluous and should be removed, because if it is equal to 2, then it must also therefore be (greater than or equal to) 2. In other words, as long as UnitSex("target") returns a value of 2 or larger, including 2, then isBoss will equal true with a simple ">= 2" check. Since UnitSex() always returns a value of 2 or larger for elite and boss targets, then the check needs no more distinctions. Secondly, your parentheses for the isBoss checks are way off. You need to enclose mathematical operations within parentheses entirely, so you would need (UnitSex("target") >= 2). The way you have it set up in your code is like you are trying to say, make isBoss true if UnitSex("target") is greater than or equal to either 2 or the value returned by UnitSex("target"), which would always be true, and then the extra "== 2" and the missing closing parentheses break the code.

If you really want to check against either >= 2 or == 2 (which you shouldn't bother doing because it is superfluous), then you would do it with the following...

Source code

1
local isBoss = (UnitSex("target") >= 2) or (UnitSex("target") == 2)
But as I said, the second check is totally unnecessary, so you only need to be using:

Source code

1
local isBoss = (UnitSex("target") >= 2)
Now if you want to be able to tell the difference between an elite target and a boss target, that *might* be possible, if all elite targets report a certain range of values for UnitSex, and all boss targets report a different range of values. Since I've never tested for this myself, I can't help you with that.

Also, for your buffs, your string.find checks should be checking for "(not string.find(pbuffs,"buffname"))". The way you currently have them set up, they will never trigger, because they are currently set to only be cast if your character already has the buff active. What you want is to check and make sure that the buff is *not* active so that you do not cast them unless you are not already affected by them. But as I said in my last post, this is just practice, as the durations and cooldowns for those skills are such that if they are not on cooldown, then there is no possible way that you are already affected. In other words, if they are available to be cast, then you will not already have them active on your character.

Also, start getting in the habit of checking your parentheses *all the time*, because right now your first 4 skill lines, "Frenzied Attack" through "Frenzy", all have incorrect parentheses. In all of them, you have only 2 opening parentheses, but you have 3 closing parentheses. This will always break your function. You have to make sure that for each line of code your parentheses match up perfectly... if you have 2 opening, then you *must* have 2 closing afterward, no more, no less, and if you have 4 opening, then you must have 4 closing, no more, no less. If your parentheses don't match up in this way, then your function *will* be broken. Lua is very picky (in fact virtually all programming and scripting languages are), and a single wrong, misplaced, missing, or extra character can break your function. You *must* pay very close attention to every detail until it becomes habitual second nature.

Drake

1,555

Sunday, July 3rd 2011, 7:26pm

Quoted from "Drake1132;438566"

Yeah, question... why are you trying to check if UnitSex() is greater than or equal to 2, and then also checking if it is equal to 2? The second check is superfluous and should be removed, because if it is equal to 2, then it must also therefore be (greater than or equal to) 2. In other words, as long as UnitSex("target") returns a value of 2 or larger, including 2, then isBoss will equal true with a simple ">= 2" check. Since UnitSex() always returns a value of 2 or larger for elite and boss targets, then the check needs no more distinctions. Secondly, your parentheses for the isBoss checks are way off. You need to enclose mathematical operations within parentheses entirely, so you would need (UnitSex("target") >= 2). The way you have it set up in your code is like you are trying to say, make isBoss true if UnitSex("target") is greater than or equal to either 2 or the value returned by UnitSex("target"), which would always be true, and then the extra "== 2" and the missing closing parentheses break the code.

If you really want to check against either >= 2 or == 2 (which you shouldn't bother doing because it is superfluous), then you would do it with the following...

Source code

1
local isBoss = (UnitSex("target") >= 2) or (UnitSex("target") == 2)
But as I said, the second check is totally unnecessary, so you only need to be using:

Source code

1
local isBoss = (UnitSex("target") >= 2)
Now if you want to be able to tell the difference between an elite target and a boss target, that *might* be possible, if all elite targets report a certain range of values for UnitSex, and all boss targets report a different range of values. Since I've never tested for this myself, I can't help you with that.

Also, for your buffs, your string.find checks should be checking for "(not string.find(pbuffs,"buffname"))". The way you currently have them set up, they will never trigger, because they are currently set to only be cast if your character already has the buff active. What you want is to check and make sure that the buff is *not* active so that you do not cast them unless you are not already affected by them. But as I said in my last post, this is just practice, as the durations and cooldowns for those skills are such that if they are not on cooldown, then there is no possible way that you are already affected. In other words, if they are available to be cast, then you will not already have them active on your character.

Also, start getting in the habit of checking your parentheses *all the time*, because right now your first 4 skill lines, "Frenzied Attack" through "Frenzy", all have incorrect parentheses. In all of them, you have only 2 opening parentheses, but you have 3 closing parentheses. This will always break your function. You have to make sure that for each line of code your parentheses match up perfectly... if you have 2 opening, then you *must* have 2 closing afterward, no more, no less, and if you have 4 opening, then you must have 4 closing, no more, no less. If your parentheses don't match up in this way, then your function *will* be broken. Lua is very picky (in fact virtually all programming and scripting languages are), and a single wrong, misplaced, missing, or extra character can break your function. You *must* pay very close attention to every detail until it becomes habitual second nature.

Drake


To be honest I never really looked close at the boss code you gave me. I didn't realize that you combined the elite and the boss both in one line. I over looked the >= the code I have is just > and then == for elite. I wanted both so I added it in without even checking your code closely that's my fault thank you for pointing that out.

I didn't even realize I had three )))'s on there. I must have mistyped the first one then I copied it four times and changed values. lol Stupidity on my part. Getting in a rush too much.

Something I mentioned in one of the posts I think the first one about the globals. I'd like for each skill to be set up to only be used once till it's been through the entire list of skills then start again at the top. Would I use one global variable for each skill or would I use one single variable. I would think a different one for each skill otherwise it will just keep overwriting the skill before it. I tried to use a global on my scout and I couldn't get it to work it kept breaking my code so I gave up and deleted it. Could you give me an example on how to use globals in my code?

1,556

Sunday, July 3rd 2011, 8:35pm

Ok,I apologize for being such a dummy but i know nothing about writing this stuff. This is what i am trying to use but get the ingame error "string "RogueKnight ()" ]1: Attempt To Call Global 'RogueKnight' (a nil value)
I'm using /run RogueKnight () for my macro
what am i doing wrong?



Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function RogueKnight(arg1,arg2)
 
local Skill = {}
local i = 0
local energy = UnitMana("player")
local mana = UnitSkill("player")
local friendly = (not UnitCanAttack("player", "target")
local combat = GetPlayerCombatState()
local tspell,ttime,telapsed = UnitCastingTime("target")
local pbuffs = BuffList("player")
local tbuffs = BuffList("target")
local tDead = UnitIsDeadOrGhost ()
local lockedOn = UnitExists("target")
 
i=i+1; Skill[i] = { name = "Blind Spot", use = ((not friendly) and (energy >= 25) and (arg2 == "behind") and (not string.find(tbuffs, "Bleed"))) }
i=i+1; Skill[i] = { name = "Shadowstab", use = ((not friendly) and (energy >= 35) and (not string.find(tbuffs, "Bleed"))) }
i=i+1; Skill[i] = { name = "Wound Attack", use = ((not friendly) and (energy >= 35) and not string.find(tbuffs, "Bleed") and string.find(tbuffs, "Grievous Wound")) }
i=i+1; Skill[i] = { name = "Low Blow", use = ((not friendly) and (energy >= 35) and string.find(tbuffs, "Bleed") and (not string.find(tbuffs, "Grievous Wound"))) }
i=i+1; Skill[i] = { name = "Disarmament", use = ((not friendly) and (mana >= 200) and (not string.find(tbuffs, "Disarmament I"))) }
i=i+1; Skill[i] = { name = "Shadowstab", use = ((not friendly) and (energy >= 35) and (not string.find(tbuffs, "Bleed"))) }
i=i+1; Skill[i] = { name = "Attack", use = (not friendly) }
&#12288;
MyCombat(Skill,arg1,arg2)
 
if (tDead) or (not lockedOn) or (not enemy) then
TargetNearestEnemy()
 
end
end
end

Peryl

Intermediate

Posts: 313

Location: Elsewhere

  • Send private message

1,557

Sunday, July 3rd 2011, 10:36pm

Quoted from "GunnyDuke;438703"

This is what i am trying to use but get the ingame error "string "RogueKnight ()" ]1: Attempt To Call Global 'RogueKnight' (a nil value)

This is Lua's way of saying that it doesn't know what RogueKnight actually is. Since you are clearly trying to create this function this typically means there is an error in the function (usually syntactical).

After a quick look, I see two problems.

Source code

1
local friendly = (not UnitCanAttack("player", "target")
This line has an extraneous parenthesis. Remove the open parenthesis (the one before the not statement) and it should work fine.

Mismatched open/close parentheses are a very common mistake. A trick to figuring out if there is a problem with them is to keep a count. Start at 0, for each open parenthesis add one to the count, and for each close subtract one. If you reach the end of the line and your count isn't 0, there is a mismatch.

The second problem I see is that there is an extra end statement at the end of the file. Remove one of them.

Edit:
Ooops.. saw a third problem. In if statement near the end of the function, you are doing

Source code

1
(not enemy)
however the variable enemy was never defined/declared. Try adding this with the other variable declarations (after the declaration of friendly):

Source code

1
local enemy = not friendly

Another way to fix this would be to replace the

Source code

1
(not enemy)
with

Source code

1
friendly
this will have the same effect.
2013... The year from hell....

Drake1132

Beginner

Posts: 11

Location: Wait a minute... you mean I'm *not* a figment of your imagination?

  • Send private message

1,558

Monday, July 4th 2011, 5:12am

@MidgetSlap:

You would need to use a variable for each skill I think, or at least an array/table with one row for each skill. But rather than messing about with all of that, why not just use WoW 'Like' Slash Commands instead of DIYCE? Assuming it hasn't been broken by the latest patches, that would allow you to use /castsequence in order to iterate though a full sequence like you're talking about. That would mean you wouldn't have to muck about with extra coding in DIYCE.

Anyway, if you decide to stick with DIYCE, you would need to make a fair number of code changes. First, you would need to set up a global variable for g_lastAction as well as one for each skill. Then you would need to edit your MyCombat function in the DIYCE.lua file to make use of those variables, and to fill them in. Then you would have to add use condition checks for each skill line that would check the appropriate skill variable.

Since you're just learning DIYCE, I don't recommend that much rewriting of the code. There's too much room to mess things up.

My suggestion is to try out WoW 'Like' Slash Commands and see if it still works for the /castsequence command. If it does, then use that. If it doesn't work, then I might try to help you rewrite DIYCE to work the way you want it to, but if I do that, you should prepare yourself for a *lot* of information.

Actually, I take that back... now I think a bout it, there might be a way to do it with only a g_lastAction variable. So that would make things easier. I still recommend you try out WoW 'Like' Slash commands first, but if it doesn't work, then I think I can help you make DIYCE work without having to rewrite everything.


@GunnyDuke:

Why does your function ask for arg2? You don't seem to use arg2 anywhere in your class function except in the call to MyCombat. The MyCombat function normally does not expect to receive that third parameter, so unless you have modified the code for MyCombat, then you shouldn't need arg2 in either place.

This might also be what's causing your error message that you're receiving. The error message is basically trying to tell you that for some reason the system thinks that your function does not exist. This may be due to calling the function, which expects two parameters, without specifying any parameters. Try removing the references to arg2 (unless you actually are using them in your MyCombat function somewhere), or call the function differently in your macro: "/run RogueKnight("v1", "threaten")"

Also, like Peryl already pointed out, you have an extra "end" line, that doesn't need to be there. You need one to close out any if statements, and you need one to close out the function itself...

Source code

1
2
3
4
5
6
function FunctionName(parameters)
     stuff to do
     if (conditions) then
          stuff to do if conditions are true
     end -- closes the if statement
end -- denotes the end of the function code
Since your code only contains one if statement, you only need two "end" lines, one to close out the if statement, and the other to close out the function.

Also, do you have your code in its own separate *.lua file, or did you add it to the end of the "DIYCE.lua" file? If you saved it in its own separate file, then make sure that the file is saved as a *.lua file, and not as a *.txt file (you'll have to set your windows folder options to *not* hide known file extensions). And also make sure that you added the file name to your "DIYCE.toc" file. If the file is not actually saved as a *.lua file, and/or if the DIYCE.toc file does not contain an entry for the new file, then as far as DIYCE and RoM are concerned, your function does not exist.

Now if you added your class function to the end of your DIYCE.lua file, rather than making its own separate file, then the third "end" might actually belong to the function above your class function. If that's the case, then that previous function is not properly closed before your own function code, and therefore your code would be considered part of that function rather than a separate function all its own. If that's the case, then Lua and RoM would consider your function to not exist, and that could also cause an error like the one you're getting (although I would somewhat expect a different error, such as: 'end' expected near 'function').


Drake

1,559

Wednesday, July 6th 2011, 11:44pm

Is there a way for this to be a bit more selective? Wasting DOT's on lvl 1 bunnies is frustrating.

Source code

1
2
3
4
      -- Next enemy
   if tDead or (not LockedOn) or (not enemy) then
         TargetNearestEnemy()
   end


Thanks

Drake1132

Beginner

Posts: 11

Location: Wait a minute... you mean I'm *not* a figment of your imagination?

  • Send private message

1,560

Thursday, July 7th 2011, 1:22am

Quoted from "hmajik;439962"

Is there a way for this to be a bit more selective? Wasting DOT's on lvl 1 bunnies is frustrating.

Source code

1
2
3
4
      -- Next enemy
   if tDead or (not LockedOn) or (not enemy) then
         TargetNearestEnemy()
   end
Thanks



You could try adding some sort of level check, maybe something like the following...

Source code

1
2
3
4
5
6
7
     -- Next enemy
   if tDead or (not LockedOn) or (not enemy) then
         TargetNearestEnemy()
         while (UnitLevel("target") < (UnitLevel("player") * 0.9)) do
             TargetNearestEnemy()
         end
   end
Theoretically, this should continue to try and target a new target if your current target's primary class level is less than 90% of your own. But that assumes that TargetNearestEnemy() will cycle through targets, rather than always targeting the *closest* creature that can be attacked (I don't remember how that works because I usually just manually select targets anyway, using the tab key). Also, this has serious limitations at lower levels. For example, if you are only level 10, then this would refuse to allow you to use DIYCE to auto-target anything level 8 or lower, even if you might want to target a level 8 critter. You could could make this work a little better at lower levels by putting in a subtractive limiter instead of a multiplicative one...

Source code

1
2
3
4
5
6
7
     -- Next enemy
   if tDead or (not LockedOn) or (not enemy) then
         TargetNearestEnemy()
         while (UnitLevel("target") < (UnitLevel("player") - 5)) do
             TargetNearestEnemy()
         end
   end
This one would theoretically allow you to continue to target a new target as long as your current target's primary level is 6 levels or more lower than your own, but if it is only 5 or less levels below your own level, or if it is equal to or above your level, then it should keep the target.

In both such cases, if you are, for example, trying to drag guild mates through a lower-level dungeon, then you might have problems with your auto-targeting not working like you want.

A third option would be to set a static and constant minimum level to check against...

Source code

1
2
3
4
5
6
7
     -- Next enemy
   if tDead or (not LockedOn) or (not enemy) then
         TargetNearestEnemy()
         while (UnitLevel("target") < 10) do
             TargetNearestEnemy()
         end
   end
In this third option, the code would theoretically try to target again if the current target is level 9 or lower, but would allow you to engage in combat with any target level 10+. This would still be problematic for a character that is low level themselves, but should be pretty functional for any character level 15-20 or higher.

You could also set up a more complex system, in which you use one method if your character is low level, and another method if your character is higher level. For example...

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
     -- Next enemy
     if tDead or (not LockedOn) or (not enemy) then
          TargetNearestEnemy()
          if ((UnitLevel("player") >= 10) and (UnitLevel("player") <= 20)) then
               while (UnitLevel("target") < 3) do
                    TargetNearestEnemy()
               end
          elseif (UnitLevel("player") >= 21) then
               while (UnitLevel("target") < 10) do
                    TargetNearestEnemy()
               end
          end
     end
In that example, if your character is level 1-9, then you will keep your target regardless of the target's level, and if you are level 10-20, then you will only keep targets that are level 3 or higher, but you will re-target if your current target is level 1 or level 2, and lastly, if your level is 21 or higher, then you will only keep targets that are level 10+.

Again, these options assume that TargetNearestEnemy() will continue to cycle through targets similar to the way manual targeting with the tab key will. If TargetNearestEnemy() does not cycle targets, then I can't think of any way to make your targeting system more selective (though that does not necessarily mean it isn't possible, just that I haven't thought of a way).

Drake