Do It Yourself Combat Engine (DIYCE)

  • I just came back to RoM at the insistence of a few friends, so bear with me while I make updates to this thread, and updates to my old code. Apparently this server and the GM team here actually do things, so I have been told, which is why I return to this game. I have found my old DIYCE files and my macros on an old hard drive, so I will be making updates here as time goes on...Stay tuned my friends.


    Installation Instructions:


    Here is the code in the DIYCE.lua file:


    Code
    -- DIY Combat Engine version 2.2local g_skill = {}local g_lastaction = ""-- Holds the created timerslocal DIYCE_Timers = {}function Msg(outstr,a1,a2,a3) DEFAULT_CHAT_FRAME:AddMessage(tostring(outstr),a1,a2,a3)endfunction ReadSkills() g_skill = {} local skillname,slotfor page = 1,4 do slot = 1 skillname = GetSkillDetail(page,slot) repeat local a1,a2,a3,a4,a5,a6,a7,a8,skillusable = GetSkillDetail(page,slot) if skillusable then g_skill[skillname] = { ["page"] = page, ["slot"] = slot } end slot = slot + 1 skillname = GetSkillDetail(page,slot) until skillname == nil endend-- Read Skills on Log-In/Class Change/Level-Up local DIYCE_EventFrame = CreateUIComponent("Frame","DIYCE_EventFrame","UIParent") DIYCE_EventFrame:SetScripts("OnUpdate", [=[ DIYCE_TimerUpdate(elapsedTime) ]=] ) DIYCE_EventFrame:SetScripts("OnEvent", [=[ if event == "PLAYER_SKILLED_CHANGED" then ReadSkills() end ]=] ) DIYCE_EventFrame:RegisterEvent("PLAYER_SKILLED_CHANGED")function PctH(tgt) return (UnitHealth(tgt)/UnitMaxHealth(tgt))endfunction PctM(tgt) return (UnitMana(tgt)/UnitMaxMana(tgt))endfunction PctS(tgt) return (UnitSkill(tgt)/UnitMaxSkill(tgt))endfunction CancelBuff(buffname) local i = 1 local buff = UnitBuff("player",i)while buff ~= nil do if buff == buffname then CancelPlayerBuff(i) return true endi = i + 1 buff = UnitBuff("player",i) end return falseendfunction BuffList(tgt) local list = {} local buffcmd = UnitBuff local infocmd = UnitBuffLeftTimeif UnitCanAttack("player",tgt) then buffcmd = UnitDebuff infocmd = UnitDebuffLeftTime end-- There is a max of 100 buffs/debuffs per unit apparently for i = 1,100 do local buff, _, stackSize, ID = buffcmd(tgt, i) local timeRemaining = infocmd(tgt,i) if buff then -- Ad to list by name list[buff:gsub("(%()(.)(%))", "%2")] = { stack = stackSize, time = timeRemaining or 0, id = ID } -- We also list by ID in case two different buffs/debuffs have the same name. list[ID] = {stack = stackSize, time = timeRemaining or 0, name = buff:gsub("(%()(.)(%))", "%2") } else break end endreturn listendfunction CD(skillname) local firstskill = GetSkillDetail(2,1) if (g_skill[firstskill] == nil) or (g_skill[firstskill].page ~= 2) then ReadSkills() endif g_skill[skillname] ~= nil then local tt,cd = GetSkillCooldown(g_skill[skillname].page,g_skill[skillname].slot) return cd <= 0.4 elseif skillname == nil then return false else Msg("Skill not available: "..skillname) --Comment this line out if you do not wish to recieve this error message. return endendfunction MyCombat(Skill, arg1) local spell_name = UnitCastingTime("player") local talktome = ((arg1 == "v1") or (arg1 == "v2")) local action,actioncd,actiondef,actioncnt if spell_name ~= nil then if (arg1 == "v2") then Msg("- ["..spell_name.."]", 0, 1, 1) end return true endfor x,tbl in ipairs(Skill) do local useit = type(Skill[x].use) ~= "function" and Skill[x].use or (type(Skill[x].use) == "function" and Skill[x].use() or false) if useit then if string.find(Skill[x].name, "Action:") then action = tonumber((string.gsub(Skill[x].name, "(Action:)( *)(%d+)(.*)", "%3"))) _1,actioncd = GetActionCooldown(action) actiondef,_1,actioncnt = GetActionInfo(action) if GetActionUsable(action) and (actioncd == 0) and (actiondef ~= nil) and (actioncnt > 0) then if talktome then Msg("- "..Skill[x].name) end UseAction(action) return true end elseif string.find(Skill[x].name, "Custom:") then action = string.gsub(Skill[x].name, "(Custom:)( *)(.*)", "%3") if CustomAction(action) then return true end elseif string.find(Skill[x].name, "Item:") then action = string.gsub(Skill[x].name, "(Item:)( *)(.*)", "%3") if talktome then Msg("- "..Skill[x].name) end UseItemByName(action) return true elseif (Skill[x].ignoretimer or GetDIYCETimerValue(Skill[x].timer) == 0) and CD(Skill[x].name) then if talktome then Msg("- "..Skill[x].name) end CastSpellByName(Skill[x].name) StartDIYCETimer(Skill[x].timer) return true elseif string.find(Skill[x].name, "Pet Skill:") then action = string.gsub(Skill[x].name, "(Pet Skill:)( *)(%d+)(.*)", "%3") UsePetAction(action) if (arg1 == "v2") then Msg(Skill[x].name.." has been fully processed") end return true end end end if (arg1 == "v2") then Msg("- [IDLE]", 0, 1, 1) end return falseend--[[ Timer Update function ]]---- Tick down any active timersfunction DIYCE_TimerUpdate(elapsed) for k,v in pairs(DIYCE_Timers) do v.timeLeft = v.timeLeft - elapsed if v.timeLeft < 0 then v.timeLeft = 0 end endend--[[ Create a named timer ]]---- if the named timer already exists, this does nothing.function CreateDIYCETimer(timerName, waitTime) if not DIYCE_Timers[timerName] then DIYCE_Timers[timerName] = { timeLeft = 0, waitTime = waitTime } endend--[[ Set/reset waitTimer of an existing timer ]]---- if the timer doesn't exist, this does nothingfunction SetDIYCETimerDelay(timerName, waitTime) if DIYCE_Timers[timerName] then DIYCE_Timers[timerName].waitTime = waitTime endend--[[ Delete named timer ]]---- if the timer doesn't exist, this does nothing-- Not really needed, but added for completenessfunction DeleteDIYCETimer(timerName) if DIYCE_Timers[timerName] then DIYCE_Timers[timerName] = nil endend--[[ Get a timer's current time ]]---- if the timer doesn't exist, this returns 0function GetDIYCETimerValue(timerName) if timerName then return DIYCE_Timers[timerName] and DIYCE_Timers[timerName].timeLeft or 0 end return 0end--[[ Starts a timer ticking down ]]---- if timer doesn't exist, this does nothingfunction StartDIYCETimer(timerName) if timerName and DIYCE_Timers[timerName] then DIYCE_Timers[timerName].timeLeft = DIYCE_Timers[timerName].waitTime endendfunction CustomAction(action) if CD(action) then if IsShiftKeyDown() then Msg("- "..action) end g_lastaction = action CastSpellByName(action) return true else return false endendfunction BuffTimeLeft(tgt, buffname) local cnt = 1 local buff = UnitBuff(tgt,cnt)while buff ~= nil do if string.find(buff,buffname) then return UnitBuffLeftTime(tgt,cnt) end cnt = cnt + 1 buff = UnitBuff(tgt,cnt) endreturn 0endfunction BuffParty(arg1,arg2)-- arg1 = Quickbar slot # for targetable, instant-cast buff without a cooldown (eg. Amp Attack) for range checking.-- arg2 = buff expiration time cutoff (in seconds) for refreshing buffs, default is 45 seconds.local selfbuffs = { "Soul Bond", "Enhanced Armor", "Holy Seal" } local groupbuffs = { "Grace of Life", "Amplified Attack", "Angel's Blessing", "Essence of Magic", "Magic Barrier", "Blessed Spring Water", "Fire Ward", "Savage Blessing", "Concentration Prayer", "Shadow Fury" }local buffrefresh = arg2 or 45 -- Refresh buff time (seconds) local spell = UnitCastingTime("player") -- Spell being cast? local vocal = IsShiftKeyDown() -- Generate feedback if Shift key heldif (spell ~= nil) then return endif vocal then Msg("- Checking self buffs on "..UnitName("player")) end for i,buff in ipairs(selfbuffs) do if (g_skill[buff] ~= nil) and CD(buff) and (BuffTimeLeft("player",buff) <= buffrefresh) then if vocal then Msg("- Casting "..buff.." on "..UnitName("player")) end TargetUnit("player") CastSpellByName(buff) return end endif vocal then Msg("- Checking group buffs on "..UnitName("player")) end for i,buff in ipairs(groupbuffs) do if (g_skill[buff] ~= nil) and CD(buff) and (BuffTimeLeft("player",buff) <= buffrefresh) then if vocal then Msg("- Casting "..buff.." on "..UnitName("player")) end TargetUnit("player") CastSpellByName(buff) return end endfor num=1,GetNumPartyMembers()-1 do TargetUnit("party"..num) if GetActionUsable(arg1) and (UnitHealth("party"..num) > 0) then if vocal then Msg("- Checking group buffs on "..UnitName("party"..num)) end for i,buff in ipairs(groupbuffs) do if (g_skill[buff] ~= nil) and CD(buff) and (BuffTimeLeft("target",buff) <= buffrefresh) then if UnitIsUnit("target","party"..num) then if vocal then Msg("- Casting "..buff.." on "..UnitName("target")) end CastSpellByName(buff) return else if vocal then Msg("- Error: "..UnitName("target").." != "..UnitName("party"..num)) end end end end else if vocal then Msg("- Player "..UnitName("party"..num).." out of range or dead.") end end endif vocal then Msg("- Nothing to do.") endend



    Much of how the DIYCE actually functions still works the same as in the original, just at a much more optimized pace, with a different setup to the code itself. One major change is this version will still tell you when a skill is not available, however the rest of the DIYCE will continue to operate. No longer stopping while in the middle of combat, possibly creating problems (eg. Death).


    Quote

    HOW IT WORKS:


    For those that want to know, this is how the Engine operates: The ReadSkills() function gets run whenever you enter the game, level-up, or switch classes. It goes through your skill book and memorizes all of your skill numbering and stores it in a global table (g_skill) to be referenced by the CD() function. The CD() function checks the cooldown on whatever skill is passed to it and will return a value of true if the named skill is not on cooldown and false otherwise, so think of this as a "is the skill ready" check. The MyCombat() function goes through a table (called "Skill") that you define with a list of each action/skill you want to perform looking for the first one that's ready to be used and meets the criteria you specify for that skill.


    The custom functions no longer require a separate function for each class combination you have. (PLEASE STOP MAKING NEW FUNCTIONS! WHEN YOU MAKE A NEW FUNCTION YOU COUNTERACT THE OPTIMIZATION I WORKED HARD TO GIVE YOU! I know everyone is used to doing it that way, but this is one of the key optimizations to this new version.) There is now one master function for every class to use, which means one macro for everyone. Every toon you create using this new version of DIYCE will have the exact same macro ( /run Killsequence() ), the only differences from one toon to the next will be the numbers that go inside the parenthesis for the use of potions or foods.



    BUILDING YOUR CUSTOM SECTION OF COMBAT SCRIPT:


    Again, you are no longer creating a custom function for each class combination you make, you will simply be editing the existing function to include a check to be ran for your particular class combo.


    You can have as many checks for class combinations as you need (there are 48 total combinations in the game at this point in time). What your class combination check will do is define a table of skills and the criteria to use those skills. Here is an example of a skill table in DIYCE v2.0:




    Code
    --Potions and buffsSkill = {{ name = "Savage Blessing", use = (pctEB1 >= .05) and ((not pbuffs['Savage Blessing']) or (pbuffs['Savage Blessing'].time <= 45)) },{ name = "Concentration Prayer", use = (pctEB1 >= .05) and ((not pbuffs['Concentration Prayer']) or (pbuffs ['Concentration Prayer'].time <= 45)) },{ name = "Intensification", use = (pctEB1 >= .05) and (not pbuffs['Intensification']) and boss and enemy },}--Combatif enemy thenSkill2 = {{ name = "Binding Silence", use = (silenceThis) },{ name = "Silence", use = (silenceThis) },{ name = "Weakening Seed", use = (pctEB1 >= .05) and boss and ((not tbuffs['Weakening Seed']) or (tbuffs['Weakening Seed'].time < 4)) },{ name = "Mother Nature's Wrath", use = (pctEB1 >= .05) },--{ name = "Briar Entwinement", use = (pctEB1 >= .05) and ((not tbuffs['Briar Entwinement']) or (tbuffs['Briar Entwinement'].time < 4)) },{ name = "Lightning", use = (pctEB1 >= .05) },{ name = "Fireball", use = (pctEB1 >= .05) },{ name = "Earth Arrow", use = (pctEB1 >= .05) },}end


    In this example the Combat Engine is checking for the buffs "Savage Blessing", "Concentration Prayer", and "Intensification" weather there is an enemy target selected or not, and if those buffs are not applied then apply them. This set of checks is done both in and out of combat. Next the Combat Engine checks to see if there is an enemy targeted, and if so then start using the damage spells that are set up based on the criteria to the right of the "use" determinate.


    For "Binding Silence" and "Silence" the Combat Engine is referencing the Silence List variable set at the top of the DIYCE.lua file. If one of those spells is being cast by the enemy target, then a silencing spell will be used. Next the Combat Engine checksif you have a boss mob targeted, and if so then it checks to see if it has the debuff from "Weakening Seed", if not apply it. The Combat Engine moves down the rest of the list in this manner.


    For each line in the combat script sections, you will want to apply a check to make sure you have enough rage/mana/energy/focus to cast a particular spell. In the example above, this is a script for a druid/mage and since both classes use mana, the check is "(pctEB1 >= .05)", which checks to see if there is more than or equal to 5% mana.


    No longer do you need to classify in your variables which form of fuel you are using for your skills to check against. In the KillSequence function the variables you will be using most often are already set (add to it the variables you will need that are not included, but be advised to not change the already existing ones). The energy/rage/focus/mana bars are now read like this:


    Code
    local EnergyBar1 = UnitMana("player")local EnergyBar2 = UnitSkill("player")local pctEB1 = PctM("player")local pctEB2 = PctS("player")



    Bar1 is the upper bar (the bar of your primary class). Bar2 is the lower bar (the bar of your secondary class. The way to use these in your combat section of the KillSequence function for rage/energy/focus would be to use the variable EnergyBar1 or EnergyBar2, since all three of those forms are based on a hard number, and will remain the same throughout game play. The way to use these in your combat section for mana would be to use either pctEB1 or pctEB2, since the amount of mana used for any given skill goes up as you increase the level of the skill, as well as the amount of mana you have is ever changing, thus it is better to use a percent rather than a static number.


    To visualize what this is doing, the Skill table might look like this (with the cooldown check listed as well) in the middle of combat when you hit the macro:


    (This table gets messed up due to the formatting of the forum.)

    Code
    skill use (CD)
    Savage Blessing false true
    Concen. Prayer false true
    Intensification false true
    Lightning true true
    Fireball false false
    Earth Arrow true true


    The MyCombat() function will go through this table until it finds the first skill with a true condition for "use" that isn't on cooldown. So in this case, "Lightning" will get executed. This does not cycle through the list executing the skills in order, instead it goes through the list every time you run it and finds the first skill that's ready. So you're building a skill priority list, not a sequence.


    Notice that I have "Briar Entwinement" defined in the function but I've commented it out ("--" at the beginning of the line). So that way if I want to add it back into my rotation later, I just un-comment the line. If you want to rearrange the priority of the skills, you just cut and paste the entire line wherever you want it in the order.

  • THE CUSTOM FUNCTION:


    The custom function that you will be editing is located in CustomFunctions.lua, and upon opening the file this is what you should see:



    Code
    -- DIY Combat Engine version 2.2local WHITE = "|cffffffff"local SILVER = "|cffc0c0c0"local GREEN = "|cff00ff00"local LTBLUE = "|cffa0a0ff"function DIYCE_DebugSkills(skillList) DEFAULT_CHAT_FRAME:AddMessage(GREEN.."Skill List:") for i,v in ipairs(skillList) do DEFAULT_CHAT_FRAME:AddMessage(SILVER.." ["..WHITE..i..SILVER.."]: "..LTBLUE.."" "..WHITE..v.name..LTBLUE.."" use = "..WHITE..(v.use and "true" or "false")) endDEFAULT_CHAT_FRAME:AddMessage(GREEN.."----------")endfunction DIYCE_DebugBuffList(buffList) DEFAULT_CHAT_FRAME:AddMessage(GREEN.."Buff List:") for k,v in pairs(buffList) do -- We ignore numbered entries because both the ID and name -- are stored in the list. This avoids doubling the output. if type(k) ~= "number" then DEFAULT_CHAT_FRAME:AddMessage(SILVER.." ["..WHITE..k..SILVER.."]: "..LTBLUE.."id: "..WHITE..v.id..LTBLUE.." stack: "..WHITE..v.stack..LTBLUE.." time: "..WHITE..v.time) end end DEFAULT_CHAT_FRAME:AddMessage(GREEN.."----------") endlocal silenceList = { ["Annihilation"] = true, ["King Bug Shock"] = true, ["Mana Rift"] = true, ["Dream of Gold"] = true, ["Flame"] = true, ["Flame Spell"] = true, ["Wave Bomb"] = true, ["Silence"] = true, ["Recover"] = true, ["Restore Life"] = true, ["Heal"] = true, ["Curing Shot"] = true, ["Leaves of Fire"] = true, ["Urgent Heal"] = true, ["Heavy Shelling"] = true, ["Dark Healing"] = true,	["Storm Pulse"] = true, ["Phantom Blade"] = true, } local subList = { ["Sharp Slash"] = true, -- 1st Boss DOD ["Conjure Energy"] = true, -- 4th boss GC HM AOE ["Cat Claw Whirlwind"] = true, --1st boss RT AOE ["Void Fire"] = true, --2nd boss RT AOE } arrowTime = 0SlotRWB = 16 --Action Bar Slot # for Rune War BowSlotMNB = 17 --Action Bar Slot # for your Main Bowlocal g_lastaction = ""function CustomAction(action) if CD(action) then if IsShiftKeyDown() then Msg("- "..action) end g_lastaction = action CastSpellByName(action) return true else return false endendfunction Potion(healthpot,manapot) local Skill = {} local i = 0 local phealth = PctH("player") local pctmana = PctM("player") healthpot = healthpot or 0 manapot = manapot or 0 Skill = { { name = "Action: "..healthpot, use = (phealth <= .70) }, { name = "Action: "..manapot, use = (pctmana <= .40) }, } MyCombat(Skill,arg1)endfunction Pet(petnum) if IsPetSummoned(petnum) then ReturnPet(petnum) else SummonPet(petnum) endendfunction WardenPet(arg1) local Skill = {} local pctEB1 = PctM("player") local pbuffs = BuffList("player")local SpiritOfTheOakActive = UnitExists("pet") and (UnitName("pet") == "Spirit of the Oak") local NatureCrystalActive = UnitExists("pet") and (UnitName("pet") == "Nature Crystal") Skill = { { name = "Summon Spirit of the Oak", use = (not pbuffs["Heart of the Oak"]) and (not SpiritOfTheOakActive) and (pctEB1 >= .15) }, { name = "Heart of the Oak", use = SpiritOfTheOakActive and (not pbuffs["Heart of the Oak"]) and (pctEB1 >= .05) }, { name = "Summon Nature Crystal", use = (pbuffs["Heart of the Oak"]) and (not NatureCrystalActive) and (pctEB1 >= .15) }, } MyCombat(Skill, arg1)endfunction PriestFairySequence(arg1) local Skill = {} local Skill2 = {} local i = 0 local FairyExists = UnitExists("playerpet") local FairyBuffs = BuffList("playerpet") local combat = GetPlayerCombatState()--Determine Class-Combo mainClass, subClass = UnitClassToken( "player" ) --main, second = UnitClass("player")--Summon Fairy if (not FairyExists) and (not combat) then if mainClass == "AUGUR" then if subClass == "THIEF" then Skill = { { name = "Shadow Fairy", use = true }, } elseif subClass == "RANGER" then Skill = { { name = "Water Fairy", use = true }, } elseif subClass == "MAGE" then Skill = { { name = "Wind Fairy", use = true }, } elseif subClass == "KNIGHT" then Skill = { { name = "Light Fairy", use = true }, } elseif subClass == "WARRIOR" then Skill = { { name = "Fire Fairy", use = true }, } end end end --Cast Halo if FairyExists then if mainClass == "AUGUR" then if subClass == "THIEF" then if (not FairyBuffs[503459]) then if (arg1 == "v1") then Msg("- Activating Halo", 0, 1, 1) end Skill = { { name = "Pet Skill: 6 (Wraith Halo)", use = true }, } end elseif subClass == "RANGER" then if (not FairyBuffs[503457]) then if (arg1 == "v1") then Msg("- Activating Halo", 0, 1, 1) end Skill = { { name = "Pet Skill: 6 (Frost Halo)", use = true }, } end elseif subClass == "MAGE" then if (not FairyBuffs[503461]) then if (arg1 == "v1") then Msg("- Activating Halo", 0, 1, 1) end Skill = { { name = "Pet Skill: 6 (Windrider Halo)", use = true }, } end elseif subClass == "KNIGHT" then if (not FairyBuffs[503507]) then if (arg1 == "v1") then Msg("- Activating Halo", 0, 1, 1) end Skill = { { name = "Pet Skill: 6 (Devotion Halo)", use = true }, } end elseif subClass == "WARRIOR" then if (not FairyBuffs[503455]) then if (arg1 == "v1") then Msg("- Activating Halo", 0, 1, 1) end Skill = { { name = "Pet Skill: 6 (Accuracy Halo)", use = true }, } end end --Cast Conceal if (not MyCombat(Skill, arg1)) then if (not FairyBuffs[503753]) then if (arg1 == "v1") then Msg("- Activating Conceal", 0, 1, 1) end Skill2 = { { name = "Pet Skill: 7 (Conceal)", use = true }, } end end end end if (not MyCombat(Skill, arg1)) then MyCombat(Skill2, arg1) endendfunction KillSequence(arg1, healthpot, manapot, Healslot, foodslot, speedpot, ragepot, HoTslot)--arg1 = "v1" or "v2" or for debugging--healthpot = # of actionbar slot for health potions--manapot = # of actionbar slot for mana potions--foodslot = # of actionbar slot for food (add more args for more foodslots if needed)local Skill = {} local Skill2 = {} local i = 0 -- Player and target status. local combat = GetPlayerCombatState() local enemy = UnitCanAttack("player","target") local EnergyBar1 = UnitMana("player") local EnergyBar2 = UnitSkill("player") local pctEB1 = PctM("player") local pctEB2 = PctS("player") local tbuffs = BuffList("target") local pbuffs = BuffList("player") local tDead = UnitIsDeadOrGhost("target") local behind = (not UnitIsUnit("player", "targettarget")) local melee = GetActionUsable(3) -- # is your melee range spell slot number local a1,a2,a3,a4,a5,ASon = GetActionInfo(1) -- # is your Autoshot slot number local _,_,_,_,RWB,_ = GetActionInfo( SlotRWB ) local _,_,_,_,MNB,_ = GetActionInfo( SlotMNB ) local phealth = PctH("player") local thealth = PctH("target") local LockedOn = UnitExists("target") local boss = UnitSex("target") > 2 local elite = UnitSex("target") == 2 local party = GetNumPartyMembers() >= 2 local PsiPoints, PsiStatus = GetSoulPoint() local zoneid = (GetZoneID() % 1000) local pvp = (zoneid == 402) --Determine Class-Combo mainClass, subClass = UnitClassToken( "player" ) --main, second = UnitClass("player")--Silence Logic local tSpell,tTime,tElapsed = UnitCastingTime("target") local silenceThis = tSpell and silenceList[tSpell] and ((tTime - tElapsed) > 0.1) --Substitute Logic (for R/S combo) local subThis = tSpell and subList[tSpell] and ((tTime - tElapsed) > 0.1) --Potion & Food Checks healthpot = healthpot or 0 manapot = manapot or 0 speedpot = speedpot or 0 foodslot = foodslot or 0--Equipment and Pet Protection if phealth <= .04 then SwapEquipmentItem(2) --Note: Remove the first double dash to re-enable equipment protection. for i=1,6 do if (IsPetSummoned(i) == true) then ReturnPet(i); end end end if (LockedOn and (UnitLevel("target") <=60 )) then TargetNearestEnemy() return end --Begin Player Skill Sequences --Priest = AUGUR, Druid = DRUID, Mage = MAGE, Knight = KNIGHT, --Scout = RANGER, Rogue = THIEF, Warden = WARDEN, Warrior = WARRIOR --Warlock = HARPSYN, Champion = PSYRON -- Class: Warrior/Mage if mainClass == "WARRIOR" and subClass == "MAGE" then local SurpriseAttack = GetActionUsable(14) --Potions and Buffs Skill = { { name = "Action: "..healthpot, use = (phealth <= .70) }, { name = "Survival Instinct", use = (phealth <= .30) and combat }, { name = "Intensification", use = (pctEB2 >= .05) and (not pbuffs["Intensification"]) and boss and enemy }, { name = "Aggressiveness", use = boss and enemy }, { name = "Electric Attack", use = (pctEB2 >= .05) and ((not pbuffs["Electric Attack"]) or (pbuffs["Electric Attack"].time <= 45)) }, } --Combat if enemy then Skill2 = { { name = "Silence", use = (silenceThis) }, { name = "Surprise Attack", use = SurpriseAttack }, { name = "Thunder Sword", use = (pctEB2 >= .05) },{ name = "Lightning's Touch", use = (pctEB2 >= .05) }, { name = "Attack", use = (thealth == 1) }, } end -- Class: Warrior/Rogue elseif mainClass == "WARRIOR" and subClass == "THIEF" then local SurpriseAttack = GetActionUsable(14) CreateDIYCETimer("SSBleed", 7) --Change the value between 6 -> 7.5 depending on your lag. CreateDIYCETimer("SlashBleed", 6) --Change the value between 5.8 -> 6.2 depending on your lag.--Ammo Check and Equip local ammo = (GetEquipSlotInfo(10) ~= nil)if (ammo == false) then local HaveAmmo = false local daggers = "" for i=1,60 do local x,y,name = GetBagItemInfo(i) if (string.find(name, " Axe")) then --[[This will equip the daggers bought in Dalanis. Change this name to whatever current throwing dagger you use.]] HaveAmmo = true daggers = name end end if (HaveAmmo == true) then i=i+1; Skill[i] = { name = "Item: "..daggers, use = (not ammo) } --Equip daggers if have elseif ((g_cnt0) == 0) then SendChatMessage(DEFAULT_CHAT_FRAME:AddMessage"I need to get throwing daggers!") end g_cnt = g_cnt + 1 end --[[if (goat = "BossBuffs") then Skill= { { name = "Aggressiveness", use = boss and enemy }, { name = "Berserk", use = boss and enemy }, { name = "Frenzied Attack", use = boss and enemy }, } end ]]-- --Potions and Buffs Skill = { { name = "Action: "..healthpot, use = (phealth <= .70) }, { name = "Survival Instinct", use = (phealth <= .33) and combat }, { name = "Action: "..Healslot, use = (phealth < .70) and (not combat) and (not party) }, { name = "Action: "..HoTslot, use = (phealth < .80) and (not party) }, } --Combat if enemy then Skill2 = { { name = "Shout", use = (silenceThis) }, { name = "Surprise Attack", use = SurpriseAttack }, { name = "Feint", use = ((_target == UnitName("target")) and (_type == "DODGE")) }, { name = "Enraged", use = (EnergyBar1 <= 30) and (boss or elite) }, { name = "Keen Attack", use = (EnergyBar2 >= 20) and (pbuffs["Vulnerable"]) }, { name = "Shadowstab", use = (EnergyBar2 >= 20)}, { name = "Attack", use = (thealth == 1) }, } end --Class: Druid/Mage elseif mainClass == "DRUID" and subClass == "MAGE" then --Potions and buffs Skill = { { name = "Action: "..healthpot, use = (phealth <= .70) }, { name = "Action: "..manapot, use = (pctEB1 <= .40) }, { name = "Concentration Prayer", use = (pctEB1 >= .05) and ((not pbuffs["Concentration Prayer"]) or (pbuffs ["Concentration Prayer"].time <= 45)) },{ name = "Intensification", use = (pctEB1 >= .05) and (not pbuffs["Intensification"]) and boss and enemy }, } --Combat if enemy then Skill2 = { { name = "Binding Silence", use = (silenceThis) }, { name = "Briar Entwinement", use = (pctEB1 >= .05) and ((not tbuffs["Briar Entwinement"]) or (tbuffs["Briar Entwinement"].time < 4)) }, { name = "Lightning", use = (pctEB1 >= .05) }, { name = "Fireball", use = (pctEB1 >= .05) }, { name = "Earth Arrow", use = (pctEB1 >= .05) }, } end --Class: Mage/Warrior elseif mainClass == "MAGE" and subClass == "WARRIOR" then --Potions and buffs Skill = { { name = "Action: "..healthpot, use = (phealth <= .70) }, { name = "Action: "..manapot, use = (pctEB1 <= .40) }, { name = "Activate Mana", use = (EnergyBar2 <= 90) and ((not pbuffs["Magical Talent"]) or (not pbuffs["Magical Enlightenment"]) or (not pbuffs["Elemental Explosion"])) }, { name = "Enraged", use = ((EnergyBar2 >= 15) and (EnergyBar2 <= 35)) and ((not pbuffs["Magical Talent"]) or (not pbuffs["Magical Enlightenment"]) or (not pbuffs["Elemental Explosion"])) }, } --Combat if enemy then Skill2 = { { name = "Silence", use = (silenceThis) }, { name = "Fireball", use = (pctEB1 >= .05) }, { name = "Lightning", use = (pctEB1 >= .05) }, } end --Class: Knight/Mage elseif mainClass == "KNIGHT" and subClass == "MAGE" then local LKBR = GetActionUsable(20) -- # is Lion King Battle Roar spell slot number--Potions and buffs Skill = { { name = "Action: "..healthpot, use = (phealth <= .70) }, { name = "Holy Seal", use = (pctEB1 >= .05) and ((not pbuffs["Holy Seal"]) or (pbuffs["Holy Seal"].time <= 45)) }, { name = "Lightning Armor", use = (pctEB1 >= .05) and ((not pbuffs["Lightning Armor"]) or (pbuffs["Lightning Armor"].time <= 45)) }, } --Mana Shield if IsShiftKeyDown() and (pbuffs["Mana Shield"]) then CancelBuff("Mana Shield") end Skill2 = { { name = "Mana Shield", use = (pctEB1 <= .25) }, } --Combat if enemy then Skill3 = { { name = "Silence", use = (silenceThis) }, { name = "Resolution", use = party and boss }, { name = "Shield of Discipline", use = party and boss }, { name = "Intensification", use = party and boss }, { name = "Shield of Valor", use = party and boss }, { name = "Hatred Strike", use = (pctEB1 >= .05) and party and boss }, { name = "Attack", use = (thealth == 1) }, } end --Class: Mage/Druid elseif mainClass == "MAGE" and subClass == "DRUID" then--Potions and buffs Skill = { { name = "Action: "..healthpot, use = (phealth <= .70) }, { name = "Action: "..manapot, use = (pctEB1 <= .40) }, { name = "Intensification", use = (pctEB1 >= .05) and (not pbuffs["Intensification"]) and boss and enemy }, { name = "Perception", use = (pctEB1 >= .05) and ((not pbuffs["Perception"]) or (pbuffs["Perception"].time <= 45)) },{ name = "Magic Target", use = (pctEB1 >= .05) and ((not pbuffs["Magic Target"]) or (pbuffs["Magic Target"].time <= 45)) }, } --Combat if enemy then Skill2 = { { name = "Silence", use = (silenceThis) }, { name = "Fireball", use = (pctEB1 >= .05) }, { name = "Lightning", use = (pctEB1 >= .05) },} end --Class: Mage/Rogue elseif mainClass == "MAGE" and subClass == "THIEF" then --Potions and buffs Skill = { { name = "Action: "..healthpot, use = (phealth <= .70) }, { name = "Action: "..manapot, use = (pctEB1 <= .40) }, { name = "Fang Ritual", use = (pctEB1 >= .05) and ((not pbuffs["Fang Ritual"]) or (pbuffs["Fang Ritual"].time <= 45)) },{ name = "Shadow Protection", use = (pctEB1 >= .05) and ((not pbuffs["Shadow Protection"]) or (pbuffs["Shadow Protection"].time <= 45)) }, } --Combat if enemy then if (not melee) then Skill2 = { { name = "Silence", use = (silenceThis) }, { name = "Cursed Fangs", use = (pctEB1 >= .05) and ((not tbuffs["Cursed Fangs"]) or (tbuffs["Cursed Fangs"].time <= 2)) and (thealth >= .10) }, { name = "Fireball", use = (pctEB1 >= .05) }, { name = "Demoralize", use = (EnergyBar2 >= 30) and (boss or elite) }, } elseif melee then Skill3 = { { name = "Silence", use = (silenceThis) }, { name = "Blind Stab", use = (EnergyBar2 >= 20) }, { name = "Shadowstab", use = (EnergyBar2 >= 20) }, } end end --Class: Rogue/Scout elseif mainClass == "THIEF" and subClass == "RANGER" then --Timers for this class CreateDIYCETimer("SSBleed", 8) --Change the value between 6 -> 7.5 depending on your lag. CreateDIYCETimer("LBBleed", 8) --Change the value between 7 -> 8.5 depending on your lag. --Ammo Check and Equip --Potions and Buffs Skill = { { name = "Action: "..healthpot, use = (phealth <= .40) }, { name = "Action: "..speedpot, use = (not pbuffs["Unbridled Enthusiasm"]) },{ name = "Action: "..foodslot, use = (not pbuffs["Spicy Meatsauce Burrito"]) }, } --Combat if enemy then Skill2 = { { name = "Throat Attack", use = melee and (silenceThis) }, { name = "Energy Thief", use = ((EnergyBar1 < 25) and (boss) and (not tDead)) }, { name = "Premeditation", use = (not combat) and boss and (EnergyBar1 >= 50) and (not pbuffs["Premeditation"]) },{ name = "Informer", use = boss }, { name = "Low Blow", use = (EnergyBar1 >= 25) and (tbuffs[500654]) and (not tbuffs[620314]), timer = "LBBleed" }, { name = "Shadowstab", use = (EnergyBar1 >= 20) and (not tbuffs[500654]), timer = "SSBleed" }, } end --Class: Rogue/Priest elseif mainClass == "THIEF" and subClass == "AUGUR" then --Timers for this class CreateDIYCETimer("SSBleed", 8.8) --Change the value between 6 -> 7.5 depending on your lag. CreateDIYCETimer("LBBleed", 8.8) --Change the value between 7 -> 8.5 depending on your lag. --Potions and Buffs Skill = { { name = "Holy Aura", use = (phealth <= .20) }, { name = "Regenerate", use = (phealth <= .90) and (pctEB2 >= .05) and (not pbuffs["Regenerate"]) }, { name = "Action: "..foodslot, use = (not pbuffs["Spicy Meatsauce Burrito"]) }, } --Combat if enemy then Skill2 = { --{ name = "Throw", use = (not melee) and (not boss) }, { name = "Premeditation", use = (not combat) and boss and (EnergyBar1 >= 50) and (not pbuffs["Premeditiation"]) }, { name = "Slowing Poison", use = boss }, { name = "Informer", use = boss }, { name = "Low Blow", use = (EnergyBar1 >= 25) and (tbuffs[620313]) and (not tbuffs[500704]), timer = "LBBleed" }, { name = "Shadowstab", use = (EnergyBar1 >= 20) and (not tbuffs[620313]), timer = "SSBleed" }, { name = "Shadowstab", use = (EnergyBar1 >= 20) }, { name = "Attack", use = (thealth == 1) }, } end --Class: Priest/Scout elseif mainClass == "AUGUR" and subClass == "RANGER" then --Ammo Check and Equip if GetCountInBagByName("Runic Thorn") > 0 then UseItemByName("Runic Thorn") return true end if GetInventoryItemDurable("player", 9) == 0 and GetTime() - arrowTime > 2 then if (not RWB) then UseAction(SlotRWB) return end UseEquipmentItem(10) arrowTime = GetTime() return true end if (not MNB) then UseAction(SlotMNB) return end --Potions and Buffs Skill = { { name = "Holy Aura", use = (phealth <= .20) }, { name = "Soul Source", use = (phealth <= .20) }, { name = "Action: "..foodslot, use = (not pbuffs["Deluxe Seafood"]) }, { name = "Action: "..speedpot, use = (not pbuffs["Unbridled Enthusiasm"]) }, } --Combat if enemy then Skill2 = { { name = "Throat Attack", use = (silenceThis) }, { name = "Ice Blade", use = (pctEB1 >= .05) }, { name = "Vampire Arrows", use = (EnergyBar2 >= 20) }, { name = "Shot", use = true }, } end elseif mainClass == "AUGUR" and subClass == "WARRIOR" then --Potions and Buffs Skill = { { name = "Holy Aura", use = (phealth <= .20) }, { name = "Soul Source", use = (phealth <= .20) }, { name = "Healing Salve", use = (phealth <= .90) and (pctEB1 >= .05) and (not pbuffs["Healing Salve"]) }, { name = "Condensed Rage", use = (EnergyBar2 >= 25) and ((not pbuffs["Condensed Rage"]) or (pbuffs["Condensed Rage"].time <= 45)) }, { name = "Action: "..manapot, use = (pctEB1 <= .60) }, { name = "Action: "..foodslot, use = (not pbuffs["Unimaginable Salad"]) }, { name = "Action: "..speedpot, use = (not pbuffs["Unbridled Enthusiasm"]) }, } --Combat if enemy then Skill2 = { { name = "Vindictive Strike", use = (silenceThis) and (EnergyBar2 >= 10) }, { name = "Fighting Spirit Combination", use = (pctEB1 >= .05) }, { name = "Explosion of Fighting Spirit",use = (pctEB1 >= .05) }, { name = "Shot", use = true }, } end elseif mainClass == "AUGUR" and subClass == "THIEF" then --Potions and Buffs Skill = { { name = "Holy Aura", use = (phealth <= .20) }, } --Combat if enemy then Skill2 = { { name = "Lure of the Snake Woman", use = (EnergyBar2 >= 40) and (boss) }, { name = "Bone Chill", use = (pctEB1 >= .05) and ((not tbuffs["Bone Chill"]) or (tbuffs["Bone Chill"].time <= 2)) }, { name = "Rising Tide", use = (pctEB1 >= .05) }, { name = "Action: "..speedpot, use = (not pbuffs["Unbridled Enthusiasm"]) }, } end elseif mainClass == "RANGER" and subClass == "AUGUR" then --Ammo Check and Equip if GetCountInBagByName("Runic Thorn") > 0 then UseItemByName("Runic Thorn") return true end if GetInventoryItemDurable("player", 9) == 0 and GetTime() - arrowTime > 2 then if (not RWB) then UseAction(SlotRWB) return end UseEquipmentItem(10) arrowTime = GetTime() return true end --[[ if (not MNB) then UseAction(SlotMNB) return end ]]-- --Potions and Buffs Skill = { { name = "Regenerate", use = (phealth <= .90) and (pctEB2 >= .05) and (not pbuffs["Regenerate"]) }, { name = "Urgent Heal", use = (phealth <= .70) and (pctEB2 >= .05) and (not combat) }, { name = "Action: "..healthpot, use = (phealth <= .70) }, { name = "Blood Arrow", use = ((not combat or (phealth <= .45)) and (pbuffs["Blood Arrow"])) }, { name = "Target Area", use = (tdead and (pbuffs["Target Area"])) }, { name = "Action: "..speedpot, use = (not pbuffs["Unbridled Enthusiasm"]) }, } --Combat if enemy then Skill2 = { { name = "Throat Attack", use = melee and (silenceThis) }, { name = "Neck Strike", use = (silenceThis) }, { name = "Vampire Arrows", use = (EnergyBar1 >= 20) }, { name = "Shot", use = true }, } end --Class: Scout/Rogue elseif mainClass == "RANGER" and subClass == "THIEF" then --Timers for this class --[[ --Ammo Check and Equip if GetCountInBagByName("Runic Thorn") > 0 then UseItemByName("Runic Thorn") return true end if GetInventoryItemDurable("player", 9) == 0 and GetTime() - arrowTime > 2 then if (not RWB) then UseAction(SlotRWB) return end UseEquipmentItem(10) arrowTime = GetTime() return true end if (not MNB) then UseAction(SlotMNB) return end ]]-- --Potions and Buffs Skill = { { name = "Action: "..healthpot, use = (phealth <= .70) }, } --Combat if enemy then Skill2 = { { name = "Neck Strike", use = melee and (silenceThis) }, { name = "Sapping Arrow", use = (EnergyBar2 >= 30) }, { name = "Weak Spot", use = (EnergyBar1 >= 30) }, { name = "Custom: Reflected Shot", use = true }, { name = "Shot", use = true }, } end --Class: Rogue/Warden elseif mainClass == "THIEF" and subClass == "WARDEN" then --Timers for this class CreateDIYCETimer("SSBleed", 8.8) --Change the value between 6 -> 7.5 depending on your lag. CreateDIYCETimer("LBBleed", 8.8) --Change the value between 7 -> 8.5 depending on your lag. CreateDIYCETimer("BBCritBonus", 20) --Timer for Bloodthirsty Blade Crit Bonus Effect CreateDIYCETimer("PotWSBonus", 20) --Timer for Power of the Wood Spirit Damage Bonus Effect--Potions and Buffs Skill = { { name = "Action: "..Healslot, use = (phealth <= .70) and (not combat) and (not party) }, { name = "Action: "..healthpot, use = (phealth <= .70) }, { name = "Action: "..speedpot, use = (not pbuffs["Unbridled Enthusiasm"]) }, { name = "Action: "..foodslot, use = (not pbuffs["Spicy Meatsauce Burrito"]) }, } --Combat if enemy then Skill2 = { { name = "Premeditation", use = (not combat) and boss and (EnergyBar1 >= 50) and (not pbuffs["Premeditation"]) }, { name = "Informer", use = boss }, { name = "Fervent Attack", use = boss }, { name = "Savage Power", use = boss }, { name = "Low Blow", use = (EnergyBar1 >= 30) and (tbuffs[620313]) and (not tbuffs["Grievous Wound"]), timer = "LBBleed" }, { name = "Shadowstab", use = (EnergyBar1 >= 20) and (not tbuffs[620313]), timer = "SSBleed" }, { name = "Shadowstab", use = (EnergyBar1 >= 20) }, { name = "Power of the Wood Spirit", use = (pctEB2 >= .1) }, { name = "Attack", use = (thealth == 1) }, } end --Class: Warden/Rogue elseif mainClass == "WARDEN" and subClass == "THIEF" then CreateDIYCETimer("SSBleed", 3.0) --Set to 3 so it will go off, then PotWS, then back to SS, etc. --Potions and Buffs Skill = { { name = "Walker Spirit", use = (phealth <= .40) }, { name = "Action: "..Healslot, use = (phealth <= .70) and (not combat) and (not party) }, { name = "Action: "..foodslot, use = (not pbuffs["Spicy Meatsauce Burrito"]) }, } --Combat if enemy then Skill2 = { { name = "Savage Power", use = boss }, { name = "Together", use = (EnergyBar2 >= 50) }, { name = "Attack", use = (thealth == 1) }, } end -- Class: Warrior/Warden elseif mainClass == "WARRIOR" and subClass == "WARDEN" then local SurpriseAttack = GetActionUsable(17) CreateDIYCETimer("SlashBleed", 6) --Change the value between 5.8 -> 6.2 depending on your lag.--Combat if enemy then Skill = { { name = "Shout", use = (silenceThis) }, { name = "Surprise Attack", use = SurpriseAttack }, { name = "Savage Whirlwind", use = (pctEB2 >= .05) }, { name = "Attack", use = (thealth == 1) }, } end --Class Warlock/Warrior elseif mainClass == "HARPSYN " and subClass == "WARRIOR" then --Combat if enemy then Skill = { { name = "Weakening Weave Curse", use = ((EnergyBar1 >= 20) and (not tbuffs["Weakened"])) }, } end end --End Player Skill Sequences if (not MyCombat(Skill, arg1)) then MyCombat(Skill2, arg1) end --Select Next Enemy if (tDead) then TargetUnit("") return end if mainClass == "RANGER" and (not party) then --To keep scouts from pulling mobs without meaning to. if (not LockedOn) or (not enemy) then TargetNearestEnemy() return end elseif mainClass ~= "RANGER" then --Let all other classes auto target. if (not LockedOn) or (not enemy) then TargetNearestEnemy() return end endend




    Edit the existing class combos to your liking, and add any that are not found here. These are not fully working class combos, you DO have to build your own! (I am not in the habit of just handing any random person a script that I have built for myself.)

  • YOUR IN-GAME MACRO:


    With all of this done, it is now time to go in-game and create the macro that will call this script to work for you. The easiest way to test your script is to create a macro like this:




    Code
    /run KillSequence()



    Try the macro and see if it works. If not, start troubleshooting, beginning with the red button with a green glowing circle around it next to your minimap.


    For more modifications to the macro, you can add in food and potion buffs, as well as the standard health and mana potions. A more advanced macro would look like this:




    Code
    /run KillSequence("v1",59,57,"","",20)



    You will have to determine just how many arguments you will need for your own use. Everyone will have different needs with this.


    The first argument ("arg1") is a feedback control for debugging. If you wish for no feedback then set arg1 as "", for feedback use either "v1" or "v2", depending on what level of feedback you would like.


    Quote

    I highly recommend downloading and using Notepad++ when editing code. It helps to catch things like unbalanced parentheses and other typos. It also displays the line numbers next to each line so if you get an error in game, you can refer to the line number it lists.


    Good luck to all of you who attempt to use DIY Combat Engine.




    Your friend,
    ~GW 8)

  • This isn't good for read, send another code with better indentation please. I wouldn't use a custom code that I couldn't read.

    the world chico, and everything in it.

  • This addon is awesome but there is no macro for rogue mage and scout warden. I have 2 char. But i cant use this addons. Is there any script for this class can you share with me guys ?