• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[vJASS] Well This is a First, Is this wrote correctly?

Status
Not open for further replies.
Level 6
Joined
Feb 10, 2011
Messages
188
First off, Sorry if the Title Prefix is wrong.

Ok so I have been working on a trigger and eventually arhowk decided he would write me a library that would do the same thing my GUI trigger did but better. So he wrote that and I decided to edit it to make it do more stuff.

Here is his version:
JASS:
library BaseDefenders initializer onBDInit
    globals
        private real radius = 175
        private real checkRadius = 375
        private real period = 0.7
        private unit host
        private filterfunc checkFilter
    endglobals
    
    private function enumFilter takes nothing returns boolean
        return GetFilterUnit() != host and GetOwningPlayer(host) == GetOwningPlayer(GetFilterUnit())
    endfunction
    
    private function looper takes nothing returns nothing
        local unit u
        local item i
        local group g = CreateGroup()
        local group g2 = CreateGroup()
        set bj_groupAddGroupDest = g
        call ForGroup(udg_BD_Bases, function GroupAddGroupEnum)
        loop  
            set host = FirstOfGroup(g)
            exitwhen host == null
            call GroupClear(g2)
            call GroupEnumUnitsInRange(g2, GetUnitX(host), GetUnitY(host), radius, checkFilter)
            if FirstOfGroup(g2) == null then
                call GroupClear(g2)
                call GroupEnumUnitsInRange(g2, GetUnitX(host), GetUnitY(host), checkRadius, checkFilter)
                set u = FirstOfGroup(g2)
                if u != null then
                    set i = CreateItem('hval', GetUnitX(host), GetUnitY(host))
                    call IssueImmediateOrder(u, "stop" )
                    call SetUnitX(u, GetItemX(i))
                    call SetUnitY(u, GetItemY(i))
                    call RemoveItem(i)
                endif
            endif
            call GroupRemoveUnit(g,host)
        endloop
        set u = null
        set i = null
        call DestroyGroup(g)
        call DestroyGroup(g2)
        set g = null
        set g2 = null
    endfunction
    private function onBDInit takes nothing returns nothing
        set checkFilter = Filter(function enumFilter)
        call TimerStart(CreateTimer(), period, true, function looper)
    endfunction
endlibrary

This is what I added/changed.
  1. Land Bases can not have ships as defenders, They will be captureable.
  2. Ships can take ownership of land bases and can be the defender of ports
  3. If a players base has no available defender(captureable), It can be captured by another player if they move a unit within 600 of the base.
  4. It checks more frequently (.05), and for larger second radius (600)
  5. To Bases will now change owner to whatever player owns the current defender, you can do that if the current owner has no defender in a 600 radius.

Specific Questions:
  1. If there are 2 bases in the large range of each other owned by the same player, and one base is has all the units killed, will it take the other bases defender? If so, how can i prevent this. (I havent been able to test this)
  2. It seems that if a ship is in range of a land base, the defender can leave. it only works with land bases and ships. other wise it works correctly. (it should not let the land defender leave if its a land base.) How can I fix this?
  3. How can I turn this on at a certain point in game, etc. after voting and set up has finished. (turn off initially, and turn on with another trigger like gui?)

