• 🏆 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!

Does this leak?

Status
Not open for further replies.
Level 7
Joined
May 11, 2010
Messages
278
Does this trigger leak?

107591d1319821191-does-leak-tillfaellig.jpg


And if i have a unit variable, will i need to remove the variable before setting it to another value?
if yes, how do i do that?
 

Attachments

  • tillfällig.jpg
    tillfällig.jpg
    21.9 KB · Views: 258
Level 26
Joined
Aug 18, 2009
Messages
4,097
JASS:
function CountLivingPlayerUnitsOfTypeId takes integer unitId, player whichPlayer returns integer
    local group g
    local integer matchedCount

    set g = CreateGroup()
    set bj_livingPlayerUnitsTypeId = unitId
    call GroupEnumUnitsOfPlayer(g, whichPlayer, filterLivingPlayerUnitsOfTypeId)
    set matchedCount = CountUnitsInGroup(g)
    call DestroyGroup(g)

    return matchedCount
endfunction

The group is destroyed but its id not released. Do not know anymore if the group is properly cleared via DestroyGroup to get rid of remaining references.
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
true not True. Jass is case-sensitive. But you have not listened to me. The function Unit - Count Living Units Owned By Player you know from GUI looks like I posted above in jass. You do not pass a group argument nor does it return one, so there is no reason to keep a group alive and it gets destroyed as you should be able to see there.
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
Shoto... fixing 'player' triggers is not needed. Almost any kind of trigger can be 'Generic', meaning that it can work for the player you want, without having to tell the trigger the exact player.

Example:
  • Trigger
  • Events
    • Time - Every 2.00 seconds of gameplay
  • Conditions
  • Actions
    • Player Group - Pick every player in (All Players) an do (Actions):
      • Loop - Actions
      • Set gold_mine_number = (Number of living ABandoned Gold Mine units owned by (Picked Player))
      • Player - Add gold_mine_number to (Picked Player).
There, it works for 1 or 12 players. Whatever you want. You can add If/then/Else if you want to filter/exclude/include certain players depending on whatever you want.
 
Level 7
Joined
May 11, 2010
Messages
278
@Spartipilo: yes, i'm aware of "generic" triggers, but i can't really come up with how to make generic triggers for everything :p
thanks for the trigger, hehe ^^ but doesn't it leak, like mine did?
...or did mine leak? you guys confuse me xD
 
Level 7
Joined
May 11, 2010
Messages
278
okay, thanks for pointing that out, i'll use the custom script posted earlier at this page to clean it up then? :)

oh and also, i have four of follwing trigger, one for each player.
is there a way to "generalize" (make only one trigger for everyone) this, or do i have to have separate ones as i have multiple regions?
I want sheep (trees) to spawn in different regions, close to the different players starting locations.
  • Sheep Spawn player 1
    • Events
      • Time - Every 30.00 seconds of game time
    • Conditions
    • Actions
      • Set number = ((Current research level of More Sheep for Player 1 (Red)) + 3)
      • Set temp_point = (Center of Region 000 <gen>)
      • Unit - Create number Dummy for Player 1 (Red) at temp_point facing Default building facing degrees
      • Unit Group - Pick every unit in (Units in Region 000 <gen>) and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Unit-type of (Picked unit)) Equal to Dummy
            • Then - Actions
              • Unit - Remove (Picked unit) from the game
              • Set temp_point = (Random point in Region 000 <gen>)
              • Destructible - Create a Sheep (Tree) at temp_point facing (Random angle) with scale 1.50 and variation 0
            • Else - Actions
              • Do nothing
      • Custom script: call RemoveLocation (udg_temp_point)
 
Last edited:
Level 20
Joined
Jul 14, 2011
Messages
3,213
Oops... Oh... you just have to declare "Number of living units owned by Player" in a Group variable before the "Pick Every Player" and use the group inside the loop, then remove it after the "Pick every player". I'm not sure if "set bj_wantDestroyGroup = true" before that variable set could work, I doubt it.

Also, filter your players using If/Then/Else inside, otherwise, if you use "All Players Matching" i've heard that leaks, you would have to declare the Force (Force = Player group) and Pick every player in the force, and then destroy the force (call DestroyForce(udg_YourForceName)).



