| 02-04-2009, 06:29 AM | #1 |
Farms and Mills work differently in my map and I want them to take up a certain area in which no other Farms/Mills can be built. Auxiliary to this is a function that displays the area a Farm/Mill takes up when it is selected by a (any) player - like a blue circle pops-up around a Protoss Pylon in Starcraft as it is selected. This script determines which player has selected w/e unit. If a unit is selected, it identifies the selecting player as the player has not had it selected but currently does. If a unit is deselected, it identifies the deselecting player as the player that has had it selected but currently does not. This method involves some indexing of selected units which seems like too much, are there any other simpler ways? JASS:library GetSelectionEventPlayer initializer Init globals private constant integer MAX_INSTANCES = 8190 //IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII// //IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII// //IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII// //IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII// player bj_LastSelectingPlayer = null player bj_LastDeselectingPlayer = null endglobals //IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII// //IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII// function GetSelectingPlayer takes nothing returns player return bj_LastSelectingPlayer endfunction function GetDeselectingPlayer takes nothing returns player return bj_LastDeselectingPlayer endfunction //IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII// //IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII// private keyword SelectedUnit private function Monitor takes nothing returns boolean local unit U = GetTriggerUnit() local SelectedUnit SU = SelectedUnit.Get(U) local integer INT_Index = 0 local player P if GetTriggerEventId() == EVENT_PLAYER_UNIT_SELECTED then loop exitwhen INT_Index == 12 set P = Player(INT_Index) if SU.boolIs[INT_Index] == false and IsUnitSelected(U, P) then set SU.boolIs[INT_Index] = true set SU.intCountSelecter = SU.intCountSelecter + 1 set bj_LastSelectingPlayer = P set U = null set P = null return false endif set INT_Index = INT_Index + 1 endloop else loop exitwhen INT_Index == 12 set P = Player(INT_Index) if SU.boolIs[INT_Index] and IsUnitSelected(U, P) == false then set SU.boolIs[INT_Index] = true set SU.intCountSelecter = SU.intCountSelecter - 1 if SU.intCountSelecter == 0 then call SU.Destroy() endif set bj_LastSelectingPlayer = P set U = null set P = null return false endif set INT_Index = INT_Index + 1 endloop endif set U = null set P = null return false endfunction private function Init takes nothing returns nothing local trigger TRIG = CreateTrigger() call TriggerRegisterAnyUnitEventBJ(TRIG, EVENT_PLAYER_UNIT_SELECTED) call TriggerRegisterAnyUnitEventBJ(TRIG, EVENT_PLAYER_UNIT_DESELECTED) call TriggerAddCondition(TRIG, Condition(function Monitor)) set TRIG = null endfunction private struct SelectedUnit[MAX_INSTANCES] public unit u public boolean array boolIs[12] public integer intCountSelecter = 0 private static method Create takes unit u returns SelectedUnit local integer INT_Index = 0 if SelectedUnit.intCountInst < MAX_INSTANCES then set SelectedUnit.Inst[SelectedUnit.intCountInst] = SelectedUnit.allocate() set SelectedUnit.Inst[SelectedUnit.intCountInst].u = u loop exitwhen INT_Index == 12 set SelectedUnit.Inst[SelectedUnit.intCountInst].boolIs[INT_Index] = false set INT_Index = INT_Index + 1 endloop set SelectedUnit.intCountInst = SelectedUnit.intCountInst + 1 return SelectedUnit.Inst[SelectedUnit.intCountInst - 1] endif return 0 endmethod public method Destroy takes nothing returns nothing call RemoveUnit(.uAreaIndicator) set SelectedUnit.intCountInst = SelectedUnit.intCountInst - 1 set this = SelectedUnit.Inst[SelectedUnit.intCountInst] set SelectedUnit.Inst[SelectedUnit.intCountInst] = 0 endmethod public static method Get takes unit u returns SelectedUnit local integer INT_Index = 0 loop exitwhen INT_Index == SelectedUnit.intCountInst if SelectedUnit.Inst[INT_Index].u == u then return SelectedUnit.Inst[INT_Index] endif set INT_Index = INT_Index + 1 endloop return SelectedUnit.Create(u) endmethod endstruct endlibrary JASS:library FarmOperator initializer Init requires SimError, GetSelectionEventPlayer ////////////////////////////////////////////////////////////////////// // FarmOperator //==================================================================== // Simulates all a Farm's functions in the map, 'The Razing'. // // Functions of Farms: // - Provide food to afford players more arms to defend // the land they have claimed from The Horde. // - Take up a certain area about them so that no other Farms // can be built in this area as they exist. // - Display the circumference of the area they are // established on. // - Maybe other functions later. // // *this script is also to be used as a template for MillOperator. ////////////////////////////////////////////////////////////////////// globals private constant integer FARM_UNIT_ID = 'h00A' private constant real FARM_AREA_RADIUS = 1000.00 private constant integer FARM_AREA_INDICATOR_UNIT_ID = 'h00A' private constant integer MAX_FARMS = 100 private constant integer BUILD_FARM_ORDER_ID = 174998somethingsomethingsomething private constant string BUILD_ERROR_MSG = "Unable to build a Farm there. That location is within the boundary of an already existing Farm." private group gUG = CreateGroup() endglobals private struct Farm[MAX_FARMS] private unit uFarm private player pOwner private real rX private real rY private unit uAreaIndicator public static method Create takes unit u returns boolean if Farm.intCountInst < MAX_FARMS then set Farm.Inst[Farm.intCountInst] = Farm.allocate() set Farm.Inst[Farm.intCountInst].uFarm = u set Farm.Inst[Farm.intCountInst].pOwner = GetOwningPlayer(u) set Farm.Inst[Farm.intCountInst].rX = GetUnitX(u) set Farm.Inst[Farm.intCountInst].rY = GetUnitY(u) set Farm.Inst[Farm.intCountInst].uAreaIndicator = CreateUnit(Farm.Inst[Farm.intCountInst].pOwner, AREA_INDICATOR_UNIT_ID, Farm.Inst[Farm.intCountInst].rX, Farm.Inst[Farm.intCountInst].rY, 0.00) call SetUnitVertexColor(Farm.Inst[Farm.intCountInst].uAreaIndicator, 100, 100, 100, 0) set Farm.intCountInst = Farm.intCountInst + 1 return true endif return false endmethod public method Destroy takes nothing returns nothing call RemoveUnit(.uAreaIndicator) set Farm.intCountInst = Farm.intCountInst - 1 set this = Farm.Inst[Farm.intCountInst] set Farm.Inst[Farm.intCountInst] = 0 endmethod private static Farm array Inst[MAX_FARMS] private static integer intCountInst = 0 public static method Get takes unit u returns Farm local integer INT_Index = 0 loop exitwhen INT_Index == Farm.intCountInst if Farm.Inst[INT_Index].uFarm == u then return Farm.Inst[INT_Index] endif endloop return 0 endstruct endstruct private function FilterFarm takes nothing returns boolean return GetUnitTypeId(GetFilterUnit()) == FARM_UNIT_ID endfunction private function EnforceAreaBoundary takes nothing returns boolean local unit U = GetTriggerUnit() if GetIssuedOrderId() == BUILD_FARM_ORDER_ID then //I think a single group-enum call is more efficient than comparison between //FARM_AREA_RADIUS and the distance of a Farm from the target point for each //existing farm as the latter method entails the evaluation of distance //for each existing Farm instance. call GroupEnumUnitsInRange(gUG, GetOrderPointX(), GetOrderPointY(), FARM_AREA_RADIUS, Filter(function FilterFarm)) if FirstOfGroup(gUG) != null then call SimError(GetOwningPlayer(U), BUILD_ERROR_MSG) call PauseUnit(U, true) call IssueImmediateOrder(U, "stop") call PauseUnit(U, false) endif call GroupClear(gUG) endif set U = null return false endfunction private function RegisterFarm takes nothing returns boolean local unit U = GetTriggerUnit() if GetUnitTypeId(U) == FARM_UNIT_ID then call Farm.Create(U) endif set U = null return false endfunction private function UnregisterFarm takes nothing returns boolean local unit U = GetTriggerUnit() local Farm FARM if GetUnitTypeId(U) == FARM_UNIT_ID then set FARM = Farm.Get(U) call FARM.Destroy() endif set U = null return false endfunction private function ToggleAreaBoundaryDisplay takes nothing returns boolean local unit U = GetTriggerUnit() local Farm FARM local player P if GetUnitTypeId(U) == FARM_UNIT_ID then set FARM = Farm.Get(U) set P = GetSelectingPlayer() if GetTriggerEventId() == EVENT_PLAYER_UNIT_SELECTED then if GetLocalPlayer() == P then call SetUnitVertexColor(FARM.uAreaIndicator, 100, 100, 100, 100) endif else if GetLocalPlayer() == P then call SetUnitVertexColor(FARM.uAreaIndicator, 100, 100, 100, 0) endif endif endif set U = null set P = null endfunction private function Init takes nothing returns nothing local trigger TRIG = CreateTrigger() local region REG = CreateRegion() call TriggerRegisterAnyUnitEventBJ(TRIG, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER) call TriggerAddCondition(TRIG, Condition(function EnforceAreaBoundary)) set TRIG = CreateTrigger() call RegionAddRect(REG, bj_mapInitialPlayableArea) call TriggerRegisterEnterRegion(TRIG, REG, Filter(function RegisterFarm)) set gTRIG = CreateTrigger() call TriggerRegisterLeaveRegion(TRIG, REG, Filter(function UnregisterFarm)) set gTRIG = CreateTrigger() call TriggerRegisterAnyUnitEventBJ(TRIG, EVENT_PLAYER_UNIT_SELECTED) call TriggerRegisterAnyUnitEventBJ(TRIG, EVENT_PLAYER_UNIT_DESELECTED) call TriggerAddCondition(TRIG, Condition(function ToggleAreaBoundaryDisplay)) set TRIG = null set REG = null endfunction endlibrary |
| 02-04-2009, 11:31 AM | #2 |
JASS:function Trig_Untitled_Trigger_005_Actions takes nothing returns nothing DO STUFF FOR PLAYER 1 endfunction //=========================================================================== function InitTrig_Untitled_Trigger_005 takes nothing returns nothing set gg_trg_Untitled_Trigger_005 = CreateTrigger( ) call TriggerRegisterPlayerSelectionEventBJ( gg_trg_Untitled_Trigger_005, Player(0), true ) call TriggerAddAction( gg_trg_Untitled_Trigger_005, function Trig_Untitled_Trigger_005_Actions ) endfunction function Trig_Untitled_Trigger_006_Actions takes nothing returns nothing DO STUFF FOR PLAYER 2 endfunction //=========================================================================== function InitTrig_Untitled_Trigger_006 takes nothing returns nothing set gg_trg_Untitled_Trigger_006 = CreateTrigger( ) call TriggerRegisterPlayerSelectionEventBJ( gg_trg_Untitled_Trigger_006, Player(1), true ) call TriggerAddAction( gg_trg_Untitled_Trigger_006, function Trig_Untitled_Trigger_006_Actions ) endfunction .... 12 separate triggers linked with its player (via any storage system). This will allow to get any data from GetTriggeringTrigger(), including player. Or linked to 12 cloned hardcoded by player functions, this way is no jass. This way easy as possible. |
| 02-05-2009, 02:42 AM | #3 |
HAHAHAHA thx for that alternative edit: like this? also, i assume that TriggerRegisterPlayerUnitEvent means 'Trigger register player event where player acts on unit' and not 'trigger register unit-of-player event'; coz if it's the latter then wouldnt this not work as intended? JASS:library GetSelectionEventPlayer initializer Init globals private trigger array gTRIG[12] player bj_LastSelectingPlayer = null player bj_LastDeselectingPlayer = null endglobals function GetSelectingPlayer takes nothing returns player return bj_LastSelectingPlayer endfunction function GetDeselectingPlayer takes nothing returns player return bj_LastDeselectingPlayer endfunction private function Evaluate takes nothing returns boolean local trigger TRIG = GetTriggeringTrigger() local integer INT_Index = 0 loop exitwhen gTRIG[INT_Index] == TRIG set INT_Index = INT_Index + 1 endloop if GetTriggerEventId() == EVENT_PLAYER_UNIT_SELECTED then set bj_LastSelectingPlayer = Player(INT_Index) else set bj_LastDeselectingPlayer = Player(INT_Index) endif set TRIG = null return false endfunction private function Init takes nothing returns nothing local integer INT_Index = 0 local player P loop exitwhen INT_Index == 12 set P = Player(INT_Index) set gTRIG[INT_Index] = CreateTrigger() call TriggerRegisterPlayerUnitEvent(gTRIG[INT_Index], P, EVENT_PLAYER_UNIT_SELECTED, null) call TriggerRegisterPlayerUnitEvent(gTRIG[INT_Index], P, EVENT_PLAYER_UNIT_DESELECTED, null) call TriggerAddCondition(gTRIG[INT_Index], Condition(function Evaluate)) set INT_Index = INT_Index + 1 endloop set P = null endfunction endlibrary |
| 02-05-2009, 03:50 AM | #4 |
I believe it is the later. |
| 02-05-2009, 07:03 AM | #5 |
Sync functions shoud not be called from callbacks or conditions. Any sync call cause trigger sleep(0.0) |
| 02-05-2009, 09:50 AM | #6 |
What is a sync function? edit: is it such a function that evaluates as the one here? edit2: how then can i determine (de)selecting player for a (de)selection event? |