Here it is
JASS:
library BaseControlPoint initializer onBDInit
    globals
        private real radius = 150
        private real checkRadius = 600
        private real period = 0.5
        private unit tower
        private unit base
        private filterfunc checkFilter
        private filterfunc checkFilterTwo
    endglobals
    
    private function enumFilter takes nothing returns boolean
        return IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) !=true and IsUnitAliveBJ(GetFilterUnit()) ==true and GetOwningPlayer(tower) == GetOwningPlayer(GetFilterUnit()) 
    endfunction
    
    private function enumFilterTwo takes nothing returns boolean
        return IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) !=true and IsUnitAliveBJ(GetFilterUnit()) ==true and GetOwningPlayer(tower) != GetOwningPlayer(GetFilterUnit())
    endfunction
    
    private function looper takes nothing returns nothing
        local unit u
        local item i
        local group g = CreateGroup()
        local group g2 = CreateGroup()
        local group g3 = CreateGroup()
        set bj_groupAddGroupDest = g
        call ForGroup(udg_BD_Towers, function GroupAddGroupEnum)
        set bj_groupAddGroupDest = g3
        call ForGroup(udg_BD_Bases, function GroupAddGroupEnum)
        loop  
            set tower = FirstOfGroup(g)
            exitwhen tower == null
            set base = FirstOfGroup(g3)
            call GroupClear(g2)
            call GroupEnumUnitsInRange(g2, GetUnitX(tower), GetUnitY(tower), radius, checkFilter)
            if FirstOfGroup(g2) == null then
                call GroupClear(g2)
                call GroupEnumUnitsInRange(g2, GetUnitX(tower), GetUnitY(tower), checkRadius, checkFilter)
                set u = FirstOfGroup(g2)
                if u != null then
                    if IsUnitType(u, UNIT_TYPE_ANCIENT) !=true then
                    call SetUnitX(u, GetUnitX(tower))
                    call SetUnitY(u, GetUnitY(tower))
                    call IssueImmediateOrder (u, "stop")
                    else
                        if ( GetUnitTypeId(base) == 'h000' ) then
                        call SetUnitX(u, GetUnitX(tower))
                        call SetUnitY(u, GetUnitY(tower))
                        call IssueImmediateOrder (u, "stop")
                        else
                        endif
                    endif
                else
                    call GroupClear(g2)
                    call GroupEnumUnitsInRange(g2, GetUnitX(tower), GetUnitY(tower), checkRadius, checkFilterTwo)
                    set u = FirstOfGroup(g2)
                    call SetUnitOwner (tower, GetOwningPlayer(u),true)
                    call SetUnitOwner (base, GetOwningPlayer(u),true)
                    if IsUnitType (u, UNIT_TYPE_ANCIENT) !=true then
                    call SetUnitX(u, GetUnitX(tower))
                    call SetUnitY(u, GetUnitY(tower))
                    call IssueImmediateOrder (u, "stop")
                    else
                        if ( GetUnitTypeId(base) == 'h000' ) then
                        call SetUnitX(u, GetUnitX(tower))
                        call SetUnitY(u, GetUnitY(tower))
                        call IssueImmediateOrder (u, "stop")
                        else
                        endif
                    endif
                endif
            else
            endif
            call GroupRemoveUnit(g,tower)
            call GroupRemoveUnit(g3,base)
        endloop
        set u = null
        set i = null
        call DestroyGroup(g)
        call DestroyGroup(g2)
        call DestroyGroup(g3)
        set g = null
        set g2 = null
        set g3 = null
    endfunction
    private function onBDInit takes nothing returns nothing
        set checkFilter = Filter(function enumFilter)
        set checkFilterTwo = Filter(function enumFilterTwo)
        call TimerStart(CreateTimer(), period, true, function looper)
    endfunction
endlibrary
 
For 1 & 2, it would help to have a bit more information. Right now I don't completely understand what the trigger is supposed to do. If you could explain it clearly, then perhaps the questions will make more sense.