Yeah... it's possible to make everything generic, MPI (Multi player instanceable) and MUI (Multi Unit Instanceable). Maybe something like this->


1) Create a "Region" type Variable, and check it as an Array, call it whatever you want.
2) Set Region[1] = Player 1 starting region (You have to create it)
Set Region[2] = Player 2 ...
Etc.

  • Sheep Spawn player 1
    • Events
      • Time - Every 30.00 seconds of game time
    • Conditions
    • Actions
      • For each integer A from 1 to *YourPlayerNumber* do (Actions):
        • Loop - Actions
          • Set number = ((Current research level of More Sheep for Player(Integer A)) + 3)
          • Set temp_point = (Random Point in Region[Integer A])
          • For each integer B from 1 to number do (Actions):
            • Loop - Actions
            • Destructible - Create a Sheep (Tree) at temp_point facing (Random angle) with scale 1.50 and variation 0
          • Custom script: call RemoveLocation (udg_temp_point)
I don't understand why you create a dummy, then remove it to create a destructible in a random point... So I'll remove that part.
EDIT: Oh... How's that you can't create destructibles with numbers the same way you create units?...
EDIT: I did this without the editor... I guess it should work.
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
... Come on... don't be scared. You're using 5 complex triggers for something you can do with 1 simple. Try it, and you'll see it's better and efficient.
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
OK. Integer A and Integer B are default functions in Wc3 GUI. The only think is that they can't be working at the same time (You can't have 2 triggers working at the same time using "For each integer A") That' why there are Integer A, integer B, and even Variable integer.


What it does is...

For each integer A from 1 to 10 do:
loop
Game - Display Message "Integer A".

It will display:
1
2
3
4
5
6
7
8
9
10.

What it does is do the actions in the loop for each one of the values between the X and Y, being "for each integer A from X to Y".

If you use:
For each integer A from 1 to (Number of Players Matching - User and Playing) do:
loop
Game - Display Message "Player(Integer A) Is a noob".

-> Player 1 is a noob
-> Player 2 is a noob
-> Player 3 is a computer, so, it won't display anything.
-> Player 4 is a noob.

It's the same than "Pick Every unit - Loop" since the actions will work for each one of the picked units. In this case are not units, but integers.

If you declare regions[1, 2, 3, 4], you can use:

For each integer A from 1 to 4 do:
-Loop
Unit - Create (Integer A) Footman for Player(Integer A) at Region(Integer A).

It will:
Create 1 footman for Player 1 at Region 1
Create 2 footman for Player 2 at Region 2
Create 3 footman for Player 3 at Region 3
Create 4 footman for Player 4 at Region 4



  • Sheep Spawn player 1
    • Events
      • Time - Every 30.00 seconds of game time
    • Conditions
    • Actions
      • For each integer A from 1 to *YourPlayerNumber* do (Actions):
        • Loop - Actions
        • Set number = ((Current research level of More Sheep for Player(Integer A)) + 3)
        • Set temp_point = (Random Point in Region[Integer A])
        • For each integer B from 1 to number do (Actions):
          • Loop - Actions
          • Destructible - Create a Sheep (Tree) at temp_point facing (Random angle) with scale 1.50 and variation 0
        • Custom script: call RemoveLocation (udg_temp_point)
