| 04-11-2009, 05:06 PM | #1 |
I get boring and realize i did'nt make something useless since a long time, so i plan to create a custom event response. In fact i've already did it since months, but i need some motivation to continue it. Because the hardest part is front of me, manage human and undead workers. If someone is really interested by this function, i will try my best to finish it. It could be useful for a TD or this kind of game. First you have to know that the build ability is hardcoded, i mean only the unit race of the builder does matter of how the worker will build it (like an human,an undead or all the other races, night elves,orcs,nagas,neutral, and so one) If you can remove the building ability in game, you can't add it, unless you use a morph ability ofc. Actually it already works for all CONSTRUCT events, but not for humans and undeads. They are pretty annoying to manage. I will try my best, but honestly i dunno if i will get something enough accurate and efficient, due the limitations of the editor. Here is the code : JASS:Jass: library DetectWorker initializer init uses Table globals // don't edit this global block private integer array WorkersId private integer I = 0 private group StartingWorkers private group FinishingWorkers private HandleTable Ht private unit U = null private boolean Found = false endglobals private struct s_data unit u unit worker static method create takes unit u returns s_data local s_data s = s_data.allocate() set s.u = u set Ht[u] = s return s endmethod method onDestroy takes nothing returns nothing call Ht.flush(.u) set .u = null set .worker = null endmethod endstruct globals private s_data S = 0 endglobals private function EnumWorkers takes nothing returns nothing if Found then return endif set U = GetEnumUnit() if IsUnitHidden(U) and IsUnitVisible(U,GetOwningPlayer(U)) and GetUnitX(U) == GetUnitX(GetTriggerUnit()) and GetUnitY(U) == GetUnitY(GetTriggerUnit()) then set Found = true endif endfunction private function FindWorker takes nothing returns boolean local eventid evd = GetTriggerEventId() if evd == EVENT_PLAYER_UNIT_CONSTRUCT_START then call ForGroup(StartingWorkers,function EnumWorkers) if not Found then set U = null else set Found = false call GroupRemoveUnit(StartingWorkers,U) call GroupAddUnit(FinishingWorkers,U) set S = Ht[GetTriggerUnit()] if S == 0 then set S = s_data.create(GetTriggerUnit()) endif set S.worker = U endif elseif evd == EVENT_PLAYER_UNIT_CONSTRUCT_FINISH then call ForGroup(FinishingWorkers,function EnumWorkers) if not Found then set U = null else set Found = false call GroupRemoveUnit(FinishingWorkers,U) endif elseif evd == EVENT_PLAYER_UNIT_CONSTRUCT_CANCEL then set S = Ht[GetTriggerUnit()] set U = S.worker endif return false endfunction private function ManageWorkers takes nothing returns boolean if IsUnitType(GetTriggerUnit(), UNIT_TYPE_STRUCTURE) then return false endif if GetTriggerEventId() == EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER then if UnitId2String(GetIssuedOrderId()) != null then call GroupAddUnit(StartingWorkers,GetTriggerUnit()) endif return false else call GroupRemoveUnit(StartingWorkers,GetTriggerUnit()) endif return false endfunction function GetWorker takes nothing returns unit local eventid evd = GetTriggerEventId() if evd == EVENT_PLAYER_UNIT_CONSTRUCT_START or evd == EVENT_PLAYER_UNIT_CONSTRUCT_CANCEL or evd == EVENT_PLAYER_UNIT_CONSTRUCT_FINISH or evd == EVENT_UNIT_CONSTRUCT_CANCEL or evd == EVENT_UNIT_CONSTRUCT_FINISH then return U endif debug call BJDebugMsg("function GetWorker() : you tried to use it with a wrong event (not a CONSTRUCT event)") return null endfunction private function CleanData takes nothing returns boolean if IsUnitType(GetTriggerUnit(), UNIT_TYPE_STRUCTURE) then if IsUnitInGroup(GetTriggerUnit(),StartingWorkers) then call GroupRemoveUnit(StartingWorkers,GetTriggerUnit()) set S = Ht[GetTriggerUnit()] call S.destroy() elseif IsUnitInGroup(GetTriggerUnit(),FinishingWorkers) then call GroupRemoveUnit(FinishingWorkers,GetTriggerUnit()) set S = Ht[GetTriggerUnit()] call S.destroy() endif return false endif return false endfunction private function init takes nothing returns nothing local trigger trig = CreateTrigger() call TriggerAddCondition(trig,Condition(function FindWorker)) call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_CONSTRUCT_START) call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_CONSTRUCT_CANCEL) call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_CONSTRUCT_FINISH) set trig = CreateTrigger() call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_ISSUED_ORDER) call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER) call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER) call TriggerAddCondition(trig,Condition(function ManageWorkers)) set trig = CreateTrigger() call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_DEATH) call TriggerAddCondition(trig,Condition(function CleanData)) set Ht = HandleTable.create() set StartingWorkers = CreateGroup() set FinishingWorkers = CreateGroup() set trig = null endfunction endlibrary Link to Table : http://www.wc3campaigns.net/showthread.php?t=101246 GetWorker() is not MUI by itself, you need use a local variable if you use waits. And for speed freak you should set a variable anyway, if you need to use it several times in the same function. If you plan to Remove buildings with the function RemoveUnit, you should use Code:
KillUnit(u) + ShowUnit(u,false) instead, because it could leak if you don't. Any (constructive) comments and ideas are welcome. To do : - Manage human workers - Manage undead workers - Manage humans building abilities like 'AIbl' |
