Page 1 of 1

Pass information from shell to game

Posted: Mon Jan 11, 2021 3:05 am
by cbadal
Hi all,

I've got an idea to enable addon support for SWBFII PSP and PS2 consoles, but I need to be able to get some information from the menus/shell Lua env to the ingame Lua env.
An you may or may not know, they are 2 different environments. Once a game is launched, the menu/shell Lua env is lost and a new one starts up for the current map.

Ideally there would simply be some 'ScriptCB_???' call and get the list setup in the 'ifs_missionselect' screen inside a 'ScriptInit()' function.

Outside of that, being able to 'save' an arbitrary table/object (or even a long string) is ideal.

I've looked over many of the functions available and some look promising; but sometimes you need to know how many return values or parameters a Lua function has in order to use it successfully.

If someone knows how to do this on PC, I could check the functionality on console (as they are very, very similar).

Re: Pass information from shell to game

Posted: Mon Jan 11, 2021 8:47 pm
by Sporadia
I have no idea how to pass custom tables/strings from the interface to ingame and vice versa. Same for saving data. But if you specifically want to get the playlist created in instant action, I think you can use ScriptCB_GetSessionList(). I don't know exactly what that's for or how it works though, but it's the only thing that really looks promising. Also there's a workaround when you don't know how many return values a function has (ie when the function returns a table). If you assign a table instead of a variable when you're calling a function, then it will put all the function's return values into that table. eg:

Code: Select all

local yourTable = { ScriptCB_GetSessionList() }
That definitely works ^. Or I think this works too:

Code: Select all

local yourTable = {}
yourTable = ScriptCB_GetSessionList()
That should collect all the return values of ScriptCB_GetSessionList() and put them into yourTable.

Re: Pass information from shell to game

Posted: Mon Jan 11, 2021 10:04 pm
by MileHighGuy
maybe you are looking for ScriptCB_SaveMissionSetup() along with ScriptCB_LoadMissionSetup() and ScriptCB_IsMissionSetupSaved()
This is how the game knows which units you have unlocked in galactic conquest, and also what map is being launched by ScriptCB_EnterMission().

or possibly ScriptCB_SaveMetagameState() and ScriptCB_LoadMetagameState()

Re: Pass information from shell to game

Posted: Tue Jan 12, 2021 6:25 am
by Anakin
Actually ScriptCB_SaveMissionSetup() is pretty limit. What you should look at is ScriptCB_SaveMetagameState(). There is another for campaign, but i don't remember the name.

Since you're working on PS2/PSP this won't touch you, but IF EVER ANYONE is using this on PC be aware that you will kill my mod!!!!

Here is a code snippet of my mod and how i pass the data on the pipe. (i call it that way would be funny, if this will become the standard name for that trick, lol)

Code: Select all

if SetState then
	
	local remaIO_setState = SetState
		
		SetState = function(...)
		
			-- we only need this data
			local lite_databse = {
				isRemaDatabase = true,
				data = rema_database.data,
				scripts_IF = rema_database.scripts_IF,
				scripts_IG = rema_database.scripts_IG,
			}
			
			if ScriptCB_IsMetagameStateSaved() then
				-- there is old data
				local temp = {ScriptCB_LoadMetagameState()}

				ScriptCB_SaveMetagameState(
					lite_databse,
					temp[1],
					temp[2],
					temp[3],
					temp[4],
					temp[5],
					temp[6],
					temp[7],
					temp[8],
					temp[9],
					temp[10],
					temp[11],
					temp[12],
					temp[13],
					temp[14],
					temp[15],
					temp[16],
					temp[17],
					temp[18],
					temp[19],
					temp[20],
					temp[21],
					temp[22],
					temp[23],
					temp[24],
					temp[25],
					temp[26]
				)
				
			else
				-- there is no old data
				ScriptCB_SaveMetagameState(lite_databse)
			end
			
			return remaIO_setState(unpack(arg))
		end
else
	print("Remaster: Error")
	print("        : SetState not found")
end

And here some code where i put data on the pipe from ingame to exit to menu or to restart the mission

Code: Select all

-- searching database
if ScriptCB_IsMetagameStateSaved() then
	
	-- load all data
	local temp = {ScriptCB_LoadMetagameState()}
	
	-- if it is the database
	if temp[1] and temp[1].isRemaDatabase then
		rema_database = temp[1]
		
		if not (next(temp, 1) == nil) then
			-- there is more, push it back to the pipe
			
			__thisIsGC__ = true
			
			if temp[21] then
				if temp[21][1] and temp[21][1] == "leader" then
					__hero1__ = true
				end
				
				if temp[21][2] and temp[21][2] == "leader" then
					__hero2__ = true
				end
				
				__faction__ = temp[3]
			end

			ScriptCB_SaveMetagameState(
				temp[2],
				temp[3],
				temp[4],
				temp[5],
				temp[6],
				temp[7],
				temp[8],
				temp[9],
				temp[10],
				temp[11],
				temp[12],
				temp[13],
				temp[14],
				temp[15],
				temp[16],
				temp[17],
				temp[18],
				temp[19],
				temp[20],
				temp[21],
				temp[22],
				temp[23],
				temp[24],
				temp[25],
				temp[26],
				temp[27]
			)
		else
			-- there is only the database, clean up
			ScriptCB_ClearMetagameState()
		end
		swbf2Remaster_runGameScripts()
	end
