[SOLVED][SCRIPT] Your fleet is victorious, Stats functions

In my game type mod I don’t get the YOUR FLEET IS VICTORIOUS message when a match ends. I understand this is in the gameoverscreen.lua UI file, but how do I trigger it? I did a grep search on the entire data folder and found no clues. Thanks.

in uisettings.lua, the type of this screen is defined (type = “GameOverScreen”), so I’m pretty sure the call to it is hardcoded for vanilla gameplay modes.

{
    name = "GameOverScreen",
    filename = "DATA:\\UI\\NewUI\\GameOverScreen.lua",
    activated = 0,
    type = "GameOverScreen",
},    

Did you try using setGameOver() in your gamerule file ?
This is what is found at the end of …\leveldata\multiplayer\lib\main.lua

function waitForEnd()
        if(Event_IsDone("endGame")) then
                setGameOver()
                Rule_Remove("waitForEnd")
        end
end

I have

function waitForEnd()
	if (Event_IsDone("endGame")) then
		WriteStatsThenEndGame()
		Rule_Remove("waitForEnd")
	end
end

and

function WriteStatsThenEndGame()
	if (AdvStats == 1) then
		WriteStats()
	end
	setGameOver()
end

is there a specific reason why you moved the setGameOver() call into the subfunction ? (yes, I know it shouldn’t change anything)
And what does your WriteStats() function do exactly ?

Convenience.

It writes statistics to the profile directory.

Did you try changing the order ? Doing the setGameOver() function before writing your stats for example ?

You should also try to comment out your WriteStats() function, to see if the game over is set in this case.

I just tested on a smaller map and the message is appearing properly. Maybe there’s just too much going on all at once on an 8 player map?

[edit]

Yeah, I just tried an 8 player map again, and there was no message. Same mod settings. The game just kind of froze when the last (actually it was a 7v1 battle) enemy died, and dropped me back to the end of game stats screen.

uhhh, straaaannge…
and if you comment out your WriteStats() function, does it work ? Could it be that the writing to a file is taking too much time when there is a lot of player, and the setGameOver() doesn’t trigger correctly ?

Yes, if I comment it out it works. But the script should wait until the writing is complete before triggering game over.

Are any error messages generated when Game Over happens (or doesn’t)?

And what happen if you put setGameOver() before WriteStats() ?

No error messages.

Calling setGameOver() before WriteStats() did not help either.

There is definitely something fishy here…
How could WriteStats() interfere with setGameOver() if it’s done only after it ? I don’t understand !

Here’s the function.

-------------------------------------------------------------------------------
-- Writes ending stats to a file. Call this before you call the setGameOver() function.
-- Does not write info on subsystems, currently, and probably never will.
--
function WriteStats()
	local fdate = date("%m-%d-%Y_%H_%M_%S")
	if (strsub(fdate, 1, 1) == "0") then
		fdate = strsub(fdate, 2)	
	end
	local WriteFile = "HWCE_EndGame_" .. fdate .. ".stats"
	local WriteHandle = openfile(WriteFile, "w+")
	closefile(WriteHandle)
	local WriteHandle = openfile(WriteFile, "a")
	local WriteString = "  GameRulesName = \"" .. GameRulesName .. "\","
	local LocalPlayer = FE_GetCurrentPlayerIndex()
	for playerIndex = 0, Universe_PlayerCount() - 1 do
		local sRace = Player_Races[playerIndex + 1]
		WST_trace("WST: Player " .. playerIndex .. " is race " .. sRace .. ".")
		WriteString = WriteString .. "\n  Player" .. playerIndex .. " = {"
		WriteString = WriteString .. "\n    DETAILS = {"
		WriteString = WriteString .. "\n      LocalPlayer = "
		if (playerIndex == LocalPlayer) then
			WriteString = WriteString .. 1 .. ","
		else
			WriteString = WriteString .. 0 .. ","
		end
		WriteString = WriteString .. "\n      IsAlive = " .. Player_IsAlive(playerIndex) .. ","
		WriteString = WriteString .. "\n      Team = " .. Player_Team(playerIndex) .. ","
		WriteString = WriteString .. "\n      RUs = " .. Player_GetRU(playerIndex) .. ","
		WriteString = WriteString .. "\n" .. "    },"
		dofilepath("data:scripts/races/" .. sRace .. "/scripts/def_build.lua")
		WriteString = WriteString .. "\n    BUILD = {"
		for i, iCount in build do
			local bldName = iCount.ThingToBuild
			local bldType = iCount.Type
			local bldAmount = Player_GetNumberOfSquadronsOfTypeAwakeOrSleeping(playerIndex, bldName)
			WST_trace("WST: Player " .. playerIndex .. " has built " .. bldName .. ".")
			WriteString = WriteString .. "\n      {Type = " .. bldType .. ", ThingToBuild = \"" .. bldName .. "\", Number = " .. bldAmount .. ",},"
		end
		WriteString = WriteString .. "\n" .. "    },"
		dofilepath("data:scripts/races/" .. sRace .. "/scripts/def_research.lua")
		WriteString = WriteString .. "\n    RESEARCH = {"
		for i, iCount in research do
			local resName = iCount.Name
			local resComplete = Player_HasResearch(playerIndex, resName)
			WST_trace("WST: Player " .. playerIndex .. " has researched " .. resName .. ".")
			WriteString = WriteString .. "\n      {Name = \"" .. resName .. "\", Completed = " .. resComplete .. ",},"
		end
		WriteString = WriteString .. "\n" .. "    },"
		WriteString = WriteString .. "\n" .. "  },"
	end
	WriteString = WriteString .. "\n"
	write(WriteHandle, WriteString)
	closefile(WriteHandle)
	print("GPE: ADVANCED STATS written to profile folder.")
