| 01-02-2009, 03:52 PM | #1 |
JASS:function Trig_GM_Units_Actions takes nothing returns nothing local unit u local group g = CreateGroup() local group g2 = CreateGroup() local rect r = GetPlayableMapRect() call GroupEnumUnitsInRect(g, r, null) loop set u = FirstOfGroup(g) exitwhen u == null if GetUnitTypeId(u) == 'h00A' then call GroupAddUnit(g2, u) elseif GetUnitTypeId(u) == 'h00D' then call GroupAddUnit(g2, u) endif call GroupRemoveUnit(g, u) endloop loop set u = FirstOfGroup(g2) exitwhen u == null call IssueImmediateOrder( u, "waterelemental" ) if GetUnitState(u, UNIT_STATE_MANA) == 0 then call KillUnit(u) endif call GroupRemoveUnit(g2, u) endloop call DestroyGroup(g) call RemoveRect(r) set u = null endfunction //=========================================================================== function InitTrig_GM_Units takes nothing returns nothing set gg_trg_GM_Units = CreateTrigger( ) call TriggerRegisterTimerEventPeriodic( gg_trg_GM_Units, 0.25 ) call TriggerAddAction( gg_trg_GM_Units, function Trig_GM_Units_Actions ) endfunction Why? |
| 01-02-2009, 06:54 PM | #2 |
You remove rect r instead of setting it to null (set r = null). |
| 01-02-2009, 08:28 PM | #3 |
You never enum for g2. Or clean it up. |
| 01-03-2009, 01:46 AM | #4 |
Since u is null because the loop ensures that it is null, you don't need to null u. Using a null boolexpr argument for GroupEnum will also cause a leak, as Griffen once pointed out to me. You might also want to consider ForGroups or Boolexpr enum'ing. |
| 01-03-2009, 02:24 AM | #5 |
JASS:function GetPlayableMapRect takes nothing returns rect return bj_mapInitialPlayableArea endfunction You don't need to remove the rect returned by GetPlayableMapRect since it returns a global already, you don't even need to null it. I suggest using the global variable instead of the bj function. EDIT: I forgot to mention that destroying the rect also destroys the rect held by bj_mapInitialPlayableArea so when you call GetPlayableMapRect, it will return a null handle since you destroyed it on the first execution. @ Captain Griffen: JASS:loop set u = FirstOfGroup(g) exitwhen u == null if GetUnitTypeId(u) == 'h00A' then call GroupAddUnit(g2, u) elseif GetUnitTypeId(u) == 'h00D' then call GroupAddUnit(g2, u) endif call GroupRemoveUnit(g, u) endloop I think he did add things to g2, But yes Tide's not destroying and cleaning g2. EDIT 2: Yo Tide-Arc Ephemera, I just want to suggest an alternate code, here it is: JASS:function UnitFilter takes nothing returns boolean return GetUnitTypeId(GetFilterUnit())=='h00A' or GetUnitTypeId(GetFilterUnit())=='h00D' endfunction function GroupCallback takes nothing returns nothing local unit u = GetEnumUnit() local integer id = GetUnitTypeId(u) call IssueImmediateOrder(u, "waterelemental") if ( GetUnitState(u, UNIT_STATE_MANA)==0 ) then call KillUnit(u) endif set u = null endfunction function Trig_GM_Units_Actions takes nothing returns nothing local group g = CreateGroup() call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, Condition(function UnitFilter) ) call ForGroup(g, function GroupCallback) call DestroyGroup(g) set g = null endfunction //=========================================================================== function InitTrig_GM_Units takes nothing returns nothing set gg_trg_GM_Units = CreateTrigger( ) call TriggerRegisterTimerEventPeriodic( gg_trg_GM_Units, 0.25 ) call TriggerAddAction( gg_trg_GM_Units, function Trig_GM_Units_Actions ) endfunction |
| 01-03-2009, 02:48 PM | #6 | ||||
Quote:
Quote:
Quote:
Quote:
+Rep to everyone who helped |
| 01-03-2009, 02:57 PM | #7 |
JASS:scope Rawr initializer Init globals private group g endglobals private function Expr takes nothing returns nothing if GetUnitTypeId(GetFilterUnit()) == 'h00A' or GetUnitTypeId(GetFilterUnit()) == 'h00D' then call IssueImmediateOrder(GetFilterUnit(), "waterelemental" ) if GetUnitState(GetFilterUnit(), UNIT_STATE_MANA) == 0 then call KillUnit(GetFilterUnit()) endif endif return false endfunction private function Trig_GM_Units_Actions takes nothing returns nothing call GroupEnumUnitsInRect(g, GetPlayableMapRect(), Condition(function Expr)) endfunction //=========================================================================== private function Init takes nothing returns nothing set gg_trg_GM_Units = CreateTrigger( ) call TriggerRegisterTimerEventPeriodic( gg_trg_GM_Units, 0.25 ) call TriggerAddAction( gg_trg_GM_Units, function Trig_GM_Units_Actions ) set g = CreateGroup() endfunction endscope |
| 01-03-2009, 03:09 PM | #8 |
I don't get it. Is it more efficient or faster or anything? I know it does the same thing by inserting the actions with the conditions... but is that better in any way? EDIT! By the way, I can't use vJass but would I be able to change the whole scope variable g thingo to... JASS:function Trig_GM_Units_Actions takes nothing returns nothing local group g = CreateGroup() call GroupEnumUnitsInRect(g, GetPlayableMapRect(), Condition(function Expr)) call DestroyGroup(g) endfunction |
| 01-03-2009, 04:06 PM | #9 |
The pure jass version would look like: JASS:globals trigger gg_trg_GM_Units = null group udg_CheckGroup = CreateGroup() endglobals function Expr takes nothing returns boolean if GetUnitTypeId(GetFilterUnit()) == 'h00A' or GetUnitTypeId(GetFilterUnit()) == 'h00D' then call IssueImmediateOrder(GetFilterUnit(), "waterelemental" ) if GetUnitState(GetFilterUnit(), UNIT_STATE_MANA) == 0 then call KillUnit(GetFilterUnit()) endif endif return false endfunction function Trig_GM_Units_Actions takes nothing returns nothing call GroupEnumUnitsInRect(udg_CheckGroup, GetPlayableMapRect(), Condition(function Expr)) endfunction //=========================================================================== function InitTrig_GM_Units takes nothing returns nothing set gg_trg_GM_Units = CreateTrigger( ) call TriggerRegisterTimerEventPeriodic( gg_trg_GM_Units, 0.25 ) call TriggerAddAction( gg_trg_GM_Units, function Trig_GM_Units_Actions ) endfunction The globals are generated in the variable editor / trigger editor, therefore the nasty udg_ and gg_trg prefix |
| 01-03-2009, 05:08 PM | #10 | |
Quote:
That's cool, less code, same functionality. @Tide-Arc Epherema: Yes it's more efficient since you remove 1 function call and you only iterate through the units once, my code iterated through all units in the rect and then put it onto group g, then ForGroup iterated through the contents of group g, and did some actions to the units. Captain Griffen's code on the other hand iterated through the units in the rect, and applied the actions for the selected\filtered unit. EDIT: guys, I think it's better to replace GetPlayableMapRect() with bj_mapInitialPlayableArea since the function returns the bj global, also the function wouldn't be inlined since Tide-Arc isn't using jasshelper. |
| 01-03-2009, 05:11 PM | #11 |
Alrighty, I'll use that idea. However, a new problem has presented itself. ____ This trigger is A-100%-OK Trigger: JASS:function WoodFilter takes integer i returns boolean return GetUnitTypeId(GetFilterUnit())=='h00H' and GetOwningPlayer(GetFilterUnit())==Player(i) endfunction function GoldFilter takes integer i returns boolean return GetUnitTypeId(GetFilterUnit())=='h00I' and GetOwningPlayer(GetFilterUnit())==Player(i) endfunction function Trig_GM_Income_Actions takes nothing returns nothing local integer i = 0 local group g = CreateGroup() call BJDebugMsg("Income has started") loop call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, Condition(function WoodFilter) ) call AdjustPlayerStateBJ( (udg_IntBasicWood + CountUnitsInGroup(g)), Player(i), PLAYER_STATE_RESOURCE_LUMBER ) call DestroyGroup(g) call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, Condition(function GoldFilter) ) call AdjustPlayerStateBJ( (udg_IntBasicGold + CountUnitsInGroup(g)), Player(i), PLAYER_STATE_RESOURCE_GOLD ) call DestroyGroup(g) set i = i + 1 exitwhen i == 12 endloop set g = null endfunction //=========================================================================== function InitTrig_GM_Income takes nothing returns nothing set gg_trg_GM_Income = CreateTrigger( ) call TriggerRegisterTimerExpireEventBJ( gg_trg_GM_Income, udg_TmrIncome ) call TriggerAddAction( gg_trg_GM_Income, function Trig_GM_Income_Actions ) endfunction |
| 01-03-2009, 05:17 PM | #12 |
JASS:function Trig_GM_Income_Actions takes nothing returns nothing local integer i = 0 local group g = CreateGroup() call BJDebugMsg("Income has started") loop call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, Condition(function WoodFilter) ) call AdjustPlayerStateBJ( (udg_IntBasicWood + CountUnitsInGroup(g)), Player(i), PLAYER_STATE_RESOURCE_LUMBER ) call DestroyGroup(g) call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, Condition(function GoldFilter) ) call AdjustPlayerStateBJ( (udg_IntBasicGold + CountUnitsInGroup(g)), Player(i), PLAYER_STATE_RESOURCE_GOLD ) call DestroyGroup(g) set i = i + 1 exitwhen i == 12 endloop set g = null endfunction You're destroying the group twice dude, try removing the highlighted line. Oh and you're trying to use an unknown handle, since g is still pointing to the destroyed handle group. |
| 01-03-2009, 05:20 PM | #13 |
But... but I thought if you set a group twice without cleaning... it... I thought GUI practices could cross over perfectly. Well, at least locations aren't used enough (as in for only 1 thing if ever, GetLocationZ) to impact THAT much else. Even with the line removed, it crashes for some reason. EDIT! But yeah, still used to the "don't set a group without destroying it!" practice. EDIT! I've also tried this. JASS:function Trig_GM_Income_Actions takes nothing returns nothing local integer i = 0 local group g = CreateGroup() call BJDebugMsg("Income has started") loop call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, Condition(function WoodFilter) ) call AdjustPlayerStateBJ( (udg_IntBasicWood + CountUnitsInGroup(g)), Player(i), PLAYER_STATE_RESOURCE_LUMBER ) call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, Condition(function GoldFilter) ) call AdjustPlayerStateBJ( (udg_IntBasicGold + CountUnitsInGroup(g)), Player(i), PLAYER_STATE_RESOURCE_GOLD ) set i = i + 1 exitwhen i == 12 endloop call DestroyGroup(g) set g = null endfunction |
| 01-03-2009, 05:36 PM | #14 |
Your conditions are causing the problem. If you want to pass the integer I, you cannot do so like you are currently doing. Instead, make global integer variable, set it to I, and then use the condition. |
| 01-03-2009, 05:38 PM | #15 |
Hmm, I didn't saw it earlier, you're destroying the group that you're still using, you got it incorrectly dude, you need to call GroupClear() before using the group again, not destroy it. When you destroy a group, you remove it's capability to store units, you also make the variable point to an unknown handle since the handle id when typecasted isn't a group handle anymore, maybe that's causing the crash. Please try this code instead: JASS:function Trig_GM_Income_Actions takes nothing returns nothing local integer i = 0 local group g = CreateGroup() call BJDebugMsg("Income has started") loop call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, Condition(function WoodFilter) ) call AdjustPlayerStateBJ( (udg_IntBasicWood + CountUnitsInGroup(g)), Player(i), PLAYER_STATE_RESOURCE_LUMBER ) call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, Condition(function GoldFilter) ) call AdjustPlayerStateBJ( (udg_IntBasicGold + CountUnitsInGroup(g)), Player(i), PLAYER_STATE_RESOURCE_GOLD ) set i = i + 1 exitwhen i == 12 endloop call DestroyGroup(g) set g = null endfunction EDIT: yes Ammorth is right, I didn't see it either, You can't pass values to boolexpr's, his suggestion is also good. Maybe that's causing the crash lol! |
