Em đang muốn cóp skill Necromastery của SF vào map của em nhưng em ko biết gì về Jass, vậy mọi người có thể giúp em sửa về mấy cái trong trigger đc ko ạ [spoil]scope Necromastery initializer SetUp // requires Timer32, GTrigger globals private integer array DAMAGEID[4] endglobals //=========================================================================== // CONFIGURABLES //=========================================================================== globals private constant integer ABILID = 'ABNe' // raw code of ability "Necromastery" public constant integer DUMABILID = 'ANe0' // raw code of ability "Necromastery (Display)" private constant integer DUMMYID = 'nECD' // raw code of unit "Necromastery Dummy" private constant integer DAMAGE = 2 // damage bonus per soul private constant real COL = 50.0 // collision size of the soul private constant real SPEED = 500.0 // distance traveled by the soul per second private constant real TRUESPEED = SPEED * T32_PERIOD // distance traveled by the soul per period private constant string DEATHART = "Abilities\\Weapons\\AvengerMissile\\AvengerMissile.mdl" // death art used upon soul expiration private constant string DEATHARTPOINT = "chest" // attachment point of DEATHART endglobals private function SetUp takes nothing returns nothing local integer i = 0 local unit u = CreateUnit(Player(13), DUMMYID, 0, 0, 0) set DAMAGEID[0] = 'dmg0' // raw code of ability "Damage (10000's) (Necromastery)" set DAMAGEID[1] = 'dmg1' // raw code of ability "Damage (1000's) (Necromastery)" set DAMAGEID[2] = 'dmg2' // raw code of ability "Damage (100's) (Necromastery)" set DAMAGEID[3] = 'dmg3' // raw code of ability "Damage (10's) (Necromastery)" set DAMAGEID[4] = 'dmg4' // raw code of ability "Damage (1's) (Necromastery)" //preload loop exitwhen i > 4 call UnitAddAbility(u, DAMAGEID) set i = i + 1 endloop call UnitAddAbility(u, DUMABILID) call RemoveUnit(u) set u = null endfunction private function GetMaxSoul takes integer level returns integer // maximum number of souls if level == 1 then return 8 elseif level == 2 then return 15 elseif level == 3 then return 23 elseif level == 4 then return 30 endif return 0 endfunction private function GetSoulLost takes integer level returns real return 0.50 // amount of souls lost on death, where 1.0 = 100% endfunction //=========================================================================== // END CONFIGURABLES //=========================================================================== private struct Data unit killer unit dummy private static method setDamage takes unit u returns nothing local integer damage = DAMAGE * (GetUnitAbilityLevel(u, DUMABILID) - 1) local integer factor = 10000 local integer level local integer i = 0 loop exitwhen i > 4 set level = damage / factor call SetUnitAbilityLevel(u, DAMAGEID, level + 1) set damage = damage - (level * factor) set factor = factor / 10 set i = i + 1 endloop endmethod private method periodic takes nothing returns nothing local integer level local real x = GetUnitX(this.dummy) local real y = GetUnitY(this.dummy) local real dx = GetUnitX(this.killer) - x local real dy = GetUnitY(this.killer) - y local real a local real height local real dist = SquareRoot(dx * dx + dy * dy) if dist <= 50.0 then set level = GetUnitAbilityLevel(this.killer, DUMABILID) if level < GetMaxSoul(GetUnitAbilityLevel(this.killer, ABILID)) + 1 then call UnitRemoveAbility(this.killer, DUMABILID) call UnitAddAbility(this.killer, DUMABILID) call SetUnitAbilityLevel(this.killer, DUMABILID, level + 1) call setDamage(this.killer) endif call DestroyEffect(AddSpecialEffectTarget(DEATHART, this.killer, DEATHARTPOINT)) call RemoveUnit(this.dummy) call this.stopPeriodic() call this.deallocate() else set a = Atan2(dy, dx) call SetUnitX(this.dummy, x + TRUESPEED * Cos(a)) call SetUnitY(this.dummy, y + TRUESPEED * Sin(a)) set height = GetUnitFlyHeight(this.dummy) call SetUnitFlyHeight(this.dummy, height + ((GetUnitFlyHeight(this.killer) + 100) - height) / (dist / TRUESPEED), 0) endif endmethod implement T32x private static method actions takes nothing returns boolean local thistype this local unit u = GetTriggerUnit() local unit killer = GetKillingUnit() local integer ulevel = GetUnitAbilityLevel(u, ABILID) local integer klevel = GetUnitAbilityLevel(killer, ABILID) local integer i local real x local real y if ulevel > 0 then set i = R2I((GetUnitAbilityLevel(u, DUMABILID) - 1) * GetSoulLost(ulevel)) call UnitRemoveAbility(u, DUMABILID) call UnitAddAbility(u, DUMABILID) call SetUnitAbilityLevel(u, DUMABILID, i + 1) call setDamage(u) elseif klevel > 0 then set this = this.allocate() set x = GetUnitX(u) set y = GetUnitY(u) set this.killer = killer set this.dummy = CreateUnit(Player(13), DUMMYID, x, y, Atan2(GetUnitY(this.killer) - y, GetUnitX(this.killer) - x) * bj_RADTODEG) call this.startPeriodic() endif set u = null set killer = null return false endmethod private static method learn takes nothing returns boolean local unit u = GetTriggerUnit() local integer i if GetUnitAbilityLevel(u, DUMABILID) == 0 then call UnitAddAbility(u, DUMABILID) set i = 0 loop exitwhen i > 4 call UnitAddAbility(u, DAMAGEID) set i = i + 1 endloop endif set u = null return false endmethod private static method onInit takes nothing returns nothing local trigger t = CreateTrigger() call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH) call TriggerAddCondition(t, Condition(function thistype.actions)) set t = null set t = CreateTrigger() call GT_RegisterLearnsAbilityEvent(t, ABILID) call TriggerAddCondition(t, Condition(function thistype.learn)) set t = null endmethod endstruct endscope[/spoil] Còn đây là mấy cái system của nó ạ [spoil]//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //~~ Timer32 ~~ By Jesus4Lyf ~~ Version 1.06 ~~ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // What is Timer32? // - Timer32 implements a fully optimised timer loop for a struct. // - Instances can be added to the loop, which will call .periodic every // PERIOD until .stopPeriodic() is called. // // =Pros= // - Efficient. // - Simple. // // =Cons= // - Only allows one period. // - The called method must be named ".periodic". // // Methods: // - struct.startPeriodic() // - struct.stopPeriodic() // // - private method periodic takes nothing returns nothing // // This must be defined in structs that implement Periodic Module. // It will be executed by the module every PERIOD until .stopPeriodic() is called. // Put "implement T32x" BELOW this method. // // Modules: // - T32x // Has no safety on .stopPeriodic or .startPeriodic (except debug messages // to warn). // // - T32xs // Has safety on .stopPeriodic and .startPeriodic so if they are called // multiple times, or while otherwise are already stopped/started respectively, // no error will occur, the call will be ignored. // // - T32 // The original, old version of the T32 module. This remains for backwards // compatability, and is deprecated. The periodic method must return a boolean, // false to continue running or true to stop. // // Details: // - Uses one timer. // // - Do not, within a .periodic method, follow a .stopPeriodic call with a // .startPeriodic call. // // How to import: // - Create a trigger named T32. // - Convert it to custom text and replace the whole trigger text with this. // // Thanks: // - Infinitegde for finding a bug in the debug message that actually altered // system operation (when in debug mode). // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ library T32 initializer OnInit globals public constant real PERIOD=0.03125 public constant integer FPS=R2I(1/PERIOD) public integer Tick=0 // very useful. //============================================================================== private trigger Trig=CreateTrigger() endglobals //============================================================================== // The standard T32 module, T32x. // module T32x private thistype next private thistype prev private static method PeriodicLoop takes nothing returns boolean local thistype this=thistype(0).next loop exitwhen this==0 call this.periodic() set this=this.next endloop return false endmethod method startPeriodic takes nothing returns nothing debug if this.prev!=0 or thistype(0).next==this then debug call BJDebugMsg("T32 ERROR: Struct #"+I2S(this)+" had startPeriodic called while already running!") debug endif set thistype(0).next.prev=this set this.next=thistype(0).next set thistype(0).next=this set this.prev=thistype(0) endmethod method stopPeriodic takes nothing returns nothing debug if this.prev==0 and thistype(0).next!=this then debug call BJDebugMsg("T32 ERROR: Struct #"+I2S(this)+" had stopPeriodic called while not running!") debug endif // This is some real magic. set this.prev.next=this.next set this.next.prev=this.prev // This will even work for the starting element. debug set this.prev=0 endmethod private static method onInit takes nothing returns nothing call TriggerAddCondition(Trig,Condition(function thistype.PeriodicLoop)) endmethod endmodule //============================================================================== // The standard T32 module with added safety checks on .startPeriodic() and // .stopPeriodic(), T32xs. // module T32xs private thistype next private thistype prev private boolean runningPeriodic private static method PeriodicLoop takes nothing returns boolean local thistype this=thistype(0).next loop exitwhen this==0 call this.periodic() set this=this.next endloop return false endmethod method startPeriodic takes nothing returns nothing if not this.runningPeriodic then set thistype(0).next.prev=this set this.next=thistype(0).next set thistype(0).next=this set this.prev=thistype(0) set this.runningPeriodic=true endif endmethod method stopPeriodic takes nothing returns nothing if this.runningPeriodic then // This is some real magic. set this.prev.next=this.next set this.next.prev=this.prev // This will even work for the starting element. set this.runningPeriodic=false endif endmethod private static method onInit takes nothing returns nothing call TriggerAddCondition(Trig,Condition(function thistype.PeriodicLoop)) endmethod endmodule //============================================================================== // The original T32 module, for backwards compatability only. // module T32 // deprecated. private thistype next private thistype prev private static method PeriodicLoop takes nothing returns boolean local thistype this=thistype(0).next loop exitwhen this==0 if this.periodic() then // This is some real magic. set this.prev.next=this.next set this.next.prev=this.prev // This will even work for the starting element. debug set this.prev=0 endif set this=this.next endloop return false endmethod method startPeriodic takes nothing returns nothing debug if this.prev!=0 or thistype(0).next==this then debug call BJDebugMsg("T32 ERROR: Struct #"+I2S(this)+" had startPeriodic called while already running!") debug endif set thistype(0).next.prev=this set this.next=thistype(0).next set thistype(0).next=this set this.prev=thistype(0) endmethod private static method onInit takes nothing returns nothing call TriggerAddCondition(Trig,Condition(function thistype.PeriodicLoop)) endmethod endmodule //============================================================================== // System Core. // private function OnExpire takes nothing returns nothing set Tick=Tick+1 call TriggerEvaluate(Trig) endfunction private function OnInit takes nothing returns nothing call TimerStart(CreateTimer(),PERIOD,true,function OnExpire) endfunction endlibrary[/spoil] [spoil]//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //~~ GT ~~ GTrigger ~~ By Jesus4Lyf ~~ Version 1.05 ~~ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // What is GTrigger? // - GTrigger is an event system that replaces the cumbersome WC3 // event system. // - GTrigger only launches the necessary threads instead of x threads, // where x is the number of times the event type occurs in the map. // // =Pros= // - Instead of having 16 events (for "16" players) per use of an, // event type, you have 0 per use and 16 total for that event type. // - If you have 100 events of one type in your map, instead of firing // 100 triggers each time any spell is cast, you fire only what's needed. // - GTrigger is faster to code with, more efficient to execute, and just // better programming practises and nicer code all round. // // =Cons= // - If a trigger with a GTrigger event is destroyed, it must have its // event unregistered first or it will leak an event (slows firing down). // - Shouldn't use "wait" actions anywhere in the triggers. // // Functions: // // General // - GT_UnregisterTriggeringEvent() // // // Ability events // - GT_RegisterStartsEffectEvent(trigger, abilityid) (returns the trigger passed in) // - GT_RegisterBeginsChanellingEvent(trigger, abilityid) (returns the trigger passed in) // - GT_RegisterBeginsCastingEvent(trigger, abilityid) (returns the trigger passed in) // - GT_RegisterStopsCastingEvent(trigger, abilityid) (returns the trigger passed in) // - GT_RegisterFinishesCastingEvent(trigger, abilityid) (returns the trigger passed in) // - GT_RegisterLearnsAbilityEvent(trigger, abilityid) (returns the trigger passed in) // // Order events // (can use String2OrderIdBJ("OrderString") for orderid // - GT_RegisterTargetOrderEvent(trigger, orderid) (returns the trigger passed in) // - GT_RegisterPointOrderEvent(trigger, orderid) (returns the trigger passed in) // - GT_RegisterNoTargetOrderEvent(trigger, orderid) (returns the trigger passed in) // // Item events // - GT_RegisterItemUsedEvent(trigger, itemtypeid) (returns the trigger passed in) // - GT_RegisterItemAcquiredEvent(trigger, itemtypeid) (returns the trigger passed in) // - GT_RegisterItemDroppedEvent(trigger, itemtypeid) (returns the trigger passed in) // // Unit events // - GT_RegisterUnitDiesEvent(trigger, unittypeid) (returns the trigger passed in) // // // Ability Events // - GT_UnregisterSpellEffectEvent(trigger, abilityid) (returns the trigger passed in) // - GT_UnregisterBeginsChanellingEvent(trigger, abilityid) (returns the trigger passed in) // - GT_UnregisterBeginsCastingEvent(trigger, abilityid) (returns the trigger passed in) // - GT_UnregisterStopsCastingEvent(trigger, abilityid) (returns the trigger passed in) // - GT_UnregisterFinishesCastingEvent(trigger, abilityid) (returns the trigger passed in) // - GT_UnregisterLearnsAbilityEvent(trigger, abilityid) (returns the trigger passed in) // // Order events // (can use String2OrderIdBJ("OrderString") for orderid // - GT_UnregisterTargetOrderEvent(trigger, orderid) (returns the trigger passed in) // - GT_UnregisterPointOrderEvent(trigger, orderid) (returns the trigger passed in) // - GT_UnregisterNoTargetOrderEvent(trigger, orderid) (returns the trigger passed in) // // Item events // - GT_UnregisterItemUsedEvent(trigger, itemtypeid) (returns the trigger passed in) // - GT_UnregisterItemAcquiredEvent(trigger, itemtypeid) (returns the trigger passed in) // - GT_UnregisterItemDroppedEvent(trigger, itemtypeid) (returns the trigger passed in) // // Unit events // - GT_UnregisterUnitDiesEvent(trigger, unittypeid) (returns the trigger passed in) // // Alternative interface (not recommended): // If you aren't familiar with how this works, you shouldn't use it. // All funcs must return false. (That is the only reason it isn't recommended.) // // General // - GT_RemoveTriggeringAction() // Use this to remove actions. // // Ability Events // - GT_AddStartsEffectAction(func, abilityid) // - GT_AddBeginsChanellingActon(func, abilityid) // - GT_AddBeginsCastingAction(func, abilityid) // - GT_AddStopsCastingAction(func, abilityid) // - GT_AddFinishesCastingAction(func, abilityid) // - GT_AddLearnsAbilityAction(func, abilityid) // // Order events // (can use String2OrderIdBJ("OrderString") for orderid // - GT_AddTargetOrderAction(func, orderid) // - GT_AddPointOrderAction(func, orderid) // - GT_AddNoTargetOrderAction(func, orderid) // // Item events // - GT_AddItemUsedAction(func, itemtypeid) // - GT_AddItemAcquiredAction(func, itemtypeid) // - GT_AddItemDroppedAction(func, itemtypeid) // // Unit events // - GT_AddUnitDiesAction(func, unittypeid) // // Details: // - Due to the storage method, only 8191 GTrigger events are possible at any one time. // // Thanks: // - Daxtreme: For voluntarily testing this system and the UnitDies event idea. // - kenny!: For the Order and Learns Ability event ideas. // // How to import: // - Create a trigger named GT. // - Convert it to custom text and replace the whole trigger text with this. // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ library GT initializer Init ////////////// // Pointers // //////////////////////////////////////////////////////////////////////////// // Assigned to abilities, and point to trigger grouping linked lists. // // Use: // GetPointer --> int (pointer) // FreePointer(int (pointer)) // set PointerTarget[int (pointer)]=int (list link) // PointerTarget[int (pointer)] --> int (list link) globals // Pointer private integer array PointerTarget private integer PointerMax=0 // Spare Pointer Stack private integer array NextPointer private integer NextPointerMaxPlusOne=1 endglobals private function GetPointer takes nothing returns integer if NextPointerMaxPlusOne==1 then set PointerMax=PointerMax+1 return PointerMax endif set NextPointerMaxPlusOne=NextPointerMaxPlusOne-1 return NextPointer[NextPointerMaxPlusOne] endfunction private function FreePointer takes integer pointer returns nothing set PointerTarget[pointer]=0 set NextPointer[NextPointerMaxPlusOne]=pointer set NextPointerMaxPlusOne=NextPointerMaxPlusOne+1 endfunction /////////////////////////////////// // Trigger Grouping Linked Lists // //////////////////////////////////////////////////////////////////////////// // Contains a chain of triggers to be executed together. // // Use: // GetMem() --> int (mem) // FreeMem(int (mem)) // Link(int (pointer), int (mem)) // Unlink(int (pointer), int (mem)) globals // Spare Link Stack private integer array NextMem private integer NextMemMaxPlusOne=1 // Linked list private trigger array Trig private integer array Next private integer array Prev private integer TrigMax=0 endglobals private function GetMem takes nothing returns integer if NextMemMaxPlusOne==1 then set TrigMax=TrigMax+1 return TrigMax endif set NextMemMaxPlusOne=NextMemMaxPlusOne-1 return NextMem[NextMemMaxPlusOne] endfunction private function FreeMem takes integer i returns nothing set Trig=null set NextMem[NextMemMaxPlusOne]=i set NextMemMaxPlusOne=NextMemMaxPlusOne+1 endfunction // Linked list functionality // NOTE: This means "Next" must be loaded BEFORE executing the trigger, which could delete the current link. private function Link takes integer pointer, integer new returns nothing set Prev[new]=0 set Next[new]=PointerTarget[pointer] set Prev[PointerTarget[pointer]]=new set PointerTarget[pointer]=new endfunction private function Unlink takes integer pointer, integer rem returns nothing if Prev[rem]==0 then set PointerTarget[pointer]=Next[rem] set Prev[Next[rem]]=0 endif set Next[Prev[rem]]=Next[rem] set Prev[Next[rem]]=Prev[rem] endfunction ////////////////////// // GTrigger General // //////////////////////////////////////////////////////////////////////////// // Only contains the UnregisterTriggeringEvent action for public use. globals boolean UnregisterLastEvent=false endglobals public function UnregisterTriggeringEvent takes nothing returns nothing set UnregisterLastEvent=true endfunction ///////////////////////////////////// // GTrigger Ability Implementation // //////////////////////////////////////////////////////////////////////////// // The nasty textmacro implementation of special "All Players" events. //! textmacro SetupSpecialAllPlayersEvent takes NAME, EVENT, GETSPECIAL globals private trigger $NAME$Trigger=CreateTrigger() // Extendable arrays private integer array $NAME$AbilityIdA private integer array $NAME$ListPointerA private integer array $NAME$AbilityIdB private integer array $NAME$ListPointerB private integer array $NAME$AbilityIdC private integer array $NAME$ListPointerC private integer array $NAME$AbilityIdD private integer array $NAME$ListPointerD private integer array $NAME$AbilityIdE private integer array $NAME$ListPointerE endglobals globals//locals private integer GetOrCreateListPointer$NAME$AbilHashed endglobals private function GetOrCreate$NAME$ListPointer takes integer abil returns integer set GetOrCreateListPointer$NAME$AbilHashed=abil-(abil/8191)*8191 if $NAME$AbilityIdA[GetOrCreateListPointer$NAME$AbilHashed]==abil then // Correct return $NAME$ListPointerA[GetOrCreateListPointer$NAME$AbilHashed] elseif $NAME$AbilityIdA[GetOrCreateListPointer$NAME$AbilHashed]<1 then // Empty set $NAME$AbilityIdA[GetOrCreateListPointer$NAME$AbilHashed]=abil set $NAME$ListPointerA[GetOrCreateListPointer$NAME$AbilHashed]=GetPointer() return $NAME$ListPointerA[GetOrCreateListPointer$NAME$AbilHashed] endif if $NAME$AbilityIdB[GetOrCreateListPointer$NAME$AbilHashed]==abil then // Correct return $NAME$ListPointerB[GetOrCreateListPointer$NAME$AbilHashed] elseif $NAME$AbilityIdB[GetOrCreateListPointer$NAME$AbilHashed]<1 then // Empty set $NAME$AbilityIdB[GetOrCreateListPointer$NAME$AbilHashed]=abil set $NAME$ListPointerB[GetOrCreateListPointer$NAME$AbilHashed]=GetPointer() return $NAME$ListPointerB[GetOrCreateListPointer$NAME$AbilHashed] endif if $NAME$AbilityIdC[GetOrCreateListPointer$NAME$AbilHashed]==abil then // Correct return $NAME$ListPointerC[GetOrCreateListPointer$NAME$AbilHashed] elseif $NAME$AbilityIdC[GetOrCreateListPointer$NAME$AbilHashed]<1 then // Empty set $NAME$AbilityIdC[GetOrCreateListPointer$NAME$AbilHashed]=abil set $NAME$ListPointerC[GetOrCreateListPointer$NAME$AbilHashed]=GetPointer() return $NAME$ListPointerC[GetOrCreateListPointer$NAME$AbilHashed] endif if $NAME$AbilityIdD[GetOrCreateListPointer$NAME$AbilHashed]==abil then // Correct return $NAME$ListPointerD[GetOrCreateListPointer$NAME$AbilHashed] elseif $NAME$AbilityIdD[GetOrCreateListPointer$NAME$AbilHashed]<1 then // Empty set $NAME$AbilityIdD[GetOrCreateListPointer$NAME$AbilHashed]=abil set $NAME$ListPointerD[GetOrCreateListPointer$NAME$AbilHashed]=GetPointer() return $NAME$ListPointerD[GetOrCreateListPointer$NAME$AbilHashed] endif if $NAME$AbilityIdE[GetOrCreateListPointer$NAME$AbilHashed]==abil then // Correct return $NAME$ListPointerE[GetOrCreateListPointer$NAME$AbilHashed] elseif $NAME$AbilityIdE[GetOrCreateListPointer$NAME$AbilHashed]<1 then // Empty set $NAME$AbilityIdE[GetOrCreateListPointer$NAME$AbilHashed]=abil set $NAME$ListPointerE[GetOrCreateListPointer$NAME$AbilHashed]=GetPointer() return $NAME$ListPointerE[GetOrCreateListPointer$NAME$AbilHashed] endif call BJDebugMsg("GTrigger Error: Ran out of storage locations for pointers on object "+GetObjectName(abil)+"!") set PointerTarget[0]=0 return 0 endfunction globals//locals private integer GetListPointer$NAME$AbilHashed endglobals private function Get$NAME$ListPointer takes integer abil returns integer set GetListPointer$NAME$AbilHashed=abil-(abil/8191)*8191 if $NAME$AbilityIdA[GetListPointer$NAME$AbilHashed]==abil then // Correct return $NAME$ListPointerA[GetListPointer$NAME$AbilHashed] elseif $NAME$AbilityIdA[GetListPointer$NAME$AbilHashed]<1 then // Empty set PointerTarget[0]=0 // Make sure. return 0 endif if $NAME$AbilityIdB[GetListPointer$NAME$AbilHashed]==abil then // Correct return $NAME$ListPointerB[GetListPointer$NAME$AbilHashed] elseif $NAME$AbilityIdB[GetListPointer$NAME$AbilHashed]<1 then // Empty set PointerTarget[0]=0 // Make sure. return 0 endif if $NAME$AbilityIdC[GetListPointer$NAME$AbilHashed]==abil then // Correct return $NAME$ListPointerC[GetListPointer$NAME$AbilHashed] elseif $NAME$AbilityIdC[GetListPointer$NAME$AbilHashed]<1 then // Empty set PointerTarget[0]=0 // Make sure. return 0 endif if $NAME$AbilityIdD[GetListPointer$NAME$AbilHashed]==abil then // Correct return $NAME$ListPointerD[GetListPointer$NAME$AbilHashed] elseif $NAME$AbilityIdD[GetListPointer$NAME$AbilHashed]<1 then // Empty set PointerTarget[0]=0 // Make sure. return 0 endif if $NAME$AbilityIdE[GetListPointer$NAME$AbilHashed]==abil then // Correct return $NAME$ListPointerE[GetListPointer$NAME$AbilHashed] elseif $NAME$AbilityIdE[GetListPointer$NAME$AbilHashed]<1 then // Empty set PointerTarget[0]=0 // Make sure. return 0 endif call BJDebugMsg("GTrigger Error: Ran out of storage locations for pointers at ability "+GetObjectName(abil)+"!") set PointerTarget[0]=0 return 0 endfunction globals//locals private integer Register$NAME$Mem endglobals public function Register$NAME$Event takes trigger t, integer abil returns trigger set Register$NAME$Mem=GetMem() set Trig[Register$NAME$Mem]=t call Link(GetOrCreate$NAME$ListPointer(abil),Register$NAME$Mem) return t endfunction globals//locals private integer Unregister$NAME$Pointer private integer Unregister$NAME$Mem endglobals public function Unregister$NAME$Event takes trigger t, integer abil returns trigger set Unregister$NAME$Pointer=Get$NAME$ListPointer(abil) set Unregister$NAME$Mem=PointerTarget[Unregister$NAME$Pointer] loop exitwhen Trig[Unregister$NAME$Mem]==t if Unregister$NAME$Mem==0 then return t // Not found. endif set Unregister$NAME$Mem=Next[Unregister$NAME$Mem] endloop call Unlink(Unregister$NAME$Pointer,Unregister$NAME$Mem) call FreeMem(Unregister$NAME$Mem) return t endfunction private function Trigger$NAME$Event takes nothing returns boolean local integer Trigger$NAME$Pointer=Get$NAME$ListPointer($GETSPECIAL$) local integer Trigger$NAME$Mem=PointerTarget[Trigger$NAME$Pointer] local integer Trigger$NAME$NextMem set UnregisterLastEvent=false loop exitwhen Trigger$NAME$Mem<1 set Trigger$NAME$NextMem=Next[Trigger$NAME$Mem] if TriggerEvaluate(Trig[Trigger$NAME$Mem]) then call TriggerExecute(Trig[Trigger$NAME$Mem]) endif if UnregisterLastEvent then set UnregisterLastEvent=false call Unlink(Trigger$NAME$Pointer,Trigger$NAME$Mem) call FreeMem(Trigger$NAME$Mem) endif set Trigger$NAME$Mem=Trigger$NAME$NextMem endloop return false endfunction private function Init$NAME$ takes nothing returns nothing local integer i=bj_MAX_PLAYER_SLOTS call TriggerAddCondition($NAME$Trigger,Condition(function Trigger$NAME$Event)) loop set i=i-1 call TriggerRegisterPlayerUnitEvent($NAME$Trigger,Player(i),EVENT_PLAYER_$EVENT$,null) exitwhen i==0 endloop endfunction //! endtextmacro //! runtextmacro SetupSpecialAllPlayersEvent("StartsEffect", "UNIT_SPELL_EFFECT", "GetSpellAbilityId()") //! runtextmacro SetupSpecialAllPlayersEvent("BeginsChanelling", "UNIT_SPELL_CHANNEL", "GetSpellAbilityId()") //! runtextmacro SetupSpecialAllPlayersEvent("BeginsCasting", "UNIT_SPELL_CAST", "GetSpellAbilityId()") //! runtextmacro SetupSpecialAllPlayersEvent("StopsCasting", "UNIT_SPELL_ENDCAST", "GetSpellAbilityId()") //! runtextmacro SetupSpecialAllPlayersEvent("FinishesCasting", "UNIT_SPELL_FINISH", "GetSpellAbilityId()") //! runtextmacro SetupSpecialAllPlayersEvent("TargetOrder", "UNIT_ISSUED_TARGET_ORDER", "GetIssuedOrderId()") //! runtextmacro SetupSpecialAllPlayersEvent("PointOrder", "UNIT_ISSUED_POINT_ORDER", "GetIssuedOrderId()") //! runtextmacro SetupSpecialAllPlayersEvent("NoTargetOrder", "UNIT_ISSUED_ORDER", "GetIssuedOrderId()") //! runtextmacro SetupSpecialAllPlayersEvent("ItemUsed", "UNIT_USE_ITEM", "GetItemTypeId(GetManipulatedItem())") //! runtextmacro SetupSpecialAllPlayersEvent("ItemAcquired", "UNIT_PICKUP_ITEM", "GetItemTypeId(GetManipulatedItem())") //! runtextmacro SetupSpecialAllPlayersEvent("ItemDropped", "UNIT_DROP_ITEM", "GetItemTypeId(GetManipulatedItem())") //! runtextmacro SetupSpecialAllPlayersEvent("UnitDies", "UNIT_DEATH", "GetUnitTypeId(GetTriggerUnit())") //! runtextmacro SetupSpecialAllPlayersEvent("LearnsAbility", "HERO_SKILL", "GetLearnedSkill()") // Note to self: Remember to update the Init function. ///////////////////////////////////////// // GTrigger All Players Implementation // //////////////////////////////////////////////////////////////////////////// // The textmacro implementation of other "All Players" events. //! textmacro SetupAllPlayersEvent takes NAME, EVENT globals private trigger $NAME$Trigger=CreateTrigger() private integer $NAME$ListPointer=0 endglobals globals//locals private integer Register$NAME$Mem endglobals public function Register$NAME$Event takes trigger t returns trigger set Register$NAME$Mem=GetMem() set Trig[Register$NAME$Mem]=t call Link($NAME$ListPointer,Register$NAME$Mem) return t endfunction globals//locals private integer Unregister$NAME$Pointer private integer Unregister$NAME$Mem endglobals public function Unregister$NAME$Event takes trigger t returns trigger set Unregister$NAME$Mem=PointerTarget[$NAME$ListPointer] loop exitwhen Trig[Unregister$NAME$Mem]==t if Unregister$NAME$Mem==0 then return t // Not found. endif set Unregister$NAME$Mem=Next[Unregister$NAME$Mem] endloop call Unlink($NAME$ListPointer,Unregister$NAME$Mem) call FreeMem(Unregister$NAME$Mem) return t endfunction private function Trigger$NAME$Event takes nothing returns boolean local integer Trigger$NAME$Mem=PointerTarget[$NAME$ListPointer] local integer Trigger$NAME$NextMem set UnregisterLastEvent=false loop exitwhen Trigger$NAME$Mem<1 set Trigger$NAME$NextMem=Next[Trigger$NAME$Mem] if TriggerEvaluate(Trig[Trigger$NAME$Mem]) then call TriggerExecute(Trig[Trigger$NAME$Mem]) endif if UnregisterLastEvent then set UnregisterLastEvent=false call Unlink($NAME$ListPointer,Trigger$NAME$Mem) call FreeMem(Trigger$NAME$Mem) endif set Trigger$NAME$Mem=Trigger$NAME$NextMem endloop return false endfunction private function Init$NAME$ takes nothing returns nothing local integer i=bj_MAX_PLAYER_SLOTS call TriggerAddCondition($NAME$Trigger,Condition(function Trigger$NAME$Event)) loop set i=i-1 call TriggerRegisterPlayerUnitEvent($NAME$Trigger,Player(i),EVENT_PLAYER_UNIT_$EVENT$,null) exitwhen i==0 endloop // Initialise the pointer. set $NAME$ListPointer=GetPointer() endfunction //! endtextmacro // Old: //! runtextmacro SetupAllPlayersEvent("AnyUnitDies", "DEATH") private function Init takes nothing returns nothing // Ability events call InitStartsEffect() call InitBeginsChanelling() call InitBeginsCasting() call InitStopsCasting() call InitFinishesCasting() call InitLearnsAbility() // Order events call InitTargetOrder() call InitPointOrder() call InitNoTargetOrder() // Item events call InitItemUsed() call InitItemAcquired() call InitItemDropped() // Unit events call InitUnitDies() endfunction ////////////// // Wrappers // //////////////////////////////////////////////////////////////////////////// // Wraps it up, for those who really want this interface. // General public function RemoveTriggeringAction takes nothing returns nothing call UnregisterTriggeringEvent() call DestroyTrigger(GetTriggeringTrigger()) endfunction // Special All Player Events //! textmacro AddSpecialAllPlayersWrapper takes EVENT public function Add$EVENT$Action takes code func, integer special returns nothing call TriggerAddCondition(Register$EVENT$Event(CreateTrigger(),special),Condition(func)) endfunction //! endtextmacro //! runtextmacro AddSpecialAllPlayersWrapper("StartsEffect") //! runtextmacro AddSpecialAllPlayersWrapper("BeginsChanelling") //! runtextmacro AddSpecialAllPlayersWrapper("BeginsCasting") //! runtextmacro AddSpecialAllPlayersWrapper("StopsCasting") //! runtextmacro AddSpecialAllPlayersWrapper("FinishesCasting") //! runtextmacro AddSpecialAllPlayersWrapper("TargetOrder") //! runtextmacro AddSpecialAllPlayersWrapper("PointOrder") //! runtextmacro AddSpecialAllPlayersWrapper("NoTargetOrder") //! runtextmacro AddSpecialAllPlayersWrapper("ItemUsed") //! runtextmacro AddSpecialAllPlayersWrapper("ItemAcquired") //! runtextmacro AddSpecialAllPlayersWrapper("ItemDropped") //! runtextmacro AddSpecialAllPlayersWrapper("UnitDies") //! runtextmacro AddSpecialAllPlayersWrapper("LearnsAbility") // Note to self: Remember to update the Init function. // All Player Events //! textmacro AddAllPlayersWrapper takes EVENT public function Add$EVENT$Action takes code func returns nothing call TriggerAddCondition(Register$EVENT$Event(CreateTrigger()),Condition(func)) endfunction //! endtextmacro // Old: //! runtextmacro AddAllPlayersWrapper("AnyUnitDies") endlibrary [/spoil] [spoil]// // ___ _ __ __ _ ___ ____ _______________________________ // | \ /_\ / |/ | /_\ / _\| __| || D E A L I T , || // | |) / _ \ / / | / |/ _ \| |/|| __| || D E T E C T I T , || // |___/_/ \_/_/|__/|_|_/ \_\___/|____| || B L O C K I T . || // By Jesus4Lyf _______________________________ // v 1.0.1 // What is Damage? // _________________ // Damage is a damage dealing, detection and blocking system. It implements // all such functionality. It also provides a means to detect what type // of damage was dealt, so long as all damage in your map is dealt using // this system's deal damage functions (except for basic attacks). // // It is completely recursively defined, meaning if you deal damage on // taking damage, the type detection and other features like blocking // will not malfunction. // // How to implement? // ___________________ // Create a new trigger object called Damage, go to 'Edit -> Convert to // Custom Text', and replace everything that's there with this script. // // At the top of the script, there is a '//! external ObjectMerger' line. // Save your map, close your map, reopen your map, and then comment out this // line. Damage is now implemented. This line creates a dummy ability used // in the system in some circumstances with damage blocking. // // Functions: // ____________ // function Damage_RegisterEvent takes trigger whichTrigger returns nothing // - This registers a special "any unit takes damage" event. // - This event supports dynamic trigger use. // - Only triggers registered on this event may block damage. // // function Damage_GetType takes nothing returns damagetype // - This will get the type of damage dealt, like an event response, // for when using a unit takes damage event (or the special event above). // // function Damage_Block takes real amount returns nothing // function Damage_BlockAll takes nothing returns nothing // - For use only with Damage_RegisterEvent. // - Blocks 'amount' of the damage dealt. // - Multiple blocks at once work correctly. // - Blocking more than 100% of the damage will block 100% instead. // - Damage_BlockAll blocks 100% of the damage being dealt. // // function Damage_EnableEvent takes boolean enable returns nothing // - For disabling and re-enabling the special event. // - Use it to deal damage which you do not want to be detected by // the special event. // // function UnitDamageTargetEx takes lots of things returns boolean // - Replaces UnitDamageTarget in your map, with the same arguments. // // function Damage_Physical takes unit source, unit target, real amount, // attacktype whichType, boolean attack, boolean ranged returns boolean // - A clean wrapper for physical damage. // - 'attack' determines if this is to be treated as a real physical // attack or just physical type damage. // - 'ranged' determines if this is to be treated as a ranged or melee // attack. // // function Damage_Spell takes unit source, unit target, real amount returns boolean // - A clean wrapper for spell damage. // // function Damage_Pure takes unit source, unit target, real amount returns boolean // - A clean wrapper for pure type damage (universal type, 100% damage). // // Thanks: // _________ // - Romek, for helping me find a better way to think about damage blocking. // library Damage initializer OnInit uses AIDS, Event //============================================================ ////! external ObjectMerger w3a AIlz dprv anam "Life Bonus" ansf "(Damage System)" Ilif 1 500000 aite 0 globals private constant integer LIFE_BONUS_ABIL='dprv' endglobals //============================================================ globals private Event OnDamageEvent private boolean EventEnabled=true endglobals public function RegisterEvent takes trigger whichTrigger returns nothing call OnDamageEvent.register(whichTrigger) endfunction public function EnableEvent takes boolean enable returns nothing set EventEnabled=enable endfunction //============================================================ globals private integer TypeStackLevel=0 private damagetype array TypeStackValue private real array ToBlock endglobals public function GetType takes nothing returns damagetype return TypeStackValue[TypeStackLevel] endfunction public function Block takes real amount returns nothing set ToBlock[TypeStackLevel]=ToBlock[TypeStackLevel]+amount endfunction public function BlockAll takes nothing returns nothing set ToBlock[TypeStackLevel]=ToBlock[TypeStackLevel]+GetEventDamage() endfunction //============================================================ globals private integer BlockNum=0 private unit array BlockUnit private real array BlockUnitLife private real array BlockRedamage private unit array BlockDamageSource private timer BlockTimer=CreateTimer() endglobals //============================================================ globals private unit array RemoveBoosted private integer RemoveBoostedMax=0 private timer RemoveBoostedTimer=CreateTimer() endglobals globals//locals private real BoostedLifeTemp private unit BoostedLifeUnit endglobals private function RemoveBoostedTimerFunc takes nothing returns nothing loop exitwhen RemoveBoostedMax==0 set BoostedLifeUnit=RemoveBoosted[RemoveBoostedMax] set BoostedLifeTemp=GetWidgetLife(BoostedLifeUnit) call UnitRemoveAbility(BoostedLifeUnit,LIFE_BONUS_ABIL) if BoostedLifeTemp>0.405 then call SetWidgetLife(BoostedLifeUnit,BoostedLifeTemp) endif set RemoveBoostedMax=RemoveBoostedMax-1 endloop endfunction //============================================================ private keyword Detector // Darn, I actually had to do this. XD globals//locals private unit ForUnit private real NextHealth endglobals private function OnDamageActions takes nothing returns boolean if EventEnabled then call OnDamageEvent.fire() endif if ToBlock[TypeStackLevel]!=0. then //==================================================== // Blocking set ForUnit=GetTriggerUnit() set NextHealth=GetEventDamage() if ToBlock[TypeStackLevel]>=NextHealth then set NextHealth=GetWidgetLife(ForUnit)+NextHealth else set NextHealth=GetWidgetLife(ForUnit)+ToBlock[TypeStackLevel] endif call SetWidgetLife(ForUnit,NextHealth) if GetWidgetLife(ForUnit)<NextHealth then // NextHealth is over max health. call UnitAddAbility(ForUnit,LIFE_BONUS_ABIL) call SetWidgetLife(ForUnit,NextHealth) set RemoveBoostedMax=RemoveBoostedMax+1 set RemoveBoosted[RemoveBoostedMax]=ForUnit call ResumeTimer(RemoveBoostedTimer) endif //==================================================== set ToBlock[TypeStackLevel]=0. endif return false endfunction //============================================================ function UnitDamageTargetEx takes unit whichUnit, widget target, real amount, boolean attack, boolean ranged, attacktype attackType, damagetype damageType, weapontype weaponType returns boolean local boolean result set TypeStackLevel=TypeStackLevel+1 set TypeStackValue[TypeStackLevel]=damageType set result=UnitDamageTarget(whichUnit,target,amount,attack,ranged,attackType,damageType,weaponType) set TypeStackLevel=TypeStackLevel-1 return result endfunction //! textmacro Damage__DealTypeFunc takes NAME, TYPE public function $NAME$ takes unit source, unit target, real amount returns boolean return UnitDamageTargetEx(source,target,amount,false,false,ATTACK_TYPE_NORMAL,$TYPE$,WEAPON_TYPE_WHOKNOWS) endfunction //! endtextmacro //! runtextmacro Damage__DealTypeFunc("Pure","DAMAGE_TYPE_UNIVERSAL") //! runtextmacro Damage__DealTypeFunc("Spell","DAMAGE_TYPE_MAGIC") // Uses different stuff, but works much the same way. public function Physical takes unit source, unit target, real amount, attacktype whichType, boolean attack, boolean ranged returns boolean return UnitDamageTargetEx(source,target,amount,attack,ranged,whichType,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS) endfunction //============================================================ private struct Detector extends array // Uses AIDS. //! runtextmacro AIDS() private static conditionfunc ACTIONS_COND private trigger t private method AIDS_onCreate takes nothing returns nothing set this.t=CreateTrigger() call TriggerAddCondition(this.t,thistype.ACTIONS_COND) call TriggerRegisterUnitEvent(this.t,this.unit,EVENT_UNIT_DAMAGED) endmethod private method AIDS_onDestroy takes nothing returns nothing call DestroyTrigger(this.t) endmethod private static method AIDS_onInit takes nothing returns nothing set thistype.ACTIONS_COND=Condition(function OnDamageActions) endmethod endstruct //============================================================ private function OnInit takes nothing returns nothing local unit abilpreload=CreateUnit(Player(15),'uloc',0,0,0) call UnitAddAbility(abilpreload,LIFE_BONUS_ABIL) call RemoveUnit(abilpreload) set abilpreload=null set OnDamageEvent=Event.create() set TypeStackValue[TypeStackLevel]=DAMAGE_TYPE_NORMAL call TimerStart(RemoveBoostedTimer,0.0,false,function RemoveBoostedTimerFunc) endfunction endlibrary [/spoil] [spoil]// // _ ___ ___ ___ _______________________________________________ // /_\ |_ _| \/ __| || A D V A N C E D I N D E X I N G || // / _ \ | || |) \__ \ || A N D || // /_/ \_\___|___/|___/ || D A T A S T O R A G E || // By Jesus4Lyf ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ // v 1.0.3 // What is AIDS? // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ // AIDS assigns unique integers between 1 and 8191 to units which enter // the map. These can be used for arrays and data attaching. // // AIDS also allows you to define structs which are created automatically // when units enter the map, and filtering which units should be indexed // as well as for which units these structs should be created. // // How to implement? // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ // Simply create a new trigger object called AIDS, go to 'Edit -> Convert // to Custom Text', and replace everything that's there with this script. // // At the top of the script, there is a 'UnitIndexingFilter' constant // function. If the function returns true for the unit, then that unit // will be automatically indexed. Setting this to true will automatically // index all units. Setting it to false will disable automatic indexing. // // Functions: // ¯¯¯¯¯¯¯¯¯¯¯¯ // function GetUnitId takes unit u returns integer // - This returns the index of an indexed unit. This will return 0 // if the unit has not been indexed. // - This function inlines. It does not check if the unit needs an // index. This function is for the speed freaks. // - Always use this if 'UnitIndexingFilter' simply returns true. // // function GetUnitIndex takes unit u returns integer // - This will return the index of a unit if it has one, or assign // an index if the unit doesn't have one (and return the new index). // - Use this if 'UnitIndexingFilter' doesn't return true. // // function GetIndexUnit takes integer index returns unit // - This returns the unit which has been assigned the 'index'. // // AIDS Structs: // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ // - Insert: //! runtextmacro AIDS() at the top of a struct to make it // an AIDS struct. // - AIDS structs cannot be created or destroyed manually. Instead, they // are automatically created when an appropriate unit enters the map. // - You cannot give members default values in their declaration. // (eg: private integer i=5 is not allowed) // - You cannot use array members. // - AIDS structs must "extend array". This will remove some unused // functions and enforce the above so there will be no mistakes. // - There are four optional methods you can use in AIDS structs: // - AIDS_onCreate takes nothing returns nothing // - This is called when the struct is 'created' for the unit. // - In here you can assign members their default values, which // you would usually assign in their declarations. // (eg: set this.i=5) // - AIDS_onDestroy takes nothing returns nothing // - This is called when the struct is 'destroyed' for the unit. // - This is your substitute to the normal onDestroy method. // - AIDS_filter takes unit u returns boolean // - This is similar to the constant filter in the main system. // - Each unit that enters the map will be tested by each AIDS // struct filter. If it returns true for that unit, that unit // will be indexed if it was not already, the AIDS struct will // have its AIDS_onCreate method called, and later have its // AIDS_onDestroy method called when the index is recycled. // - Not declaring this will use the default AIDS filter instead. // - AIDS_onInit takes nothing returns nothing // - This is because I stole your onInit function with my textmacro. // - You can use '.unit' from any AIDS struct to get the unit for which // the struct is for. // - The structs id will be the units index, so getting the struct for // a unit inlines to a single native call, and you can typecast between // different AIDS structs. This is the premise of AIDS. // - Never create or destroy AIDS structs directly. // - You can call .AIDS_addLock() and AIDS_removeLock() to increase or // decrease the lock level on the struct. If a struct's lock level is // not 0, it will not be destroyed until it is reduced to 0. Locks just // put off AIDS struct destruction in case you wish to attach to a timer // or something which must expire before the struct data disappears. // Hence, not freeing all locks will leak the struct (and index). // // PUI and AutoIndex: // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ // - AIDS includes the PUI textmacros and the AutoIndex module, because // these systems are not compatible with AIDS but have valid and distinct // uses. // - The PUI textmacros are better to use for spells than AIDS structs, // because they are not created for all units, just those targetted by // the spell (or whatever else is necessary). // - The AutoData module is good for very simple array syntax for data // attachment (although I don't recommend that people actually use it, // it's here mostly for compatability). Note that unlike the PUI textmacros, // units must pass the AIDS filter in order for this module to work with // them. This is exactly as the same as in AutoIndex itself (AutoIndex // has a filter too). // // Thanks: // ¯¯¯¯¯¯¯¯¯ // - Romek, for writing 90% of this user documentation, challenging my // interface, doing some testing, suggesting improvements and inspiring // me to re-do my code to include GetUnitIndex as non-inlining. // - grim001, for writing the AutoData module, and AutoIndex. I used the // on-enter-map method that he used. Full credits for the AutoData module. // - Cohadar, for writing his PUI textmacros. Full credits to him for these, // except for my slight optimisations for this system. // Also, I have used an optimised version of his PeriodicRecycler from // PUI in this system to avoid needing a RemoveUnitEx function. // - Vexorian, for helping Cohadar on the PUI textmacro. // - Larcenist, for suggesting the AIDS acronym. Originally he suggested // 'Alternative Index Detection System', but obviously I came up with // something better. In fact, I'd say it looks like the acronym was // an accident. Kinda neat, don't you think? :P // // Final Notes: // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ // - With most systems, I wouldn't usually add substitutes for alternative // systems. However, UnitData systems are an exception, because they // are incompatible with eachother. Since using this system forbids // people from using the real PUI or AutoIndex, and a lot of resources // use either of these, it made sense not to break them all. // // - If this documentation confused you as to how to use the system, just // leave everything as default and use GetUnitId everywhere. // // - To use this like PUI (if you don't like spamming indices) simply // make the AIDS filter return false, and use GetUnitIndex. // library AIDS initializer InitAIDS //============================================================================== // Configurables // globals private constant real PERIOD = 0.03125 // Recycles 32 units/second max. endglobals // Lower to be able to recycle faster. private constant function UnitIndexingFilter takes unit u returns boolean return true endfunction //============================================================================== // System code // globals // The unit stored at an index. private unit array IndexUnit private integer array LockLevel endglobals //============================================================================== globals // Recycle stack private integer array RecycledIndex private integer MaxRecycledIndex = 0 // Previous highest index private integer MaxIndex = 0 endglobals //============================================================================== globals private integer array DecayingIndex private integer MaxDecayingIndex=0 private integer DecayChecker=0 endglobals //============================================================================== globals // The Add/Remove stack (or assign/recycle stack). // // Indexing can become recusive since units can be created on index // assignment or deallocation. // To support this, a stack is used to store the event response results. private integer ARStackLevel=0 private integer array ARStackIndex private unit array ARStackUnit // A later discovery revealed that the Add/Remove stack did not need to be // used for deallocation. The alternative used works fine... endglobals public constant function GetEnteringIndexUnit takes nothing returns unit return ARStackUnit[ARStackLevel] endfunction public function GetIndexOfEnteringUnit takes nothing returns integer // Called in AIDS structs when units do not pass the initial AIDS filter. if ARStackIndex[ARStackLevel]==0 then // Get new index, from recycler first, else new. // Store the current index on the (new) top level of the AR stack. if MaxRecycledIndex==0 then // Get new. set MaxIndex=MaxIndex+1 set ARStackIndex[ARStackLevel]=MaxIndex else // Get from recycle stack. set ARStackIndex[ARStackLevel]=RecycledIndex[MaxRecycledIndex] set MaxRecycledIndex=MaxRecycledIndex-1 endif // Store index on unit. call SetUnitUserData(ARStackUnit[ARStackLevel],ARStackIndex[ARStackLevel]) set IndexUnit[ARStackIndex[ARStackLevel]]=ARStackUnit[ARStackLevel] // Add index to recycle list. set MaxDecayingIndex=MaxDecayingIndex+1 set DecayingIndex[MaxDecayingIndex]=ARStackIndex[ARStackLevel] endif return ARStackIndex[ARStackLevel] endfunction public constant function GetIndexOfEnteringUnitAllocated takes nothing returns integer // Called in AIDS structs when units have passed the initial AIDS filter. return ARStackIndex[ARStackLevel] endfunction public constant function GetDecayingIndex takes nothing returns integer return DecayingIndex[DecayChecker] endfunction //============================================================================== globals // For structs and such which need to do things on unit index assignment. private trigger OnEnter=CreateTrigger() // The same, but for when units pass the initial filter anyway. private trigger OnEnterAllocated=CreateTrigger() // For structs and such which need to do things on unit index deallocation. private trigger OnDeallocate=CreateTrigger() endglobals public function RegisterOnEnter takes boolexpr b returns triggercondition return TriggerAddCondition(OnEnter,b) endfunction public function RegisterOnEnterAllocated takes boolexpr b returns triggercondition return TriggerAddCondition(OnEnterAllocated,b) endfunction public function RegisterOnDeallocate takes boolexpr b returns triggercondition return TriggerAddCondition(OnDeallocate,b) endfunction //============================================================================== function GetIndexUnit takes integer index returns unit debug if index==0 then debug call BJDebugMsg("|cFFFF0000Error using AIDSr Trying to get the unit of index 0.") debug elseif IndexUnit[index]==null then debug call BJDebugMsg("|cFFFF0000Error using AIDSr Trying to get the unit of unassigned index.") debug endif return IndexUnit[index] endfunction function GetUnitId takes unit u returns integer debug if u==null then debug call BJDebugMsg("|cFFFF0000Error using AIDSr Trying to get the id (inlines) of null unit.") debug elseif GetUnitUserData(u)==0 then debug call BJDebugMsg("|cFFFF0000Error using AIDSr Trying to use GetUnitId (inlines) when you should be using GetUnitIndex (unit didn't pass filter).") debug endif return GetUnitUserData(u) endfunction globals//locals private integer getindex endglobals function GetUnitIndex takes unit u returns integer // Cannot be recursive. set getindex=GetUnitId(u) if getindex==0 then // Get new index, from recycler first, else new. // Store the current index in getindex. if MaxRecycledIndex==0 then // Get new. set MaxIndex=MaxIndex+1 set getindex=MaxIndex else // Get from recycle stack. set getindex=RecycledIndex[MaxRecycledIndex] set MaxRecycledIndex=MaxRecycledIndex-1 endif // Store index on unit. call SetUnitUserData(u,getindex) set IndexUnit[getindex]=u // Add index to recycle list. set MaxDecayingIndex=MaxDecayingIndex+1 set DecayingIndex[MaxDecayingIndex]=getindex // Do not fire things here. No AIDS structs will be made at this point. endif return getindex endfunction //============================================================================== public function AddLock takes integer index returns nothing set LockLevel[index]=LockLevel[index]+1 endfunction public function RemoveLock takes integer index returns nothing set LockLevel[index]=LockLevel[index]-1 endfunction //============================================================================== private function PeriodicRecycler takes nothing returns nothing if MaxDecayingIndex>0 then set DecayChecker=DecayChecker+1 if DecayChecker>MaxDecayingIndex then set DecayChecker=1 endif if GetUnitUserData(IndexUnit[DecayingIndex[DecayChecker]])==0 then if LockLevel[DecayingIndex[DecayChecker]]==0 then // Fire things. call TriggerEvaluate(OnDeallocate) // Add the index to the recycler stack. set MaxRecycledIndex=MaxRecycledIndex+1 set RecycledIndex[MaxRecycledIndex]=DecayingIndex[DecayChecker] // Null the unit. set IndexUnit[DecayingIndex[DecayChecker]]=null // Remove index from decay list. set DecayingIndex[DecayChecker]=DecayingIndex[MaxDecayingIndex] set MaxDecayingIndex=MaxDecayingIndex-1 endif endif endif endfunction //============================================================================== public function IndexEnum takes nothing returns boolean // Can be recursive... // Start by adding another level on the AR stack (for recursion's sake). set ARStackLevel=ARStackLevel+1 // Store the current unit on the (new) top level of the AR stack. set ARStackUnit[ARStackLevel]=GetFilterUnit() if UnitIndexingFilter(ARStackUnit[ARStackLevel]) then // Get new index, from recycler first, else new. // Store the current index on the (new) top level of the AR stack. if MaxRecycledIndex==0 then // Get new. set MaxIndex=MaxIndex+1 set ARStackIndex[ARStackLevel]=MaxIndex else // Get from recycle stack. set ARStackIndex[ARStackLevel]=RecycledIndex[MaxRecycledIndex] set MaxRecycledIndex=MaxRecycledIndex-1 endif // Store index on unit. call SetUnitUserData(ARStackUnit[ARStackLevel],ARStackIndex[ARStackLevel]) set IndexUnit[ARStackIndex[ARStackLevel]]=ARStackUnit[ARStackLevel] // Add index to recycle list. set MaxDecayingIndex=MaxDecayingIndex+1 set DecayingIndex[MaxDecayingIndex]=ARStackIndex[ARStackLevel] // Fire things. call TriggerEvaluate(OnEnter) else // The unit did not pass the filters, so does not need to be auto indexed. // However, for certain AIDS structs, it may still require indexing. // These structs may index the unit on their creation. // We flag that an index must be assigned by setting the current index to 0. set ARStackIndex[ARStackLevel]=0 // Fire things. call TriggerEvaluate(OnEnter) endif // Decrement the stack. set ARStackLevel=ARStackLevel-1 return false endfunction //============================================================================== private function InitAIDS takes nothing returns nothing local region r=CreateRegion() local group g=CreateGroup() local integer n=15 // This must be done first, due to recursion. :) call RegionAddRect(r,bj_mapInitialPlayableArea) call TriggerRegisterEnterRegion(CreateTrigger(),r,Condition(function IndexEnum)) set r=null loop call GroupEnumUnitsOfPlayer(g,Player(n),Condition(function IndexEnum)) //Enum every non-filtered unit on the map during initialization and assign it a unique //index. By using GroupEnumUnitsOfPlayer, even units with Locust can be detected. exitwhen n==0 set n=n-1 endloop call DestroyGroup(g) set g=null call TimerStart(CreateTimer(),PERIOD,true,function PeriodicRecycler) endfunction //============================================================================== public struct DEFAULT extends array method AIDS_onCreate takes nothing returns nothing endmethod method AIDS_onDestroy takes nothing returns nothing endmethod static method AIDS_filter takes unit u returns boolean return UnitIndexingFilter(u) endmethod static method AIDS_onInit takes nothing returns nothing endmethod endstruct //=========================================================================== // Never create or destroy AIDS structs directly. // Also, do not initialise members except by using the AIDS_onCreate method. //=========================================================================== //! textmacro AIDS // This magic line makes default methods get called which do nothing // if the method are otherwise undefined. private static delegate AIDS_DEFAULT AIDS_DELEGATE=0 //----------------------------------------------------------------------- // Gotta know whether or not to destroy on deallocation... private boolean AIDS_instanciated //----------------------------------------------------------------------- static method operator[] takes unit whichUnit returns thistype return GetUnitId(whichUnit) endmethod method operator unit takes nothing returns unit // Allows structVar.unit to return the unit. return GetIndexUnit(this) endmethod //----------------------------------------------------------------------- method AIDS_addLock takes nothing returns nothing call AIDS_AddLock(this) endmethod method AIDS_removeLock takes nothing returns nothing call AIDS_RemoveLock(this) endmethod //----------------------------------------------------------------------- private static method AIDS_onEnter takes nothing returns boolean // At this point, the unit might not have been assigned an index. if thistype.AIDS_filter(AIDS_GetEnteringIndexUnit()) then // Flag it for destruction on deallocation. set thistype(AIDS_GetIndexOfEnteringUnit()).AIDS_instanciated=true // Can use inlining "Assigned" function now, as it must be assigned. call thistype(AIDS_GetIndexOfEnteringUnitAllocated()).AIDS_onCreate() endif return false endmethod private static method AIDS_onEnterAllocated takes nothing returns boolean // At this point, the unit must have been assigned an index. if thistype.AIDS_filter(AIDS_GetEnteringIndexUnit()) then // Flag it for destruction on deallocation. Slightly faster! set thistype(AIDS_GetIndexOfEnteringUnitAllocated()).AIDS_instanciated=true // Can use inlining "Assigned" function now, as it must be assigned. call thistype(AIDS_GetIndexOfEnteringUnitAllocated()).AIDS_onCreate() endif return false endmethod private static method AIDS_onDeallocate takes nothing returns boolean if thistype(AIDS_GetDecayingIndex()).AIDS_instanciated then call thistype(AIDS_GetDecayingIndex()).AIDS_onDestroy() // Unflag destruction on deallocation. set thistype(AIDS_GetDecayingIndex()).AIDS_instanciated=false endif return false endmethod //----------------------------------------------------------------------- private static method onInit takes nothing returns nothing call AIDS_RegisterOnEnter(Condition(function thistype.AIDS_onEnter)) call AIDS_RegisterOnEnterAllocated(Condition(function thistype.AIDS_onEnterAllocated)) call AIDS_RegisterOnDeallocate(Condition(function thistype.AIDS_onDeallocate)) // Because I robbed you of your struct's onInit method. call thistype.AIDS_onInit() endmethod //! endtextmacro endlibrary library PUI uses AIDS //=========================================================================== // Allowed PUI_PROPERTY TYPES are: unit, integer, real, boolean, string // Do NOT put handles that need to be destroyed here (timer, trigger, ...) // Instead put them in a struct and use PUI textmacro //=========================================================================== //! textmacro PUI_PROPERTY takes VISIBILITY, TYPE, NAME, DEFAULT $VISIBILITY$ struct $NAME$ private static unit array pui_unit private static $TYPE$ array pui_data //----------------------------------------------------------------------- // Returns default value when first time used //----------------------------------------------------------------------- static method operator[] takes unit whichUnit returns $TYPE$ local integer pui = GetUnitId(whichUnit) // Changed from GetUnitIndex. if .pui_unit[pui] != whichUnit then set .pui_unit[pui] = whichUnit set .pui_data[pui] = $DEFAULT$ endif return .pui_data[pui] endmethod //----------------------------------------------------------------------- static method operator[]= takes unit whichUnit, $TYPE$ whichData returns nothing local integer pui = GetUnitIndex(whichUnit) set .pui_unit[pui] = whichUnit set .pui_data[pui] = whichData endmethod endstruct //! endtextmacro //=========================================================================== // Never destroy PUI structs directly. // Use .release() instead, will call .destroy() //=========================================================================== //! textmacro PUI private static unit array pui_unit private static integer array pui_data private static integer array pui_id //----------------------------------------------------------------------- // Returns zero if no struct is attached to unit //----------------------------------------------------------------------- static method operator[] takes unit whichUnit returns integer local integer pui = GetUnitId(whichUnit) // Changed from GetUnitIndex. // Switched the next two lines for optimisation. if .pui_unit[pui] != whichUnit then if .pui_data[pui] != 0 then // recycled index detected call .destroy(.pui_data[pui]) set .pui_unit[pui] = null set .pui_data[pui] = 0 endif endif return .pui_data[pui] endmethod //----------------------------------------------------------------------- // This will overwrite already attached struct if any //----------------------------------------------------------------------- static method operator[]= takes unit whichUnit, integer whichData returns nothing local integer pui = GetUnitIndex(whichUnit) if .pui_data[pui] != 0 then call .destroy(.pui_data[pui]) endif set .pui_unit[pui] = whichUnit set .pui_data[pui] = whichData set .pui_id[whichData] = pui endmethod //----------------------------------------------------------------------- // If you do not call release struct will be destroyed when unit handle gets recycled //----------------------------------------------------------------------- method release takes nothing returns nothing local integer pui= .pui_id[integer(this)] call .destroy() set .pui_unit[pui] = null set .pui_data[pui] = 0 endmethod //! endtextmacro endlibrary library AutoIndex uses AIDS module AutoData private static thistype array data // Fixed up the below to use thsitype instead of integer. static method operator []= takes unit u, thistype i returns nothing set .data[GetUnitId(u)] = i //Just attaching a struct to the unit endmethod //using the module's thistype array. static method operator [] takes unit u returns thistype return .data[GetUnitId(u)] //Just returning the attached struct. endmethod endmodule endlibrary [/spoil] [spoil]//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~ Event ~~ By Jesus4Lyf ~~ Version 1.02 ~~ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // What is Event? // - Event simulates Warcraft III events. They can be created, // registered for, fired and also destroyed. // - Event, therefore, can also be used like a trigger "group". // - This was created when there was an influx of event style systems // emerging that could really benefit from a standardised custom // events snippet. Many users were trying to achieve the same thing // and making the same kind of errors. This snippet aims to solve that. // // Functions: // - Event.create() --> Creates a new Event. // - .chainDestroy() --> Destroys an Event. // DO NOT use .destroy(). // - .fire() --> Fires all triggers which have been // registered on this Event. // - .register(trigger) --> Registers another trigger on this Event. // // Details: // - Event is extremely efficient and lightweight. // - It is safe to use with dynamic triggers. // - Internally, it is just a singularly linked list. Very simple. // // How to import: // - Create a trigger named Event. // - Convert it to custom text and replace the whole trigger text with this. // // Thanks: // - Builder Bob for the trigger destroy detection method. // - Azlier for inspiring this by ripping off my dodgier code. // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ library Event /////////////// // EventRegs // //////////////////////////////////////////////////////////////////////////// // For reading this far, you can learn one thing more. // Unlike normal Warcraft III events, you can attach to Event registries. // // Event Registries are registrations of one trigger on one event. // These cannot be created or destroyed, just attached to. // // It is VERY efficient for loading and saving data. // // Functions: // - set eventReg.data = someStruct --> Store data. // - eventReg.data --> Retreive data. // - Event.getTriggeringEventReg() --> Get the triggering EventReg. // struct EventReg integer data method clear takes nothing returns nothing set this.data=0 endmethod endstruct struct Event private trigger trig private Event next static method create takes nothing returns Event local Event this=Event.allocate() set this.next=0 return this endmethod private static Event current static method getTriggeringEventReg takes nothing returns EventReg return .current endmethod private static trigger t method fire takes nothing returns nothing // this = last. loop set .current=this.next exitwhen .current==0 set .t=.current.trig if IsTriggerEnabled(.t) then if TriggerEvaluate(.t) then call TriggerExecute(.t) endif set this=.current else call EnableTrigger(.t) // Was trigger destroyed? if IsTriggerEnabled(.t) then call DisableTrigger(.t) set this=.current else // If trigger destroyed... set .current.trig=null set this.next=.current.next call .current.destroy() endif endif endloop endmethod method register takes trigger t returns EventReg local Event new=Event.allocate() set new.next=this.next set new.trig=t set this.next=new call EventReg(new).clear() return new endmethod method chainDestroy takes nothing returns nothing loop call this.destroy() set this=this.next exitwhen this==0 set this.trig=null endloop endmethod endstruct ///////////////////////////////////////////////////// // Demonstration Functions & Alternative Interface // //////////////////////////////////////////////////////////////////////////// // What this would look like in normal WC3 style JASS (should all inline). // function CreateEvent takes nothing returns Event return Event.create() endfunction function DestroyEvent takes Event whichEvent returns nothing call whichEvent.chainDestroy() endfunction function FireEvent takes Event whichEvent returns nothing call whichEvent.fire() endfunction function TriggerRegisterEvent takes trigger whichTrigger, Event whichEvent returns EventReg return whichEvent.register(whichTrigger) endfunction // And for EventRegs... function SetEventRegData takes EventReg whichEventReg, integer data returns nothing set whichEventReg.data=data endfunction function GetEventRegData takes EventReg whichEventReg returns integer return whichEventReg.data endfunction function GetTriggeringEventReg takes nothing returns integer return Event.getTriggeringEventReg() endfunction endlibrary [/spoil] [spoil]//! textmacro CreateNec takes CODE, NAME, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN //! external ObjectMerger w3a AItg dmg$CODE$ aart "" anam "Damage ($NAME$)" ansf "(Necromastery)" alev 10 Iatt 1 $ONE$ Iatt 2 $TWO$ Iatt 3 $THREE$ Iatt 4 $FOUR$ Iatt 5 $FIVE$ Iatt 6 $SIX$ Iatt 7 $SEVEN$ Iatt 8 $EIGHT$ Iatt 9 $NINE$ Iatt 10 $TEN$ aite 0 //! endtextmacro //! runtextmacro CreateNec("0", "10000's", "0", "10000", "20000", "30000", "40000", "50000", "60000", "70000", "80000", "90000") //! runtextmacro CreateNec("1", "1000's", "0", "1000", "2000", "3000", "4000", "5000", "6000", "7000", "8000", "9000") //! runtextmacro CreateNec("2", "100's", "0", "100", "200", "300", "400", "500", "600", "700", "800", "900") //! runtextmacro CreateNec("3", "10's", "0", "10", "20", "30", "40", "50", "60", "70", "80", "90") //! runtextmacro CreateNec("4", "1's", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9") //! external ObjectMerger w3a Acri ARS0 aart "" alev 3 arac "other" areq "" arqa "" ansf "(Reduction)" anam "Requiem of Souls" Cri2 1 0 Cri3 1 0.15 Cri3 2 0.20 Cri3 3 0.25 Cri1 1 0.15 Cri1 2 0.20 Cri1 3 0.25 abuf 1 BRS0 abuf 2 BRS0 abuf 3 BRS0 aran 1 99999 aran 2 99999 aran 3 99999 acdn 1 0 ahdu 1 0 ahdu 2 0 ahdu 3 0 adur 1 0 adur 2 0 adur 3 0 amcs 1 0 atar 1 "" atp1 1 "" aub1 1 "" //! external ObjectMerger w3h Bcri BRS0 fart "ReplaceableTextures\CommandButtons\BTNDizzy.blp" ftat "Abilities\Spells\Undead\Possession\PossessionTarget.mdl" fta0 "overhead" ftac 1 frac "other" fnam "Requiem of Souls" ftip "Requiem of Souls" fube "This unit has been hit by evil spirits; its movement speed and damage have been reduced." //! external ObjectMerger w3u nalb nECD uabi Aloc ucbs 0 udtm 0 ushr 0 umdl "Abilities\Weapons\AvengerMissile\AvengerMissile.mdl" usca 1 ushu "None" util " " umvh 0 umvf 0 umvs 522 umas 522 umis 522 ucol 0 urac "human" unam "Necromastery Dummy" utip " " utub " " usid 0 usin 0 //! external ObjectMerger w3u nalb sHAD uabi Aloc ucbs 0 udtm 0 ushr 0 umdl "Abilities\Spells\Undead\AnimateDead\AnimateDeadTarget.mdl" usca 1 ushu "None" util " " umvh 0 umvf 0 umvs 522 umas 522 umis 522 ucol 0 urac "human" unam "Shadowraze Dummy" utip " " utub " " usid 0 usin 0 //! external ObjectMerger w3u nalb rOSD uabi Aloc ucbs 0 udtm 0 ushr 0 umdl "Objects\Spawnmodels\Undead\UndeadDissipate\UndeadDissipate.mdl" usca 1 ushu "None" util " " umvh 0 umvf 0 umvs 522 umas 522 umis 522 ucol 0 urac "human" unam "Requiem of Souls Dummy" utip " " utub " " usid 0 usin 0 //! external ObjectMerger w3u nalb cAST uabi Aloc ucbs 0 udtm 0 ushr 0 umdl "none.mdl" usca 0.1 ushu "None" util " " umvh 0 umvf 0 umvs 0 umas 0 umis 0 ucol 0 urac "human" unam "Caster Dummy" utip " " utub " " usid 0 usin 0 //! external ObjectMerger w3u nalb prel uabi Aloc ucbs 0 udtm 0 ushr 0 umdl "none.mdl" usca 0.1 ushu "None" util " " umvh 0 umvf 0 umvs 0 umas 0 umis 0 ucol 0 urac "human" unam "Preloader" utip " " utub " " usid 0 usin 0[/spoil] Ai rảnh có thể giúp em để sửa được ko ạ em luôn gặp lỗi khi save map ạ.
Đầu tiên cần Jassnewgenpack 1.5d! nếu đã có mà save không được mời bạn xem và tải về ngay X Design Pack của dh-g ! Từ đó có thể save được! Thứ hai là muốn sửa vui lòng bạn bỏ vào Mã: [/code.] để dễ nhìn bạn nhé! Như vậy người ta dễ trả lời hơn!
Thêm 1 trigger này nữa ạ, khi em copy nó vào map thì nó báo lỗi là... Mã: call PolledWait2(1.) Mã: scope BloodBath globals private integer abil_id = 'A066' // Blood Bath ability rawcode private real unit_id = .05 // Factor per level for units killed private real hero_id = .1 // Factor per level for heroes killed private string SFX = "Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilSpecialArt.mdl" // Effect created on killer endglobals private function Conditions takes nothing returns boolean return GetUnitAbilityLevel(GetKillingUnit(),abil_id)>0 and not IsUnitType(GetDyingUnit(),UNIT_TYPE_STRUCTURE) endfunction private function Actions takes nothing returns nothing local real hp local effect sfx = AddSpecialEffectTarget(SFX,GetKillingUnit(),"overhead") if(IsUnitType(GetDyingUnit(),UNIT_TYPE_HERO))then set hp = hero_id else set hp = unit_id endif set hp = GetUnitAbilityLevel(GetKillingUnit(),abil_id)*hp*GetUnitState(GetDyingUnit(),UNIT_STATE_MAX_LIFE) call SetWidgetLife(GetKillingUnit(),GetUnitState(GetKillingUnit(),UNIT_STATE_LIFE)+hp) call PolledWait2(1.) call DestroyEffect(sfx) set sfx = null endfunction //=========================================================================== public function InitTrig takes nothing returns nothing local trigger trig = CreateTrigger( ) call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_DEATH) call TriggerAddAction( trig, function Actions ) call TriggerAddCondition(trig,Condition(function Conditions)) endfunction endscope có ai giải thích được hộ em tại sao nó lại bị thế được ko ạ :(
Đơn giản lắm, nếu muốn biết đúng hay sai, cứ việc gõ call PolledW rồi nó gợi ý ra đúng nghĩ liền hà! Hàm trên bỏ số 2 ở call PolledWait đi nghĩ sẽ là: call PolledWait(.1)
Cảm ơn anh , anh có thể cho em yahoo để em tiện hỏi về Jass được ko ạ (nhân tiện em học hỏi thêm từ anh )
em mới lấy 1 spell Jass ở trên Hiveworkshop về nhưng sau khi chỉnh lại hết raw code thì nó báo là lỗi cái trigger của system đó ạ, cụ thể như sau: Mã: Line 8186: "type", "struct", "interface", "function", "keyword" or "scope" private static unit thistype array [spoil] Mã: // // _ ___ ___ ___ _______________________________________________ // /_\ |_ _| \/ __| || A D V A N C E D I N D E X I N G || // / _ \ | || |) \__ \ || A N D || // /_/ \_\___|___/|___/ || D A T A S T O R A G E || // By Jesus4Lyf ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ // v 1.0.5 // What is AIDS? // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ // AIDS assigns unique integers between 1 and 8191 to units which enter // the map. These can be used for arrays and data attaching. // // AIDS also allows you to define structs which are created automatically // when units enter the map, and filtering which units should be indexed // as well as for which units these structs should be created. // // How to implement? // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ // Simply create a new trigger object called AIDS, go to 'Edit -> Convert // to Custom Text', and replace everything that's there with this script. // // Save the map, close it, reopen it, and then delete the "!" from the // FAR left side of the next lines (so "external" will line up with this line): // external ObjectMerger w3a Adef AIDS anam "State Detection" ansf "(AIDS)" aart "" arac 0 // // At the top of the script, there is a 'UnitIndexingFilter' constant // function. If the function returns true for the unit, then that unit // will be automatically indexed. Setting this to true will automatically // index all units. Setting it to false will disable automatic indexing. // // Functions: // ¯¯¯¯¯¯¯¯¯¯¯¯ // function GetUnitId takes unit u returns integer // - This returns the index of an indexed unit. This will return 0 // if the unit has not been indexed. // - This function inlines. It does not check if the unit needs an // index. This function is for the speed freaks. // - Always use this if 'UnitIndexingFilter' simply returns true. // // function GetUnitIndex takes unit u returns integer // - This will return the index of a unit if it has one, or assign // an index if the unit doesn't have one (and return the new index). // - Use this if 'UnitIndexingFilter' doesn't return true. // // function GetIndexUnit takes integer index returns unit // - This returns the unit which has been assigned the 'index'. // // AIDS Structs: // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ // - Insert: //! runtextmacro AIDS() at the top of a struct to make it // an AIDS struct. // - AIDS structs cannot be created or destroyed manually. Instead, they // are automatically created when an appropriate unit enters the map. // - You cannot give members default values in their declaration. // (eg: private integer i=5 is not allowed) // - You cannot use array members. // - AIDS structs must "extend array". This will remove some unused // functions and enforce the above so there will be no mistakes. // - There are four optional methods you can use in AIDS structs: // - AIDS_onCreate takes nothing returns nothing // - This is called when the struct is 'created' for the unit. // - In here you can assign members their default values, which // you would usually assign in their declarations. // (eg: set this.i=5) // - AIDS_onDestroy takes nothing returns nothing // - This is called when the struct is 'destroyed' for the unit. // - This is your substitute to the normal onDestroy method. // - AIDS_filter takes unit u returns boolean // - This is similar to the constant filter in the main system. // - Each unit that enters the map will be tested by each AIDS // struct filter. If it returns true for that unit, that unit // will be indexed if it was not already, the AIDS struct will // have its AIDS_onCreate method called, and later have its // AIDS_onDestroy method called when the index is recycled. // - Not declaring this will use the default AIDS filter instead. // - AIDS_onInit takes nothing returns nothing // - This is because I stole your onInit function with my textmacro. // - You can use '.unit' from any AIDS struct to get the unit for which // the struct is for. // - The structs id will be the units index, so getting the struct for // a unit inlines to a single native call, and you can typecast between // different AIDS structs. This is the premise of AIDS. // - Never create or destroy AIDS structs directly. // - You can call .AIDS_addLock() and AIDS_removeLock() to increase or // decrease the lock level on the struct. If a struct's lock level is // not 0, it will not be destroyed until it is reduced to 0. Locks just // put off AIDS struct destruction in case you wish to attach to a timer // or something which must expire before the struct data disappears. // Hence, not freeing all locks will leak the struct (and index). // // PUI and AutoIndex: // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ // - AIDS includes the PUI textmacros and the AutoIndex module, because // these systems are not compatible with AIDS but have valid and distinct // uses. // - The PUI textmacros are better to use for spells than AIDS structs, // because they are not created for all units, just those targetted by // the spell (or whatever else is necessary). // - The AutoData module is good for very simple array syntax for data // attachment (although I don't recommend that people actually use it, // it's here mostly for compatability). Note that unlike the PUI textmacros, // units must pass the AIDS filter in order for this module to work with // them. This is exactly as the same as in AutoIndex itself (AutoIndex // has a filter too). // // Thanks: // ¯¯¯¯¯¯¯¯¯ // - Romek, for writing 90% of this user documentation, challenging my // interface, doing some testing, suggesting improvements and inspiring // me to re-do my code to include GetUnitIndex as non-inlining. // - grim001, for writing the AutoData module, and AutoIndex. I used the // on-enter-map method that he used. Full credits for the AutoData module. // - Cohadar, for writing his PUI textmacros. Full credits to him for these, // except for my slight optimisations for this system. // Also, I have used an optimised version of his PeriodicRecycler from // PUI in this system to avoid needing a RemoveUnitEx function. // - Vexorian, for helping Cohadar on the PUI textmacro. // - Larcenist, for suggesting the AIDS acronym. Originally he suggested // 'Alternative Index Detection System', but obviously I came up with // something better. In fact, I'd say it looks like the acronym was // an accident. Kinda neat, don't you think? :P // // Final Notes: // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ // - With most systems, I wouldn't usually add substitutes for alternative // systems. However, UnitData systems are an exception, because they // are incompatible with eachother. Since using this system forbids // people from using the real PUI or AutoIndex, and a lot of resources // use either of these, it made sense not to break them all. // // - If this documentation confused you as to how to use the system, just // leave everything as default and use GetUnitId everywhere. // // - To use this like PUI (if you don't like spamming indices) simply // make the AIDS filter return false, and use GetUnitIndex. // library AIDS initializer InitAIDS //============================================================================== // Configurables // globals private constant boolean USE_PERIODIC_RECYCLER = false private constant real PERIOD = 0.03125 // Recycles 32 units/second max. // Lower to be able to recycle faster. // Only used if USE_PERIODIC_RECYCLER // is set to true. private constant integer LEAVE_DETECTION_ABILITY = 'AIDS' endglobals private function UnitIndexingFilter takes unit u returns boolean return true endfunction //============================================================================== // System code // globals // The unit stored at an index. private unit array IndexUnit private integer array LockLevel endglobals //============================================================================== globals // Recycle stack private integer array RecycledIndex private integer MaxRecycledIndex = 0 // Previous highest index private integer MaxIndex = 0 endglobals //============================================================================== globals private integer array DecayingIndex private integer MaxDecayingIndex=0 private integer DecayChecker=0 endglobals globals private timer UndefendTimer=CreateTimer() private integer array UndefendIndex private integer UndefendStackIndex=0 endglobals globals private integer array UndefendExpiringIndex private integer UndefendExpiringIndexLevel=0 endglobals //============================================================================== globals // The Add/Remove stack (or assign/recycle stack). // // Indexing can become recusive since units can be created on index // assignment or deallocation. // To support this, a stack is used to store the event response results. private integer ARStackLevel=0 private integer array ARStackIndex private unit array ARStackUnit // A later discovery revealed that the Add/Remove stack did not need to be // used for deallocation. The alternative used works fine... endglobals public constant function GetEnteringIndexUnit takes nothing returns unit return ARStackUnit[ARStackLevel] endfunction public function GetIndexOfEnteringUnit takes nothing returns integer // Called in AIDS structs when units do not pass the initial AIDS filter. if ARStackIndex[ARStackLevel]==0 then // Get new index, from recycler first, else new. // Store the current index on the (new) top level of the AR stack. if MaxRecycledIndex==0 then // Get new. set MaxIndex=MaxIndex+1 set ARStackIndex[ARStackLevel]=MaxIndex else // Get from recycle stack. set ARStackIndex[ARStackLevel]=RecycledIndex[MaxRecycledIndex] set MaxRecycledIndex=MaxRecycledIndex-1 endif // Store index on unit. call SetUnitUserData(ARStackUnit[ARStackLevel],ARStackIndex[ARStackLevel]) set IndexUnit[ARStackIndex[ARStackLevel]]=ARStackUnit[ARStackLevel] // Add index to recycle list. set MaxDecayingIndex=MaxDecayingIndex+1 set DecayingIndex[MaxDecayingIndex]=ARStackIndex[ARStackLevel] endif return ARStackIndex[ARStackLevel] endfunction public constant function GetIndexOfEnteringUnitAllocated takes nothing returns integer // Called in AIDS structs when units have passed the initial AIDS filter. return ARStackIndex[ARStackLevel] endfunction public constant function GetDecayingIndex takes nothing returns integer static if USE_PERIODIC_RECYCLER then return DecayingIndex[DecayChecker] else return UndefendExpiringIndex[UndefendExpiringIndexLevel] endif endfunction //============================================================================== globals // For structs and such which need to do things on unit index assignment. private trigger OnEnter=CreateTrigger() // The same, but for when units pass the initial filter anyway. private trigger OnEnterAllocated=CreateTrigger() // For structs and such which need to do things on unit index deallocation. private trigger OnDeallocate=CreateTrigger() endglobals public function RegisterOnEnter takes boolexpr b returns triggercondition return TriggerAddCondition(OnEnter,b) endfunction public function RegisterOnEnterAllocated takes boolexpr b returns triggercondition return TriggerAddCondition(OnEnterAllocated,b) endfunction public function RegisterOnDeallocate takes boolexpr b returns triggercondition return TriggerAddCondition(OnDeallocate,b) endfunction //============================================================================== function GetIndexUnit takes integer index returns unit debug if index==0 then debug call BJDebugMsg("|cFFFF0000Error using AIDS:|r Trying to get the unit of index 0.") debug elseif IndexUnit[index]==null then debug call BJDebugMsg("|cFFFF0000Error using AIDS:|r Trying to get the unit of unassigned index.") debug endif return IndexUnit[index] endfunction function GetUnitId takes unit u returns integer debug if u==null then debug call BJDebugMsg("|cFFFF0000Error using AIDS:|r Trying to get the id (inlines) of null unit.") debug elseif GetUnitUserData(u)==0 then debug call BJDebugMsg("|cFFFF0000Error using AIDS:|r Trying to use GetUnitId (inlines) when you should be using GetUnitIndex (unit didn't pass filter).") debug endif return GetUnitUserData(u) endfunction globals//locals private integer getindex endglobals function GetUnitIndex takes unit u returns integer // Cannot be recursive. debug if u==null then debug call BJDebugMsg("|cFFFF0000Error using AIDS:|r Trying to get the index of null unit.") debug endif set getindex=GetUnitUserData(u) if getindex==0 then // Get new index, from recycler first, else new. // Store the current index in getindex. if MaxRecycledIndex==0 then // Get new. set MaxIndex=MaxIndex+1 set getindex=MaxIndex else // Get from recycle stack. set getindex=RecycledIndex[MaxRecycledIndex] set MaxRecycledIndex=MaxRecycledIndex-1 endif // Store index on unit. call SetUnitUserData(u,getindex) set IndexUnit[getindex]=u static if USE_PERIODIC_RECYCLER then // Add index to recycle list. set MaxDecayingIndex=MaxDecayingIndex+1 set DecayingIndex[MaxDecayingIndex]=getindex else // Add leave detection ability. call UnitAddAbility(ARStackUnit[ARStackLevel],LEAVE_DETECTION_ABILITY) call UnitMakeAbilityPermanent(ARStackUnit[ARStackLevel],true,LEAVE_DETECTION_ABILITY) endif // Do not fire things here. No AIDS structs will be made at this point. endif return getindex endfunction //============================================================================== public function AddLock takes integer index returns nothing set LockLevel[index]=LockLevel[index]+1 endfunction public function RemoveLock takes integer index returns nothing set LockLevel[index]=LockLevel[index]-1 static if not USE_PERIODIC_RECYCLER then if GetUnitUserData(IndexUnit[index])==0 and LockLevel[index]==0 then // Increment stack for recursion. set UndefendExpiringIndexLevel=UndefendExpiringIndexLevel+1 set UndefendExpiringIndex[UndefendExpiringIndexLevel]=index // Fire things. call TriggerEvaluate(OnDeallocate) // Decrement stack for recursion. set UndefendExpiringIndexLevel=UndefendExpiringIndexLevel-1 // Add the index to the recycler stack. set MaxRecycledIndex=MaxRecycledIndex+1 set RecycledIndex[MaxRecycledIndex]=index // Null the unit. set IndexUnit[index]=null endif endif endfunction //============================================================================== static if USE_PERIODIC_RECYCLER then private function PeriodicRecycler takes nothing returns nothing if MaxDecayingIndex>0 then set DecayChecker=DecayChecker+1 if DecayChecker>MaxDecayingIndex then set DecayChecker=1 endif if GetUnitUserData(IndexUnit[DecayingIndex[DecayChecker]])==0 then if LockLevel[DecayingIndex[DecayChecker]]==0 then // Fire things. call TriggerEvaluate(OnDeallocate) // Add the index to the recycler stack. set MaxRecycledIndex=MaxRecycledIndex+1 set RecycledIndex[MaxRecycledIndex]=DecayingIndex[DecayChecker] // Null the unit. set IndexUnit[DecayingIndex[DecayChecker]]=null // Remove index from decay list. set DecayingIndex[DecayChecker]=DecayingIndex[MaxDecayingIndex] set MaxDecayingIndex=MaxDecayingIndex-1 endif endif endif endfunction else private function UndefendFilter takes nothing returns boolean return IsUnitType(GetFilterUnit(),UNIT_TYPE_DEAD) endfunction private function OnUndefendTimer takes nothing returns nothing loop exitwhen UndefendStackIndex==0 set UndefendStackIndex=UndefendStackIndex-1 set UndefendExpiringIndex[0]=UndefendIndex[UndefendStackIndex] if IndexUnit[UndefendExpiringIndex[0]]!=null then if GetUnitUserData(IndexUnit[UndefendExpiringIndex[0]])==0 then if LockLevel[UndefendExpiringIndex[0]]==0 then // Fire things. call TriggerEvaluate(OnDeallocate) // Add the index to the recycler stack. set MaxRecycledIndex=MaxRecycledIndex+1 set RecycledIndex[MaxRecycledIndex]=UndefendExpiringIndex[0] // Null the unit. set IndexUnit[UndefendExpiringIndex[0]]=null endif endif endif endloop endfunction globals//locals private integer UndefendFilterIndex endglobals private function OnUndefend takes nothing returns boolean if GetIssuedOrderId()==852056 then // If undefend then... set UndefendFilterIndex=GetUnitUserData(GetOrderedUnit()) if UndefendIndex[UndefendStackIndex-1]!=UndefendFilterIndex then // Efficiency perk. set UndefendIndex[UndefendStackIndex]=UndefendFilterIndex set UndefendStackIndex=UndefendStackIndex+1 call TimerStart(UndefendTimer,0,false,function OnUndefendTimer) endif endif return false endfunction endif //============================================================================== public function IndexEnum takes nothing returns boolean // Can be recursive... // Start by adding another level on the AR stack (for recursion's sake). set ARStackLevel=ARStackLevel+1 // Store the current unit on the (new) top level of the AR stack. set ARStackUnit[ARStackLevel]=GetFilterUnit() if GetUnitUserData(ARStackUnit[ARStackLevel])==0 then // Has not been indexed. if UnitIndexingFilter(ARStackUnit[ARStackLevel]) then // Get new index, from recycler first, else new. // Store the current index on the (new) top level of the AR stack. if MaxRecycledIndex==0 then // Get new. set MaxIndex=MaxIndex+1 set ARStackIndex[ARStackLevel]=MaxIndex else // Get from recycle stack. set ARStackIndex[ARStackLevel]=RecycledIndex[MaxRecycledIndex] set MaxRecycledIndex=MaxRecycledIndex-1 endif // Store index on unit. call SetUnitUserData(ARStackUnit[ARStackLevel],ARStackIndex[ARStackLevel]) set IndexUnit[ARStackIndex[ARStackLevel]]=ARStackUnit[ARStackLevel] static if USE_PERIODIC_RECYCLER then // Add index to recycle list. set MaxDecayingIndex=MaxDecayingIndex+1 set DecayingIndex[MaxDecayingIndex]=ARStackIndex[ARStackLevel] else // Add leave detection ability. call UnitAddAbility(ARStackUnit[ARStackLevel],LEAVE_DETECTION_ABILITY) call UnitMakeAbilityPermanent(ARStackUnit[ARStackLevel],true,LEAVE_DETECTION_ABILITY) endif // Fire things. call TriggerEvaluate(OnEnter) else // The unit did not pass the filters, so does not need to be auto indexed. // However, for certain AIDS structs, it may still require indexing. // These structs may index the unit on their creation. // We flag that an index must be assigned by setting the current index to 0. set ARStackIndex[ARStackLevel]=0 // Fire things. call TriggerEvaluate(OnEnter) endif endif // Decrement the stack. set ARStackLevel=ARStackLevel-1 return false endfunction //============================================================================== private function InitAIDS takes nothing returns nothing local region r=CreateRegion() local group g=CreateGroup() local integer n=15 static if USE_PERIODIC_RECYCLER then call TimerStart(UndefendTimer,PERIOD,true,function PeriodicRecycler) else local trigger t=CreateTrigger() loop call TriggerRegisterPlayerUnitEvent(t,Player(n),EVENT_PLAYER_UNIT_ISSUED_ORDER,Filter(function UndefendFilter)) call SetPlayerAbilityAvailable(Player(n),LEAVE_DETECTION_ABILITY,false) // Capture "undefend" orders. exitwhen n==0 set n=n-1 endloop set n=15 call TriggerAddCondition(t,Filter(function OnUndefend)) set t=null endif // This must be done first, due to recursion. :) call RegionAddRect(r,GetWorldBounds()) call TriggerRegisterEnterRegion(CreateTrigger(),r,Filter(function IndexEnum)) set r=null loop call GroupEnumUnitsOfPlayer(g,Player(n),Filter(function IndexEnum)) //Enum every non-filtered unit on the map during initialization and assign it a unique //index. By using GroupEnumUnitsOfPlayer, even units with Locust can be detected. exitwhen n==0 set n=n-1 endloop call DestroyGroup(g) set g=null endfunction //============================================================================== public struct DEFAULT extends array method AIDS_onCreate takes nothing returns nothing endmethod method AIDS_onDestroy takes nothing returns nothing endmethod static method AIDS_filter takes unit u returns boolean return UnitIndexingFilter(u) endmethod static method AIDS_onInit takes nothing returns nothing endmethod endstruct //=========================================================================== // Never create or destroy AIDS structs directly. // Also, do not initialise members except by using the AIDS_onCreate method. //=========================================================================== //! textmacro AIDS // This magic line makes default methods get called which do nothing // if the methods are otherwise undefined. private static delegate AIDS_DEFAULT AIDS_DELEGATE=0 //----------------------------------------------------------------------- // Gotta know whether or not to destroy on deallocation... private boolean AIDS_instanciated //----------------------------------------------------------------------- static method operator[] takes unit whichUnit returns thistype return GetUnitId(whichUnit) endmethod method operator unit takes nothing returns unit // Allows structVar.unit to return the unit. return GetIndexUnit(this) endmethod //----------------------------------------------------------------------- method AIDS_addLock takes nothing returns nothing call AIDS_AddLock(this) endmethod method AIDS_removeLock takes nothing returns nothing call AIDS_RemoveLock(this) endmethod //----------------------------------------------------------------------- private static method AIDS_onEnter takes nothing returns boolean // At this point, the unit might not have been assigned an index. if thistype.AIDS_filter(AIDS_GetEnteringIndexUnit()) then // Flag it for destruction on deallocation. set thistype(AIDS_GetIndexOfEnteringUnit()).AIDS_instanciated=true // Can use inlining "Assigned" function now, as it must be assigned. call thistype(AIDS_GetIndexOfEnteringUnitAllocated()).AIDS_onCreate() endif return false endmethod private static method AIDS_onEnterAllocated takes nothing returns boolean // At this point, the unit must have been assigned an index. if thistype.AIDS_filter(AIDS_GetEnteringIndexUnit()) then // Flag it for destruction on deallocation. Slightly faster! set thistype(AIDS_GetIndexOfEnteringUnitAllocated()).AIDS_instanciated=true // Can use inlining "Assigned" function now, as it must be assigned. call thistype(AIDS_GetIndexOfEnteringUnitAllocated()).AIDS_onCreate() endif return false endmethod private static method AIDS_onDeallocate takes nothing returns boolean if thistype(AIDS_GetDecayingIndex()).AIDS_instanciated then call thistype(AIDS_GetDecayingIndex()).AIDS_onDestroy() // Unflag destruction on deallocation. set thistype(AIDS_GetDecayingIndex()).AIDS_instanciated=false endif return false endmethod //----------------------------------------------------------------------- private static method onInit takes nothing returns nothing call AIDS_RegisterOnEnter(Filter(function thistype.AIDS_onEnter)) call AIDS_RegisterOnEnterAllocated(Filter(function thistype.AIDS_onEnterAllocated)) call AIDS_RegisterOnDeallocate(Filter(function thistype.AIDS_onDeallocate)) // Because I robbed you of your struct's onInit method. call thistype.AIDS_onInit() endmethod //! endtextmacro endlibrary library PUI uses AIDS //=========================================================================== // Allowed PUI_PROPERTY TYPES are: unit, integer, real, boolean, string // Do NOT put handles that need to be destroyed here (timer, trigger, ...) // Instead put them in a struct and use PUI textmacro //=========================================================================== //! textmacro PUI_PROPERTY takes VISIBILITY, TYPE, NAME, DEFAULT $VISIBILITY$ struct $NAME$ private static unit array pui_unit private static $TYPE$ array pui_data //----------------------------------------------------------------------- // Returns default value when first time used //----------------------------------------------------------------------- static method operator[] takes unit whichUnit returns $TYPE$ local integer pui = GetUnitId(whichUnit) // Changed from GetUnitIndex. if .pui_unit[pui] != whichUnit then set .pui_unit[pui] = whichUnit set .pui_data[pui] = $DEFAULT$ endif return .pui_data[pui] endmethod //----------------------------------------------------------------------- static method operator[]= takes unit whichUnit, $TYPE$ whichData returns nothing local integer pui = GetUnitIndex(whichUnit) set .pui_unit[pui] = whichUnit set .pui_data[pui] = whichData endmethod endstruct //! endtextmacro //=========================================================================== // Never destroy PUI structs directly. // Use .release() instead, will call .destroy() //=========================================================================== //! textmacro PUI private static unit array pui_unit private static integer array pui_data private static integer array pui_id //----------------------------------------------------------------------- // Returns zero if no struct is attached to unit //----------------------------------------------------------------------- static method operator[] takes unit whichUnit returns integer local integer pui = GetUnitId(whichUnit) // Changed from GetUnitIndex. // Switched the next two lines for optimisation. if .pui_unit[pui] != whichUnit then if .pui_data[pui] != 0 then // recycled index detected call .destroy(.pui_data[pui]) set .pui_unit[pui] = null set .pui_data[pui] = 0 endif endif return .pui_data[pui] endmethod //----------------------------------------------------------------------- // This will overwrite already attached struct if any //----------------------------------------------------------------------- static method operator[]= takes unit whichUnit, integer whichData returns nothing local integer pui = GetUnitIndex(whichUnit) if .pui_data[pui] != 0 then call .destroy(.pui_data[pui]) endif set .pui_unit[pui] = whichUnit set .pui_data[pui] = whichData set .pui_id[whichData] = pui endmethod //----------------------------------------------------------------------- // If you do not call release struct will be destroyed when unit handle gets recycled //----------------------------------------------------------------------- method release takes nothing returns nothing local integer pui= .pui_id[integer(this)] call .destroy() set .pui_unit[pui] = null set .pui_data[pui] = 0 endmethod //! endtextmacro endlibrary library AutoIndex uses AIDS module AutoData [B]private static thistype array[/B] // Fixed up the below to use thsitype instead of integer. static method operator []= takes unit u, thistype i returns nothing set .data[GetUnitId(u)] = i //Just attaching a struct to the unit endmethod //using the module's thistype array. static method operator [] takes unit u returns thistype return .data[GetUnitId(u)] //Just returning the attached struct. endmethod endmodule endlibrary [/spoil] ai có thể fix lại dùm em được ko ạ :( em mò cả đêm rồi mà vẫn chưa tìm được cách fix
em sửa như anh nói nhưng giờ nó lại bị lỗi ở 1 trigger khác ạ... Mã: private module InitModule Trigger Damage [spoil] Mã: // // ___ _ __ __ _ ___ ____ _______________________________ // | \ /_\ / |/ | /_\ / _\| __| || D E A L I T , || // | |) / _ \ / / | / |/ _ \| |/|| __| || D E T E C T I T , || // |___/_/ \_/_/|__/|_|_/ \_\___/|____| || B L O C K I T . || // By Jesus4Lyf ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ // v 1.0.5 // What is Damage? // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ // Damage is a damage dealing, detection and blocking system. It implements // all such functionality. It also provides a means to detect what type // of damage was dealt, so long as all damage in your map is dealt using // this system's deal damage functions (except for basic attacks). // // It is completely recursively defined, meaning if you deal damage on // taking damage, the type detection and other features like blocking // will not malfunction. // // How to implement? // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ // Create a new trigger object called Damage, go to 'Edit -> Convert to // Custom Text', and replace everything that's there with this script. // // At the top of the script, there is a '//! external ObjectMerger' line. // Save your map, close your map, reopen your map, and then comment out this // line. Damage is now implemented. This line creates a dummy ability used // in the system in some circumstances with damage blocking. // // Functions: // ¯¯¯¯¯¯¯¯¯¯¯¯ // function Damage_RegisterEvent takes trigger whichTrigger returns nothing // - This registers a special "any unit takes damage" event. // - This event supports dynamic trigger use. // - Only triggers registered on this event may block damage. // - Only fires when the damage dealt is not 0. // // function Damage_RegisterZeroEvent takes trigger whichTrigger returns nothing // - The same as Damage_RegisterEvent, but for only zero damage events // (which are excluded from Damage_RegisterEvent). // - Note that getting the damage type may be unreliable, since spells // like faerie fire trigger 0 damage, but it will count as an attack. // // function Damage_GetType takes nothing returns damagetype // - This will get the type of damage dealt, like an event response, // for when using a unit takes damage event (or the special event above). // // function Damage_IsPhysical takes nothing returns boolean // function Damage_IsSpell takes nothing returns boolean // function Damage_IsPure takes nothing returns boolean // - Wrappers to simply check if Damage_GetType is certain types. // // function Damage_IsAttack takes nothing returns boolean // - Checks if the damage is from a physical attack (so you can deal // physical damage without it being registered as an actual attack). // // function Damage_Block takes real amount returns nothing // function Damage_BlockAll takes nothing returns nothing // - For use only with Damage_RegisterEvent. // - Blocks 'amount' of the damage dealt. // - Multiple blocks at once work correctly. // - Blocking more than 100% of the damage will block 100% instead. // - Damage_BlockAll blocks 100% of the damage being dealt. // // function Damage_EnableEvent takes boolean enable returns nothing // - For disabling and re-enabling the special event. // - Use it to deal damage which you do not want to be detected by // the special event. // // function UnitDamageTargetEx takes lots of things returns boolean // - Replaces UnitDamageTarget in your map, with the same arguments. // // function Damage_Physical takes unit source, unit target, real amount, // attacktype whichType, boolean attack, boolean ranged returns boolean // - A clean wrapper for physical damage. // - 'attack' determines if this is to be treated as a real physical // attack or just physical type damage. // - 'ranged' determines if this is to be treated as a ranged or melee // attack. // // function Damage_Spell takes unit source, unit target, real amount returns boolean // - A clean wrapper for spell damage. // // function Damage_Pure takes unit source, unit target, real amount returns boolean // - A clean wrapper for pure type damage (universal type, 100% damage). // // Thanks: // ¯¯¯¯¯¯¯¯¯ // - Romek, for helping me find a better way to think about damage blocking. // library Damage uses AIDS, Event //============================================================ globals private constant integer LIFE_BONUS_ABIL='dprv' endglobals //============================================================ globals private Event OnDamageEvent private Event OnZeroDamageEvent private boolean EventEnabled=true endglobals public function RegisterEvent takes trigger whichTrigger returns nothing call OnDamageEvent.register(whichTrigger) endfunction public function RegisterZeroEvent takes trigger whichTrigger returns nothing call OnZeroDamageEvent.register(whichTrigger) endfunction public function EnableEvent takes boolean enable returns nothing set EventEnabled=enable endfunction //============================================================ globals private integer TypeStackLevel=0 private damagetype array TypeStackValue private boolean array TypeStackAttack private real array ToBlock endglobals public function GetType takes nothing returns damagetype return TypeStackValue[TypeStackLevel] endfunction public function IsAttack takes nothing returns boolean return TypeStackAttack[TypeStackLevel] endfunction public function Block takes real amount returns nothing set ToBlock[TypeStackLevel]=ToBlock[TypeStackLevel]+amount endfunction public function BlockAll takes nothing returns nothing set ToBlock[TypeStackLevel]=ToBlock[TypeStackLevel]+GetEventDamage() endfunction //============================================================ globals private integer BlockNum=0 private unit array BlockUnit private real array BlockUnitLife private real array BlockRedamage private unit array BlockDamageSource private timer BlockTimer=CreateTimer() endglobals //============================================================ globals private unit array RemoveBoosted private integer RemoveBoostedMax=0 private timer RemoveBoostedTimer=CreateTimer() endglobals globals//locals private real BoostedLifeTemp private unit BoostedLifeUnit endglobals private function RemoveBoostedTimerFunc takes nothing returns nothing loop exitwhen RemoveBoostedMax==0 set BoostedLifeUnit=RemoveBoosted[RemoveBoostedMax] set BoostedLifeTemp=GetWidgetLife(BoostedLifeUnit) call UnitRemoveAbility(BoostedLifeUnit,LIFE_BONUS_ABIL) if BoostedLifeTemp>0.405 then call SetWidgetLife(BoostedLifeUnit,BoostedLifeTemp) endif set RemoveBoostedMax=RemoveBoostedMax-1 endloop endfunction //============================================================ private keyword Detector // Darn, I actually had to do this. XD globals//locals private unit ForUnit private real NextHealth endglobals private function OnDamageActions takes nothing returns boolean if EventEnabled then if GetEventDamage()==0. then call OnZeroDamageEvent.fire() else call OnDamageEvent.fire() endif if ToBlock[TypeStackLevel]!=0. then //==================================================== // Blocking set ForUnit=GetTriggerUnit() set NextHealth=GetEventDamage() if ToBlock[TypeStackLevel]>=NextHealth then set NextHealth=GetWidgetLife(ForUnit)+NextHealth else set NextHealth=GetWidgetLife(ForUnit)+ToBlock[TypeStackLevel] endif call SetWidgetLife(ForUnit,NextHealth) if GetWidgetLife(ForUnit)<NextHealth then // NextHealth is over max health. call UnitAddAbility(ForUnit,LIFE_BONUS_ABIL) call SetWidgetLife(ForUnit,NextHealth) set RemoveBoostedMax=RemoveBoostedMax+1 set RemoveBoosted[RemoveBoostedMax]=ForUnit call ResumeTimer(RemoveBoostedTimer) endif //==================================================== set ToBlock[TypeStackLevel]=0. endif endif return false endfunction //============================================================ function UnitDamageTargetEx takes unit whichUnit, widget target, real amount, boolean attack, boolean ranged, attacktype attackType, damagetype damageType, weapontype weaponType returns boolean local boolean result set TypeStackLevel=TypeStackLevel+1 set TypeStackValue[TypeStackLevel]=damageType set TypeStackAttack[TypeStackLevel]=attack set result=UnitDamageTarget(whichUnit,target,amount,attack,ranged,attackType,damageType,weaponType) set TypeStackLevel=TypeStackLevel-1 return result endfunction //! textmacro Damage__DealTypeFunc takes NAME, TYPE public function $NAME$ takes unit source, unit target, real amount returns boolean return UnitDamageTargetEx(source,target,amount,false,false,ATTACK_TYPE_NORMAL,$TYPE$,WEAPON_TYPE_WHOKNOWS) endfunction public function Is$NAME$ takes nothing returns boolean return GetType()==$TYPE$ endfunction //! endtextmacro //! runtextmacro Damage__DealTypeFunc("Pure","DAMAGE_TYPE_UNIVERSAL") //! runtextmacro Damage__DealTypeFunc("Spell","DAMAGE_TYPE_MAGIC") // Uses different stuff, but works much the same way. public function Physical takes unit source, unit target, real amount, attacktype whichType, boolean attack, boolean ranged returns boolean return UnitDamageTargetEx(source,target,amount,attack,ranged,whichType,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS) endfunction public function IsPhysical takes nothing returns boolean return GetType()==DAMAGE_TYPE_NORMAL endfunction //============================================================ private struct Detector extends array // Uses AIDS. //! runtextmacro AIDS() private static conditionfunc ACTIONS_COND private trigger t private method AIDS_onCreate takes nothing returns nothing set this.t=CreateTrigger() call TriggerAddCondition(this.t,thistype.ACTIONS_COND) call TriggerRegisterUnitEvent(this.t,this.unit,EVENT_UNIT_DAMAGED) endmethod private method AIDS_onDestroy takes nothing returns nothing call DestroyTrigger(this.t) endmethod private static method AIDS_onInit takes nothing returns nothing set thistype.ACTIONS_COND=Condition(function OnDamageActions) endmethod endstruct //============================================================ private module InitModule private static method onInit takes nothing returns nothing local unit abilpreload=CreateUnit(Player(15),'uloc',0,0,0) call UnitAddAbility(abilpreload,LIFE_BONUS_ABIL) call RemoveUnit(abilpreload) set abilpreload=null set OnDamageEvent=Event.create() set OnZeroDamageEvent=Event.create() set TypeStackValue[TypeStackLevel]=DAMAGE_TYPE_NORMAL set TypeStackAttack[TypeStackLevel]=true call TimerStart(RemoveBoostedTimer,0.0,false,function RemoveBoostedTimerFunc) endmethod endmodule private struct InitStruct extends array implement InitModule endstruct endlibrary [/spoil] đây là spell em down từ hive work shop về ạ, nó khá hay nhưng em ko biết làm cách nào để cóp hẳn vào map mình nên đành nhờ anh xem hộ em http://www.mediafire.com/?xo7hkasur9nncsq (Link sạch ko virus)
Em cóp 1 cái system từ map blade n demon của anh dragon, nhưng khi save thì nó bị lỗi như sau: Mã: Line xxx: Function redeclared: H2I Line xxxx: previous declaration [b]Function H2I takes handle h returns integer[/b] Em đã hỏi anh Romek về lỗi nhưng sau khi fix xong thì nó bị như thế này...