end

-- hook ScriptCB_QuitFromStats to give data back
local rema_QuitFromStats = ScriptCB_QuitFromStats
ScriptCB_QuitFromStats = function(...)

	if ScriptCB_IsMetagameStateSaved() then
		
		-- there is old data
		local temp = {ScriptCB_LoadMetagameState()}
		
		ScriptCB_SaveMetagameState(
			rema_database,
			temp[1],
			temp[2],
			temp[3],
			temp[4],
			temp[5],
			temp[6],
			temp[7],
			temp[8],
			temp[9],
			temp[10],
			temp[11],
			temp[12],
			temp[13],
			temp[14],
			temp[15],
			temp[16],
			temp[17],
			temp[18],
			temp[19],
			temp[20],
			temp[21],
			temp[22],
			temp[23],
			temp[24],
			temp[25],
			temp[26]
		)
		
	else
		-- there is no old data
		ScriptCB_SaveMetagameState(rema_database)
	end
	
	-- let the original function happen
	return rema_QuitFromStats(unpack(arg))
end

-- hook ScriptCB_QuitToShell to give data back
local rema_QuitToShell = ScriptCB_QuitToShell
ScriptCB_QuitToShell = function(...)

	if ScriptCB_IsMetagameStateSaved() then
		
		-- there is old data
		local temp = {ScriptCB_LoadMetagameState()}
		
		ScriptCB_SaveMetagameState(
			rema_database,
			temp[1],
			temp[2],
			temp[3],
			temp[4],
			temp[5],
			temp[6],
			temp[7],
			temp[8],
			temp[9],
			temp[10],
			temp[11],
			temp[12],
			temp[13],
			temp[14],
			temp[15],
			temp[16],
			temp[17],
			temp[18],
			temp[19],
			temp[20],
			temp[21],
			temp[22],
			temp[23],
			temp[24],
			temp[25],
			temp[26]
		)
		
	else
		-- there is no old data
		
		if rema_database then 
			ScriptCB_SaveMetagameState(rema_database)
		end
	end
	
	-- let the original function happen
	return rema_QuitToShell(unpack(arg))
end

-- hook ScriptCB_RestartMission to add data to the pipe
local rema_RestartMission = ScriptCB_RestartMission
ScriptCB_RestartMission = function(...)
	
	ScriptCB_SaveMetagameState(rema_database)
	
	-- let the original function happen
	return rema_RestartMission(unpack(arg))
end

There are a few things you need to take care of:
1) The pipe is limit in size. I cannot tell you the exact size, just the gc pipe is bigger then the galactic conquest. Things that can help to transfer as many data as possible
- Maybe you can use both side by side if you have much data
- avoid strings. If you want to transfer strings, write them in the localize file under a number code and in the game env you catch the name from localize database with the passed number code.

2) There may be already other data on the pip
- In case there is a other mod
- In case you are loading a galactic conquest mod

3) If there is data on the pipe on return the interface will direct you to galactic conquest loading. This will fail because the data is garbage from GC point of view and the game will crash.

4) Restarting a mission means you exit a mission on a unusual way and reenter it. So make sure needed information are on the pipe

Re: Pass information from shell to game

Posted: Tue Jan 12, 2021 7:31 pm
by cbadal
Thanks guys for the replies.

To give a better feel for the idea, here is some psudocode:

Code: Select all

-- mod_mission.lua
-- This is a mission bootloader, intended to be used in a SWBFII game 
-- that does not already support 'addons' (PSP/PS2)
-- But could also theoretically be used for xbox (without the Title Update) as well 

function GetModMissionFile()
    local data = ScriptCB_???() -- get the piece of data left for us by the menu/shell env 
    --  get a path to the correct mission.lvl 
    return data.missionPath -- should be something like 'addon/abc/mission.lvl'
end 

function GetMissionScriptName()
    local data = ScriptCB_???() -- get the piece of data left for us by the menu/shell env 
    --  get the correct script name to load
    return data.scriptName -- this should be a normal mission script name (like "abcc_con").
end 

my_mod_mission_file    = GetModMissionFile()
ReadDataFile(my_mod_mission_file)       -- read in the mission file containing our target script 
my_mission_script_name = GetMissionScriptName() 
ScriptCB_DoFile(my_mod_mission_script_name)  -- execute the target mission script 

------============end mod_mission.lua=============

---====== addme for PSP/PS2 ===================
--in the addme, it has something like the following entry; maplua file for a mod would always be 'mod_mission'.
...

table.add(sp_missionselect_listbox_contents,  { 
    isModLevel = 1, 
    map_desc = "mapname.description.ABC", -- we'll need to modify mission select screen a little for localization to work nicely
    map_name = "mapname.name.ABC",
    --mapluafile = "ABC%s_%s",
    mapluafile = "mod_mission",
    missionPath = "addon/ABC/mission.lvl",--  <-- the path to the correct mission.lvl
    scriptName = "abcc_con", -- I'll have to figure out this part better, but something like this for script
    era_g = 1, 
    era_c = 1, 
    mode_con_g = 1, 
    mode_con_c  = 1,  
  })
--==========================
I'll see if I can get this working and report back what I find.