Game Development Community

Enhanced Scoreboard (Score, Kills, Deaths)

by Jesse (Midhir) Liles · 07/03/2006 (11:25 am) · 11 comments

Download Code File

This is my 'enhanced scoreboard' resource that displays score, kills, and deaths for each player. I thought
I'd share it as I've seen alot of people asking about this kind of thing. All the necessary code and
instructions are contained in the zip file. There are two script files (drop-in replacements for playerlist.cs
and playerlist.gui)

and a readme containing instructions on how to modify a stock starter.fps to make use of it.


I have tested this on a stock TGE 1.4 install and it works (initial values are blank until a kill or death occurs).

This code is a highly simplified version of what I'm using in my game, so errors are bound to exist. This is
primarily to demonstrate a method of extending the existing playerlist GUI. It is NOT a complete scoring
implementation, as that is up to the game developer. Anyway, this is my first resource so let me know
what you think.

This is the contents of the readme file:

Enhanced Scoreboard for TGE/TSE
by Midhir - Crossbones Studios
-------------------------------


To install, back up your old client/scripts/playerlist.cs and client/ui/playerlist.gui files. Replace them with
the files included in this archive.








Insert the following into your existing server/scripts/game.cs :
================================================================


/////-------------------------------------------------------------------------
// SCORE FUNCTIONS
/////-------------------------------------------------------------------------

function GameConnection::incKills(%client, %kill)
{
   %client.kills += %kill;
   
   messageAll('MsgClientScoreChanged', "", %client.score, %client.kills, %client.deaths, %client);
}

function GameConnection::incDeaths(%client, %death)
{
   %client.deaths += %death;
   
   messageAll('MsgClientScoreChanged', "", %client.score, %client.kills, %client.deaths, %client);
}

function GameConnection::incScore(%client, %score)
{
   %client.score += %score;

   messageAll('MsgClientScoreChanged', "", %client.score, %client.kills, %client.deaths, %client);
}

function GameConnection::getScore(%client)  { return %client.score; }
function GameConnection::getKills(%client)  { return %client.kills; }
function GameConnection::getDeaths(%client) { return %client.deaths;}

/////-------------------------------------------------------------------------
// END SCORE FUNCTIONS
/////-------------------------------------------------------------------------





If you are using an unmodified starter.fps from TGE, you can replace your GameConnection::onDeath() function with this:
================================================================================================

function GameConnection::onDeath(%this, %sourceObject, %sourceClient, %damageType, %damLoc)
{
   // Clear out the name on the corpse
   %this.player.setShapeName("");

   // Switch the client over to the death cam and unhook the player object.
   if (isObject(%this.camera) && isObject(%this.player)) {
      %this.camera.setMode("Corpse",%this.player);
      %this.setControlObject(%this.camera);
   }
   %this.player = 0;

   // Doll out points and display an appropriate message
   if (%damageType $= "Suicide" || %sourceClient == %this) {
      %this.incScore(-1);
      %this.incDeaths(1);
      messageAll('MsgClientKilled','%1 takes his own life!',%this.name);
   }
   else {
      %sourceClient.incScore(1);
      %sourceClient.incKills(1);
      %this.incDeaths(1);
      messageAll('MsgClientKilled','%1 gets nailed by %2!', %this.name, %sourceClient.name);
      if (%sourceClient.score >= $Game::EndGameScore)
         cycleGame();
   }
   messageAll('MsgClientScoreChanged', "", %client.score, %client.kills, %client.deaths, %client);
}






And in common/server/clientConnection.cs replace the function GameConnection::onConnect() with the following:
======================================


function GameConnection::onConnect( %client, %name )
{
   // Send down the connection error info, the client is
   // responsible for displaying this message if a connection
   // error occures.
   messageClient(%client,'MsgConnectionError',"",$Pref::Server::ConnectionError);

   // Send mission information to the client
   sendLoadInfoToClient( %client );

   // Simulated client lag for testing...
   // %client.setSimulatedNetParams(0.1, 30);

   // Get the client's unique id:
   // %authInfo = %client.getAuthInfo();
   // %client.guid = getField( %authInfo, 3 );
   %client.guid = 0;
   addToServerGuidList( %client.guid );
   
   // Set admin status
   if (%client.getAddress() $= "local") {
      %client.isAdmin = true;
      %client.isSuperAdmin = true;
   }
   else {
      %client.isAdmin = false;
      %client.isSuperAdmin = false;
   }

   // Save client preferences on the connection object for later use.
   %client.gender = "Male";
   %client.armor = "Light";
   %client.race = "Human";
   %client.skin = addTaggedString( "base" );
   %client.setPlayerName(%name);
   %client.score = 0;

   // 
   $instantGroup = ServerGroup;
   $instantGroup = MissionCleanup;
   echo("CADD: " @ %client @ " " @ %client.getAddress());

   // Inform the client of all the other clients
   %count = ClientGroup.getCount();
   for (%cl = 0; %cl < %count; %cl++) {
      %other = ClientGroup.getObject(%cl);
      if ((%other != %client)) {
         // These should be "silent" versions of these messages...
         messageClient(%client, 'MsgClientJoin', "", 
               %other.name,
               %other,
               %other.sendGuid,
               %other.score,
               %other.kills,  //Added by Midhir
               %other.deaths, //Added by Midhir
               %other.isAIControlled(),
               %other.isAdmin, 
               %other.isSuperAdmin);
      }
   }

   // Inform the client we've joined up
   messageClient(%client,
      'MsgClientJoin', '\c2Welcome to the Torque demo app %1.', 
      %client.name, 
      %client,
      %client.sendGuid,
      %client.score,
      %client.kills,   // Added by Midhir
      %client.deaths,  // Added by Midhir
      %client.isAiControlled(), 
      %client.isAdmin, 
      %client.isSuperAdmin);

   // Inform all the other clients of the new guy
   messageAllExcept(%client, -1, 'MsgClientJoin', '\c1%1 joined the game.', 
      %client.name, 
      %client,
      %client.sendGuid,
      %client.score,
      %client.kills,   // Added by Midhir
      %client.deaths,  // Added by Midhir
      %client.isAiControlled(), 
      %client.isAdmin, 
      %client.isSuperAdmin);

   // If the mission is running, go ahead download it to the client
   if ($missionRunning)
      %client.loadMission();
   $Server::PlayerCount++;
}

