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. :)
#21
01/01/2006 (1:53 am)
True True , But then theres those who can create and model items very well and want to put them into there own game, However they lack on the coding skills to do it but are willing to learn. Its hard to get started for those who lack in coding to begin when most of the resources and tuts available are based on those who know the coding already and not on those who do not know the coding very well. Roll playing games theres more resources and very some very good ones at that, Dreamers tut for example are pretty good but base on RPG, Where those resources available to support FPS are lacking full understandment.

Where is a demo was to be put out with a few more selections in it then it would be a great starter as then you can at least see where to place things a bit easier and or add to it like building a mod on to existing games shall we say. Its hard to get coders and scripters on your team if you really can't out something out there for them to look at other than a few items on a terrain.

I'd be willing to pay to have a good resource from start to finish a player selection in FPS with no bugs with team sides to be chooseable. Take for instance the tank packs, item packs and all the others there all good resources/products and a good player selection would be another great one to have up there for some of us non coders (Still learning) Just basic buttons nothing fancy or anything just plain as can be.

I know if i did know how to code and do all that fancy stuff i would have more tutorials with pics to help everyone , Even if someone new how to code but didn't have the time to write a good tutorial up for something i wouldn't mind lending a hand to make it available. I have done alot of tutorials up for NovaLogic games for modding and item building and alot of people loved them. I have started up a forum which isn't yet public that will have more tutorials written up for the basic item building and such.

I wrote one up for the helicopter resource here in pdf , I had asked permission to do so and was granted, I wrote it up on his code and provided screen shots and such to show exactly what had to be done. Think it turned out pretty good, and whill be updated if and when ever the resource gets updated.

Anyhow been over to your site C2 and you game looks amazing and can't wait to see it in action. Really nice weapons i seen and terrains, Well done , Please pass this on to your team mate helping you that they as well are doing a fantastic job.
#22
01/01/2006 (11:20 am)
Great resource C2. Now this is how it should be done. LOL I had to work but I learned a lot more from this than any other tutorial I've worked with. Thank you so much!!!
#23
01/02/2006 (9:11 am)
@C2
Got it working, thanks C2. Does your profile e-mail work, I need to ask your permission for something.
#24
01/10/2006 (12:51 am)
Allan, did you get this to work with the preference variable in pref.cs? I have been trying for two days and always come up with this in the console.log

chaos/server/scripts/game.cs (302): Register object failed for object (null) of class Player.
Set::add: Object "0" doesn't exist
chaos/server/scripts/game.cs (306): Unable to find object: '0' attempting to call function 'setTransform'
chaos/server/scripts/game.cs (307): Unable to find object: '0' attempting to call function 'setShapeName'
chaos/server/scripts/game.cs (310): Unable to find object: '0' attempting to call function 'setInventory'
chaos/server/scripts/game.cs (311): Unable to find object: '0' attempting to call function 'setInventory'
chaos/server/scripts/game.cs (312): Unable to find object: '0' attempting to call function 'mountImage'
chaos/server/scripts/game.cs (315): Unable to find object: '0' attempting to call function 'getEyeTransform'

Ive set the preference variable but for some reason it still cannot find the played model. Locks up right when it says "Loading Objects"
#25
01/10/2006 (3:49 am)
Have you added the changes in joinServerGui.gui and startMissionGui.gui?
#26
01/10/2006 (9:27 am)
Yeah, I went throught thre tutorial step by step. Changed the references to match my folder names and everything. I'm not sure whats going on.
#27
01/10/2006 (9:56 am)
Sorry, I found out what it was. My dts files were not loading because of errors. Thanks
#28
01/11/2006 (11:30 am)
One more question C2.


%filename = "starter.fps/data/shapes/player/*.cs";



How would i write this statement if I was looking for a file name in seperate folders? Such as

%filename = "fps/data/shapes/player/red/*.cs";
%filename = "fps/data/shapes/player/blue/*.cs";
%filename = "fps/data/shapes/player/green/*.cs";
#29
01/11/2006 (1:21 pm)
Not exactly sure. I was wondering about that too, but then I just put all my player models in one directory and it suits alright for me. Sorry.
#30
01/12/2006 (2:16 am)
If some of you guys are getting this error message

