Units not removed properly

waaaks!

Zinctified
Reaction score
255
ok I made this system which acts like a unit capture system, here's how it works:
  • creates a struct which assigns the unit to be captured and the player which we set the unit's owner
  • when steal method is called, it converts the unit owner to the assigned player and creating dummy units (based on zone indicator) for each player in a force
  • when clear method is called, it takes a force argument and removes the dummy units (based on its unit type) around the assigned unit (in create method) only for each player in the assigned force, regardless computer or user or playing or not playing
JASS:
library BaseCapture initializer init needs GroupUtils
    
    globals
        private constant string sfx = "Abilities\\Spells\\Human\\Thunderclap\\ThunderClapCaster.mdl"
    endglobals
    
    struct controlTower
        unit c
        player p
        
        method clear takes force f returns nothing
            local group g
            local unit u
            local integer n
            if( f == teamGwapo ) then
                set g = NewGroup()
                set n = 0
                call GroupEnumUnitsInRange(g,GetUnitX(.c),GetUnitY(.c),300,BOOLEXPR_TRUE)
                loop
                    set u = FirstOfGroup(g)
                    exitwhen u == null
                    loop
                        exitwhen n > 5
                        if( GetUnitTypeId(u) == 'n000' and GetOwningPlayer(u) == Player(n) ) then
                            call KillUnit(u)
                        endif
                        set n = n + 1
                    endloop
                    call GroupRemoveUnit(g,u)
                endloop
                call ReleaseGroup(g)
            elseif( f == teamPangit ) then
                set g = NewGroup()
                set n = 6
                call GroupEnumUnitsInRange(g,GetUnitX(.c),GetUnitY(.c),300,BOOLEXPR_TRUE)
                loop
                    set u = FirstOfGroup(g)
                    exitwhen u == null
                    loop
                        exitwhen n > 11
                        if( GetUnitTypeId(u) == 'n000' and GetOwningPlayer(u) == Player(n) ) then
                            call KillUnit(u)
                        endif
                        set n = n + 1
                    endloop
                    call GroupRemoveUnit(g,u)
                endloop
                call ReleaseGroup(g)
            endif
            set g = null
            set u = null
        endmethod
        
        method steal takes nothing returns nothing
            local integer n = 0
            local unit u
            call SetUnitOwner(.c,.p,true)
            call DestroyEffect(AddSpecialEffectTarget(sfx,.c,"origin"))
            if( .p == playerGwapo ) then
                if (IsPlayerInForce(GetLocalPlayer(), teamGwapo)) then
                    call PingMinimap(GetUnitX(.c), GetUnitY(.c), 3)
                endif
                loop
                    exitwhen n > 5
                    set u = CreateUnit(Player(n),'n000',GetUnitX(.c),GetUnitY(.c),0.0)
                    set n = n + 1
                endloop
            elseif( .p == playerPangit ) then
                if (IsPlayerInForce(GetLocalPlayer(), teamPangit)) then
                    call PingMinimap(GetUnitX(.c), GetUnitY(.c), 3)
                endif
                set n = 6
                loop
                    exitwhen n > 11
                    set u = CreateUnit(Player(n),'n000',GetUnitX(.c),GetUnitY(.c),0.0)
                    set n = n + 1
                endloop
            endif
            set u = null
        endmethod
    
        static method create takes unit c, player p returns controlTower
            local controlTower d = controlTower.allocate()
            set d.c = c
            set d.p = p
            return d
        endmethod
        
    endstruct
endlibrary

now I have this as an example to call the struct
JASS:
...
private function act takes nothing returns nothing
        local unit c = SpellEvent.CastingUnit
        local unit t = SpellEvent.TargetUnit
        local controlTower d
        if( IsPlayerInForce(GetOwningPlayer(c), teamGwapo) )then
            set d = controlTower.create(t,playerGwapo)
            call d.steal()
            call d.clear(teamPangit)
            call d.destroy()
        elseif ( IsPlayerInForce(GetOwningPlayer(c), teamPangit) )then
            set d = controlTower.create(t,playerPangit)
            call d.steal()
            call d.clear(teamGwapo)
            call d.destroy()
        endif
        set c = null
        set t = null
    endfunction
