1. Are you planning to upload your awesome spell or system to Hive? Please review the rules here.
    Dismiss Notice
  2. Head to the 33rd Modeling Contest Poll and drink to your heart's desire.
    Dismiss Notice
  3. Choose your means of doom in the 17th Mini Mapping Contest Poll.
    Dismiss Notice
  4. A slave to two rhythms, the 22nd Terraining Contest is here.
    Dismiss Notice
  5. The heavens smile on the old faithful. The 16th Techtree Contest has begun.
    Dismiss Notice
  6. The die is cast - the 6th Melee Mapping Contest results have been announced. Onward to the Hive Cup!
    Dismiss Notice
  7. The glory of the 20th Icon Contest is yours for the taking!
    Dismiss Notice
  8. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

[GUI-Friendly] Capture Point System 1.5b

Submitted by Tasyen
This bundle is marked as approved. It works and satisfies the submission rules.

  • Capture Point allows a Mapper to make any Unit they want to be Capturable by standing next to it long enough.

    Features


    • Register/Unregister any Unit you want in real time.
    • Change Ownership of Capture Points as soon Influence is maxed.
    • Supports any kind of Teaming.
    • Choose CaptureStyle/Influence/Range for each Capture Point specific.
    • Units can have different Influence-Power; default Hero 2, non-Hero 1, summoned 0.
    • A Progressbar as indicator.
    • Supports moving Capture Points.
    • Taken Capture Points have to be Neutralised before they can be captured again.
    • Throws Events, if influence rises/drops over % values.
    • Throws an Event as soon an Unit starts/stops influencing an Capture Point.
    • Supports the concept of TeamLeaders (A Team Leader captures all units for his team)

    1. Check Preferences "Copy unknown Variables"
    2. Copy the Empty function of "Cards Specific" Code into the target map, if yours has none ( Only default World Editor has some problems with jass calls if there is none)
    3. Copy "WithinRange"-Folder
    4. Copy "CapturePoint"-Folder - Below the "WithinRange"-Folder
    5. Copy the Bar Model.
      • Import it into your Map.
      • Inside "CapturePoint Init" choose the bar as model, if it is not.

  • Capture Style Defines how and under which situations Influence is generated.
    Code (vJASS):

    //=========================================================================================================
    //Capture Style:
    //=========================================================================================================
    //           0 = +1 Influence, if only Allies are inside the CaptureZone. -1 If only Foes.
    //           1 = Like 0; but Lose Influence, if no Ally is inside.
    //           2 = +1 Influence if more allies; -1 if more foes
    //           3 = Like 2; but Lose Influence, if no Ally is inside.
    //           4 = Influence gain/loss is done by difference of Foes and allies
    //           5 = Like 4; but Lose Influence, if no Ally is inside.

    // to define new Styles Checkout "function CaptureGetInfluenceChange" and inser them.
     


  • Definitions allows you to change some Values: They are the first real functions inside the CapturePoint-Trigger
    Code (vJASS):

    //=============================================================================
    //=========================================================================================================
    //Definitions:
    //=========================================================================================================
    //who is on default excluded from influenceing Capture Points.
    //   function CapturePointDefaultFiler takes nothing returns boolean
    //       default Structures, Neutral Passive Units, Capture Points and Aloc Units

    //   function CaptureInflunece takes unit u returns integer
    //       Definies how much a unit does Influence CapturePoints
    //           Default: Hero 2, Non-Hero 1, summoned 0.

    //   constant function CaptureTimerInterval takes nothing returns real
    //       Defines Bar/Influence Update Interval

    //   constant function CaptureBarUnitType takes nothing returns integer
    //       The ObjectId of the used GenericBar Unit, Make sure it is correct.

    //   constant function CaptureUsePercentEvents takes nothing returns boolean
    //       Enables % Influence Events

    //   constant function CapturePercentEventBase takes nothing returns integer
    //       On which x * base % a Event is Thrown

    //   constant function CapturePointDefaultStyle takes nothing returns integer
    //   constant function CapturePointDefaultInfluence takes nothing returns integer
    //   constant function CapturePointDefaultRange takes nothing returns real
    //       These 3 are used in RegisterCapturePointSimple

    //   constant function CaptureBarOffsetX takes nothing returns real
    //       Default XOffset used by not Specific CapturePoints

    //   constant function CaptureBarOffsetY takes nothing returns real
    //       Default YOffset used by not Specific CapturePoints

    //   constant function CaptureBarOffsetZ takes nothing returns real
    //       Default Flying Height of all Bars + Flying height of attached Unit
    //       used by not Specific CapturePoints
     


    They look like this one
    Code (vJASS):

    constant function CaptureUsePercentEvents takes nothing returns boolean
       return true
    endfunction
     


  • You can catch any Capturing by using this method
    • Demo ControlPoint Converted
      • Events
        • Unit - A unit Changes owner
      • Conditions
        • ((Triggering unit) is in CapturePoints) Equal to True
      • Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (Owner of (Triggering unit)) Equal to Neutral Passive
          • Then - Actions
            • Game - Display to (All players) for 6.00 seconds the text: Neutralisiert
          • Else - Actions
            • Game - Display to (All players) for 6.00 seconds the text: (farbcode[(Player number of (Triggering player))] + ((Name of (Triggering player)) + (|r has captured: + (Name of (Triggering unit)))))



    After beeing Captured this specific demolisher does not change ownership anymore.
    • Demo Demolisher one time controll
      • Events
        • Unit - Demolisher 0006 <gen> Changes owner
      • Conditions
        • (Owner of (Triggering unit)) Not equal to Neutral Passive
      • Actions
        • Set CapturePoint_Register_Unit = (Triggering unit)
        • Trigger - Run CapturePoint_DeRegister (ignoring conditions)


  • Capture Point Event allows you catch the moment an Unit starts/stopps influencening an Capture Point or if an % of the needed influence is reached.
    Code (vJASS):

    //=========================================================================================================
    //CapturePointEvent
    //=========================================================================================================
    // With CapturePointEvent you can catch some nice Situations.
    //
    //        CatpurePointEvent = 1      udg_CapturePointEventMovedUnit Starts Influenceing udg_CapturePointEventUnit
    //        CapturePointEvent = -1   udg_CapturePointEventMovedUnit stopps Influenceing udg_CapturePointEventUnit

    //        InfluencePercent Steps: udg_CapturePointEventPlayer = leadingPlayer, on a negative capturePointEvent its equal to owner.

    //        CapturePointEvent = 25  udg_CapturePointEventPlayer reached 25% Influence on udg_CapturePointEventUnit
    //        CapturePointEvent = 50  udg_CapturePointEventPlayer reached 50% Influence on udg_CapturePointEventUnit
    //        CapturePointEvent = 75  udg_CapturePointEventPlayer reached 75% Influence on udg_CapturePointEventUnit
    //        CapturePointEvent = -75 controlled CapturePoint udg_CapturePointEventUnit was reduced below 75%
    //        CapturePointEvent = -50 controlled CapturePoint udg_CapturePointEventUnit was reduced below 50%
    //        CapturePointEvent = -25 controlled CapturePoint udg_CapturePointEventUnit was reduced below 25%

    // You can modify the Percent Events in the approaching Definition

    //   constant function CapturePercentEventBase takes nothing returns integer
     

    This Trigger prints out any Percentlimit reached.
    • Demo Send Warning Controll
      • Events
        • Game - CapturePointEvent becomes greater Equal 5.00
        • Game - CapturePointEvent becomes smaller Equal -5.00
      • Conditions
      • Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • CapturePointEvent smaller as 0.00
          • Then - Actions
            • Game - Display to (All players) for 5.00 seconds the text: ((farbcode[(Player number of CapturePointEventPlayer)] + ((Name of CapturePointEventPlayer) + |r's Influence on )) + ((Name of CapturePointEventUnit) + ( went below: + ((String((Abs(CapturePointEvent)))) + %))))
          • Else - Actions
            • Game - Display to (All players) for 5.00 seconds the text: ((farbcode[(Player number of CapturePointEventPlayer)] + ((Name of CapturePointEventPlayer) + |r's Influence on )) + ((Name of CapturePointEventUnit) + ( went above: + ((String((Abs(CapturePointEvent)))) + %))))


  • The Demo Map contains an easy to use example of CapturePoints.

    Register to be capturable:


    • Demo ControlPoint init
      • Events
        • Time - Elapsed game time is 0.00 seconds
      • Conditions
      • Actions
        • Custom script: set bj_wantDestroyGroup=true
        • Unit Group - Pick every unit in (Units in (Playable map area)) and do (Actions)
          • Loop - Actions
            • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
              • If - Conditions
                • Or - Any (Conditions) are true
                  • Conditions
                    • (Unit-type of (Picked unit)) Equal to Demolisher
                    • ((Picked unit) is A structure) Equal to True
              • Then - Actions
                • -------- default Turn Intervall is 1/2 second. 16 => 8 seconds to capture --------
                • Set CapturePoint_Register_Influ = 16
                • Set CapturePoint_Register_Range = (200.00 + (Collision Size of (Picked unit)))
                • Set CapturePoint_Register_Unit = (Picked unit)
                • Set CapturePoint_Register_Style = 2
                • Trigger - Run CapturePoint_Register (ignoring conditions)
              • Else - Actions



  • The functions you call from outside.
    Code (vJASS):

    //=========================================================================================================
    //API:
    //=========================================================================================================

    //  function RegisterCapturePointSpecific takes unit u, real range, integer influence, integer style, real x, real y, real z, real scale returns boolean
    //       Makes an Unit Captureable and generateds an CaptureBar over it.

    //    function RegisterCapturePoint takes unit u, real range, integer influence, integer style returns boolean
    //       Makes an Unit Captureable and generateds an CaptureBar over it.
    //       Simple Ones use default X/Y/Z offset and the unit scale from Object Editor

    //   function RegisterCapturePointSimple takes unit u returns boolean
    //       Wrapper for RegisterCapturePoint by using the Default Values in Definitions
    //       Except for the unit.

    //   function DeRegisterCapturePoint takes unit u, boolean DeregisterUnitWithin returns boolean
    //       Makes an Captureable Unit uncaptureable again.
    //       If true the unit will be kicked out of UnitWithin too.

    //   function CapturePointStopTimer takes nothing returns nothing
    //       Stops the Influence Timer and the Grafic Update Timer of CapturePoint

    //   function CapturePointStartTimer takes nothing returns nothing
    //       Starts the timers of this System.
    //       Is done if you call this System the first time.

    //   udg_CatpurePointEvent = 1 | -1

    //API UnitWithinRange
    //   function RegisterUnitWithinRange takes unit u, real range, boolean cleanOnKilled returns boolean
    //       Start the detection for this Unit with this range
    //       can not register twice the same range onto 1 unit.

    //   function DeRegisterUnitWithinRange takes unit u, real range returns boolean
    //       Destroys the range detection with this specific Range and Unit.

    //   function DeRegisterUnitWithinRangeUnit takes unit u returns boolean
    //       Destroys all Triggers used by the unit from UnitWithinRange.
     

  • Code (vJASS):

    //CapturePoint System 1.5b
    //    By Tasyen

    //Allows to Make any Unit, you Register, captureable by staying near to it.
    //This System has to be called before it starts working, is done in "CapturePoint Init" on default.
    //Uses the UnitWithinRangeEvent

    //=========================================================================================================
    //Capture Style:
    //=========================================================================================================
    //        0 = +1 Influence, if only Allies are inside the CaptureZone. -1 If only Foes.
    //        1 = Like 0; but Lose Influence, if no Ally is inside.
    //        2 = +1 Influence if more allies; -1 if more foes
    //        3 = Like 2; but Lose Influence, if no Ally is inside.
    //        4 = Influence gain/loss is done by difference of Foes and allies
    //        5 = Like 4; but Lose Influence, if no Ally is inside.

    // to define new Styles Checkout "function CaptureGetInfluenceChange" and inser them

    //=========================================================================================================
    //CapturePointEvent
    //=========================================================================================================
    // With CapturePointEvent you can catch some nice Situations.
    //
    //         CatpurePointEvent = 1      udg_CapturePointEventMovedUnit Starts Influenceing udg_CapturePointEventUnit
    //         CapturePointEvent = -1    udg_CapturePointEventMovedUnit stopps Influenceing udg_CapturePointEventUnit
       
    //         InfluencePercent Steps: udg_CapturePointEventPlayer = leadingPlayer, on a negative capturePointEvent its equal to owner.

    //         CapturePointEvent = 25  udg_CapturePointEventPlayer reached 25% Influence on udg_CapturePointEventUnit
    //         CapturePointEvent = 50  udg_CapturePointEventPlayer reached 50% Influence on udg_CapturePointEventUnit
    //         CapturePointEvent = 75  udg_CapturePointEventPlayer reached 75% Influence on udg_CapturePointEventUnit
    //         CapturePointEvent = -75 controlled CapturePoint udg_CapturePointEventUnit was reduced below 75%
    //         CapturePointEvent = -50 controlled CapturePoint udg_CapturePointEventUnit was reduced below 50%
    //         CapturePointEvent = -25 controlled CapturePoint udg_CapturePointEventUnit was reduced below 25%

    // You can modify the Percent Events in the approaching Definition

    //=========================================================================================================
    //Definitions:
    //=========================================================================================================
    //    function CapturePointDefaultFiler takes nothing returns boolean
    //        Defines who is excluded from influencing capture points.
    //            Default: Structures, Neutral Passive Units, Capture Points and Aloc Units are exclude from using capturing.

    //    function Captureinfluence takes unit u returns integer
    //        Definies how much a unit does Influence CapturePoints
    //            Default: Hero 2, Non-Hero 1, summoned 0.

    //    constant function CaptureTimerInterval takes nothing returns real
    //        Defines Bar/Influence Update Interval

    //    constant function CaptureBarUnitType takes nothing returns integer
    //        The ObjectId of the used GenericBar Unit, Make sure it is correct.

    //    constant function CaptureUsePercentEvents takes nothing returns boolean
    //        Enables % Influence Events

    //    constant function CapturePercentEventBase takes nothing returns integer
    //        On which x * base % a Event is Thrown

    //    constant function CapturePointDefaultStyle takes nothing returns integer
    //    constant function CapturePointDefaultInfluence takes nothing returns integer
    //    constant function CapturePointDefaultRange takes nothing returns real
    //        used in RegisterCapturePointSimple

    //    constant function CaptureBarDefaultX_Offset takes nothing returns real
    //    constant function CaptureBarDefaultY_Offset takes nothing returns real
    //    constant function CaptureBarDefaultZ_Offset takes nothing returns real
    //        used by RegisterCapturePointSimple & RegisterCapturePoint

    //=========================================================================================================
    //API:
    //=========================================================================================================

    //    function RegisterCapturePointSpecific takes unit u, real range, integer influence, integer style, real x, real y, real z, real scale returns boolean
    //        Makes an Unit Captureable and generateds an CaptureBar over it.

    //     function RegisterCapturePoint takes unit u, real range, integer influence, integer style returns boolean
    //        Makes an Unit Captureable and generateds an CaptureBar over it.
    //        Simple Ones use default X/Y/Z offset and the unit scale from Object Editor

    //    function RegisterCapturePointSimple takes unit u returns boolean
    //        Wrapper for RegisterCapturePoint by using the Default Values in Definitions
    //        Except for the unit.

    //    function DeRegisterCapturePoint takes unit u, boolean DeregisterUnitWithin returns boolean
    //        Makes an Captureable Unit uncaptureable again.
    //        If true the unit will be kicked out of UnitWithin too.

    //    function CapturePointStopTimer takes nothing returns nothing
    //        Stops the Influence Timer and the Grafic Update Timer of CapturePoint

    //    function CapturePointStartTimer takes nothing returns nothing
    //        Starts the timers of this System.
    //        Is done if you call this System the first time.

    //    udg_CatpurePointEvent = 1 | -1

    //=========================================================================================================
    //        Definitions:
    //=========================================================================================================

    //Define how much influnce Influnce Generated by unit u
    //If you don't want such a behaviour simply remove anything except the last "return 1"
    function Captureinfluence takes unit u returns integer
        if IsUnitType(u, UNIT_TYPE_HERO) then
            return 2
        else
            if IsUnitType(u, UNIT_TYPE_SUMMONED) then
                return 0
            else
                return 1
            endif
        endif
        return 1  
    endfunction

    //Structures, Neutral Passive Units, Capture Points and Aloc Units are exclude from using capturing.
    function CapturePointDefaultFiler takes nothing returns boolean
        local unit u = GetTriggerUnit()
        local boolean b = not IsUnitType(u, UNIT_TYPE_STRUCTURE) and GetOwningPlayer(u) != Player(PLAYER_NEUTRAL_PASSIVE) and not IsUnitInGroup(u, udg_CapturePoints) and GetUnitAbilityLevel(u,'Aloc') == 0
        set u = null
        return b
    endfunction

    constant function CaptureUsePercentEvents takes nothing returns boolean
        return true
    endfunction
    //If Influence Rises/Falls over a negative/positive x time of this value a Event with this Value is thrown
    //Default 25/50/75 %;
    //0% Event is hardcoded excluded.
    // Anything below 5 is not Recommented.
    // Insering 0 or 1 will break the system.
    constant function CapturePercentEventBase takes nothing returns integer
        return 25
    endfunction

    //Is used in RegisterCapturePointSimple
    constant function CapturePointDefaultStyle takes nothing returns integer
        return 0
    endfunction
    constant function CapturePointDefaultRange takes nothing returns real
        return 200.0
    endfunction
    constant function CapturePointDefaultInfluence takes nothing returns integer
        return 30
    endfunction

    //Is used in RegisterCapturePointSimple & RegisterCapturePoint
    constant function CaptureBarDefaultX_Offset takes nothing returns real
        return 0.0
    endfunction
    constant function CaptureBarDefaultY_Offset takes nothing returns real
        return 50.0
    endfunction
    constant function CaptureBarDefaultZ_Offset takes nothing returns real
        return 300.0
    endfunction
    constant function CaptureBarDefaultScale takes nothing returns real
        return 3.0
    endfunction

    //How long is one Interval of Capture, The time to capture a CapturePoint is CaptureTimerInterval*Influence (*2, if Controled by foe)
    //Capture Points first have to be neutralised
    constant function CaptureTimerInterval takes nothing returns real
        return 0.5
    endfunction  


    //=========================================================================================================
    //Hashtable Indexes:
    //=========================================================================================================
    //Handle
    function CapturePointHashIndex_Group takes nothing returns integer
        return 0
    endfunction
    function CapturePointHashIndex_LeadingPlayer takes nothing returns integer
        return 1
    endfunction
    function CapturePointHashIndex_Bar takes nothing returns integer
        return 2
    endfunction
    //Real
    function CapturePointHashIndex_Range takes nothing returns integer
        return 0
    endfunction
    function CapturePointHashIndex_XOffset takes nothing returns integer
        return 1
    endfunction
    function CapturePointHashIndex_YOffset takes nothing returns integer
        return 2
    endfunction
    function CapturePointHashIndex_ZOffset takes nothing returns integer
        return 3
    endfunction
    //Int
    function CapturePointHashIndex_Influence takes nothing returns integer
        return 0
    endfunction
    function CapturePointHashIndex_InfluenceNeed takes nothing returns integer
        return 1
    endfunction
    function CapturePointHashIndex_Style takes nothing returns integer
        return 2
    endfunction
    //Boolean
    function CapturePointHashIndex_UseOffset takes nothing returns integer
        return 0
    endfunction
    //======================================================================================================
    //System Code Start
    //======================================================================================================

    function CapturePointCreateBar takes unit u, real x, real y, real z, real scale returns nothing
        local integer cpId = GetHandleId(u)
        local player owner = GetOwningPlayer(u)
        local effect bar = AddSpecialEffect(udg_CapturePointBarType, GetUnitX(u)+x, GetUnitY(u)+y)
        call BlzSetSpecialEffectTimeScale(bar, 0)    //Disalbe AutoAnimation
        call BlzSetSpecialEffectTime(bar, 0)
        call BlzSetSpecialEffectScale(bar, scale)
        call BlzSetSpecialEffectHeight(bar, GetUnitFlyHeight(u) + z + BlzGetLocalUnitZ(u))
        call SaveEffectHandle(udg_CapturePointHash,cpId,CapturePointHashIndex_Bar(), bar)
       
        if x !=  CaptureBarDefaultX_Offset() or y != CaptureBarDefaultY_Offset() or z != CaptureBarDefaultZ_Offset() then
            call SaveBoolean(udg_CapturePointHash,cpId,CapturePointHashIndex_UseOffset(),true)
            call SaveReal(udg_CapturePointHash,cpId,CapturePointHashIndex_XOffset(),x)
            call SaveReal(udg_CapturePointHash,cpId,CapturePointHashIndex_YOffset(),y)
            call SaveReal(udg_CapturePointHash,cpId,CapturePointHashIndex_ZOffset(),z)
        endif  
        if owner != Player(PLAYER_NEUTRAL_PASSIVE) then
            call BlzSetSpecialEffectTime(bar, 1)
            call BlzSetSpecialEffectColorByPlayer(bar, owner)
        endif
        set bar = null
        set owner = null
    endfunction

    function CapturePointSetupData takes unit u, real range, integer influence, integer style returns boolean
        local integer cpId = GetHandleId(u)
        local player owner = GetOwningPlayer(u)
        if IsUnitInGroup( u, udg_CapturePoints) then
            return false
        endif
        call RegisterUnitWithinRangeSuper(u, range, true, udg_CapturePointDefaultFilter, gg_trg_CapturePoint, 0, false)
        call GroupAddUnit(udg_CapturePoints, u)
        call SaveGroupHandle(udg_CapturePointHash,cpId,CapturePointHashIndex_Group(), CreateGroup() )
        call SavePlayerHandle(udg_CapturePointHash,cpId,CapturePointHashIndex_LeadingPlayer(),owner)
        call SaveReal(udg_CapturePointHash,cpId,CapturePointHashIndex_Range(),range)
        call SaveInteger(udg_CapturePointHash,cpId,CapturePointHashIndex_InfluenceNeed(),influence)
        //Start with Max Influence, if Controled already
        if owner != Player(PLAYER_NEUTRAL_PASSIVE) then
            call SaveInteger(udg_CapturePointHash,cpId,CapturePointHashIndex_Influence(),influence)
        endif
        call SaveInteger(udg_CapturePointHash,cpId,CapturePointHashIndex_Style(),style)
       
        set owner = null
        return true
    endfunction

    //Inser a Unit as Captureable Capture Unit, Range is the distance from which the unit can be captured,
    //Influence * CaptureTimerInterval() time in seconds, style defines under which situation influences changes
    //Uses more arguments to define x/y/z/facing indiviudal
    function RegisterCapturePointSpecific takes unit u, real range, integer influence, integer style, real x, real y, real z, real scale returns boolean
        if CapturePointSetupData(u, range, influence, style) then
            call CapturePointCreateBar(u, x, y, z, scale)
            return true
        else
            return false
        endif  
    endfunction


    function RegisterCapturePoint takes unit u, real range, integer influence, integer style returns boolean
        if CapturePointSetupData(u, range, influence, style) then
            call CapturePointCreateBar(u, CaptureBarDefaultX_Offset(), CaptureBarDefaultY_Offset(), CaptureBarDefaultZ_Offset(), CaptureBarDefaultScale())
            return true
        else
            return false
        endif
    endfunction

    function RegisterCapturePointSimple takes unit u returns boolean
        return RegisterCapturePoint( u, CapturePointDefaultRange(), CapturePointDefaultInfluence(), CapturePointDefaultStyle())
    endfunction

    //Makes a Capture Point uncapturable, second argument asks if it should be removed from the "Unit within"-System too.
    //Removes the Bar Unit from the game.
    function DeRegisterCapturePoint takes unit u, boolean DeregisterUnitWithin returns boolean
        local integer cpId = GetHandleId(u)
        if DeregisterUnitWithin then
            call DeRegisterUnitWithinRangeUnit(u)
        endif
        call GroupRemoveUnit(udg_CapturePoints, u)
        call DestroyGroup(LoadGroupHandle(udg_CapturePointHash,cpId,CapturePointHashIndex_Group()) )
        call BlzSetSpecialEffectTimeScale(LoadEffectHandle(udg_CapturePointHash,cpId,CapturePointHashIndex_Bar()), 10)
        call DestroyEffect(LoadEffectHandle(udg_CapturePointHash,cpId,CapturePointHashIndex_Bar()))
        call FlushChildHashtable(udg_CapturePointHash, cpId)  
        return true
    endfunction

    //This catches the WithingRangeEvent = -1
    // aka Removed/Killed/Replaced
    //We do not clean in WithinRange cause it does it onitself if this event is thrown.
    function CapturePointAutoClean takes nothing returns nothing
        call DeRegisterCapturePoint (udg_WithinRangeUnit,false)
    endfunction

    function CapturePointGetOwner takes player p returns player
        local integer teamNr = GetPlayerTeam(p)
        if GetPlayerId(p) <= GetBJMaxPlayers() and udg_CapturePointTeamLeader[teamNr] != null then
            //swap owner to the Team Leader
            return udg_CapturePointTeamLeader[teamNr]
        else
            return p
        endif
    endfunction

    //Is Called with the Custom-Event UnitWithin = 1.
    function CapturePointEnter takes nothing returns nothing
        local integer cpId = GetHandleId(udg_WithinRangeUnit)
        local player owner = GetOwningPlayer(udg_WithinRangeEnteringUnit)
        local group g = LoadGroupHandle( udg_CapturePointHash,cpId,CapturePointHashIndex_Group())
        if IsUnitInGroup(udg_WithinRangeEnteringUnit, g) then
            set owner = null
            set g = null
            return    //Do not allow twice
        endif  
        call GroupAddUnit(g ,udg_WithinRangeEnteringUnit)
       
        //Become the Leading Player if current Leadingplayer is Neutral_Passive.
        if LoadPlayerHandle(udg_CapturePointHash,cpId,CapturePointHashIndex_LeadingPlayer()) == Player(PLAYER_NEUTRAL_PASSIVE) then
            //this team has a Leader?
            set owner = CapturePointGetOwner(owner)
            call SavePlayerHandle(udg_CapturePointHash, cpId, CapturePointHashIndex_LeadingPlayer(), owner)
            call BlzSetSpecialEffectColorByPlayer(LoadEffectHandle(udg_CapturePointHash, cpId,CapturePointHashIndex_Bar()), owner)
        endif
        //Event Entered
        set udg_CapturePointEventMovedUnit = udg_WithinRangeEnteringUnit
        set udg_CapturePointEventUnit = udg_WithinRangeUnit
        set udg_CapturePointEvent = 1
        set udg_CapturePointEvent = 0
        set owner = null
        set g = null
    endfunction

    //Will Return influenceChange the result will be in Bounds of 0 to Max depending on Style regarding foes/allies.
    function CaptureGetInfluenceChange takes integer influence, integer influenceMax, integer allies, integer foes, integer style returns integer
        if style == 0 then
            if allies != 0 and foes == 0 then    //Only Allies?
                if influence == influenceMax then    //Exceed Limit?
                    return 0    //It execeeds.
                else
                    return 1
                endif  
            endif
            if allies == 0 and foes != 0 then    //Only Foes?
                if influence == 0 then    //Exceed Limit?
                    return 0    //It execeeds.
                else
                    return -1
                endif
            endif  
        endif
        if style == 1 then
            if allies != 0 and foes == 0 then    //Only Allies?
                if influence == influenceMax then
                    return 0
                else
                    return 1
                endif  
            else
                if allies == 0 then    //No allies?
                    if influence == 0 then
                        return 0
                    else
                        return -1
                    endif
                else
                    return 0    //There are Allies and Foes, do nothing!
                endif
            endif
        endif
        if style == 2 then
            if allies > foes then    //More Allies?
                if influence == influenceMax then
                    return 0
                else
                    return 1
                endif
            endif
            if  allies < foes then    //Less Allies?
                if influence == 0 then
                    return 0
                else
                    return -1
                endif
            endif
        endif
        if style == 3 then
            if allies > foes then
                if influence == influenceMax then
                    return 0
                else
                    return 1
                endif
            endif
            if  allies < foes or allies == 0 then    //Less Allies or none Ally?
                if influence == 0 then
                    return 0
                else
                    return -1
                endif
            endif
        endif
        if style == 4 then
            if influence + (allies - foes) < influenceMax then    //New Influence below Upper Limit?
                if influence + (allies - foes) > 0 then        //New Influence above lower Limit?
                    return (allies - foes)
                else
                    return    -influence    //Below Lower Limit Reduce by current Influence, to 0 it!
                endif  
            else
                return influenceMax - influence    //Above Upper Limit Return Missing to Upper Limit!
            endif
        endif
        if style == 5 then
            if allies == 0 and foes == 0 then //No Influncing Unit -> Lose 1 Influence?
                if influence == 0 then
                    return 0
                else
                    return -1
                endif
            else //Style 4
                if influence + (allies - foes) < influenceMax then  
                    if influence + (allies - foes) > 0 then
                        return (allies - foes)
                    else
                        return    -influence
                    endif      
                else
                    return influenceMax - influence
                endif
            endif  
        endif  
        return 0
    endfunction

    //Checks all x times of CapturePercentEventBase() and throws the first found Event.
    //Throws negative Events if Influence fall and a positive if Influence Rises.
    // udg_CapturePointEventUnit CapturePoint;
    // udg_CapturePointEventPlayer = leadingPlayer  -> Rising = the one will get the Point; falling the one who is losing this Point
    function CapturePointThrowEvent takes integer oldPercent, integer newPercent, unit cp, player p returns boolean
        local integer oldStep = oldPercent / CapturePercentEventBase()
        local integer newStep = newPercent / CapturePercentEventBase()
        if oldStep != newStep then    //Step changed?
            set udg_CapturePointEventUnit = cp
            set udg_CapturePointEventPlayer = p
            if oldStep < newStep then    //Rise?
                set udg_CapturePointEvent = newStep * CapturePercentEventBase()
            else    //Fallen below newstep + 1 (old => 8 new = 6 you enter 60% realm -> lose the 70% Influence)
                set udg_CapturePointEvent = -(newStep+1) * CapturePercentEventBase()
            endif
            set udg_CapturePointEvent = 0
            return true
        endif
        return false
    endfunction

    //Group Enumeration for all CapturePoints, Changes Influence, Ownership and Bar Color.
    function CapturePointsLoop takes nothing returns nothing
        local unit cp = GetEnumUnit()
        local unit u
        local real oldPercent
        local real newPercent
        local integer cpId = GetHandleId(cp)
        local player leadingPlayer = LoadPlayerHandle(udg_CapturePointHash,cpId,CapturePointHashIndex_LeadingPlayer())
        local group influencingUnits = LoadGroupHandle(udg_CapturePointHash,cpId,CapturePointHashIndex_Group())
        local integer index = 0
        local integer allies = 0
        local integer foes = 0
        local real range = LoadReal(udg_CapturePointHash,cpId,CapturePointHashIndex_Range())
        local integer influence = LoadInteger(udg_CapturePointHash,cpId,CapturePointHashIndex_Influence())
        local integer influenceMax = LoadInteger(udg_CapturePointHash,cpId,CapturePointHashIndex_InfluenceNeed())
        local integer array playerInfluence
        local integer playerId
        local integer playerIdMax = bj_MAX_PLAYER_SLOTS
        local integer influenceGain
        local integer style = LoadInteger(udg_CapturePointHash,cpId,CapturePointHashIndex_Style())
        local effect bar = LoadEffectHandle(udg_CapturePointHash,cpId,CapturePointHashIndex_Bar())
        local integer influencePower
        set playerInfluence[playerIdMax] = -1
        //call GroupClear(udg_CapturePoint_TempGroup)
        loop
            set u = FirstOfGroup(influencingUnits)
            exitwhen u == null
            call GroupRemoveUnit(influencingUnits, u)
           
            //Is Unit still Influencing?
            if not IsUnitType(u, UNIT_TYPE_DEAD) and IsUnitInRange (u, cp, range) and GetUnitTypeId(u)!=0 then
                call GroupAddUnit(udg_CapturePoint_TempGroup, u)
                if not (IsUnitPaused(u)) and not (IsUnitHidden(u)) then    //can it influence now?
                    //Save Influence of this Player
                    set playerId = GetPlayerId( GetOwningPlayer (u))
                    set influencePower = Captureinfluence(u)
                    set playerInfluence[playerId] = playerInfluence[playerId] + influencePower
                    if playerInfluence[playerId] > playerInfluence[playerIdMax] then
                        set playerIdMax = playerId
                    endif  
                    //Count allies/Foes.
                    if IsUnitAlly (u, leadingPlayer) then
                        set allies = allies + influencePower
                    else
                        set foes = foes + influencePower
                    endif  
                endif
            else
                //This unit is no Influencer for this point anymore.
                //Event Unit stops Influenceing
                set udg_CapturePointEventUnit = cp
                set udg_CapturePointEventMovedUnit = u
                set udg_CapturePointEvent = -1
                set udg_CapturePointEvent = 0
            endif
        endloop
        //Refill
        loop
            set u = FirstOfGroup(udg_CapturePoint_TempGroup)
            exitwhen u == null
            call GroupRemoveUnit(udg_CapturePoint_TempGroup, u)
            call GroupAddUnit(influencingUnits,u)
        endloop  
       
        set influenceGain = CaptureGetInfluenceChange(influence,influenceMax, allies, foes, style)
        //Is there InfluenceGain?
        if influenceGain != 0  then
            set oldPercent = I2R(influence) / influenceMax
            set influence = influence + influenceGain      
            call SaveInteger(udg_CapturePointHash,cpId,CapturePointHashIndex_Influence(),influence)
            set newPercent = I2R(influence) / influenceMax
            call BlzSetSpecialEffectTime(bar, newPercent)
            //Call Influence %-Event?
            if CaptureUsePercentEvents() then
                call CapturePointThrowEvent(R2I(oldPercent*100),R2I(newPercent*100),cp,leadingPlayer)
            endif  
        endif
        if influenceGain != 0 or not IsUnitOwnedByPlayer (cp, leadingPlayer) then  
            //Neutralise the Point?
            if influence == 0 then
                //ControlLose with units?
                if FirstOfGroup(influencingUnits) != null then
                    set leadingPlayer = Player(playerIdMax)
                    call BlzSetSpecialEffectColorByPlayer(bar, leadingPlayer)
                else
                    set leadingPlayer = Player(PLAYER_NEUTRAL_PASSIVE)
                    call BlzSetSpecialEffectColorByPlayer(bar, leadingPlayer)
                endif
                call SetUnitOwner (cp, Player(PLAYER_NEUTRAL_PASSIVE), true)
                call SavePlayerHandle(udg_CapturePointHash, cpId, CapturePointHashIndex_LeadingPlayer(), CapturePointGetOwner(leadingPlayer))
                call BlzSetSpecialEffectTime(bar, 0)
            else
                //Leading Player captures it?
                if influence == influenceMax and not IsUnitOwnedByPlayer (cp, leadingPlayer) then
                    call SetUnitOwner (cp, leadingPlayer, true)
                    //Added 1.4a to support changing the ownership of the captured unit inside the change owner event
                    set leadingPlayer = GetOwningPlayer(cp)
                    call SavePlayerHandle(udg_CapturePointHash,cpId,CapturePointHashIndex_LeadingPlayer(),leadingPlayer)
                endif
                call BlzSetSpecialEffectColorByPlayer(bar, leadingPlayer)
            endif
        endif  
        //Clear Unit stack
        set leadingPlayer = null
        set cp = null
        set bar = null
        set influencingUnits = null
    endfunction

    //Group Enumeration for all CapturePoints repos Bars
    function CapturePointsReposBar takes nothing returns nothing
        local unit cp = GetEnumUnit()
        local integer cpId = GetHandleId(cp)
        local effect bar =LoadEffectHandle(udg_CapturePointHash,cpId,CapturePointHashIndex_Bar())
        //use Speciifc Offset?
        if LoadBoolean(udg_CapturePointHash,cpId,CapturePointHashIndex_UseOffset()) then
            call BlzSetSpecialEffectPosition(bar, GetUnitX(cp) + LoadReal(udg_CapturePointHash,cpId,CapturePointHashIndex_XOffset()), GetUnitY(cp) + LoadReal(udg_CapturePointHash,cpId,CapturePointHashIndex_YOffset()), GetUnitFlyHeight(cp) + LoadReal(udg_CapturePointHash,cpId,CapturePointHashIndex_ZOffset()) )
        else
            //Used Default
            call BlzSetSpecialEffectPosition(bar, GetUnitX(cp) + CaptureBarDefaultX_Offset(), GetUnitY(cp) + CaptureBarDefaultY_Offset(), GetUnitFlyHeight(cp) + BlzGetLocalUnitZ(cp) + CaptureBarDefaultZ_Offset())
        endif
        set cp = null
        set bar = null
    endfunction

    function CaptureTimerReposBar takes nothing returns nothing
        call ForGroup (udg_CapturePoints, function CapturePointsReposBar)
    endfunction

    function CaptureTimerInfluence takes nothing returns nothing
         call ForGroup (udg_CapturePoints, function CapturePointsLoop)
    endfunction

    function CapturePointStartTimer takes nothing returns nothing
        call TimerStart(udg_CapturePointTimer[0], CaptureTimerInterval(), true, function CaptureTimerInfluence)
        call TimerStart(udg_CapturePointTimer[1], 1.0/32.0, true, function CaptureTimerReposBar)
    endfunction

    function CapturePointStopTimer takes nothing returns nothing
        call PauseTimer(udg_CapturePointTimer[0])
        call PauseTimer(udg_CapturePointTimer[1])
    endfunction

    //Is Executed if you run CapturePoint the first time.
    //Start Catching Events thrown by UnitWithinRange
    //Start timer[0][1]
    function CaptureInit takes nothing returns nothing
        //Auto deregister on death/Killed/Removed
        set udg_CapturePointDefaultFilter = Condition( function CapturePointDefaultFiler)
        set udg_CapturePointAutoDeregister = CreateTrigger()
        call TriggerRegisterVariableEvent( udg_CapturePointAutoDeregister, "udg_WithinRangeEvent", EQUAL, -1 )
        call TriggerAddAction(udg_CapturePointAutoDeregister,function CapturePointAutoClean)
        //enable Capturing
        call TriggerClearActions(gg_trg_CapturePoint)
        call TriggerRegisterVariableEvent( gg_trg_CapturePoint, "udg_WithinRangeEvent", EQUAL, 1 )
        call TriggerAddAction(gg_trg_CapturePoint,function CapturePointEnter)
        call CapturePointStartTimer()
       
        set udg_CapturePointHash = InitHashtable()
       
        set udg_CapturePoint_Register_Range = CapturePointDefaultRange()
        set udg_CapturePoint_Register_Influ = CapturePointDefaultInfluence()
        set udg_CapturePoint_Register_Style = CapturePointDefaultStyle()
    endfunction

    function CaptureRegisterGUI takes nothing returns nothing
        if udg_CapturePoint_Register_Range <= 0 then
            set udg_CapturePoint_Register_Range = CapturePointDefaultRange()
        endif
        call RegisterCapturePoint(udg_CapturePoint_Register_Unit, udg_CapturePoint_Register_Range, udg_CapturePoint_Register_Influ, udg_CapturePoint_Register_Style)
        set udg_CapturePoint_Register_Range = CapturePointDefaultRange()
        set udg_CapturePoint_Register_Influ = CapturePointDefaultInfluence()
        set udg_CapturePoint_Register_Style = CapturePointDefaultStyle()
    endfunction
    function CaptureDeRegisterGUI takes nothing returns nothing
        call DeRegisterCapturePoint(udg_CapturePoint_Register_Unit, true)
    endfunction

    //===========================================================================
    function InitTrig_CapturePoint takes nothing returns nothing
        set gg_trg_CapturePoint = CreateTrigger()
        call TriggerAddAction(gg_trg_CapturePoint, function CaptureInit)
        set udg_CapturePoint_DeRegister = CreateTrigger()
        set udg_CapturePoint_Register = CreateTrigger()
        call TriggerAddAction(udg_CapturePoint_DeRegister, function CaptureDeRegisterGUI)
        call TriggerAddAction(udg_CapturePoint_Register, function CaptureRegisterGUI)
    endfunction

     

  • V1.5a/b)
    Bar now cares about terrain height.​
    V1.5)
    One can setup TeamLeaders, this TeamLeaders control capturable units for their team.​
    V1.4a)
    Supports changing owner inside final capturing.​
    V1.4)
    uses now SpecialEffects instead of Units to display the Bar.
    CPT V1.3 bugs with Warcraft 1.29 (one can select the bar units which is quite ugly).​
    uses now UnitWithin 1.5
    Less Magic Numbers
    Does not throw UnitWithin events anymore.
    Uses now Groups instead of emulating them.
    The GUI Registering will now ReLoad itself with Default values after each execution.​
    V1.3)
    uses now UnitWithin 1.4
    the bar unit Type is now defined inside "CapturePoint Init" with a variable.
    the default filter is now a variable of boolexpr used by CapturePoint.
    Included the GUI Triggers into the main Code.​
    V1.2d)
    Autocleans CapturePoints on death/Removed/Replaced, this can be disabled by disabling trigger udg_CapturePointAutoDeregister after starting the system.
    Insert some missing variables into the autogeneration block.​
    V1.2c)
    Changed function CapturePointThrowEvent
    code is now smaller/intuitiver
    throws the highest/lowest(except 0) event, if jumping multiple % limits at once.​
    fixed a bug in the demo Influence Event trigger.
    Changed repos intervale from 0.03 -> 1.0/32.0​
    V1.2b)
    There was a bug with Capture-Style 4/5.
    The demo Capture Points are included again.
    Sets Bar's XYZ/offset at Capture Point generation.
    Insert an disabled PauseTimer[1], aka Reposing Timer, inside the init.​
    V1.2a) CapturePointEvent Units are now called capturePointEventUnit and CapturePointEventMovedUnit
    V1.2) Owned Capture Points starting with a filled bar
    Renamed all RegisterUnitWithinRange Variables
    Added the new Feature CapturePointEvent:
    renamed the current Register Functions
    RegisterCapturePointSimple -> RegisterCapturePoint
    RegisterCapturePoint -> RegisterCapturePointSpecific
    Added a new one which takes only 1 argument
    RegisterCapturePointSimple takes unit u
    V1.1b) Removed a Leak in UnitWithinRange.
    V1.1a) - Fixed an Error with V1.1 and made it better.
    Version 1.1)
    Speededup The Refilling of Lost Influencer by using kind of Dynamic indexing, but will not maintain the Entering-Order anymore.​