It will run the loop for 1, 2, 3, 4 5... etc untill your number of players. Lets take the 1.

  • Sheep Spawn player 1
    • Events
      • Time - Every 30.00 seconds of game time
    • Conditions
    • Actions
      • Set number = ((Current research level of More Sheep for Player(1) + 3)
      • Set temp_point = (Random Point in Region[1])
      • For each integer B from 1 to number do (Actions):
        • Loop - Actions
        • Destructible - Create a Sheep (Tree) at temp_point facing (Random angle) with scale 1.50 and variation 0
      • Custom script: call RemoveLocation (udg_temp_point)
It's important to know that "For each Integer A" it will create the Temp_Point, so, for each integer A, you have to remove it too inside the loop :p
- When it runs for Integer A = 1, It will turn all the values inside the loop using [Integer A] to 1.
- When Integer A = 3, It will turn all the values inside the loop using [Integer A] to 3.

So, when you say "For Each integer A from 1 to 5", it will run the trigger 5 times making A=1, A=2, A=3, A=4, A=5.


That should be enough :p
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,180
The idea is to reduce procedural coupling by generalizing procedures. When programming using real languages like C the reduction in code complexity makes for more efficient instruction caching which means fewer memory reads. It also makes your code easier to maintain as you only need to change it at 1 location instead of many (and each change introduces probabilities of errors being made).

Ironicly, the actual execution advantage is often lost in JASS due to how the language is interpreted by a very slow interpreter. The main reason to do it is so your script is more readable and maintainable.
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
An example of something Dr Super Good Said:

If you want to add one more player to your map, you don't have to copy all the trigger and edit all the player values... You just increase The max Integer A by 1.
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
Follow the instructions I gave:

1- Create the regions in the world editor
2- Create a Region type array variable, I called it "Region". It will request you an index this way Region[index].
3- In your first trigger (Map Initialization) you have to ->
3.1 Set Region[1] = Player 1 region
3.2 Set Region[2] = Player 2 region
... and so on.

Then, when you're setting the point, choose the Region variable, and it will request you an [index]. There you place "For integer A" option.
 
Level 7
Joined
May 11, 2010
Messages
278
@ Vladadamm: that's not what i was having issues with.
@Spartipilo: ah, thanks :) works fine, exept i miswrote something that made multiple sheep spawn at the same point xD fixed it though, thanks alot :))))
 
Level 7
Joined
May 11, 2010
Messages
278
will it work without leaking if i do this?
(tested, it ticks correctly, but does it leak?)
  • Gold Tick
    • Events
      • Time - Every 2.00 seconds of game time
    • Conditions
    • Actions
      • Player Group - Pick every player in player_group and do (Actions)
        • Loop - Actions
          • Set gold_mine_number = (Number of living Abandoned Gold Mine units owned by (Picked player))
          • Player - Add gold_mine_number to (Picked player) Current gold
The "player_group" is a variable:
  • Melee Initialization
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set player_group = (All players matching (((Matching player) controller) Equal to User))
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
Every 2 secs.

-> Set player_group = (All players matching (((Matching player) controller) Equal to User))
-> Pick every player in player_group and do:
-----> Loop: bla bla
-> call DestroyForce(udg_player_group)
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,180
Every 2 secs.

-> Set player_group = (All players matching (((Matching player) controller) Equal to User))
-> Pick every player in player_group and do:
-----> Loop: bla bla
-> call DestroyForce(udg_player_group)

Shoto's apprach is better. Pointless rebuilding a force every 2 seconds if it is unlikly to change in that time.

Ultimatly you only ever want to change the force at...
1. Map initilization when you first can test who is playing.
2. When a player leaves / is no longer taking part.

This saves unnescescary overhead of continiously reconstructing the force and freeing it. Your approach might leave a lower continious memory footprint, but that means nothing compared to the CPU time you are wasting.
 
Level 7
Joined
May 11, 2010
Messages
278
so if i "set bj_wantDestroyGroup = true" it shouldn't leak?

  • Gold Tick
    • Events
      • Time - Every 2.00 seconds of game time
    • Conditions
    • Actions
      • Player Group - Pick every player in player_group and do (Actions)
        • Loop - Actions
          • Custom script: set bj_wantDestroyGroup = true
          • Set gold_mine_number = (Number of living Abandoned Gold Mine units owned by (Picked player))
          • Player - Add gold_mine_number to (Picked player) Current gold
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
No.

You have to

1- Declare the group "(Number of living Abandoned Gold Mine units owned by (Picked player))" inside the loop, use Add Number of Living Abandoned Gold Mine units in GoldMines(This is a Unit-Group), and then "call DestroyGroup(udg_GoldMines)"

OR

2- Create that group (with an array) in map init with size = Number of players that can play, and use a trigger to add the "Abandoned Gold Mines" to that UnitGroup[Player Number of (Owner of The Mine)] <- This way you don't have to destroy the groups.

I don't know if there's another way (there is, for sure).

I would pick the first one :p Since it's easier, though not the fastest and efficient. I don't know which one would that be.
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
Pick every player in Player_Group and do:
Set Group = (living Abandoned Gold Mine units owned by (Picked player))
Add (Number of Units in Group) to (Picked Player) Current Gold.
call DestroyGroup(udg_Group)
 
Status
Not open for further replies.
Top