chaos/server/scripts/game.cs (302): Register object failed for object (null) of class Player.
Set::add: Object "0" doesn't exist
chaos/server/scripts/game.cs (306): Unable to find object: '0' attempting to call function 'setTransform'
chaos/server/scripts/game.cs (307): Unable to find object: '0' attempting to call function 'setShapeName'
chaos/server/scripts/game.cs (310): Unable to find object: '0' attempting to call function 'setInventory'
chaos/server/scripts/game.cs (311): Unable to find object: '0' attempting to call function 'setInventory'
chaos/server/scripts/game.cs (312): Unable to find object: '0' attempting to call function 'mountImage'
chaos/server/scripts/game.cs (315): Unable to find object: '0' attempting to call function 'getEyeTransform'

comment out %client.armor = "Light"; in clientConnection.cs in function GameConnection::onConnect. Even though I put in the switch statement, it was always setting it to Light. I am not sure when this was added to that file because I didnt do it
#31
01/12/2006 (4:04 am)
Oops. Forgot about that. You should replace that code with:

%client.armor = %armor;

in clientConnection.cs.
#32
01/17/2006 (4:30 pm)
this might help
------------------------------------------This code-------------------------------------------
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();
}
--------------------------------------------------------------------------------------------------

you should use the increment and decrement scripting options instead of -1 or +1 like shown here



--------------------------------------------------------------New code----------------------------------
function SP_showNextModel()
{
if ( ($modelCur) == $modelNum ) $modelCur = 1; // go back to the first model
else $modelCur += $modelCur; // go to the next model **Edited**
$pref::Player::Armor = "" @ $modelName[$modelCur];
SP_setModel(); //i think something should go in the parenthasies.
}

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

I could be wrong just try it, it cold help.
#33
01/18/2006 (5:57 am)
Thanks a lot, I will give that a try.

Edit: Nope, breaks it.
#34
01/29/2006 (10:45 am)
I have been able to get the dialog to load and to select a player for my game. Unfortunately, as the mission file is loaded the app crashes with the following message:

game/server/scripts/aiPlayer.cs (30): Unable to find parent object PlayerBody for PlayerData.

To get around this problem I have modified the following line of code to be:
// shapeFile = "~/data/shapes/player/blue.dts";
shapeFile = "~/data/shapes/player/" @ $pref::Player::Armor @ ".dts";

This appears to work, but I wonder if there is something I might have missed in this resource where I should not have needed to modify the PlayerBody datablock.
#35
03/30/2006 (5:48 pm)
how does this work?
// Create the player object
%player = new Player() {
dataBlock = %this.armor;
client = %this;
};

what this %this? the client object? what class is %this?
#36
08/10/2006 (7:17 pm)
Very cool resource ... took a little work to get going, but got there in the end :)

If you're using TLK like me, you'll need to update the GuiObjectView script ... go here to grab the updated version.

The actual character select stuff works a treat :)
#37
09/05/2006 (3:05 am)
I read over the code you posted, /C2/ and i got to make it work, (not exactly the same code, i altered it a bit) But it gave results! Take a peek! (models are mine, BTW)

http://img221.imageshack.us/img221/1086/screenshot01200001wn6.jpg

Thank you very much!
#38
12/03/2006 (5:13 pm)
It's been a while since anyone has posted to this resource, but....

After makeing the changes above, and changeing the switch statement from:
switch$(%armor)     { 
         case "blue": 
            %client.armor = "blueArmor"; 
         case "black": 
            %client.armor = "blackArmor";
          case "green": 
            %client.armor = "greenArmor";
          default:
             %client.armor = "blueArmor";     }

to:

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

I have finally rid myself of all the error messages. I have compiled in the attached resource (objectgui) and have no errors there eather.
My problem stems from, nothing shows. Do I need pictures of my avatars somewhere?
I had to add a "continue" button to get past this, and now my avatar animations aren't working.
Any ideas?
I'm using tge1.5
#39
12/03/2006 (6:15 pm)
Hi Mike,

Did you add the latest version of guiObjectView from the 1.5 resource bundle (www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=11518)?

For 1.4 you can use www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=9981

The one attached to this resource doesn't work with 1.4+ as far as I know, so that may be your problem.

Good luck!
#40
12/03/2006 (6:45 pm)
Thankyou for showing me that resource. I didn't even know it existed.
My problem now has changed.

client/ui/selectScreen.gui (94): Unable to instantiate non-conobject class GuiObjectView.
Model Name set ---> 
./client/scripts/playerSelectGui.cs (76): Unable to find object: 'view' attempting to call function 'setObject'
./client/scripts/playerSelectGui.cs (77): Unable to find object: 'view' attempting to call function 'loadDSQ'
./client/scripts/playerSelectGui.cs (78): Unable to find object: 'view' attempting to call function 'setSequence'
Model Name set --->