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

Massive desyncs in my map (Help!)

Status
Not open for further replies.
Level 7
Joined
May 30, 2018
Messages
290
Dear Hive,

I made a map, which is really simple and nothing spectacular, since Iam a noob in triggering and I am trying to learn about it at the moment. Now when I wanted to test my map with real players they all (including me) start to desync rapidly as soon as the game went on for a few minutes. I thought I cleared all the leaks that occured and I also rechecked, but I just can't find the source(trigger) for my problems. So now I'd like to attach my whole map and maybe somone of you could help me find the source of the mass desyncs. It's a really simple/small map so I hope it's not to complicated to find my errors. (I also do not wish to get several hints and improvements on everything not regarding the desyncs, since I want to find out and fix as much as possible by myself. I also know that it's not set up that cleanly, you don't have to tell me xd). Anyways, hopefully someone can help me out!

My suspicion lays on the following triggers - especially the "loop array leak clear" in the end:
  • Checkpoint Green
    • Events
      • Unit - Beacon 0109 <gen> Dies
    • Conditions
    • Actions
      • Set VariableSet SpawningPool2_Green = (Units owned by Player 7 (Green) of type Spawning Pool 2)
      • Set VariableSet CheckpointPoint_Green[1] = (Center of Region 010 <gen>)
      • Set VariableSet CheckpointPoint_Green[2] = (Center of Region 016 <gen>)
      • Set VariableSet CheckpointPoint_Green[3] = (Center of Region 017 <gen>)
      • Set VariableSet CheckpointPoint_Green[4] = (Center of Region 018 <gen>)
      • Set VariableSet CheckpointPoint_Green[5] = (Center of Region 019 <gen>)
      • Unit - Kill Spawning Pool 0044 <gen>
      • Unit - Kill Beastiary 0047 <gen>
      • Unit - Kill Murloc Effigy 0256 <gen>
      • Unit Group - Pick every unit in SpawningPool2_Green and do (Unit - Kill (Picked unit))
      • Unit - Create 1 Spawning Pool 2 for Player 7 (Green) at CheckpointPoint_Green[1] facing 150.00 degrees
      • Unit - Create 1 Potion Seller for Player 7 (Green) at CheckpointPoint_Green[2] facing Default building facing degrees
      • Unit - Create 1 Murloc Effigy for Player 7 (Green) at CheckpointPoint_Green[3] facing 175.00 degrees
      • Unit - Create 1 Spawning Pool for Player 7 (Green) at CheckpointPoint_Green[4] facing 130.00 degrees
      • Unit - Create 1 Beastiary for Player 7 (Green) at CheckpointPoint_Green[5] facing 235.00 degrees
      • Custom script: call DestroyGroup( udg_SpawningPool2_Green)
      • For each (Integer A) from 1 to 5, do (Actions)
        • Loop - Actions
          • Custom script: call RemoveLocation(udg_CheckpointPoint_Green[GetForLoopIndexA()])

Thanks so much in advance.

Kind regards
Mechcash
 

Attachments

  • Colony Defense Alpha 0.2e.w3m
    284.2 KB · Views: 10

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,561
I've never seen someone use GetForLoopIndexA() but I doubt it's a problem. Just in case, try replacing that with bj_forLoopAIndex.

That aside, be on the lookout for uses of GetLocalPlayer(), that is generally the cause of desyncs. You'd find this inside of a Custom script action.
 
Level 7
Joined
May 30, 2018
Messages
290
I've never seen someone use GetForLoopIndexA() but I doubt it's a problem. Just in case, try replacing that with bj_forLoopAIndex.

That aside, be on the lookout for uses of GetLocalPlayer(), that is generally the cause of desyncs. You'd find this inside of a Custom script action.
Thanks for your answer. Ill try to replace the loop part. For specification: Do you mean it should look something like that: : call RemoveLocation(udg_CheckpointPoint_Green[bj_forLoopAIndex()])?