#1
05/19/2006 (1:51 pm)
why r the screenshots so small??
#2
05/19/2006 (2:48 pm)
Right click the picture and select 'view image'

The shot is cropped down to only show the scoreboard GUI as I have implemented it here.
#3
05/20/2006 (10:34 am)
Hey I have also added a resource, Team Scoreboard. Still waiting for GG to approve it. Here's the link.
#4
05/21/2006 (1:16 pm)
Very cool =)
#5
05/22/2006 (10:07 am)
Edit: Fixed now
#6
05/22/2006 (3:33 pm)
Ah yes, sorry about that, thank you for bringing it back to my attention =)

I fixed the post above and the download. Anybody not noticing what the change he suggested was; in my additions to server/scripts/game.cs:

%client.score += score;

should be:

%client.score += %score;

edit: Uhh...yeah...I should be more careful =)
#7
05/27/2006 (12:40 pm)
Ah, good info.

I don't suppose you know of a way to change the GUI setScoreCounter based on the skin of the object that is shot? I'm changing skins instead of shapes and wanted to score accordingly, it works fine in the shootableShape.cs as far as changing skins, but passing differing values out of the shape::damage function is proving to be "over my head". I'm using a slightly modified .fps tutorial whose scores are passed from the shape.cs to the clientGame.cs.

I suspect that I can determine different variables according to whatever getSkinName returns and clientGame can update one of the GUI scores based on whatever value is received. Here's what I'm working with:

function brick::damage(%this, %obj, %sourceObject, %position, %damage, %damageType){

//If shot directly, the brick determines it's skin (it's color)
%curSkin = %obj.getSkinName();

//Then changes it's color according to order; from base (grey), to red, to blue, to yellow
if(%curSkin $= "base")
%obj.setSkinName("red");

else if(%curSkin $= "red")
%obj.setSkinName("blue");

else if(%curSkin $= "blue")
%obj.setSkinName("yellow");

else if(%curSkin $= "yellow")
%obj.setSkinName("red");

else if(%curSkin !$= "yellow") //allows change from yellow to red instead of base (grey)
%obj.setSkinName("red");


}

It's probable that the answer is staring me in the face, but I don't see it.
#8
06/12/2006 (3:09 pm)
@n8man: Sorry, I didn't notice your post. You need to look into network ghosting if you want to send the actual object reference from the server to the client. On the other hand, sending a simple text string and the client ID to the client from the server is quite easily done with the 'messageClient()' function from the server side. The client then intercepts this message with a message handling function added with the 'addMessageCallback()' function on the client side. Try searching your TGE game scripts for these two functions to see how they're used. You could also examine the playerlist.cs and the changes to game.cs included in this resource to see how this works. Good luck.
#9
06/21/2006 (10:53 pm)
I got some help with classmates, basically what we did was similar to what you said:

commandToClient(%client, 'SetScoreCounter', %client);

This is pretty much already in the tutorial, which is nice. So, I have some variables that are put into play in the onDamage function of my "Brick" datablock (brick.cs) which are assigned to the client (if "assigned" is the right word), like this:

%client.yellowScore++;

Then I have counters in the clientGame.cs folder that receive the variable %client which contains the strings that command the counters to decriment, or in this case increment:

YellowCounter.setText("Yellow:" SPC %client.yellowScore);

This works, but it has taken me a long time to understand why. I'm very thankful for all the help. Thanks for getting back to me!
#10
08/08/2006 (6:03 pm)
GREAT resource! Thanks :)
#11
03/10/2007 (1:45 am)
hey hi
i tried to use this resource and did all the modifications as was mentioned in here but even after that i could not get the scores on the screen as was shown in the screen shot
can anyone please help me regarding this unusual problem of mine
thanking you