For #3, there are a lot of ways. The easiest way is probably to remove the initializer part and call it through ExecuteFunc().
JASS:
library BaseControlPoint // initializer onBDInit
// I commented out the "initializer onBDInit" so that
// it wouldn't be called on initialization

    globals
        private real radius = 150
        private real checkRadius = 600
        private real period = 0.5
        private unit tower
        private unit base
        private filterfunc checkFilter
        private filterfunc checkFilterTwo
    endglobals
    
    private function enumFilter takes nothing returns boolean
        return IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) !=true and IsUnitAliveBJ(GetFilterUnit()) ==true and GetOwningPlayer(tower) == GetOwningPlayer(GetFilterUnit()) 
    endfunction
    
    private function enumFilterTwo takes nothing returns boolean
        return IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) !=true and IsUnitAliveBJ(GetFilterUnit()) ==true and GetOwningPlayer(tower) != GetOwningPlayer(GetFilterUnit())
    endfunction
    
    private function looper takes nothing returns nothing
        local unit u
        local item i
        local group g = CreateGroup()
        local group g2 = CreateGroup()
        local group g3 = CreateGroup()
        set bj_groupAddGroupDest = g
        call ForGroup(udg_BD_Towers, function GroupAddGroupEnum)
        set bj_groupAddGroupDest = g3
        call ForGroup(udg_BD_Bases, function GroupAddGroupEnum)
        loop  
            set tower = FirstOfGroup(g)
            exitwhen tower == null
            set base = FirstOfGroup(g3)
            call GroupClear(g2)
            call GroupEnumUnitsInRange(g2, GetUnitX(tower), GetUnitY(tower), radius, checkFilter)
            if FirstOfGroup(g2) == null then
                call GroupClear(g2)
                call GroupEnumUnitsInRange(g2, GetUnitX(tower), GetUnitY(tower), checkRadius, checkFilter)
                set u = FirstOfGroup(g2)
                if u != null then
                    if IsUnitType(u, UNIT_TYPE_ANCIENT) !=true then
                    call SetUnitX(u, GetUnitX(tower))
                    call SetUnitY(u, GetUnitY(tower))
                    call IssueImmediateOrder (u, "stop")
                    else
                        if ( GetUnitTypeId(base) == 'h000' ) then
                        call SetUnitX(u, GetUnitX(tower))
                        call SetUnitY(u, GetUnitY(tower))
                        call IssueImmediateOrder (u, "stop")
                        else
                        endif
                    endif
                else
                    call GroupClear(g2)
                    call GroupEnumUnitsInRange(g2, GetUnitX(tower), GetUnitY(tower), checkRadius, checkFilterTwo)
                    set u = FirstOfGroup(g2)
                    call SetUnitOwner (tower, GetOwningPlayer(u),true)
                    call SetUnitOwner (base, GetOwningPlayer(u),true)
                    if IsUnitType (u, UNIT_TYPE_ANCIENT) !=true then
                    call SetUnitX(u, GetUnitX(tower))
                    call SetUnitY(u, GetUnitY(tower))
                    call IssueImmediateOrder (u, "stop")
                    else
                        if ( GetUnitTypeId(base) == 'h000' ) then
                        call SetUnitX(u, GetUnitX(tower))
                        call SetUnitY(u, GetUnitY(tower))
                        call IssueImmediateOrder (u, "stop")
                        else
                        endif
                    endif
                endif
            else
            endif
            call GroupRemoveUnit(g,tower)
            call GroupRemoveUnit(g3,base)
        endloop
        set u = null
        set i = null
        call DestroyGroup(g)
        call DestroyGroup(g2)
        call DestroyGroup(g3)
        set g = null
        set g2 = null
        set g3 = null
    endfunction
    // private function onBDInit takes nothing returns nothing
    // I commented out the line above me^
    // and removed the "private" keyword from the function
    // (you can technically call it with private, but it is ugly IMO)
    function onBDInit takes nothing returns nothing
        set checkFilter = Filter(function enumFilter)
        set checkFilterTwo = Filter(function enumFilterTwo)
        call TimerStart(CreateTimer(), period, true, function looper)
    endfunction
endlibrary

Then you would call it from GUI like this:
  • Custom script: call ExecuteFunc("onBDInit")
Make sure you spell it correctly, and be sure to have the quotes around the function name. Just add that line after you do the votes or w/e and it should work.
 
Level 6
Joined
Feb 10, 2011
Messages
188
Ok I have attached an image that will help me explain question one better

let me expalin a few quick things
one base = 1 barracks 1 CoP 1 Tower
the cop is placed just under each barracks, then the tower is placed in the center of the COP. the defender uses the tower as the control point for the base.

As you can see in the image the radius stems from a bases tower
There is 2 radius's the trigger will check First, the smaller radius wich is represented by the black outline. If there is no available defender (defenders must be owned by current owner of the base) then it will check in the larger radius for defenders. As you can see the 2 bases large radius check distance overlaps the other.

So as you can see in the screen shot the left base has a defender and the right does not. Currently the way I have my trigger set up is that when the defender from the left base leaves his small radius he is then picked to be the right bases defender, and u can repeat this process by again moving out of the small radius. the defender will just go from the left to right base. I would like to prevent this.


Thankyou for ansering number 3, I am working on a better way to explain number 2. Ill edit this when I do.

New Question:

Sometimes a bases tower will change owner but the barracks will not, I am not sure what causes it, it seems to be random.
How can i make sure the base and tower always change to the correct player


Oh and this is exactly what the trigger does

1. Every .05 seconds it checks each bases small radius for an available defender (only the current owners units can be defender), If there is one, do nothing, If there is not one proceed to step 2.
2. Check the larger radius for an available defender (when checking larger radius, any player can become to owner of the base) If there is an available defender it will take that unit and move it to the bases control point. If the new defender is not the same as the current owner, the base will change owner

*Filters & Conditions
If a base is a land base, the defender can not be a naval unit (ship)
If a base is a port, the defender can be any unit. naval or land
Any unit land or sea can take control of any base
When a ship takes control of a land base, the ship is not marked as defender, the base changes owner. and there is no currently selected defender.
A base will only change ownership if the current owner has no units in the small radius check. (and) there is available defenders from other players in the large radius check.
 

Attachments

  • example 1.png
    example 1.png
    668.6 KB · Views: 80
Status
Not open for further replies.
Top