And I guess GetLocalPlayer() means the triggers which use "Player-Player 1 (Red)..." as (GUI) event or are you pointing at something else when talking about "custom script action"? oooor do you mean triggers like these

  • Vision Gates
    • Events
      • Time - Elapsed game time is 5.00 seconds
    • Conditions
    • Actions
      • Unit - Grant shared vision of Gate Closed Vertical 0277 <gen> to Player 5 (Yellow)
      • Unit - Grant shared vision of Gate Closed Vertical 0277 <gen> to Player 6 (Orange)
      • Unit - Grant shared vision of Gate Closed Vertical 0277 <gen> to Player 7 (Green)
      • Unit - Grant shared vision of Gate Closed Vertical 0277 <gen> to Player 8 (Pink)
      • Unit - Grant shared vision of Gate Closed Horizontal 0164 <gen> to Player 5 (Yellow)
      • Unit - Grant shared vision of Gate Closed Horizontal 0164 <gen> to Player 6 (Orange)
      • Unit - Grant shared vision of Gate Closed Horizontal 0164 <gen> to Player 7 (Green)
      • Unit - Grant shared vision of Gate Closed Horizontal 0164 <gen> to Player 8 (Pink)


Edit: I just went over every trigger again and can't seem to find the issue...could it be related to me using HD/Reforged-mode and that the desyncs are just inherently existing?
 
Last edited:
Level 23
Joined
Oct 18, 2008
Messages
938
local player is what each pc calls itself. for you localplayer is you, for others it's themselves. it's used to make the game do different things for different people, to play sounds or display effects that only one player can see and things like that.

if you don't have custom script that says GetLocalPlayer() your problem is something else. checking terrain type if your map has any blight in it can be asynchronous. some selection trigger actions can also cause it.

I don't know if it's been fixed yet but reforged had some kind of issue with hosting maps that are in any other folder than "download".
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,561
It would look like: call RemoveLocation(udg_CheckpointPoint_Green[bj_forLoopAIndex])

And yeah, you're looking for Custom script that literally has the words "GetLocalPlayer()" in it. If you're confused about it then there's a good chance that you don't have any. People often use it to play a Sound or create Special Effects for a single player since it's the only method we have available to do so.
 
Level 7
Joined
May 30, 2018
Messages
290
local player is what each pc calls itself. for you localplayer is you, for others it's themselves. it's used to make the game do different things for different people, to play sounds or display effects that only one player can see and things like that.

if you don't have custom script that says GetLocalPlayer() your problem is something else. checking terrain type if your map has any blight in it can be asynchronous. some selection trigger actions can also cause it.

I don't know if it's been fixed yet but reforged had some kind of issue with hosting maps that are in any other folder than "download".
Thanks for the contribution.

You mean potentially selection triggers like this :
  • Page 2 Murloc
    • Events
      • Unit - A unit Finishes casting an ability
    • Conditions
      • (Ability being cast) Equal to Page 2
    • Actions
      • Selection - Select (Units owned by (Owner of (Casting unit)) of type Murloc Gathering Page 2) for (Owner of (Casting unit))
🤔
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,561
I edited your map and fixed any issues I saw in the triggers. Note that I disabled those Page 2 triggers with the Selection actions. Maybe you can test to see if it still desyncs now.

If it still desyncs then I'm not sure... Your triggers are very simple and there's nothing concerning going on besides that. I guess you could also get rid of that Custom Model you have imported, maybe there's something weird with that?
 

Attachments

  • Colony Defense Alpha 0.2e UNCLE 1.w3m
    283.4 KB · Views: 9
Last edited:
Level 23
Joined
Oct 18, 2008
Messages
938
Thanks for the contribution.

You mean potentially selection triggers like this :
  • Page 2 Murloc
    • Events
      • Unit - A unit Finishes casting an ability
    • Conditions
      • (Ability being cast) Equal to Page 2
    • Actions
      • Selection - Select (Units owned by (Owner of (Casting unit)) of type Murloc Gathering Page 2) for (Owner of (Casting unit))
🤔
it was something like that, yeah. I don't remember specifics, though. try with those triggers disabled and see if it gets fixed.
 
Level 7
Joined
May 30, 2018
Messages
290
I edited your map and fixed any issues I saw in the triggers. Note that I disabled those Page 2 triggers with the Selection actions. Maybe you can test to see if it still desyncs now.

If it still desyncs then I'm not sure... Your triggers are very simple and there's nothing concerning going on besides that. I guess you could also get rid of that Custom Model you have imported, maybe there's something weird with that?
Thanks a bunch! I will test it out this evening to see if it worked :)

Another question regarding the selection triggers: Is there a way around this kind of trigger to make a "second page" for a building? SO is there another way of getting the page 2 switch to work?
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,561
I think you need to use one of those other Selection actions. Something like: Clear selection for player, Select unit for player.

Also, what does the Instructor do? Train units? Sell items? Cast abilities? There's "page" systems that only use a single unit.
 
Level 7
Joined
May 30, 2018
Messages
290
I think you need to use one of those other Selection actions. Something like: Clear selection for player, Select unit for player.

Also, what does the Instructor do? Train units? Sell items? Cast abilities? There's "page" systems that only use a single unit.
The instructor is for units and the other building is for upgrades. I looked around and couldn' t find any usefull page system here. If I want to work with the Select Unit for player option how can I define the Page 2 Building so it can be selected?
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,561
Remember we linked the Instructor to the Page 2 unit with a Hashtable. So if you have access to the Instructor then you also have access to it's Page 2.
You may need to do the opposite and link the Page 2 to it's Instructor as well, so you can always get the other unit in the pair.

Also, I think I forgot to clear the Hashtable data when the Instructor dies. It's not super important but it helps with performance:
  • Hashtable - Clear all child hashtables of child (Key (Triggering unit)) in I2_Hash
You would want to put that Action BEFORE you remove the Instructor but AFTER you've removed Page 2. So you may need to move your Actions around to get them in the proper order.
 
Last edited:
Level 7
Joined
May 30, 2018
Messages
290
Remember we linked the Page 2 building to the Instructor with a Hashtable. So if you have access to the Instructor then you also have access to it's Page 2.
Ah thats a good hint! I forgot about that, thanks will have a look :)

Edit: Your answer fits shockingly well to your profile picture xd
 
Level 7
Joined
May 30, 2018
Messages
290
Remember we linked the Instructor to the Page 2 unit with a Hashtable. So if you have access to the Instructor then you also have access to it's Page 2.
You may need to do the opposite and link the Page 2 to it's Instructor as well, so you can always get the other unit in the pair.

Also, I think I forgot to clear the Hashtable data when the Instructor dies. It's not super important but it helps with performance:
  • Hashtable - Clear all child hashtables of child (Key (Triggering unit)) in I2_Hash
You would want to put that Action BEFORE you remove the Instructor but AFTER you've removed Page 2. So you may need to move your Actions around to get them in the proper order.
I think I got it right for the Instructor Part now! But Iam struggling with the research building, since the page 2's of the research buildings are all "pre-placed" in the map I can't find a proper way to detect them as units I can assign handles to.

Like in the Instructor-Trigger I know that I can refer to the Instructor as the unit the handle should be saved to. With the research building I don't have an event/condition that describes it, so I cant really refer to it.

I had the idea to do something like this??

  • Page2Initiliazation
    • Events
      • Time - Elapsed game time is 1.00 seconds
    • Conditions
    • Actions
      • Unit - Create 1 Murloc Gathering Page 2 for Player 5 (Yellow) at (Center of (Playable map area)) facing Default building facing degrees
      • Hashtable - Save Handle Of(Last created unit) as 1 of (Key (Units of type Murloc Gathering Page 2).) in I2_Hash.
      • Unit - Create 1 Murloc Gathering Page 2 for Player 6 (Orange) at (Center of (Playable map area)) facing Default building facing degrees
      • Hashtable - Save Handle Of(Last created unit) as 2 of (Key (Units of type Murloc Gathering Page 2).) in I2_Hash.
      • Unit - Create 1 Murloc Gathering Page 2 for Player 7 (Green) at (Center of (Playable map area)) facing Default building facing degrees
      • Hashtable - Save Handle Of(Last created unit) as 3 of (Key (Units of type Murloc Gathering Page 2).) in I2_Hash.
      • Unit - Create 1 Murloc Gathering Page 2 for Player 8 (Pink) at (Center of (Playable map area)) facing Default building facing degrees
      • Hashtable - Save Handle Of(Last created unit) as 4 of (Key (Units of type Murloc Gathering Page 2).) in I2_Hash.
  • Page 2 Murloc
    • Events
      • Unit - A unit Finishes casting an ability
    • Conditions
      • (Ability being cast) Equal to Page 2
    • Actions
      • Selection - Select (Load (Key (Units of type Murloc Gathering Page 2).) of 1 in I2_Hash.) for Player 5 (Yellow)
just roughly sketched out
 
Last edited:

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,561
Regarding the Instructor/Page 2 selection stuff:
You want to save the Handle of the Instructor as Key(Page 2).
So in the same trigger that you create and save Page 2 to the Instructor, you also do the opposite and save the Instructor to Page 2.
So Page 2 would be the Last created unit. Instructor would be the Triggering unit (constructed structure).