--	Rule_Remove("WriteStats")		-- should this function be a rule or not?
end

The question I have is, does WriteStats work at all? If you call it in a situation where the game isn’t ending, does anything get written? There were to be some changes to lua filesystem access with 2.0, so it seems worth checking.

Yes it works.

Do you know how the regular stats get written? The ones in “HomeworldRM\Bin\Profiles\Profile2\Stats” folder I mean. I just noticed that they are not being written when I play using my game rule. But when I play with the regular Deathmatch scenario, then they do get written.

The way he used it is ok, no worries on that part.

@Mikali :
why do you open then close the file in the beginning ?
If you create a new file each time, you could directly use writeto(“HWCE_EndGame_” … fdate … “.stats”) which create the file and open it for writing, and writeto() to close it.
write() doesn’t need the filehandle information when the file is already open.

Rule_Remove(“WriteStats”) should definitely NOT be here as this function is not a rule (you do the WriteStats() only one time from what I understand)

Also, I don’t know if having so many concatenate operation is a good idea.
Otherwise, I don’t see anything wrong in the code :confused:

Edit : The code I posted had a big booboo ^^

Edit2 : this I found in lua5 documentation. Too much concatenation is indeed bad :

Doing a large number of concatenation operations may be slow because 
each concatenation may allocate a new string in memory.  The following 
three examples give the same result except the first may be much slower:

-- slow
local s = ''
for i=1,10000 do s = s .. math.random() .. ',' end
io.stdout:write(s)

-- fast
for i=1,10000 do io.stdout:write(tostring(math.random()), ',') end

-- fast, but uses more memory
local t = {}
for i=1,10000 do t[i] = tostring(math.random()) end
io.stdout:write(table.concat(t,','), ',') 

This should run faster :

-------------------------------------------------------------------------------
-- Writes ending stats to a file. Call this before you call the setGameOver() function.
-- Does not write info on subsystems, currently, and probably never will.
--
function WriteStats()
    local fdate = date("%m-%d-%Y_%H_%M_%S")
    if (strsub(fdate, 1, 1) == "0") then
        fdate = strsub(fdate, 2)    
    end
    writeto("HWCE_EndGame_" .. fdate .. ".stats")
    write("  GameRulesName = \"" .. GameRulesName .. "\",")
    local LocalPlayer = FE_GetCurrentPlayerIndex()
    for playerIndex = 0, Universe_PlayerCount() - 1 do
        local sRace = Player_Races[playerIndex + 1]
        WST_trace("WST: Player " .. playerIndex .. " is race " .. sRace .. ".")
        write("\n  Player" .. playerIndex .. " = {")
        write("\n    DETAILS = {")
        write("\n      LocalPlayer = ")
        if (playerIndex == LocalPlayer) then
            write(1 .. ",")
        else
            write(0 .. ",")
        end
        write("\n      IsAlive = " .. Player_IsAlive(playerIndex) .. ",")
        write("\n      Team = " .. Player_Team(playerIndex) .. ",")
        write("\n      RUs = " .. Player_GetRU(playerIndex) .. ",")
        write("\n    },")
        dofilepath("data:scripts/races/" .. sRace .. "/scripts/def_build.lua")
        write("\n    BUILD = {")
        for i, iCount in build do
            local bldName = iCount.ThingToBuild
            local bldType = iCount.Type
            local bldAmount = Player_GetNumberOfSquadronsOfTypeAwakeOrSleeping(playerIndex, bldName)
            WST_trace("WST: Player " .. playerIndex .. " has built " .. bldName .. ".")
            write("\n      {Type = " .. bldType .. ", ThingToBuild = \"" .. bldName .. "\", Number = " .. bldAmount .. ",},")
        end
        write("\n    },")
        dofilepath("data:scripts/races/" .. sRace .. "/scripts/def_research.lua")
        write("\n    RESEARCH = {")
        for i, iCount in research do
            local resName = iCount.Name
            local resComplete = Player_HasResearch(playerIndex, resName)
            WST_trace("WST: Player " .. playerIndex .. " has researched " .. resName .. ".")
            write("\n      {Name = \"" .. resName .. "\", Completed = " .. resComplete .. ",},")
        end
        write("\n    },")
        write("\n  },")
    end
    write("\n")
    writeto()
    print("GPE: ADVANCED STATS written to profile folder.")
end

good question ! Perhaps they’re are written during the execution of setGameOver() !
It could explain why writting too many things nearly at the same time is a problem (but it definitely should not)

Are they written when you only use 2 players ?
Same question differently : is the apparition of the GameOver message (or not) linked to the vanilla stats being written (or not) ?

@Mikali : previous post updated, as too much concatenation is indeed bad