Game Development Community

Creating separate player spawn points through a network

by Djekko Spurgin · in Torque 3D Beginner · 03/17/2016 (5:15 am) · 7 replies

I'm trying to create a simple 2 player game in torque3D. I have managed get the a LAN server working and I have two separate spawns, one for each player. I've also figured out how limit the server to just 2 players. The problem I cant seem to overcome is making sure each player is a different character. When I join the game there is always a 50/50 chance on which character the player will be. I want it so player 1 will be one character and player 2 will always be the other character. I've tried re working the scripts for the spawn but everything I try to implement comes with no success.

I have thought about testing if there is any players in the server something along the lines of this

if (numberOfPlayers == 0)
{
spawn player as character 1
}
else //There is someone already in the game
{
spawn player as character 2
}

This is what I am currently trying but I don't know yet how to retrieve that kind of information from the server or if its possible.

I am fairly new to Torque and C# so I might be missing something obvious I should be doing instead.

#1
03/17/2016 (10:07 am)
Torque engines use TorqueScript, formally called C-Script, it is not C# (C-Sharp) even though they share the same file extensions, unfortunately, and C-Script was the first to use it.

As for your spawn problem you'll need to keep track of which player is what. Because you can't simply rely on current player count, cause what if first player leaves and another joins, then relying on player count would cause the just joined player to become the second player when there's already one. So best thing to do is a simple team management like this:

1) Edit game/scripts/server/game.cs and locate function onServerCreated(). Somewhere in that function do:
// create teams
new SimSet(TeamSet1);
new SimSet(TeamSet2);
and should do clean this up by placing this code into function onServerDestroyed() in the same file:
// destroy teams
if (isObject(TeamSet1))
   TeamSet1.delete();
if (isObject(TeamSet2))
   TeamSet2.delete();

2) Edit game/scripts/server/gameCore.cs and find this function and just after commandToClient:
function GameCore::onClientEnterGame(%game, %client)
{
   //echo (%game @"\c4 -> "@ %game.class @" -> GameCore::onClientEntergame");

   // Sync the client's clocks to the server's
   commandToClient(%client, 'SyncClock', $Sim::Time - $Game::StartTime);
Do this procedure:
// place player into a team of one
if(TeamSet1.getCount())
{
   // 1st team already has a player, new player goes into 2nd team
   TeamSet2.add(%client);
   %client.team = 2;
} else
{
   // 1st team has no players, new player goes into 1st team
   TeamSet1.add(%client);
   %client.team = 1;
}
No need for code to remove the client from a SimSet because they'll be removed automatically upon disconnect due to how SimSet and SimGroup classes work. However if you wanted a player to switch teams then you would have to of course remove them from their current team SimSet.
Note that an object can belong to multiple SimSets, but can only belong to one SimGroup at a time. Adding an object to a SimGroup automatically removes from it from an existing SimGroup.

3) So now finally on spawn you can control which player is what by doing something like this, probably somewhere in GameCore::spawnPlayer function:
if(%client.team == 1)
{
   // spawn team 1 player
} else
{
   // spawn team 2 player
}
#2
03/17/2016 (3:01 pm)
Or, realize that it's two players - if you don't know what team you're on the problem runs deeper than the color of your clothing....

This is where setting the skin happens:
https://github.com/RichardRanft/Torque3D/blob/development/Templates/Full/game/scripts/server/gameCore.cs#L908

So, instead of:
%client.skin = addTaggedString( getField(%availableSkins, getRandom(%count)) );
you could use
%client.skin = addTaggedString( getField(%availableSkins, %client.team) );
assuming you had set the team number on the client previously.
#3
03/17/2016 (9:45 pm)
Oh - you could also set it in the spawnsphere's spawn script - so that any player who spawns from that spawnsphere will have that skin.
#4
03/19/2016 (1:38 am)
Thanks Nathan Ill try that when I am back at my desk. And your right i did get to to work through player count but as you said if the first person leaves and joins again it goes wrong.

Richard Ill also look into yours as well but each player is a different model so I don't think changing the skin would help too much.

