[Vanilla] gameplay related lua scripts in multiplayer

Aldollin

Chieftain
Joined
Mar 7, 2017
Messages
87
does anyone have experience with lua scripts (gameplay context) in multiplayer?

looking at some of the weird things/bugs that are happening with my mod i feel like i am missing something essential:
it seems to me like the lua scripts i have act in every players game seperatly, resulting in 2 people seeing different results from random effects
Example: i have a lua script that randomly places resources when you build mines, giving you a chance to "discover hidden resources"
But say i am playing a game with one other player, teams enabled so we see each others territory, i build a mine, on my screen a resources spawns, but on his nothing happens (or the other way around) causing either a desync/reload or crashing the game

similar things happen with some other lua scripts as well

so:
is there something i am missing to make sure the script runs only once and affects everyones game without causing desyncs/reloads?
 
what function are you using to get your random number ?

and on which event are you hooking your function ?
 
For the random numberes:
math.random(k) for a random number from 1 to k

Events:
TurnEnd, TurnBegin, PlayerTurnActivated, PlayerTurnDeactivated, UnitAddedToMap, UnitRemovedFrom Map, ImprovementAddedToMap, ImprovementRemovedFromMap, ResourceRemovedFrom Map
might be some more, but these are the ones i used most.

in one script (for my map) i have math.randomseed(os.time()), which explains why the random effects there are different for every player if the scripts act independent from each other.
but the bugs happen in the scripts that don't contain this as well

I think i remember getting the exact same results multiple times when restarting the map before i used a random seed, thats why i added it.
 
math.random is most likely the culprit, since it relies on the individual computer to "seed" the random number generation.

This was a problem in civ5 also.

Try this function instead
Code:
-- GetRandom
-- Stolen from Sukritact and complicated a bit
----------------------------
function GetRandom(iLower, iUpper, sReason)
	local sWhatfor = "NO_REASON"
	if (sReason ~= nil) and (type(sReason) == "string") then
		sWhatfor = sReason
	end
	--return Game.GetRandNum((iUpper + 1) - iLower, sWhatfor) + iLower
	return TerrainBuilder.GetRandomNumber((iUpper + 1) - iLower, sWhatfor) + iLower
end
Place the function towards the top of your lua file.

To to get a random number you would use as like
Code:
iRandomNumber = GetRandom(1, 50)
Which would give a random number between 1 and 50

I am using the TerrainBuilder to get the random number hoping it is like civ5's Map.GetRandomNumber (or whatever it was called) that is based on the game map and therefore shared across all players. If you look in the Firaxis-made lua files they always use TerrainBuilder.GetRandomNumber() to generate a random number.

-----------------------------

I do not know for a fact that Game.GetRandNum() will not also work but I reworked Suk's code for my own mods based merely on the fact that Firaxis never seemed to use it.
 
Yes, as LeeS said you'll have to use TerrainBuilder.GetRandomNumber to get your number and (if it works like civ5) you have to make sure it's never called by a local event (ie events related to UI) that could happen only on one of the computers in the network game, else the next number called will not be synchronized.

Note that Automation.GetRandomNumber you'll found in some of the game's Lua files can't be used for gameplay use: it's not synchronized in MP.

Also note that if you use pair() to iterate a table for gameplay use, you'll have problems too as it's iterating in an arbitrary order, and will do things in a different orders on each of the computers in a network game. Either use ipairs or a custom function to iterate a table in a fixed order, I'm using this : http://lua-users.org/wiki/SortedIteration

IIRC there is also a great tutorial somewhere in the civ4 forums giving some good coding advices for MP mods, that I think would still apply for civ6

edit: and do not link gameplay changing code directly to an UI event
 
Back
Top Bottom