How to change victory conditions in singleplayer skirmish deathmatchRM game rule? [Resolved, Op success]

Hello
I’m looking for an advice on how to add one or two options for the regular deathmatchRM game type in player vs cpu skirmish games.
I’m particularily interested in an option to only finish the match by quitting manually or having to destroy every single enemy ship.
There don’t seem to be any additional RM game types for download anywhere out there, and I’ve already tried “HW Classic Enhanced for HWRM,” but I need access to my own edited starting fleets and all four races instead of only HW1 ones.
Already extracted the main .big file and found the rules folder, yet haven’t figured out where victory conditions are described in the files.
Can anyone point me to a solution elsewhere or guide me through what needs to be done?

The function that describes victory conditions is in Data:leveldata\multiplayer\lib\main.lua

Allright then;
I’ve had a look at main.lua. Peered at its waving lines… and regretably failed at nailing the command I was looking for.
Never been into coding. Kinda hoped I’d find some relatively simple cause and effect formula, though.
I don’t suppose tracking down every “gameover = 1” and switching that number to 0 will do the trick.
I mean, these values… “playercount,” “playerindex,” “player_kill”? What? A lot of it appears dependant on equations, comparing remaining fleet numbers, but I’m too inexperienced with this otherwordly matter.
Help! I just want to have my ships regrouped, repaired and hyperspaced out after a battle. I’m no programist :expressionless:
Why after so long after release there still isn’t a bunch of game type adding mods to choose from…?

Why after so long after release there still isn’t a bunch of game type adding mods to choose from…?

Be happy to work on that as soon as you fork over several hundred dollars.

We work on the projects we prefer, since it’s our personal hobby. If you want a mod to exist, nobody is going to make it except you.

1 Like

I could use the money :smiley:

2 Likes

Ouch
You work on projects that respond to your tastes and needs – I’m perfectly aware of that and that’s exactly what I had in mind stating I’m surprised no modder contributed to an increased game type selection so far. It seems everyone is content with the default options.

I used to play skirmish with deathmatch plus in classic HW2. Didn’t need anything more, maybe except a “no research” option, but I’ve added all the techs to my racial luas and it did the trick just as fine.

Here I have no idea how to advance. Can’t find a formula simply going by “if x then game over”. All I ask is to be pointed towards the specific lines requiring specific changes or a clear statement it is far more complex of a task, demanding multiple file editing, and that I shouldn’t get my hopes up. Sheesh.

1 Like

So, let me break down some things going in in the file @506933395 indicated…

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
						local playerNameW = Player_GetName(playerIndex)								
						Sound_SpeechPlay("data:sound\\speech\\missions\\m_15\\47100")
						Player_AddLocalChatMessage("$1231", playerNameW);
				end
		end
		playerIndex = playerIndex+1
end

I’ve omitted a few lines because they’re commented out and don’t actually do anything as a consequence.

So first the playerindex and playercount variables are set. The index value is how the code knows what player we’re talking to the engine about. Then we loop through all the players. I’ll break the code into two sections here, an inner and an outer one. The outer one first.

local playerIndex = 0
local playerCount = Universe_PlayerCount()
while (playerIndex < playerCount) do
		--omitted code was here
		playerIndex = playerIndex+1
end

What this does is simply cycle through every player in the game. You start at player zero(Most code counts from zero instead of one. There are good reasons for this), do something in the omitted code, and then step forward to the next player. Once your player index goes over the player count, you stop looping.

Now lets look at the inner code that actually does things.

if (Player_IsAlive(playerIndex) == 1 and Player_HasShipWithBuildQueue(playerIndex) == 0) then
		Player_Kill(playerIndex)
		if playerIndex ~= Universe_CurrentPlayer() then
				local playerNameW = Player_GetName(playerIndex)								
				Sound_SpeechPlay("data:sound\\speech\\missions\\m_15\\47100")
				Player_AddLocalChatMessage("$1231", playerNameW);
		end
end

So there’s a conditional statement here at the outset. If the things in the parenthesis on the first line are true then the contained code is executed, otherwise it is skipped. We have two equality comparisons in there, so there’s two functions, Player_IsAlive(playerIndex) and Player_HasShipWithBuildQueue(playerIndex), that we can think of as questions the script is asking the engine. Then we’ll compare the responses the engine gives us to the values next to them in that code. Generally speaking in this kind of thing 0 means false and 1 means true. The names of these functions are fairly self expanatory.