Thanks guys ill let you know where I get with this
#5
03/19/2016 (5:42 pm)
Different model is fine too - just create the player using the desired datablock instead of skin.
#6
03/22/2016 (4:20 am)
I am still having Trouble with this. With Nathans solution it made a lot of sense to me but the last bit with the GameCore::spawnPlayer seems to loose me I understand what its doing but I'm not entirely sure where to put it and how I would spawn to a specific spawn sphere or player datablock.
#7
03/22/2016 (7:18 am)
I've managed to achieve what I wanted now. It took a lot of trail and error but i got there in the end. I ended up using GameCore::preparePlayer instead of GameCore::spawnPlayer like this.

function GameCore::preparePlayer(%game, %client)
{
   //echo (%game @"\c4 -> "@ %game.class @" -> GameCore::preparePlayer");

   // Find a spawn point for the player
   // This function currently relies on some helper functions defined in
   // core/scripts/spawn.cs. For custom spawn behaviors one can either
   // override the properties on the SpawnSphere's or directly override the
   // functions themselves.
   if(%client.team == 1){
   %playerSpawnPoint = pickPlayerSpawnPoint($Game::DefaultPlayerSpawnGroups);
   } else{
   %playerSpawnPoint = pickSecondPlayerSpawnPoint($Game::DefaultPlayerSpawnGroups);
   }
   // Spawn a camera for this client using the found %spawnPoint
   //%client.spawnPlayer(%playerSpawnPoint);
   %game.spawnPlayer(%client, %playerSpawnPoint);

   // Starting equipment
   %game.loadOut(%client.player);
}

Then in core/scripts/server/spawn.cs I changed the original pickPlayerSpawnPoint and added [b]pickSecondPlayerSpawnPoint[b/]. Each function is the same but each one tests the possible spawn points against the given name for the spawns.

function pickPlayerSpawnPoint(%spawnGroups, %client)
{
	%targetName = BeaverSpawn;

	if(%targetName $= "")
	{
	 %targetName = "DefaultSpawnSphere";
	}
	// Walk through the groups until we find a valid object
	for (%i = 0; %i < getWordCount(%spawnGroups); %i++)  
	{  
		%group = getWord(%spawnGroups, %i);  

		if (isObject(%group))  
		{  
			// Gets number of spawn points under current spawn group
			%spawnCount = %group.getCount();

			// If there are no valid spawn points, let us know
			if (%spawnCount $= 0)
			{
			   echo("****c4 -> No valid spawn points found in this group!");
			}
			else
			{
			   // If spawn points are found, iterate through them
			   for (%x = 0; %x < %spawnCount; %x++)
			   {
				  %spawn = %group.getObject(%x);
				  %name = %spawn.getName();
				  
				  // Test the current spawn point for a match
				  echo(%spawn @ "c4 -> Testing spawn point " @ %name);
				  if (%targetName $= %name)
				  {
					 // Once a match is found, spawn player at matching location
					 echo(%spawn @ "c4 -> SPAWNING AT LOCATION: " @ %name);
					 return %spawn;
					 
				  }
			   }
			}
		}
	}  
}
function pickSecondPlayerSpawnPoint(%spawnGroups, %client)
{

	%targetName = PandaSpawn;

	if(%targetName $= "")
	{
	 %targetName = "DefaultSpawnSphere";
	}
	// Walk through the groups until we find a valid object
	for (%i = 0; %i < getWordCount(%spawnGroups); %i++)  
	{  
		%group = getWord(%spawnGroups, %i);  

		if (isObject(%group))  
		{  
			// Gets number of spawn points under current spawn group
			%spawnCount = %group.getCount();

			// If there are no valid spawn points, let us know
			if (%spawnCount $= 0)
			{
			   echo("****c4 -> No valid spawn points found in this group!");
			}
			else
			{
			   // If spawn points are found, iterate through them
			   for (%x = 0; %x < %spawnCount; %x++)
			   {
				  %spawn = %group.getObject(%x);
				  %name = %spawn.getName();
				  
				  // Test the current spawn point for a match
				  echo(%spawn @ "c4 -> Testing spawn point " @ %name);
				  if (%targetName $= %name)
				  {
					 // Once a match is found, spawn player at matching location
					 echo(%spawn @ "c4 -> SPAWNING AT LOCATION: " @ %name);
					 return %spawn;
					 
				  }
			   }
			}
		}
	} 
}

I know this isnt the shortest way of achieving what I wanted but it does the job. I just need to spend some time cleaning it up now. Thanks for the help