Game Development Community

dev|Pro Game Development Curriculum

Player Selection

by Chris Byars · 12/18/2005 (6:44 pm) · 51 comments

You will need the guiObjectView resource in your engine.

Well after nearly a year and much frustration, I've implemented some form of multiplayer character selection into my project, based off of the Beaver Patrol 1.3 alpha and a player selection post from Gonzo T. Clown. It's linked to a guiObjectView which has a GUI that lets you hit next and previous to view the models and choose the one you like. It has one small flaw, and is in need of some experienced TGE-ers' aid.

Problem:

I think there's something wrong with the calculation or handling of the "next" and "previous" code. Sometimes if you hit Previous, the guiObjectView will be empty, and then you'll have to press Next twice to get back to a model.

It'd be nice for someone to take a look at this code and say "This sucks, here's the right way." :)

How:

After looking through all of these changes they should make some form of sense. I have the soldier pack animations and my own models, so if you want to use this code you will need to change names/animation references to match what you want.

In fps/server/scripts/game.cs, under function GameConnection::createPlayer(%this, %spawnPoint), change the bolded to be what it is below:

// Create the player object
   %player = new Player() {
      [b]dataBlock = %this.armor;[/b]
      client = %this;
   };

Also you will want to put in fps/data/player/ a green.cs, a blue.cs, and a black.cs, with corresponding blue.dts, green.dts, and black.dts player models. (Or just substitute all references to the player models with your own.

In fps/server/scripts/player.cs, at the top, add:

// Load dts shapes and merge animations
//execute the scripts to load the dts values
%filename = "fps/data/shapes/player/*.cs";
$servmodelNum = 0;
for (%file = findFirstFile(%filename); %file !$= ""; %file = findNextFile(%filename)) {
	exec(%file);
}
//Load up the models
%filename = "fps/data/shapes/player/*.dts";
$servmodelNum = 0;
for (%file = findFirstFile(%filename); %file !$= ""; %file = findNextFile(%filename)) {
	if ( %file !$= "fps/data/shapes/player/debris_player.dts" ) {
		$servmodelNum++;
		$servmodelList[$servmodelNum] = %file;
		$servmodelName[$servmodelNum] = fileBase(%file);
	}
}

Then further down, after the entire datablock PlayerData(PlayerBody) section, I've added the player models. I've shortened it to 3 rather than my full 11 for simplicity:

datablock PlayerData (blue : PlayerBody)
{
   shapeFile = "~/data/shapes/player/blue.dts";
};

datablock PlayerData (black : PlayerBody)
{
   shapeFile = "~/data/shapes/player/black.dts";
};

datablock PlayerData (green : PlayerBody)
{
   shapeFile = "~/data/shapes/player/green.dts";
};

Now to the client side. In fps/common/server/clientConnection.cs, change your function GameConnection::onConnect to say:

function GameConnection::onConnect( %client, %name, %armor )

And then right underneath that and its opening bracket, place the following code:

switch$(%armor)
     {
          case "blue":
             %client.armor = "blueArmor";
          case "black":
             %client.armor = "blackArmor";
          case "green":
             %client.armor = "greenArmor";
          default:
             %client.armor = "blueArmor";
     }

Now in fps/client/scripts/, make a new file named playerSetupGui.cs, and in it, put the following and then save it:

function playerSetupGui::onWake(%this)
{
   echo( "Model Name set ---> " @ $pref::Player::Armor );

	//execute the scripts to load the dts values
	%filename = "fps/data/shapes/player/*.cs";
	echo("filename:" @ %filename @ "\n");
	$modelNum = 0;
	for (%file = findFirstFile(%filename); %file !$= ""; %file = findNextFile(%filename)) {
		echo("file:" @ %file @ "\n");
		exec(%file);
	}

	//Load up the models
	%filename = "fps/data/shapes/player/*.dts";
	echo("filename:" @ %filename @ "\n");
	$modelNum = 0;
	for (%file = findFirstFile(%filename); %file !$= ""; %file = findNextFile(%filename)) {
	//  exec(filePath(%file) @ "/player_info.cs");
		//exec(%file);
		//echo("file:" @ %file @ "\n");
		if ( %file !$= "fps/data/shapes/player/debris_player.dts" ) {
			$modelNum++;
			$modelList[$modelNum] = %file;
			$modelName[$modelNum] = fileBase(%file);
			echo("model num " @ $modelNum @ ", model name:" @ $modelName[$modelNum]);
		}
	}
	//Check for valid file name.. we dont want to explode
	%foundnum = 0;
    for ( %i = 0; %i < $modelNum; %i++ )
	{	
		if ( $pref::Player::Armor $= $modelName[%i] ){
		  //Filename is valid
		  %foundnum = %i;
		}
	}

	//if we dont find this model then we have a problem
	//reset it to something safe
	if ( %foundnum == 0  ){
		echo("WARNING MODEL NAME --->" @ $pref::Player::Armor @ " NOT FOUND. Reseting to " @ $modelName[1]);
		$modelCur = 1;
		$pref::Player::Armor = "" @ $modelName[1];
	}

    if ($modelNum > 0) SP_setModel();
}


//------------------------------------------------------------------------------
function playerSetupGui::onSleep(%this)
{

}

function SP_showNextModel()
{
   if ( ($modelCur) == $modelNum )   $modelCur = 1;   // go back to the first model
   else  $modelCur = $modelCur +1;   // go to the next model
   $pref::Player::Armor = "" @ $modelName[$modelCur];
   SP_setModel();
}

function SP_showPrevModel()
{
   if ( $modelCur == 1 )   $modelCur = $modelNum;   // we were at the first model so lets go to the last
	else   $modelCur = $modelCur -1;
   $pref::Player::Armor = "" @ $modelName[$modelCur];
   SP_setModel();
}

function SP_setModel()
{
   echo( "Model Name set ---> " @ $pref::Player::Armor );

   // Set main object
   view.setObject("player", "fps/data/shapes/player/" @ $pref::Player::Armor @ ".dts", "", 0); // set the model that should be showing

   view.loadDSQ("player", "fps/data/shapes/player/soldier_root.dsq"); //load an animation

   view.setSequence("player", "root", "1"); //play the animation
}

Make sure to add an execute line in fps/client/init.cs that reads:

exec("./scripts/playerSetupGui.cs");

Now in fps/client/ui/startMissionGui.gui, in function SM_StartMission(), change %conn.setConnectArgs to say:

%conn.setConnectArgs($pref::Player::Name, $pref::Player::Armor);

Do the same in fps/client/ui/joinServerGui.gui, but in function JoinServerGui::join(%this).

Now just make a nice GUI in which you choose separate models, similar to the following. (I just have the guiObjectView, and the buttons, below)

// Here's where the model is displayed.
      new GuiObjectView(view) { 
         profile = "GuiDefaultProfile";
         horizSizing = "center";
         vertSizing = "center";
         position = "150 150";
         extent = "300 300";
         minExtent = "8 2";
         visible = "1";
         cameraZRot = "0";
         forceFOV = "55";
         lightDirection = "-0.57735 -0.57735 -0.57735";
         lightColor = "0.600000 0.580000 0.500000 1.000000";
         ambientColor = "0.300000 0.300000 0.300000 1.000000";
      };

// This is the Next button
      new GuiBitmapButtonCtrl() {
         profile = "GuiDefaultProfile";
         horizSizing = "right";
         vertSizing = "bottom";
         position = "412 45";
         extent = "180 512";
         minExtent = "8 2";
         visible = "1";
         command = "SP_showNextModel();";
         text = "Button";
         groupNum = "-1";
         buttonType = "PushButton";
         bitmap = "./nextModel";
      };

// This is the Previous button
      new GuiBitmapButtonCtrl() {
         profile = "GuiDefaultProfile";
         horizSizing = "right";
         vertSizing = "bottom";
         position = "18 42";
         extent = "180 512";
         minExtent = "8 2";
         visible = "1";
         command = "SP_showPrevModel();";
         text = "Button";
         groupNum = "-1";
         buttonType = "PushButton";
         bitmap = "./previousModel";
      };

And that should do it. I'm sure everyone would really appreciate help to fix that minor flaw. :)
Page«First 1 2 3 Next»
#41
12/03/2006 (7:32 pm)
Hey Mike,

The first error ...

client/ui/selectScreen.gui (94): Unable to instantiate non-conobject class GuiObjectView.

.. suggests that it doesn't recognize the GuiObjectView class at all. Are you sure you added it (by going Add Existing Item to your project)? Try removing it and adding it again, then do a Clean and recompile to see if it works.

It just doesn't appear to be recognizing the guiObjectView .. other than making sure that it appears in your project view (in Visual Studio or whatever you use to compile with) I'm not sure what else to tell you...sorry.

Jeff.
#42
12/04/2006 (2:34 pm)
I went back and read the new directions in the cc file, moved the files to the correct folder, added them to my project (using vs2005 express) and still get the same error. I don't know.
#43
12/04/2006 (3:18 pm)
Hey Mike,

Do you see the GuiObjectView component in the GUI editor? Should be in the list of components you can add... if not, then it definately hasn't registered as part of the project.

If you see the GuiObjectView control in the list (in the GUI editor) are you able to delete the old GuiObjectView component and add a new one?

Jeff.
#44
12/04/2006 (3:59 pm)
For some reason, tge isn't recognising it. I don't have the guiObjectView in the gui inspector.
I don't know what else to do. It's linked, it's showing up in vc2005, but tge isn't recognising it.
I've made sure that the code pages are in the correct places, and that the compiler has added them to the project, cleaned the whole sln, and build. Nothing seems to be working.
Well, back to the drawing board.
#45
03/30/2007 (11:54 pm)
ok, first off this is an awesome link so I tried to follow these directions exactly but I got lost at the gui part. I am still a noob so I kind of need a little more help. I am trying to set up a push button in the main menu to open the the character selection gui, but when I press the button the menu kind of freezes. The mouse will move but it leaves a sick trail of arrows. I know the guiObjectView is working now so I'm pretty sure its somewhere in my gui. Any help would be greatly appreciated. Is there something else I need to include in the gui script?
#46
04/02/2007 (9:16 pm)
I got around the gui problem but my show previous and next functions aren't working.

Model Name set ---> test
Error: Unable to load: Doomsday1/data/shapes/soldier/.dts
Error: Could not find object player
Error: Could not find object player

I put the test in just to figure out which Model Name set --> was being called. I've read this forum over and over trying to follow the directions given to others, and I've read my own code trying to figure out where I missed something I forgot to change but I just can't figure it out. It seems like $pref::Player::Armor isn't getting set. In pref.cs $pref::Player::Armor = " ";

If anyone can tell me how they fixed their problem it would be greatly appreciated. Thanks
#47
08/29/2007 (1:39 pm)
I have tried this resource and it will allow me to use a different character in Stand-Alone/Client only mode.
But whenever I try to use it on a network (LAN) I still only get the character selected at the server or host.
I have no problems networking at all I just get the same character as the server uses. I can select any character at the server and all of the clients will use that character. I really need different characters on each client.
There are several resources out there to do this operation but all fail at the server implementation. I have tried them all on a clean build each time and the results are all the same. This issue needs to be resolved once and for always.
HELP!!!! I have been working on this for several days and know there is a solution.
#48
11/13/2007 (7:15 pm)
Hey Shon, I was just looking at this resource and the reason it doesn't work in multiplayer is that it doesn't make any changes to setConnectionargs in the joinServerGui. It only changes the one in startMissionGui. If you modify all instances of setConnectargs it should work like a charm.
#49
11/14/2007 (6:06 am)
@Ryan: So good to hear from ya, hope everything is good. Thanks for the input and I did figure all that out. Got a copy of the old Beaver Patrol and the old Realm Wars and trace, trace and more trace and eventually it sank in. Got my first multi-player server up and running yesterday and everything is running beautiful. Running a dedicated server is another subject I learned. Everything is totally different running dedicated, for one it ignores the entire client directory and doesn't compile any of those. So had to scramble to put code in the right places to make sure it is accessible by all, especially global variables being set in the client/gui section.
Heard you got a new job. Hope it's good.
#50
10/26/2008 (10:07 pm)
Can someone please help me with making the GUI. I go into the GUI editor and selct GUIbuttonCtrl but i don't know what the command is to load up the player selction. Can someone please tell me the command?
#51
04/08/2012 (11:44 pm)
Oftentimes, expensive tiffany and co jewelry jewelry get learned merely women of all ages that contain dads. Charm bracelets seemed to be often Cheap beats times with the toys that this little girl earns on birth records or sometimes top selling baptism. occasions True Religion Outlet because a young stumbling crazy about charm additionally, the thinking in it, they begin picking the True Religion Outlet appropriate that. Once the author grows to perhaps passes across True Religion sale the actual youth, your girl repeatedly has an big selection of them dearest valuables.
Page«First 1 2 3 Next»