...

as you can see, I called steal method and then calls clear method after it, which means if a unit uses an ability that captures a unit that I already captured, I will lose visibility to that unit and its previous position, because the zone indicators are killed inside the clear method

the problem is, even though the enemy captured one of my captured units, I still gain visibility on its position, which means there are still zone indicators alive in that area, not sure if its my allies' zone indicators

this won't conflict on games that has some missing players because zone indicators are created for each player on a team, also the zone indicators only has the invulnerable ability
 

Nestharus

o-o
Reaction score
84
Ok, I think you are way over complicating it. I'm not sure why you want dummy units and so on, but all you have to do is change the owner of the current unit to the next owner... allies will auto get vision and new owner will auto get vision.



What is up with all of these dummy units??


If you want to associate units with a given unit, the simplest way is to create a stack...

while stack.size != 0
stack.push(origin.stack, new unit)
RemoveUnit(origin.stack, stack.pop())


And look how easy that is. Very simple code.



Now, if you are worried about missing players you can use a Player utility. It stores all current players and all current computer players and keeps them indexed. You can generate the teams at the start based on current players and remove a player from a given team when that player leaves by registering the function or w/e in the Player Utility.


You are just over complicating everything. As a result the code you write is slower, harder to maintain, and just : o.



I'm not going to read through your code. I'm not going to fix it. Why? You didn't point out the code that was causing the issue.


Here are some good guidelines when getting help-
0. State the problem in-depth and show the code that is directly associated with that problem

1. Show exactly what code is causing the issue (paste it or put comments around it). If you don't know what code is causing the issue, then you better find it -.-. When you find it, you can mostly figure out why it's causing the issue, but if you can't you come here and get help from a super vet who can figure it out : ).


2. Include debug messages for all your code so we can easily track the changes when messing with it.


3. Include all relevant code to that code so we can debug your code and fix it for you.



You did half of 0 and you didn't do 1-3 at all. As it stands the most I'm going to do is tell you how you should have written it =).
 

waaaks!

Zinctified
Reaction score
255
I created those dummy units to have nearby patron on a captured unit, its not just ordinary units I'm talking around here, these units I'm referring to are structures with units where I can hire. They are there for a purpose.
 

Nestharus

o-o
Reaction score
84
Ok, first rather than KillUnit() use RemoveUnit()

Next, you don't need a struct. You can have a struct, but do this and it'll make it easier and better-


JASS:

struct ControlTower extends array
    public static unit c
    public static player p

    public static method clear takes force f returns nothing
    endmethod

    public static method steal takes nothing returns nothing
    endmethod
endstruct


The reason is because you aren't actually using the objects. Don't use object orientated programming unless you plan on having objects : ).


Now, you could store the necessary values into an object and return that object. You can also attach that object to the unit in question. From here, you could have a linked list and so on which would speed things up.

I really think you need to redo all of the code to follow an object orientated design. A bad design is a bad design, and that is what you have here. Quick fixes are not the answer, you just need to delete it all and start over.



Now, here are some tips for the new model-
Use object orientated programmed. If you have a base or w/e to be stolen, then store the origin unit in the base and associate a linked list with it.

JASS:

struct ControlTower
    unit origin
    list dummies
    force owner
endstruct


And you would attach ControlTower to a unit like this-
JASS:

library Setup initializer Ini
    public hashtable memory

    private function Ini takes nothing returns nothing
        memory = InitHashtable()
        SaveInteger(memory, GetHandleId(unit1), 0, ControlTower.create(unit1)) //etc
    endfunction
endlibrary



So, when you steal it

JASS:

controlTower = LoadInteger(memory, GetHandleId(unit), 0)
controlTower.clear()
controlTower.owner(newForce)



Also, I suggest a team struct with a linked list for players of a team. It's just much faster than a ForForce call.


So, for creating dummy units-
controlTower.push(team.player[current])


And well, yea : ).
 

chobibo

Level 1 Crypt Lord
Reaction score
48
Hey waaaks!, could you explain your problem and what the script does in a much simpler words, I can't understand it lol.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top