Regarding your last post with the preplaced units here's a trick you can do to easily get the Handle of anything:
  • Actions
    • Set Variable UnitVar = Paladin 0004 <gen>
    • Custom script: set udg_HandleVar = udg_UnitVar
    • Hashtable - Save Handle of Something as (Key HandleVar) of 0 in (Last created hashtable)
This requires that you create a Handle variable. I named mine HandleVar.

So using that Custom script you can set your Handle variable to ANY other variable type. In this case I set HandleVar to UnitVar which is referencing our preplaced unit (Paladin 0004). So now I can reference Paladin 0004 inside of the Hashtable by referencing HandleVar. It's an extra step but it gets the job done.

This means that you could have 2 Handle variables and set them both to be different preplaced units, then you could pair them together in the Hashtable fairly easily.

And like I said, you can set HandleVar to ANY variable type, so it could be set as the handle of a Unit Group, Item, Player Group, etc.


Also, just to clarify what's going on here, a handle is just a hidden integer id that every "object" has in the game. An object is basically everything in the game, so that means units, items, unit groups, player groups, timers, etc.

All of these things have a hidden handle id. This is how the game can differentiate between different things, for example, if you created 2 Footman, sure they're both the same Unit-TYPE and thus share the same Unit-Type Id (another integer id), but they have separate unit handle ids because they're different UNITS.

It's sort of confusing I know but it's just the way these games work, everything is given a unique id that allows it to be differentiated from other things.

So since everything is actually stored as an Integer then what you're really saving in the Hashtable is Integers:

So this...
  • Hashtable - Save Handle of Something as (Key HandleVar) of 0 in (Last created hashtable)
Is actually more like this:
  • Hashtable - Save 1000001 as 1000002 of 0 in (Last created hashtable)

I picked random Integers for the sake of the example but that's what's really going on here. Obviously it'd be very confusing to work with numbers like these, so that's why the Trigger Editor is designed to hide that stuff behind easier to understand things like Unit variables.
 
Last edited:
Level 7
Joined
May 30, 2018
Messages
290
Regarding the Instructor/Page 2 selection stuff:
You want to save the Handle of the Instructor as Key(Page 2).
So in the same trigger that you create and save Page 2 to the Instructor, you also do the opposite and save the Instructor to Page 2.
So Page 2 would be the Last created unit. Instructor would be the Triggering unit (constructed structure).


Regarding your last post with the preplaced units here's a trick you can do to easily get the Handle of anything:
  • Actions
    • Set Variable UnitVar = Paladin 0004 <gen>
    • Custom script: set udg_HandleVar = udg_UnitVar
    • Hashtable - Save Handle of Something as (Key HandleVar) of 0 in (Last created hashtable)
This requires that you create a Handle variable. I named mine HandleVar.

So using that Custom script you can set your Handle variable to ANY other variable type. In this case I set HandleVar to UnitVar which is referencing our preplaced unit (Paladin 0004). So now I can reference Paladin 0004 inside of the Hashtable by referencing HandleVar. It's an extra step but it gets the job done.

This means that you could have 2 Handle variables and set them both to be different preplaced units, then you could pair them together in the Hashtable fairly easily.

And like I said, you can set HandleVar to ANY variable type, so it could be set as the handle of a Unit Group, Item, Player Group, etc.


Also, just to clarify what's going on here, a handle is just a hidden integer id that every "object" has in the game. An object is basically everything in the game, so that means units, items, unit groups, player groups, timers, etc.

All of these things have a hidden handle id. This is how the game can differentiate between different things, for example, if you created 2 Footman, sure they're both the same Unit-TYPE and thus share the same Unit-Type Id (another integer id), but they have separate unit handle ids because they're different UNITS.

It's sort of confusing I know but it's just the way these games work, everything is given a unique id that allows it to be differentiated from other things.

So since everything is actually stored as an Integer then what you're really saving in the Hashtable is Integers:

So this...
  • Hashtable - Save Handle of Something as (Key HandleVar) of 0 in (Last created hashtable)
Is actually more like this:
  • Hashtable - Save 1000001 as 1000002 of 0 in (Last created hashtable)

I picked random Integers for the sake of the example but that's what's really going on here. Obviously it'd be very confusing to work with numbers like these, so that's why the Trigger Editor is designed to hide that stuff behind easier to understand things like Unit variables.
Thank you very much for the explanation I'll try to work with it. :)
Annnd btw: The selection trigger revamp fixed the desyncs in my map! It really were the original selection triggers, which caused the issues.
 
Status
Not open for further replies.
Top