Credits

Andrewgosu
Dr Super Good
JesusHipster
rulerofiron99
LSI.Foley


Keywords: Control Point, King of hills, Hold Ground, Influence, Take Over
Previews
Contents

CapturePoint System 1.5b (Map)

Reviews
Dr Super Good
Useful, feature filled, well documented and reasonably well written. Approved... There seems to be a lot of use of magic number constants which might effect maintainability. Additionally there is some hard coded inflexible logic which might effect...
  1. UmbraUnda

    UmbraUnda

    Joined:
    Mar 31, 2016
    Messages:
    658
    Resources:
    1
    Maps:
    1
    Resources:
    1
    Nice, very useful. Works well for many instances. 5/5
     
  2. IcemanBo

    IcemanBo

    Joined:
    Sep 6, 2013
    Messages:
    6,532
    Resources:
    23
    Maps:
    3
    Spells:
    11
    Template:
    1
    Tutorials:
    5
    JASS:
    3
    Resources:
    23
    Such a "WithinRange" submission is useful as standalone. And I would feel better, too, if it's looked at/judged seperatly, if it's used by this system.
     
  3. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    1,661
    Resources:
    37
    Tools:
    2
    Maps:
    3
    Spells:
    11
    Tutorials:
    20
    JASS:
    1
    Resources:
    37
    Good, WithinRange will be uploaded as standalone.
     
  4. Dr Super Good

    Dr Super Good

    Spell Reviewer

    Joined:
    Jan 18, 2005
    Messages:
    26,102
    Resources:
    3
    Maps:
    1
    Spells:
    2
    Resources:
    3
    Useful, feature filled, well documented and reasonably well written. Approved...

    There seems to be a lot of use of magic number constants which might effect maintainability. Additionally there is some hard coded inflexible logic which might effect usability for some people.
     
  5. Hazop

    Hazop

    Joined:
    Jul 2, 2015
    Messages:
    824
    Resources:
    2
    Maps:
    2
    Resources:
    2
    What you mean by "Correct the Raw-Code inside the "ControlPoint"-Trigger"
     
  6. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    1,661
    Resources:
    37
    Tools:
    2
    Maps:
    3
    Spells:
    11
    Tutorials:
    20
    JASS:
    1
    Resources:
    37
    Object Editor gives each existing object (UnitType, itemType, ability...) a 4 sign number. When copying the Bar Unit into a map this number is not taken over, World Editor calculates a new one, which in almost any case differs from the one which is expected inside the jass code.

    Inside object Editor you can show raw codes of objects under the menu "view".

    then the name will be displayed in this style:

    'A000:Absk' (berserk2)
    unique id : orginal: (name)
    The first 4 signs are important.
    'A000' <- representing the wanted object​

    Inside the Jass Code you have to change the return value of the function "CaptureBarUnitType", seen below.
    Code (vJASS):

    //=========================================================================================================
    //       Definitions:
    //=========================================================================================================
    //Id of The Generic Bar Unit in Object Editor
    constant function CaptureBarUnitType takes nothing returns integer
       return 'h000'  <---- this value have to be the same as the number the bar unit inside your map got.
    endfunction
     
     
    Last edited: Feb 1, 2018
  7. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    1,661
    Resources:
    37
    Tools:
    2
    Maps:
    3
    Spells:
    11
    Tutorials:
    20
    JASS:
    1
    Resources:
    37
    Updated to V1.3.
     
  8. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    1,661
    Resources:
    37
    Tools:
    2
    Maps:
    3
    Spells:
    11
    Tutorials:
    20
    JASS:
    1
    Resources:
    37
    Updated to V1.5
    Does no consider that the mapper could have changed the ownership when capturing an unit.

    Does now support the concept of TeamLeaders. A TeamLeader gains all captures of players of his team.
    This trigger below would be suited for a TeamGame with 2 Teams. Red and Green are seen as the Leaders, gaining the captured units and are displayed colorwise in the bar.
    • -------- You can Setup Leaders of Teams, Teams start with 0. Teams are the ones inside game Lobby right to the race selection (-1). --------
    • -------- A Team Leader will take control of all Captur points his team takes. --------
    • -------- You don't need to setup team Leaders in FFA --------
    • Set CapturePointTeamLeader[0] = Player 1 (Red)
    • Set CapturePointTeamLeader[1] = Player 7 (Green)
     
  9. dtnmang

    dtnmang

    Joined:
    Apr 20, 2010
    Messages:
    555
    Resources:
    12
    Models:
    5
    Maps:
    2
    Ported Models:
    1
    Tutorials:
    4
    Resources:
    12
    Very useful system. Should be recommended for everyone who wants to make a control points map.
     
  10. xoachimtachi

    xoachimtachi

    Joined:
    Nov 15, 2019
    Messages:
    6
    Resources:
    0
    Resources:
    0