• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[GUI-Friendly] Capture Point System 1.5b

Overview

How to Install

Capture Style

Definition

Captured

CapturePointEvent

API GUI

API Jass

CapturePoint

Changelog


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.
JASS:
//=========================================================================================================
//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
JASS:
//=============================================================================
//=========================================================================================================
//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
JASS:
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.
JASS:
//=========================================================================================================
//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.
JASS:
//=========================================================================================================
//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.
JASS:
//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...

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,178
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.
 
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.
JASS:
//=========================================================================================================
//       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:
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)
 
Top