GROUND BRANCH

GROUND BRANCH

Not enough ratings
Extra lives in multiplayer
By Bishop
This guide describes how to modify a game type script to provide extra lives shared across your team in multiplayer. It combines techniques from other guides with some new code to make spawn limits work correctly.
   
Award
Favorite
Favorited
Unfavorite
The plan
My plan was to add extra lives to the game. I originally thought I'd add respawns per player, but this would have been kind of difficult to achieve, and it doesn't seem as fun anyway. Instead, I decided I would add a number of extra lives shared across the whole team.

This is superior because it maintains the importance of teamwork: every time you let someone on your team get killed, you're hurting yourself, too! Besides, if everyone got extra lives, the effect on difficulty would scale with the number of players on your team--one person has two extra lives, two have four, etc. The difficulty would quickly become trivial. What we want instead is just a little forgiveness for the weaker members of your squad. Anyway, the process is similar to other lua mods listed in the guides section, so I'll keep this short.
The files
The lua script files that govern each game type are found in your Steam installation under Ground Branch/GroundBranch/Content/GroundBranch/Lua. Yeah, the path is kind of repetitive.


You can probably add this modification to any game type by just modifying the correct file, but in my opinion it makes the most sense for coop game types--either Intel Retreival or Terrorist Hunt. As you can see, I made a copy of my TerroristHunt.lua file (TerroristHunt.lua.bak) before proceeding. You should do the same!
The properties
At the top of each file, you will find a section that lays out a local variable containing settings and so forth. In the case of our file, it's a local variable (a "table" in lua) called terroristhunt. We need to add several properties to this variable and its children.


Under the "Settings" section, add a property called "ExtraLives." (The name actually doesn't matter, but the name of the property determines the label of the UI element generated by this property. Also, you have to reference this object again later, so be sure you at least remember the name! ...Maybe just stick with "ExtraLives.") Just adding this config property will add a menu item in the game setup phase.


ExtraLives = { Min = 0, Max = 10, Value = 3, },

Of course, we still need to make use of this new config item, but let's add two more properties first, because we'll need them later.

After "BumRushMode," add the following lines:

Players = {}, PlayerCount = 0,

In just a second, we're going to use these new properties to make this whole thing work.
The secret sauce
Ok, this sauce isn't all that secret. Again, the big lua guide contained most of this stuff (so props to that guy!), but there are some differences. First, let's add the required initialization code. Actually, we're going to put it in a slightly different place, because the method modified in the original guide is only called when the level is first initialized--which actually happens all the way back in the ready room, I think.

Modify the OnRoundStageSet function like this:

function terroristhunt:OnRoundStageSet(RoundStage) if RoundStage == "WaitingForReady" then ai.CleanUp(self.OpForTeamTag) self.BumRushMode = false elseif RoundStage == "PreRoundWait" then self.Lives = self.Settings.ExtraLives.Value self:SpawnOpFor() end end


This resets our number of extra lives right before the game spawns the bad guys for us to kill. Neat, huh? (Without this change, it seemed like you'd get extra lives on your first round on a given map, but not on any subsequent rounds.) Next up, we make some more substantial changes to OnCharacterDied. This is where it really gets interesting.

function terroristhunt:OnCharacterDied(Character, CharacterController, KillerController) if gamemode.GetRoundStage() == "PreRoundWait" or gamemode.GetRoundStage() == "InProgress" then if CharacterController ~= nil then if actor.HasTag(CharacterController, self.OpForTeamTag) then timer.Set("CheckOpForCount", self, self.CheckOpForCountTimer, 1.0, false) elseif self.Lives > 0 then self.Lives = self.Lives - 1 gamemode.BroadcastGameMessage("Extra lives remaining: "..self.Lives, "Engine", 5.0) else for idx = 1, self.PlayerCount do player.SetAllowedToRestart(self.Players[idx], false) end player.SetLives(CharacterController, player.GetLives(CharacterController) - 1) timer.Set("CheckBluForCount", self, self.CheckBluForCountTimer, 1.0, false) end end end end


(If you haven't guessed yet, the new lines are highlighted in red in my screenshots.)

Basically, the new code here says "if the character dies but there are extra lives remaining, allow the character to respawn. Otherwise..." Ok, well, the otherwise part is what's new. "...Otherwise, iterate through our players table and deactivate respawn ability for EVERYONE." The reason for this is that the CheckBlueForCountTimer function won't end the game if anyone else is still alive, and respawn is either "on" or "off." The game itself does not, as far as I know, have any concept of a number of lives--which seems to conflict with what the whole player.SetLives thing appears to do. (I could be wrong about all this, but I tried it the other way first. /shrug)

Lastly, we need to add this whole function, which again is a little different from the one in the other guide:

-- Allow respawn function terroristhunt:PlayerEnteredPlayArea(PlayerState) self.PlayerCount = self.PlayerCount + 1; self.Players[self.PlayerCount] = PlayerState; player.SetAllowedToRestart(PlayerState, true) end


This function activates respawn ability for each player as the players spawn in one by one. Because they spawn in one by one, and because we need to turn off respawn for everyone at the same time, we store each player on a list of players (actually a lua table again). It's this list of players that we iterate over (in the OnCharacterDied function) to deactivate respawn once the team is out of lives.

And.... Well, that's it. You're done. If you've made the changes the way I did, your game should work. If you load in and don't see any menu options on "Terrorist Hunt" (or whatever game mode you modified) you probably missed a comma somewhere. If the game doesn't end properly after everyone dies, it's because of a syntax or logic error in the OnCharacterDied function. Double check your copypasta accordingly. As a last resort, you could always check this gist[gist.github.com] for a full copy of my code. (Note: a gist might look kind of scary, but this code can't execute, and GitHub is not going to hurt your computer, so don't worry about it.)
A few final thoughts
There are probably still some edge cases here that don't work--like if your whole team gets wiped out at once and your extra life count goes to zero, in which case no one would get the chance to respawn because the game would end immediately. (My suggestion is "don't get wiped out.") I don't know. Let me know if you find something.

Also, you could probably just make a table that tracks how many times each character has died and disallow respawn for that character only, but I haven't figured out a way to link a given Character to a given PlayerState in order to make the change. It's something you could look into if you really want to attack the each-player-gets-n-extra-lives problem, even if I don't think that would be as fun.

Hope you enjoy. :)
3 Comments
[±] itsBorked Aug 9, 2022 @ 12:05am 
btw, you've got it set as 'for idx' 2 times instead of 'for i' in your example code.

Your gist file is correct, however.
Lstor Jul 17, 2021 @ 6:51pm 
Awesome stuff, cool to see you improving on my code! Also thank you for doing the right thing and reference the source. I returned the favor and linked to your improvements from the relevant section in my guide.
iTzRaDiaNT ™ Jul 17, 2021 @ 2:32pm 
Love this Second addition of the Ula Game modes / mods / tweaking of the Game! Sooo Dope! its like having a whole other game mode now! :steamthumbsup::carx_drift: Great work!! i find this one easyer to understand and in more detail for the Lives, Thanks again!! 5/5 Stuff you Rock! :cta_emo7: :steamthumbsup: