| 04-03-2006, 01:56 PM | #1 |
I am making an activateable aura type ability for my map, but I am running into some really stupid issues. My logic SEEMS to make sense, but the aura is failing to remove the effect ability from units who are no longer eligable. Any help is appreciated. Edit: And before anyone mentions it, yes I could use Vexorian's excellent aura template, but I want to do this myself, since I won't learn jack if I just use a precreated template. JASS:constant function Trig_Favor_of_Elune_BonusSpellId takes nothing returns integer return 'A006' endfunction constant function Trig_Favor_of_Elune_SpellId takes nothing returns integer return 'A007' endfunction function Trig_Favor_of_Elune_Filter takes nothing returns boolean return GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) > 0 endfunction function Trig_Favor_of_Elune_ActiveCons takes nothing returns boolean return GetIssuedOrderId()==852177 endfunction function Trig_Favor_of_Elune_PeriodicActs takes nothing returns nothing local timer t=GetExpiredTimer() local string s=GetAttachmentTable(t) local unit cast=GetTableUnit(s, "caster") local group current=CreateGroup() local group previous=GetTableGroup(s, "previous") local integer lvl=GetUnitAbilityLevel(cast, Trig_Favor_of_Elune_SpellId()) local unit temp local boolexpr cons=Condition(function Trig_Favor_of_Elune_Filter) local group aux=CreateGroup() local group aux2=CreateGroup() if GetUnitAbilityLevel(cast, 'B000') > 0 then call GroupEnumUnitsInRange(current, GetUnitX(cast), GetUnitY(cast), 500, cons) call GroupAddGroup(previous, aux) loop set temp=FirstOfGroup(current) exitwhen temp==null if IsUnitAlly(temp, GetOwningPlayer(cast)) then call UnitAddAbility(temp, Trig_Favor_of_Elune_BonusSpellId()) call SetUnitAbilityLevel(temp, Trig_Favor_of_Elune_BonusSpellId(),lvl) call GroupAddUnit(aux2, temp) endif call GroupRemoveUnit(current, temp) set temp=null endloop loop set temp=FirstOfGroup(aux) exitwhen temp==null if IsUnitInGroup(temp, aux2) then call SetUnitAbilityLevel(temp, Trig_Favor_of_Elune_BonusSpellId(),lvl) call GroupAddUnit(previous, temp) else call GroupRemoveUnit(previous, temp) call UnitRemoveAbility(temp, Trig_Favor_of_Elune_BonusSpellId()) endif call GroupRemoveUnit(aux, temp) set temp=null endloop call SetTableObject(s, "previous", previous) else loop set temp=FirstOfGroup(previous) exitwhen temp==null call UnitRemoveAbility(temp, Trig_Favor_of_Elune_BonusSpellId()) call GroupRemoveUnit(previous, temp) set temp=null endloop call DestroyGroup(previous) call ClearTimer(t) endif call DestroyGroup(aux) call DestroyGroup(aux2) call DestroyGroup(current) set aux=null set aux2=null set previous=null set current=null set cast=null set t=null endfunction function Trig_Favor_of_Elune_ActiveActs takes nothing returns nothing local unit cast=GetTriggerUnit() local timer t=CreateTimer() local string s=GetAttachmentTable(t) local group previous=CreateGroup() call SetTableObject(s, "caster", cast) call SetTableObject(s, "previous", previous) call TriggerSleepAction(1) call TimerStart(t, 2, true, function Trig_Favor_of_Elune_PeriodicActs) set cast=null set t=null set previous=null endfunction //=========================================================================== function InitTrig_Favor_of_Elune takes nothing returns nothing set gg_trg_Favor_of_Elune = CreateTrigger( ) call TriggerRegisterAnyUnitEventBJ( gg_trg_Favor_of_Elune, EVENT_PLAYER_UNIT_ISSUED_ORDER ) call TriggerAddCondition( gg_trg_Favor_of_Elune, Condition( function Trig_Favor_of_Elune_ActiveCons ) ) call TriggerAddAction( gg_trg_Favor_of_Elune, function Trig_Favor_of_Elune_ActiveActs ) endfunction |
| 04-03-2006, 02:55 PM | #2 |
Hmm ... I think it's better to do it this way like: JASS:function Trig_Favor_of_Elune_PeriodicActs takes nothing returns nothing local timer t=GetExpiredTimer() local string s=GetAttachmentTable(t) local unit cast=GetTableUnit(s,"caster") local group current local group previous=GetTableGroup(s,"previous") local integer sp=Trig_Favor_of_Elune_SpellId()///Just to make it easier to read and to improve speed a very lil local integer lvl=GetUnitAbilityLevel(cast,s) local unit temp local boolexpr cons=Condition(function Trig_Favor_of_Elune_Filter) local group aux if(GetUnitAbilityLevel(cast, 'B000')>0)then ///What's that???? Tell me set aux=CreateGroup() set current=CreateGroup() set bj_groupEnumOwningPlayer=GetOwningPlayer(cast)///just for the conditions call GroupEnumUnitsInRange(current,GetUnitX(cast),GetUnitY(cast),500,cons) call GroupAddGroup(previous,aux) call GroupClear(previous)//this must be done, or you'll keep all your units 'as' they were in range loop set temp=FirstOfGroup(current) exitwhen temp==null if not IsUnitInGroup(temp,previous) then //wasn't in range before? -> add abilitie call UnitAddAbility(temp,sp) endif call SetUnitAbilityLevel(temp,sp,lvl)//just to update it every cycle call GroupAddUnit(previous,temp)//mark the unit for next round call GroupRemoveUnit(aux,temp) //because the unit is still in range, you don't need to check it in the second loop call GroupRemoveUnit(current,temp)//remove the unit to keep the looop going on set temp=null endloop //these are just the remaining units, which aren't anymore inrange loop set temp=FirstOfGroup(aux) exitwhen temp==null call UnitRemoveAbility(temp,sp) call GroupRemoveUnit(aux,temp) set temp=null endloop ///call SetTableObject(s,"previous",previous) you don't need to store this again, it's just timewaste call DestroyGroup(aux) set aux=null call DestroyGroup(current) set current=null else loop set temp=FirstOfGroup(previous) exitwhen temp==null call UnitRemoveAbility(temp,sp) call GroupRemoveUnit(previous,temp) set temp=null endloop call DestroyGroup(previous) call ClearTimer(t) endif set previous=null set cast=null set t=null endfunction but... you just forgott to clear the group >previous< so you'll keep all units which were once affected forever affected. Thats it, I think so at least. |
| 04-03-2006, 03:12 PM | #3 |
Won't work, you are destroying 'previous'. Which is supposed to hold all the units who were given the aura effects in the previous execution of this function. And that overall condition is a buff, because this is an immolation based ability that is activateable. |
| 04-03-2006, 03:24 PM | #4 |
I don't destroy the previous group, I just clear it. |
| 04-03-2006, 03:28 PM | #5 |
I meant in essence you destroy it, when it comes time for the next execution won't it be empty? So it won't know what units were in it before. Edit: Working now, I just forgot to shunt the units who are currently being added into the previous group. |
| 04-05-2006, 07:29 PM | #6 |
No! I don't destroy it! I just clear it! And before I store all info in aux. So info is kept and next round can start. OK? |
| 04-06-2006, 11:55 AM | #7 |
Tried your way. And I am telling you dude, it doesn't work. It left shit on the guys, either way once I added another line to it it works fine. |
| 04-06-2006, 05:05 PM | #8 |
I didn't really expect it to work, cause I've done this really fast. So.. Let's do a complete rework...>>>PLEASE WAIT>>> I hope this works now (in my way): I hope you'll test this too (I did not). JASS:function Elune_SpellId takes nothing returns integer return 'your id' endfunction function Elune_BuffId takes nothing returns integer return 'your id' endfunction function Elune_Radius takes real level returns real return 500+0*level endfunction function Elune_Filter takes nothing returns boolean return((GetWidgetLife(GetFilterUnit())>0.405)and IsUnitAlly(GetFilterUnit(),bj_groupEnumOwningPlayer)) //here you can change if it affects allies or enemies or whatever you want endfunction function Elune_Actions takes nothing returns nothing local timer t=CreateTimer() local unit c=GetTriggerUnit() local unit u local group inrange=CreateGroup() local group aux=CreateGroup() local group previous=CreateGroup() local integer sp=Trig_Favor_of_Elune_SpellId() local integer lvl=GetUnitAbilityLevel(c,s) local real next=0 local boolexpr cons=Condition(function Trig_Favor_of_Elune_Filter) call TimerStart(t,3600,false,null)//I guess, the effect won't last longer than 2h ;D loop exitwhen((GetUnitAbilityLevel(c,Elune_BuffId())==0)or(GetWidgetLife(c)<=0.405)) if(TimerGetElapsed(t)>=next)then set next=next+1//the cycle when the action comes again set bj_groupEnumOwningPlayer=GetOwningPlayer(c) call GroupEnumUnitsInRange(inrange,GetUnitX(c),GetUnitY(c),Elune_Radius(lvl),cons) if(FirstOfGroup(previous)!=null)then set bj_wantDestroyGroup=false call GroupAddGroup(previous,aux) call GroupClear(previous) endif loop set u=FirstOfGroup(inrange) exitwhen u==null call GroupRemoveUnit(inrange,u) if IsUnitInGroup(u,aux) then call GroupRemoveUnit(aux,u) else call UnitAddAbility(u,sp) endif call SetUnitAbilityLevel(u,sp,lvl) call GroupAddUnit(previous,u) endloop //these are just the remaining units, which aren't anymore inrange loop set u=FirstOfGroup(aux) exitwhen u==null call GroupRemoveUnit(aux,u) call UnitRemoveAbility(u,sp) endloop call GroupClear(aux) call GroupClear(inrange) endif call TriggerSleepAction(0) endloop loop set u=FirstOfGroup(previous) exitwhen u==null call UnitRemoveAbility(u,sp) call GroupRemoveUnit(previous,u) endloop call DestroyTimer(t) set t=null call DestroyBoolExpr(cons) set cons=null call DestroyGroup(previous) set previous=null call DestroyGroup(aux) set aux=null call DestroyGroup(inrange) set inrange=null set c=null endfunction function Elune_Conditions takes nothing returns boolean return(Elune_SpellId()==GetSpellAbilityId()) endif function InitTrig_Elune takes nothing returns nothing local trigger t=CreateTrigger() call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT) call TriggerAddCondition(t,Condition(function Elune_Conditions)) call TriggerAddAction(t,function Elune_Actions) set t=null endfunction |
| 04-06-2006, 07:54 PM | #9 |
JASS:loop set u=FirstOfGroup(previous) exitwhen u==null call UnitRemoveAbility(u,sp) call GroupRemoveUnit(previous,u) set u=null endloop You can remove the set u = null line. As long as you change u before it runs out of scope, it will not hold any memory hostage. People use "null" because it is a particularly convenient value to change to. Also, the set u = null at the end of the function is unnecessary since you exitwhen null. |
| 04-08-2006, 07:56 AM | #10 |
I know. I used ChuckleBrother's code as starting resouce and was just too lazy to change. Fixed |
