| 04-12-2009, 10:45 PM | #1 | ||
A library to ease stacking orbs. And to add limitations to stacking orbs. This uses vJass, DamageEvent, DamageModifiers, AutoIndex, Table and optionally GroupUtils.
Script Code:// ************************************************************* // * OrbStacking -- Version 1.8.1 // * by Deaod // ************************************************************* // * // * CREDITS: // * - Anitarf (DamageEvent, DamageModifiers) // * - grim001 (AutoIndex) // * - Rising_Dusk (GroupUtils) // * - Vexorian (JassHelper, Table) // * - MindWorX and PitzerMike (JassNewGenPack) // * - Pipedream (Grimoire) // * - SFilip (TESH) // * // * HOW TO IMPORT: // * * Copy over this library and save. Its that easy. // * // * HOW TO USE: // * * use Orb.create(integer AID, integer Method, integer Priority, OrbCallback Func) // * to create a new Orb. // * - AID is the ID of the ability representing the orb // * (in the case of an item representing the orb, pass // * the rawcode of the item) // * - Method is the type of ability triggerin the orb // * (either ORB_TYPE_SKILL, if the ability is a // * skill, or ORB_TYPE_ITEM, if an item triggers // * the orb) // * - Priority is the priority of the orb. When stacking // * different orbs on the same unit, the orb with the // * highest priority will get executed first. // * If a unit has two orbs of equal priority, the one // * acquired first will be executed first. // * - Func is the function being run when the orb is // * triggered. It has to follow the OrbCallback // * interface defined below. A function following that // * interface has to return a boolean, either // * ORB_APPLIED or ORB_NOT_APPLIED. // * If you return ORB_APPLIED, all Categories of type // * WRITE will be written (their execution-count will // * be increased) // * // * * add that Orb to a category using YourOrb.addToCategory(string Label, integer Type) // * - Label is the label of the category you want to // * add that orb to. // * Every Orb can belong to up to MAX_CATEGORIES // * categories // * - Type defines the behaviour of the orb. // * ORB_CATEGORY_TYPE_READ makes the orb only "read" from // * the Category. That means it only checks whether // * that category has been written in any orb before. // * ORB_CATEGORY_TYPE_WRITE makes the orb only "write" to // * the Category. That means it only marks the Category // * as executed but does not depend on the Category not // * being executed before. // * ORB_CATEGORY_TYPE_READWRITE combines READ and WRITE. // * That means, the orb will not be executed, if the // * Category has been executed before and it will mark // * the Category as executed when the orb is triggered // * // * * each Category has an execution limit and cant be executed // * more often than that limit. You can change that limit // * using this: set OrbCategory[label].execLimit=some_new_limit // * - label is the label of the Category which's execution // * limit you want to change // * // * * you can add a missile modifier to each Orb by using // * YourOrb.setMissileModifier(integer Ability) // * - Ability is the rawcode of an ability that places BID // * on the attacked unit and modifies the missile. // * You should base this ability off of AIcb for optimum // * performance. // * If a unit has an orb with a missile modifier, that // * modifier gets used. If the unit has more than one, the // * one of the orb with highest priority gets used. // * Missile modifiers currently dont get added to units already // * having the ability/item for the orb when the orb is created // * in the code. Though i dont think this will ever be an issue // * please tell me if you run into a situation where it is. // * Note that you wont be able to change the missile if the // * dummy ability isnt able to change the missile under the // * given circumstances. // * // * * GetDamagingUnit(), GetDamagedUnit() and GetDamage() can be // * used to access GetEventDamageSource(), GetTriggerUnit() // * and GetEventDamage() inside OrbCallback functions // * executed by this script // * // * * if you want to prevent damage or deal additional damage // * through orbs, use the SetDamage(real new) function. // * Pass the new amount of damage that attack should deal. // * Using it outside Orb Callbacks wont have any effect. // * // * * by default, all units that get indexed by AutoIndex upon // * entering the map, automatically get the dummy ability for // * OrbStacking. If there are specific types you want to // * exclude from acquiring orbs, filter them out using the // * UnitFilter function right below the first globals block. // * If you add the dummy ability to a unit, that unit wont // * be able to use other orbs anymore. They also should not // * be able to attack ground as that can cause crashes. // * // ************************************************************* library OrbStacking uses Table, DamageEvent, DamageModifiers, AutoIndex, optional GroupUtils // these are the objects required for this library to function // you can deactivate these after saving and immediately reopening the map (by removing the ! or adding a / in the front). //! external ObjectMerger w3a AIcb AOrb anam "Generic Orb" aart "" arac "0" amat "" asat "" aspt "" atat "" ata0 "" Iarp 1 0 Idic 1 0 Iob5 1 0 abuf 1 "BORB" ahdu 1 "0.01" adur 1 "0.01" aite "0" //! external ObjectMerger w3h Bfro BORB fnam "Proxy Orb" ftat "" ftip "Proxy Orb" fube "" globals constant key ORB_TYPE_SKILL // constant key ORB_TYPE_ITEM // constant key ORB_CATEGORY_TYPE_READ // categories of this type for the orb must not have been written before constant key ORB_CATEGORY_TYPE_WRITE // whenever an orb belonging to this type of category is triggered that category becomes unusable constant key ORB_CATEGORY_TYPE_READWRITE // combines READ and WRITE constant boolean ORB_APPLIED = true constant boolean ORB_NOT_APPLIED = false private constant integer AID = 'AOrb' // Based off of AIcb, places BID on attacked unit. private constant integer BID = 'BORB' // the buff placed by the dummy orb ability // based on Orb of Corruption private constant integer MAX_CATEGORIES = 5 // the maximum categories an orb can belong to private constant integer DEFAULT_CATEGORY_EXEC_LIMIT = 1 // the default execution limit of a newly created OrbCategory private constant boolean REMOVE_BUFF_BEFORE = true // change to false, if you need the buff in one of your callbacks private constant integer ORB_PRIORITY = 0x7FFFFFFF // highest possible value, meaning all orbs will get executed before any other damage modifiers get a chance endglobals // If theres any specific unit-type you want to exclude from using Orbs at all, filter it out here. // Note that AutoIndex already filters out xe's dummies, and that units not indexed by AutoIndex wont be able to use Orbs private function UnitFilter takes unit u returns boolean return true endfunction // Dont touch it, its just here for you to see function interface OrbCallback takes nothing returns boolean // Dont touch anything below. globals private unit Damaging private unit Damaged private real Damage endglobals struct OrbCategory private integer execlimit private static StringTable CategoryTable method operator execLimit takes nothing returns integer return execlimit endmethod method operator execLimit= takes integer new returns nothing debug if new<=0 then debug call BJDebugMsg("OrbCategory: New execution limit too low!") debug return debug endif set execlimit=new endmethod private static method Create takes string label returns thistype local thistype s=allocate() set s.execLimit=DEFAULT_CATEGORY_EXEC_LIMIT set CategoryTable[label]=s return s endmethod static method create takes string label returns thistype if CategoryTable.exists(label) then return CategoryTable[label] else return Create(label) endif endmethod static method operator [] takes string label returns thistype // a cleaner wrapper return create(label) endmethod private method destroy takes nothing returns nothing // i hope this prevents idiots from destroying a Category endmethod private static method onInit takes nothing returns nothing set OrbCategory.CategoryTable=StringTable.create() endmethod endstruct private keyword UnitOrb // the following are terrible hacks to create library-private struct members private keyword aid private keyword Method private keyword Cat private keyword CatType private keyword CatCnt private keyword cb private keyword Priority private keyword MissileModAbil private struct OrbUnit extends DamageModifier private unit self private integer id readonly UnitOrb missileMod private static integer array OrbCount private static thistype array UnitInstance method destroy takes nothing returns nothing set OrbCount[id]=OrbCount[id]-1 if OrbCount[id]==0 then set self=null set UnitInstance[id]=0 call deallocate() endif endmethod method newMissileMod takes UnitOrb newmod returns nothing call UnitRemoveAbility(self, missileMod.orb.MissileModAbil) call UnitAddAbility(self, newmod.orb.MissileModAbil) set missileMod=newmod endmethod method resetMissileMod takes nothing returns nothing call UnitRemoveAbility(self, missileMod.orb.MissileModAbil) call UnitAddAbility(self, AID) set missileMod=UnitOrb[self] endmethod private method onDamageDealt takes unit target, real damage returns real local integer i local Orb s local integer array b // counts the execution of each category local boolean t local UnitOrb o if GetUnitAbilityLevel(target, BID)<=0 then // not triggered by an attack. return 0. endif static if REMOVE_BUFF_BEFORE then call UnitRemoveAbility(target, BID) endif set Damaging=self set Damaged=target set Damage=damage set o=UnitOrb[self] loop exitwhen o==0 set s=o.orb set i=0 set t=true loop exitwhen i>=s.CatCnt // lets see if were allowed to trigger the Orb if (s.CatType[i]==ORB_CATEGORY_TYPE_READ or s.CatType[i]==ORB_CATEGORY_TYPE_READWRITE) and b[s.Cat[i]]>=s.Cat[i].execLimit then set t=false // we arent exitwhen true endif set i=i+1 endloop if t and s.cb.evaluate()==ORB_APPLIED then // additionally check if the Orb actually triggered (for chance based Orbs) set i=0 loop exitwhen i>=s.CatCnt // now, lets mark the categories as execute once more if s.CatType[i]==ORB_CATEGORY_TYPE_WRITE or s.CatType[i]==ORB_CATEGORY_TYPE_READWRITE then set b[s.Cat[i]]=b[s.Cat[i]]+1 endif set i=i+1 endloop endif set o=o[o.index+1] // and loop through the Orbs of the unit endloop return Damage-damage // return newdamage-olddamage endmethod static method create takes unit u returns thistype local integer id=GetUnitId(u) if UnitInstance[id]==0 then set UnitInstance[id]=allocate(u, ORB_PRIORITY) set UnitInstance[id].id=id set UnitInstance[id].self=u set UnitInstance[id].missileMod=AID endif set OrbCount[id]=OrbCount[id]+1 return UnitInstance[id] endmethod endstruct private struct UnitOrb Orb orb OrbUnit orbunit implement AutoDestroy static method clear takes unit u returns nothing local thistype o local thistype p set o=UnitOrb[u] loop exitwhen o==0 set p=o[o.index+1] call o.destroy() set o=p endloop endmethod private method onDestroy takes nothing returns nothing local thistype o if orbunit.missileMod==this then set o=o[o.index+1] // start with the next orb in line loop exitwhen o==0 if o.orb.MissileModAbil!=AID then call o.orbunit.newMissileMod(o) endif set o=o[o.index+1] endloop if o.orbunit.missileMod==this then call o.orbunit.resetMissileMod() endif endif call orbunit.destroy() endmethod static method create takes unit u, Orb orb returns thistype local thistype s=allocate() local thistype o local boolean b // theres a missile modifier with higher priority or the orb does not have a missile modifier. set s.orb=orb set s.orbunit=OrbUnit.create(u) set o=UnitOrb[u] set b=s.orb.MissileModAbil==AID // search the right place to insert loop exitwhen o==0 or o.orb.Priority<orb.Priority if not b and o.orb.MissileModAbil!=AID then set b=true endif set o=o[o.index+1] endloop set s.me=u // insert at end if not b then // apply new Missile Modifier call s.orbunit.newMissileMod(s) endif loop // shift instances moving new instance to the right place exitwhen o==0 set o.me=u set o=o[o.index+1] endloop return s endmethod endstruct struct Orb integer aid integer Method OrbCategory array Cat[MAX_CATEGORIES] integer array CatType[MAX_CATEGORIES] integer CatCnt=0 OrbCallback cb integer Priority=0 integer MissileModAbil=AID private integer i private static thistype array Structs private static integer Count=0 private static Table OrbTable private static rect WorldRect private static group InitGroup private static thistype TempOrb private static method OnDestroyCheck takes nothing returns boolean local UnitOrb o local UnitOrb next set o=UnitOrb[GetFilterUnit()] loop exitwhen o<=0 if o.orb==TempOrb then set next=o[o.index+1] call o.destroy() set o=next else set o=o[o.index+1] endif endloop return false endmethod method onDestroy takes nothing returns nothing set TempOrb=this static if LIBRARY_GroupUtils then call GroupEnumUnitsInRect(ENUM_GROUP, WorldRect, function thistype.OnDestroyCheck) else call GroupEnumUnitsInRect(InitGroup, WorldRect, function thistype.OnDestroyCheck) endif if Method==ORB_TYPE_SKILL then set Count=Count-1 set Structs[i]=Structs[Count] set Structs[i].i=i endif call OrbTable.flush(.aid) endmethod private static method OnCreateCheck takes nothing returns boolean local unit u=GetFilterUnit() if UnitFilter(u) then if TempOrb.Method==ORB_TYPE_SKILL and GetUnitAbilityLevel(u, TempOrb.aid)>0 then call UnitOrb.create(u, TempOrb) elseif TempOrb.Method==ORB_TYPE_ITEM and UnitHasItemOfTypeBJ(u, TempOrb.aid) then call UnitOrb.create(u, TempOrb) endif endif set u=null return false endmethod static method create takes integer AID, integer Method, integer Priority, OrbCallback Func returns Orb local thistype s=allocate() set s.aid=AID set s.cb=Func if Method==ORB_TYPE_SKILL then set Structs[Count]=s set s.i=Count set Count=Count+1 endif set s.Method=Method set s.Priority=Priority set OrbTable[AID]=s set TempOrb=s static if LIBRARY_GroupUtils then call GroupEnumUnitsInRect(ENUM_GROUP, WorldRect, function thistype.OnCreateCheck) else call GroupEnumUnitsInRect(InitGroup, WorldRect, function thistype.OnCreateCheck) endif return s endmethod method addToCategory takes string Label, integer Type returns nothing debug if CatCnt>=MAX_CATEGORIES or Label=="" or Label==null or (Type!=ORB_CATEGORY_TYPE_READ and Type!=ORB_CATEGORY_TYPE_WRITE and Type!=ORB_CATEGORY_TYPE_READWRITE) then debug call BJDebugMsg("OrbStacking: Can't add Orb["+I2S(this)+"] to another OrbCategory (wrong label, invalid type, or maximum categories exceeded)!") debug return debug endif set Cat[CatCnt]=OrbCategory.create(Label) set CatType[CatCnt]=Type set CatCnt=CatCnt+1 endmethod method setMissileModifier takes integer Ability returns nothing set MissileModAbil=Ability endmethod private static method UnitCreated takes unit u returns nothing local integer i=Orb.Count-1 local thistype s if UnitFilter(u) then call UnitAddAbility(u, AID) loop exitwhen i<0 set s=Structs[i] if GetUnitAbilityLevel(u, s.aid)>0 then call UnitOrb.create(u, s) endif set i=i-1 endloop endif endmethod private static method OnUpgrade takes nothing returns nothing local unit u=GetTriggerUnit() call UnitOrb.clear(u) call UnitCreated(u) set u=null endmethod private static method OnSkill takes nothing returns nothing local thistype s=OrbTable[GetLearnedSkill()] local UnitOrb o if UnitFilter(GetTriggerUnit()) and s>0 and GetLearnedSkillLevel()==1 then set o=UnitOrb.create(GetTriggerUnit(), s) endif endmethod private static method OnItemPickup takes nothing returns nothing local thistype s=OrbTable[GetItemTypeId(GetManipulatedItem())] local UnitOrb o if UnitFilter(GetTriggerUnit()) and s>0 then set o=UnitOrb.create(GetTriggerUnit(), s) endif endmethod private static method OnItemDrop takes nothing returns nothing local thistype s=OrbTable[GetItemTypeId(GetManipulatedItem())] local UnitOrb o if s>0 then set o=UnitOrb[GetTriggerUnit()] loop exitwhen o<=0 if o.orb==s then call o.destroy() return endif set o=o[o.index+1] endloop endif endmethod private static method OnUnitAddAbility takes unit u, integer aid returns nothing local thistype s=OrbTable[aid] local UnitOrb o if UnitFilter(u) and s>0 and GetUnitAbilityLevel(u, aid)<=0 then set o=UnitOrb.create(u, s) endif endmethod private static method OnUnitAddAbilityBJ takes integer aid, unit u returns nothing call OnUnitAddAbility(u, aid) endmethod private static method OnUnitRemoveAbility takes unit u, integer aid returns nothing local thistype s=OrbTable[aid] local UnitOrb o if s>0 and GetUnitAbilityLevel(u, aid)>0 then set o=UnitOrb[u] loop exitwhen o<=0 if o.orb==s then call o.destroy() return endif set o=o[o.index+1] endloop endif endmethod private static method OnUnitRemoveAbilityBJ takes integer aid, unit u returns nothing call OnUnitRemoveAbility(u, aid) endmethod private static method onInit takes nothing returns nothing local trigger t // Listener for units entering the map call OnUnitIndexed(UnitCreated) // Listener for upgrading a unit set t=CreateTrigger() call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_UPGRADE_FINISH) call TriggerAddAction(t, function thistype.OnUpgrade) // Listener for learning an ability set t=CreateTrigger() call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_HERO_SKILL) call TriggerAddAction(t, function thistype.OnSkill) // Listener for picking up and item set t=CreateTrigger() call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_PICKUP_ITEM) call TriggerAddAction(t, function thistype.OnItemPickup) // Listener for dropping an item set t=CreateTrigger() call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DROP_ITEM) call TriggerAddAction(t, function thistype.OnItemDrop) set OrbTable=Table.create() set WorldRect=GetWorldBounds() // sadly, you cant initialize rects using this function inside the globals block, unless you want the game to crash static if not LIBRARY_GroupUtils then set InitGroup=CreateGroup() // only initialize if necessary. endif endmethod endstruct hook UnitAddAbility Orb.OnUnitAddAbility hook UnitAddAbilityBJ Orb.OnUnitAddAbilityBJ hook UnitRemoveAbility Orb.OnUnitRemoveAbility hook UnitRemoveAbilityBJ Orb.OnUnitRemoveAbilityBJ hook UnitRemoveBuffBJ Orb.OnUnitRemoveAbilityBJ function GetDamagingUnit takes nothing returns unit return Damaging endfunction function GetDamagedUnit takes nothing returns unit return Damaged endfunction function GetDamage takes nothing returns real return Damage endfunction function SetDamage takes real new returns nothing set Damage=new endfunction endlibrary I additionally attached a map with two samples. |
| 04-16-2009, 02:19 PM | #2 |
Hmnn, an item based addon for LLDD sounds like a good idea, however: - Heroes only have 6 items while a map could have like err 20 orbs. In other words, instead of iterating through all the orbs and checking if the hero has such item, iterate through all the items and if the item is an orb, do it. - Maybe also add randomization into the equation? Most orbs would like to be random and I think it would be better to handle the random stuff inside your script so it doesn't have to call TriggerEvaluate - Also some stacking is better, a hero could have the same orb multiple times, but for mapmakers just doubling the power of the orb is not that of a great idea, how about running the orb's function once but passing an argument/variable that tells the coder how many of those orbs does he have? |
| 04-16-2009, 03:17 PM | #3 |
i could use table, but that would make this thing slow. Adding the randomization will be a pain in the ass, but ill see what i can do. Having the same orb twice will not do anything (as long as they share at least one category). The user could still check how many times the unit has that orb. |
| 04-16-2009, 03:26 PM | #4 | |
Quote:
|
| 04-16-2009, 04:40 PM | #5 |
Version 1.1.0 Edit: Version 1.2.0 |
| 04-23-2009, 04:56 PM | #6 |
Version 1.3.0 |
| 04-23-2009, 07:46 PM | #7 |
Can you make a demo map with blizzard's orb as sample but using you're system ??? (Ice orb, lightning otb ... etc) And this line private constant integer AID = 'A005' mean the character have the item A005 or the spell A005 (Learned or on an item) (i think it spell, if it, can we trigger this from an item and not a skill ? (Item without any skill on it all triggered, or item with allready these 4 skills max that i want to add an other effect)) Sorry about my very poor english >_> |
| 04-29-2009, 06:22 PM | #8 |
Version 1.3.1 I added a map with two sample orbs created by blizzard initially (you could probably replicate those two orbs with simple object editor work, but they wouldnt stack). Yes, you can make items have orbs easily, just pass ABILITY_TYPE_ITEM instead of ABILITY_TYPE_SKILL to Orb.Create(). And yes, you technically dont need a separate ability on the item to trigger the orb, but if you, for example, want to modify the missile art of the unit, you have to add one (either you add one, or you find a way to modify the units missile art through scripting). EDIT: Version 1.4.0 |
| 05-08-2009, 09:39 PM | #9 |
Version 1.5.0 |
| 05-22-2009, 12:38 AM | #10 |
Approving it. |
| 05-22-2009, 07:55 PM | #11 |
Version 1.5.1 |
| 08-07-2009, 02:26 PM | #12 |
Version 1.5.2 |
| 11-04-2009, 08:13 AM | #13 |
Can you provide more examples for: ORB_APPLIED ORB_NOT_APPLIED CATEGORY_TYPE_READ CATEGORY_TYPE_WRITE CATEGORY_TYPE_READWRITE We really can't get it clearly if you are only using 1 type for both spells, it would be better if you will create examples for each category type, each ability type and something that uses ORB_NOT_APPLIED as the returned boolean. Or if you are too lazy to create actual spells and items for examples, can you please state them into words? Thank you. Is CATEGORY_TYPE_READ stacking? or non stacking? I really don't get these category types, and ORB_APPLIED and ORB_NOT_APPLIED are explained before you explained category types, which is really confusing. |
| 11-04-2009, 08:54 AM | #14 |
Okay, i will try. Each category has an execution limit associated to it (which defaults to DEFAULT_CATEGORY_EXEC_LIMIT). Each orb can be associated to multiple categories. For the orb to trigger, its necessary that all categories its associated with (and are of type READ or READWRITE) have not yet reached their respective execution limits. If the category for an orb is of type READ, that orb ONLY checks if another orb of that category can be executed but does not increase the execution count of that category. If the category for an orb is of type WRITE, that orb ONLY increases the execution count, but does not check if another orb of that category can be executed. Given that all preconditions are met, and the callback for that orb is executed, you can return ORB_APPLIED or ORB_NOT_APPLIED from the callback, since you might want to trigger an orb like bash or critical strike (which trigger based on chance). If you return ORB_NOT_APPLIED, the execution count for all categories (of type WRITE or READWRITE) the orb is associated with will not be increased. If you return ORB_APPLIED, the execution count for those categories will be increased. The category type READWRITE combines those two. Meaning, it checks whether the execution limit of that category has been reached, and if the orb is successfully executed (its callback returned ORB_APPLIED) it increases the execution count of the category. |
| 11-04-2009, 09:38 AM | #15 |
Thanks for the information. In your life steal spell example, you stated above that it acts like blizzard's life steal spell. Lets say I created an item which also acts like life steal orb in your system, then I want it to stack with the same item, then what types will I use? Example: Mask of Death item, an orb item that steals 10% of the damage dealt which stacks with another Mask of Death item, meaning if I have two Mask of Death, then I will have 20% life steal per attack. Edit: Looks like my code isn't working, I imported it right using the same abilities and buffs inside your test map and still using its raw codes in my map, I don't need to calibrate the script because it has the same raw codes used in my map. Heres the code. unworking code:scope Bear initializer init globals private constant integer superBeing = 'A00D' private constant integer tr = 'A009' endglobals private function trash takes nothing returns boolean local unit c = GetDamagingUnit() local unit t = GetDamagedUnit() local xecast xe debug call BJDebugMsg("trash is called") if(GetUnitAbilityLevel(c,superBeing)>0 and GetUnitAbilityLevel(c, tr) > 0 and GetUnitAbilityLevel(t,'mark') == 0 and IsUnitEnemy(c,GetOwningPlayer(t)) )then if GetRandomInt(0,100) <= 30 then call UnitDamageTarget(c,t,60.0,true,false,ATTACK_TYPE_MELEE,DAMAGE_TYPE_NORMAL,null) set xe = xecast.createA() set xe.abilityid = cr set xe.orderstring = "cripple" set xe.owningplayer = GetOwningPlayer(c) call xe.castOnTarget(t) debug call BJDebugMsg("with bonus") endif elseif GetUnitAbilityLevel(c,superBeing) == 0 and GetUnitAbilityLevel(c, tr) > 0 and GetUnitAbilityLevel(t,'mark') == 0 and IsUnitEnemy(c,GetOwningPlayer(t)) then if GetRandomInt(0,100) <= 20 then call UnitDamageTarget(c,t,30.0,true,false,ATTACK_TYPE_MELEE,DAMAGE_TYPE_NORMAL,null) debug call BJDebugMsg("without bonus") if GetUnitAbilityLevel(c,bb) > 0 then set xe = xecast.createA() set xe.abilityid = cr set xe.orderstring = "cripple" set xe.owningplayer = GetOwningPlayer(c) call xe.castOnTarget(t) debug call BJDebugMsg("buff applied") endif endif endif set c = null set t = null return ORB_APPLIED endfunction private function init takes nothing returns nothing call Orb.Create(tr,ABILITY_TYPE_SKILL,Orb_Callback.trash).AddToCategory("trasher",CATEGORY_TYPE_READWRITE) endfunction endscope |