So, to put the logic here in plainer english

Check each player
If the player is still alive and doesn’t have any build-capable ships left then kill the player
If the previous line was true and the player being killed is the local player in MP or the human player in a local skirmish, play a sound and send a chat message
Move to the next player

If what you want to do is simply have players survive until every last ship is dead then you might want to change line 13 of that file to something along the lines of this:

				if (Player_IsAlive(playerIndex) == 1 and SobGroup_Count("Player_Ships"..playerIndex) == 0) then

Might get you what you want. But I haven’t tested it, and it may end up being more complicated than that. Off the top of my head this may result in a player dying if all their ships are in hyperspace at the same time.

Which comes to the crux of the problem…

Figuring out exactly what changes need to be made amounts to making the mod for you. Sometimes seemingly simple changes can balloon into big tasks and there’s no way to really know that until you’re really in there, that’s just the nature of modding. And it sounds like from the comment

you’ve got ambitions a bit beyond just altering the win condition too. Ultimately teaching the game to behave differently does require some programming. People here are generally willing to help you figure out how to do things, you just need to meet us halfway and be willing to learn the system too.

1 Like

That looks like a great explanation. My main question is how you put colours into your code on this forum - I’ve wanted to do that for ages but didn’t think it was possible…

1 Like

I enclosed those bits in [ code ] tags and automatic highlight happened. Not sure what syntax it’s trying to highlight there, it doesn’t seem to quite like lua.

Tried your suggestion with a huge success, Eat.

Can you clarify something though – what’s this “SobGroup” thing, did you mean “SubGroup”? Tested only with “Sub” anyway. Also, these dots after “Player_Ships” – what are they for?

Before an attempt with your line, I’ve found out a way of preventing the match from ending upon CPU’s defeat. So had the manual quitting already, but remaining CPU ships still despawned after its carrier’s destruction.

	local numAlive = 0
	local numEnemies = 0
	local gameOver = [1] (Got it by placing a 0 here)
	playerIndex = 0

I hope this won’t make anybody mad around here, but I’ll place the entire main.lua’s content below, so even people who haven’t extracted the .big file can make their file and use it to their joy. Brace yourselves, a forum noob here:

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 SubGroup_Count(“Player_Ships”…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
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

To sum up, placing a notepad file with the above content within a self made directory of HomeworldRM > Data > leveldata > multiplayer > lib and naming it main.lua will get you, fellow noobies, an opportunity to fight the remaining CPU opponent’s ships after you deal with each and every one of their production ships.

Also, the match will not end even if the opponent is left without a single unit to control – only until you manually quit it (my own editing mentioned above proved unnecessary).

All thanks to EatThePath and his effort to put it all here for us.

o7

“sobgroup” is the correct term. It is used in HW scripts to refer to a group of ships. No idea what sob stands for, if anything…

1 Like

No, I didn’t mean SubGroup, SobGroup is a standard part of the scripting interface refering to a collection of ships. The dots here are gluing the player’s index number to the name of the sob group being referenced to refer to a built in collection for all the ships of a particular player. Your code isn’t actually working, it’s erroring out and thus the game doesn’t actually have a victory condition, which is why the behavior you’re seeing, the game never ending unless done manually, isn’t what you asked for, which is the game ending if a player loses all their ships.

1 Like

Oh well, in the end, using the “subgroup” term actually got me what I wanted…

Manual quitting is exactly what I’ve aimed for from the beginning. Otherwise I’d have to leave some resource collector or sth alive after the battle is decided, before I could tend to my wounded vessels and send them into hyperspace. Just a habit of mine.

Thanks again.

If that’s what you want you’d be better off just deleting the contents of mainrule_updating() entirely. What you’ve done could have side effects like preventing other scripted stuff(relics etc) from working at all.

1 Like

SobGroup = ***S***pace ***Ob***ject Group

2 Likes

Did you make that up :stuck_out_tongue:

1 Like

my bet’s generally been on ShipOBject

No.

4 Likes