Removing a ship from the build menu based on a research

Hi guys,

I’m trying to get a ship to not show up in the build tree based on whether or not a research item has been granted. I was thinking of the HW1 research ships, but this one should be a lot simpler actually.

The background of why I even want to do that is:
The ship is a shipyard that should only be built by the AI in order to help balance out CPU skirmishes. The HW2 guys always trounce the HW1 guys, but in order to balance them out, the additional stuff would make them too mighty when a human was playing them. So the solution was to give them an extra build slot for big stuff in a shipyard that only they can build, and then the build speeds between the HW2 guys and the HW1 guys can be about the same.

Anyway, there’s a dummy research item called ‘BuildOff’ that gets granted to all CPU players so that the scripting can go off of that to control which ships to allow. using the ‘!’ modifier for the research and build LUAs, all of the ships and research items that should be available to CPU players or humans are set up and they all work.

I’d like to get this unavailable shipyard out of the build menu though:

The ship I want to remove is called Tai_Shipyard2.

This line is added to the SHIP file:

addCustomCode(NewShipType,"data:Ship/Tai_Shipyard2/Tai_Shipyard2.lua","Remove_Shipyard","","","","Tai_Shipyard2",10)

and this is the lua file in the ship folder:

function Remove_Shipyard(playerIndex)
	if Player_HasResearch(playerIndex, "BuildOff")==0 then

	Player_RestrictBuildOption(playerIndex, "Tai_Shipyard2")
    end
end

I’ve tried some other stuff too, but it’s super not working.

Help!

1 Like

&=and
|=or
!=not
so you can just define this in build.lua

Hi, thanks for your answer! …but that’s not what I mean. :slight_smile:

Here is the part of the def_build.lua with the two shipyards:

	{
		Type =					Ship,
		ThingToBuild =			"Tai_shipyard",
		RequiredResearch =		"SuperCapitalShipDrive & !BuildOff",
		RequiredShipSubSystems =	"",
		DisplayPriority =		75,
		DisplayedName =			"Imperial Shipyard",
		Description =			"<b>Description:</b> The Emperor has graciously granted your request for reinforcements by decreeing that the Royal Shipworks shall hyperspace an Imperial Shipyard to the front.\n\n<b>Prerequisites:</b> Super-Capital Ship Drive Research.\n\n<b>Requires 1 Free Shipyard Unit Space and 1 Free Carrier Unit Space to build. </b>"
	},
	{
		Type =					Ship,
		ThingToBuild =			"Tai_shipyard2",
		RequiredResearch =		"SuperCapitalShipDrive & BuildOff",
		RequiredShipSubSystems =	"",
		DisplayPriority =		76,
		DisplayedName =			"Imperial Shipyard AI",
		Description =			"AI only. (We'll get this out of the tree once we figure out how.)"
	},

And ‘BuildOff’ gets granted to all AIs from the cpu_players.lua. So it all works like it should, but it still shows up in the build tree like the screenshot above. I’ll like to get it out of there, and the only example I can think of from the game like that is the HW1 research ships, which have a lua file in the ship folder. That lus is pretty complicated, and I think mine can be pretty simple, but I bet I’m doing something wrong that’s obvious to someone who knows what they’re doing.

I sort of remember a HW2 mod that had base level ships and their upgraded versions on the same build menu slot.
You might be able to do the same, I think it was accomplished by Display Priority being the same number, with the upgraded version being the one further down the list

(I think. It’s been years and years)

Try giving these two items a same display priority.

So, I tried giving the build items the same DisplayPriority, but it always showed the one that the player can’t build regardless of which one came first in the def_build.lua.

I also tried adding “AIOnly = 1,” and DisplayPriority 0 , but those didn’t work either.

I did find one of the problems with the ship.lua though. It needed parenthesis. So this one works for the player:

0 works in the ship file to make the script only run one time:

addCustomCode(NewShipType,"data:Ship/Tai_Shipyard2/Tai_Shipyard2.lua","Remove_Shipyard","","","","Tai_Shipyard2",0)

and this lua file works to remove the build item:

function Remove_Shipyard(playerIndex)
	if (Player_HasResearch(playerIndex, "BuildOff")==0) then

	--Player_RestrictBuildOption(playerIndex, "Tai_Shipyard2")
	
	--else

	Player_RestrictBuildOption(playerIndex, "Tai_Scout")

	end
end

It’s just set up with the scout so I could see if it’s working right away, but apparently, whatever the result of this script is, it gets applied to everybody, even the AI players. crud.

I’m pretty sure, this is the line that sets up an individual group in order to apply a script to it:

function Create_Tai_ResearchShip(CustomGroup, playerIndex, shipID)	
	SobGroup_CreateIfNotExist("researchship_temp")
end

But the function I’m trying to run doesn’t apply to a specific ship; it applies to the player himself. Anybody ever do something like this?

Thanks!

Remove_Shipyard should not be a custom script. It should be defined as a gamerule:

in the MainRule function:

playerIndex = 0;
while (playerIndex < playerCount) do
	if (Player_HasResearch(playerIndex, "BuildOff") == 0) then
		Player_RestrictBuildOption(playerIndex, "Tai_Shipyard2")
	end
	-- go to next player
	playerIndex = playerIndex+1
end
3 Likes

it works!! =D

the playerIndex line has to be after " local playerCount = Universe_PlayerCount() " and the semi-colon shouldn’t be there, but you sir are a GENIUS - good karma for you!

here’s the whole main.lua file in case someone’s looking for this in a million years:

mainrule_flag = 1

function mainrule_updating()		
		if mainrule_flag == 1 then
				objectivePrimary = Objective_Add("$3005", OT_Primary)
				Objective_AddDescription(objectivePrimary, "$3006")
				Subtitle_Message_Handler("$3007", 2, "data:sound\\speech\\allships\\emperor\\CHALLENGE_DESTROYMOTHERSHIPS_2", Universe_CurrentPlayer())		
				mainrule_flag = 0
		end

		
		local playerIndex = 0
		local playerCount = Universe_PlayerCount()
		while (playerIndex < playerCount) do
				if (Player_IsAlive(playerIndex) == 1 and Player_HasShipWithBuildQueue(playerIndex) == 0) then
						Player_Kill(playerIndex)
						if playerIndex ~= Universe_CurrentPlayer() then
--								UI_SetScreenEnabled("PlayerDestroyedScreen", 1)
--								UI_SetScreenVisible("PlayerDestroyedScreen", 1)			
								local playerNameW = Player_GetName(playerIndex)								
--								UI_SetTextLabelTextWF1("PlayerDestroyedScreen", "lblDescription1", "$1231", playerNameW);
								Sound_SpeechPlay("data:sound\\speech\\missions\\m_15\\47100")
								Player_AddLocalChatMessage("$1231", playerNameW);
						end
				end
				playerIndex = playerIndex+1
		end
		local numAlive = 0
		local numEnemies = 0
		local gameOver = 1

--shipyard check tai
		playerIndex = 0
		while (playerIndex < playerCount) do
			if (Player_HasResearch(playerIndex, "BuildOff") == 0) then
			Player_RestrictBuildOption(playerIndex, "Tai_Shipyard2")
			end
		-- go to next player
		playerIndex = playerIndex+1
		end
--end of shipyard check

		playerIndex = 0
		while (playerIndex < playerCount) do
				if (Player_IsAlive(playerIndex) == 1) then
						local otherPlayerIndex = 0
						while (otherPlayerIndex < playerCount) do
								if (AreAllied(playerIndex, otherPlayerIndex) == 0) then
										if (Player_IsAlive(otherPlayerIndex) == 1) then
												gameOver = 0
										else
												numEnemies = numEnemies + 1
										end
								end
								otherPlayerIndex = otherPlayerIndex + 1
						end
						numAlive = numAlive + 1
				end
				playerIndex = playerIndex + 1
		end
		if (numEnemies == 0 and numAlive > 0) then
				gameOver = 0
		end
		if (gameOver == 1) then
				Rule_Add("waitForEnd")
				Event_Start("endGame")
				Rule_Remove("mainrule_updating")
		end
end

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

Glad I could help!

(as an aside:)

I wouldn’t say “shouldn’t”:

https://www.lua.org/manual/4.0/manual.html#2.