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 «Previous 1 2 3 Last »
#1
12/19/2005 (4:29 am)
Thank you much. Don't we love that Beaver Patrol download. Best docs you can find. Hope you checked out Realm Wars too. I sing both praises. I would have never figured this out without them.
This may be redundant but we at ATOMIX Productions use a character selection dialog also and simply use the one already in the engine. GuiPlayerView
I set it up in the gui like this
new GuiPlayerView(CharView) {
profile = "GuiDefaultProfile";
horizSizing = "right";
vertSizing = "bottom";
position = "6 5";
extent = "242 209";
minExtent = "8 2";
visible = "1";
cameraZRot = "0";
forceFOV = "0";
};

Then in onWake function I use this
// Character Viewer
CharView.setModel("base/data/shapes/player/Human/player.dts", base/data/shapes/player/Human/player.jpg");

Throw in a previous and next button and you have a viewer with changeable skins.
Look at the code and if you don't have it go and buy Tribes 2 everthing in there is in TGE especially the older builds if you keep them, I do.
Shon Gale
ATOMIX Productions
www.theatomizer.com
#2
12/19/2005 (11:42 am)
Hi...I test this resource but i have a problem =(
In console of loadMainManu have:
Could not locate texture: starter.fps/client/ui/previousModel_n
Could not locate texture: starter.fps/client/ui/previousModel_h
Could not locate texture: starter.fps/client/ui/previousModel_d
Could not locate texture: starter.fps/client/ui/previousModel_i
Could not locate texture: starter.fps/client/ui/nextModel_n
Could not locate texture: starter.fps/client/ui/nextModel_h
Could not locate texture: starter.fps/client/ui/nextModel_d
Could not locate texture: starter.fps/client/ui/nextModel_i
Model Name Set --->
Error: Unable to load: starter.fps/data/shapes/player/.dts
Error: Could not find object player

Error: Could not find object player

In game.cs have:
starter.fps/server/scripts/game.cs (320) Unable to find object: attempting to call function 'setTransform'
starter.fps/server/scripts/game.cs (321) Unable to find object: attempting to call function 'setShapeName'
starter.fps/server/scripts/game.cs (324) Unable to find object: attempting to call function 'setInventory'
starter.fps/server/scripts/game.cs (325) Unable to find object: attempting to call function 'setInventory'
starter.fps/server/scripts/game.cs (326) Unable to find object: attempting to call function 'setMountImage'
starter.fps/server/scripts/game.cs (329) Unable to find object: attempting to call function 'setEyeTransform'

And game not start =(

1) - I have a base folder "starter.fps" and rename this script at "fps" in "starter.fps"
2) - Help me Pleaseeeeeeeeeeeeeeeeee =(
------
#3
12/19/2005 (12:34 pm)
For one, the resource page seems to be cut off.. quite a bit. Something's screwy with the new site layout.
#4
12/19/2005 (12:47 pm)
Ok layout is ok but my problem persist..... Help me please
Your resource is GREAT!!
But i became crazy for operate with this resource =(
I'm a stupid but would succeed in this resource.
Thanks
#5
12/21/2005 (3:49 am)
It looks like the web page layout has been optimized for my big code blocks and cut-off text. Read through the resource again and make sure you do exactly as is written. I tested it out on a clean build only using these instructions. It should work.
#6
12/21/2005 (5:58 am)
Never..My problem persist...
Any idea?
#7
12/21/2005 (12:13 pm)
Make sure you've changed every "fps" to "starter.fps"
#8
12/21/2005 (5:22 pm)
OK but this problem is persist

In game.cs have:
starter.fps/server/scripts/game.cs (320) Unable to find object: attempting to call function 'setTransform'
starter.fps/server/scripts/game.cs (321) Unable to find object: attempting to call function 'setShapeName'
starter.fps/server/scripts/game.cs (324) Unable to find object: attempting to call function 'setInventory'
starter.fps/server/scripts/game.cs (325) Unable to find object: attempting to call function 'setInventory'
starter.fps/server/scripts/game.cs (326) Unable to find object: attempting to call function 'setMountImage'
starter.fps/server/scripts/game.cs (329) Unable to find object: attempting to call function 'setEyeTransform'

And game not start =(
#9
12/22/2005 (5:16 pm)
I'm lost here in 2 sections of this wonderful script. The first one is when i add the script to the player.cs for teh blue,green and such dts . What do i do with the rest of the script that was originally there, If i try to run the game after everything else is done i get line errors on all the stuff under the new script.

Quote:
//datablock PlayerData(PlayerBody)
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";
};
{
renderFirstPerson = false;
emap = true;

className = Armor;
//shapeFile = "~/data/shapes/player/soldier/soldier.dts";
cameraMaxDist = 3;
computeCRC = true;

canObserve = true;
cmdCategory = "Clients";

cameraDefaultFov = 90.0;
cameraMinFov = 5.0;
cameraMaxFov = 120.0;

debrisShapeName = "~/data/shapes/player/debris_player.dts";
debris = playerDebris;

aiAvoidThis = true;

minLookAngle = -1.4;
maxLookAngle = 1.4;
maxFreelookAngle = 3.0;

mass = 90;
drag = 0.3;
maxdrag = 0.4;
density = 10;
maxDamage = 100;
maxEnergy = 60;
repairRate = 0.33;
energyPerDamagePoint = 75.0;

rechargeRate = 0.256;

runForce = 48 * 90;
runEnergyDrain = 0;
minRunEnergy = 0;
maxForwardSpeed = 14;
maxBackwardSpeed = 13;
maxSideSpeed = 13;

maxUnderwaterForwardSpeed = 8.4;
maxUnderwaterBackwardSpeed = 7.8;
maxUnderwaterSideSpeed = 7.8;

jumpForce = 8.3 * 90;
jumpEnergyDrain = 0;
minJumpEnergy = 0;
jumpDelay = 15;

recoverDelay = 9;
recoverRunForceScale = 1.2;

minImpactSpeed = 45;
speedDamageScale = 0.4;

boundingBox = "1.2 1.2 2.3";
pickupRadius = 0.75;

// Damage location details
boxNormalHeadPercentage = 0.83;
boxNormalTorsoPercentage = 0.49;
boxHeadLeftPercentage = 0;
boxHeadRightPercentage = 1;
boxHeadBackPercentage = 0;
boxHeadFrontPercentage = 1;

// Foot Prints
decalData = PlayerFootprint;
decalOffset = 0.25;

footPuffEmitter = LightPuffEmitter;
footPuffNumParts = 10;
footPuffRadius = 0.25;

dustEmitter = LiftoffDustEmitter;

splash = PlayerSplash;
splashVelocity = 4.0;
splashAngle = 67.0;
splashFreqMod = 300.0;
splashVelEpsilon = 0.60;
bubbleEmitTime = 0.4;
splashEmitter[0] = PlayerFoamDropletsEmitter;
splashEmitter[1] = PlayerFoamEmitter;
splashEmitter[2] = PlayerBubbleEmitter;
mediumSplashSoundVelocity = 10.0;
hardSplashSoundVelocity = 20.0;
exitSplashSoundVelocity = 5.0;

// Controls over slope of runnable/jumpable surfaces
runSurfaceAngle = 70;
jumpSurfaceAngle = 80;

minJumpSpeed = 20;
maxJumpSpeed = 30;

horizMaxSpeed = 68;
horizResistSpeed = 33;
horizResistFactor = 0.35;

upMaxSpeed = 80;
upResistSpeed = 25;
upResistFactor = 0.3;

footstepSplashHeight = 0.35;

//NOTE: some sounds commented out until wav's are available

// Footstep Sounds
FootSoftSound = FootLightSoftSound;
FootHardSound = FootLightHardSound;
FootMetalSound = FootLightMetalSound;
FootSnowSound = FootLightSnowSound;
FootShallowSound = FootLightShallowSplashSound;
FootWadingSound = FootLightWadingSound;
FootUnderwaterSound = FootLightUnderwaterSound;

//FootBubblesSound = FootLightBubblesSound;
//movingBubblesSound = ArmorMoveBubblesSound;
//waterBreathSound = WaterBreathMaleSound;

//impactSoftSound = ImpactLightSoftSound;
//impactHardSound = ImpactLightHardSound;
//impactMetalSound = ImpactLightMetalSound;
//impactSnowSound = ImpactLightSnowSound;

//impactWaterEasy = ImpactLightWaterEasySound;
//impactWaterMedium = ImpactLightWaterMediumSound;
//impactWaterHard = ImpactLightWaterHardSound;

groundImpactMinSpeed = 10.0;
groundImpactShakeFreq = "4.0 4.0 4.0";
groundImpactShakeAmp = "1.0 1.0 1.0";
groundImpactShakeDuration = 0.8;
groundImpactShakeFalloff = 10.0;

//exitingWater = ExitingWaterLightSound;

observeParameters = "0.5 4.5 4.5";

// Allowable Inventory Items
maxInv[BulletAmmo] = 20;
maxInv[HealthKit] = 1;
maxInv[RifleAmmo] = 100;
maxInv[CrossbowAmmo] = 50;
maxInv[Crossbow] = 1;
maxInv[Rifle] = 1;
};


So this i'm not sure what i'm doing wrong , If i take it all out then nothing works still.

2nd problem where do i add the player selection gui so it pops up and people can choose ? I saved it as GuiObjectView.cs but it doesn't say above where to actually place, I can place it in the int.cs but what tells it to actually load.

I new to coding for the most part and some resources i find hard to follow for beginners :( any help would be great.
#10
12/23/2005 (6:09 am)
Edited: Incorrect information
#11
12/23/2005 (8:34 am)
Cool NP mate, I'll come up with something , Still can't get the player.cs file to compile, But Np
#12
12/23/2005 (10:02 am)
It may be helpful for you if you separate major lines of code with spaces, so you can read them better and make sure things aren't getting jumbled together and causing errors. If you want, post the error information from the console on that player.cs file and I might be able to give you some pointers.
#13
12/23/2005 (11:57 am)
Well more than likely i'm putting it in the wrong place . Heres the top section of teh player.cs file of the player data

datablock PlayerData(PlayerBody) <<<<<< {

datablock PlayerData (blue : PlayerBody) <<<<<<<<<<<<<<<<<<< Line: 540 - Syntax error.
{
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";
};

And then the rest of the mumble jumble of the stock player.cs file goes below here , Post in the above code.

In the log error this is all that i'm getting :

Compiling starter.fps/server/scripts/player.cs...
starter.fps/server/scripts/player.cs Line: 540 - Syntax error. <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Compiling starter.fps/server/scripts/aiPlayer.cs...
Loading compiled script starter.fps/server/scripts/aiPlayer.cs.

Like i said i totally new to most of this stuff but willing to learn and been trying to learn, Just not much of a scripter on some things i guess, I have gotten weapon selection and all that to work .
#14
12/23/2005 (2:49 pm)
Oh noes. Looks like I made a mistake. The additional PlayerDatas should go after the entire original datablock PlayerData(PlayerBody), not within it. Edited resource to reflect change.
#15
12/23/2005 (4:12 pm)
Thx mate got that sorted out , Much thx. Now just need to implement the actual selection screen :)

Whats you advice before choosing the mission or after the mission ?
#16
12/26/2005 (11:02 am)
Everything compiles perfect as for all the above coding now, No errors at all in the log file.

The game crashes though when i go to test the map.

I know why its crashing just can't find the location to fix it. The game is crashing because i have no spot to actually select the character. I have made up a selection GUI screen and all but not sure where to implement it in the scripts to have it appear to be able to choose the player.

I looked at Realm Wars but i can't find it in there either where they call the player selection screen forward. They do theres at the end of the mission loading . I wouldn;t mind doing it either way at the end and or before you select the mission.
#17
12/26/2005 (2:44 pm)
Theirs is set up quite differently than this one.

As for the crashing, make sure you have a preference variable (which would be automatically created if you had the GUI) that names a model, like:
$pref::Player::Armor = "blue";
in fps/client/prefs.cs
#18
12/28/2005 (3:04 pm)
@C2 Curious if the Wacky Sleigh Ride player selection code was any help?
thanks
#19
12/28/2005 (4:11 pm)
I think its a good start for anyone, considering theres not really much out there for FPS game on player selection, Mostly on RPG . Although i'm at a lost with it i think its a good start though. Still hung up on the player selction gui :( i messed it up so bad i had to restart the whole thing all over again and now i'm back at the same spot LMAO . This is when you wish you had the money to higher a coder to do the initial start of the game and what not lol.

Building items and texturing i shuold have stayed at lol but i guess its hard to get any further when you don;t have all the coding to go with the wonderful items lol

Still plucking away joyfully though , No sence in getting down on a project when theres so much $ tied up in packs here and there just need to keep plucking away and asking annoying questions to great people of the community lol .

I think the perfect demo that should come out with TGE is a FPS game with a player selection some what all ready coded , 2 or 3 game types and a basic hud this would make getting started alot easier :)
#20
12/29/2005 (7:14 am)
I believe it would make getting started much easier, but the way it is now makes it more of a challenge, to separate those who aren't really focused, and those who truly believe in designing their own game, and are able to stand strong with it. :)

@Eric: Haven't fiddled with the code yet. :P
Page «Previous 1 2 3 Last »