Game Development Community

Swapping player character in TGE

by Nmuta Jones · in Torque Game Engine · 02/07/2010 (10:14 am) · 11 replies

During the game, I want you to be able to hit a key (1,2,3,or 4) to toggle between four possible characters.

I've tried to switch the player's datablock during the game but this does not seem to work.

I also imagine this could be done using setControlObject() but I'm unsure about the specifics.

Can anyone point me in the right direction?


#1
02/07/2010 (12:50 pm)
Spawn the new player, set it as the control object, and then ... if I remember correctly, in TGE you have to mount or align the camera on to the eyenode (in T3D it does this automatically).

I think everything you need is in game.cs.
#2
02/07/2010 (2:46 pm)
wow.... and all of that can happen in a split second during real time?
#3
02/07/2010 (11:14 pm)
Ok, this *kind of* works but creates several problems. I am using AFX 2.0 for TGE.

When I hit "b", it sends a server command to swap player, and it does swap my player.

But as soon as I jump, I respawn as the original player.
And then if I jump again the game crashes. So my code must be very batty. What's wrong with this code:

function serverCmdChangePlayer(%client){

echo("changing up now"); 

%spawnpoint = %client.player.getPosition(); 
echo ("I am ata "@%spawnpoint); 

%name = %client.name;

 
  %client.getControlObject().delete()

   // Create the player object
   %player = new Player() {
      dataBlock = NonPlayerData;
      client = %client;
   };
   MissionCleanup.add(%player);

   // Player setup...
   %player.setTransform(%spawnPoint);
   %player.setShapeName(%name);
   
   // Starting equipment
   %player.setInventory(Crossbow,1);
   %player.setInventory(CrossbowAmmo,10);
   %player.mountImage(CrossbowImage,0);

   // Update the camera to start with the player
   %client.camera.setTransform(%player.getEyeTransform());

   // Give the client control of the player
   %client.player = %player;
   %client.setControlObject(%player);
}
#4
02/08/2010 (10:50 am)
Ok, I've got it.

The following code is just the start, since I still have to add the part that allows you to toggle between several characters, and toggle back.

I found out the reason why hitting the "jump" key caused you to re-spawn..... when you switch into your new skin, and take control of a new player, when the OLD player is deleted, it triggers the engine callback that forces a respawn of the deleted character , which then reclaims setControObject on the old character. So you're not getting rid of the deleted guy.

I just implemented a crude workaround where in default.bind.cs I see if the death was caused by a playerchange, and if so, then I disable the respawn of that dead character:
// JUMP
function jump(%val)
{
  if (isObject(ServerConnection.player) && ServerConnection.player.isEnabled())
  {
    if (%val == 1)
    {
      if (($mvTriggerCount2 % 2) == 0)
        $mvTriggerCount2++;
    }//end if val
    else
    {
      if (($mvTriggerCount2 % 2) == 1)
        $mvTriggerCount2++;
    }
  }//end if isObject
  else if ($justchanged==true){
  
       $mvTriggerCount2++;
   
  } else {
  if (%val)
      commandToServer('RespawnPlayerAfterDeath');
  }
}//end function jump val

Then I went into the players death method and made sure that the $justchanged variable is set to true again upon a legitimate death.

This all works but the last part is a work around,because I'm not dealing with re-establishing the server connection, it appears, with the new player, but I'm getting to that part now. This at least is a starting point for a fast player change in game.

#5
02/08/2010 (11:00 am)
Quote:wow.... and all of that can happen in a split second during real time?
Don't worry - it's not that impressive when you realise just how much work the game engine actually does behind the scenes every millisecond ;).

Good job getting it working. The respawn thing is a classic example of what can happen when you modify someone else's code to do your own stuff - it sometimes surprises you. I recommend just rewriting the respawn scripts completely to do it the way you want it, rather than the way it worked in Tribes - nobody says you have to do it that way just because its already done that way.
#6
02/08/2010 (11:03 am)
thanks. Yeah, I'll probably end up re-writing all of the player and enemy death, rebirth, and respawn scripts....that's what I did with my last game.

thanks for the feedback. I love this engine. and Torque3D got even better.
#7
02/08/2010 (11:05 am)
Moved to the TGE section.
#9
01/22/2011 (12:25 am)
I tried your code in game.cs and it did not work in starter.fps (TGE 1.5.2). Can you tell me how you make it work?

I add those code in my TGE_1_5_2\example\starter.fps\server\scripts\game.cs file.
#10
01/22/2011 (9:55 am)
Post your code.
#11
01/23/2011 (4:36 am)
I post the code here:



In game.cs:

<code>
function GameConnection::createPlayer(%this, %spawnPoint)
{
if (%this.player > 0) {
// The client should not have a player currently
// assigned. Assigning a new one could result in
// a player ghost.
error( "Attempting to create an angus ghost!" );
}


switch ($playerClass)
{
// Class 1
case 1:
%classDatablock = PlayerBody; // change to another datablock for new models

// Class 2
case 2:
%classDatablock = PlayerBody2;

}


// Create the player object
%player = new Player() {
dataBlock = %classDatablock;
client = %this;
};
MissionCleanup.add(%player);

// Player setup...
%player.setTransform(%spawnPoint);
%player.setShapeName(%this.name);

// Starting equipment
//%player.setInventory(Crossbow,1);
//%player.setInventory(CrossbowAmmo,10);
//%player.mountImage(CrossbowImage,0);

// Update the camera to start with the player
%this.camera.setTransform(%player.getEyeTransform());

// Give the client control of the player
%this.player = %player;
%this.setControlObject(%player);
}



function GameConnection::joinPlayerClass(%this, %classid)
{
if (%classid > 2 || %classid < 0) //We only have 2 player classes
return false;

if (%this.respawn == 1)
return false; // If player is spawning then dont spawn again!

if (%classid == 1)
$playerClass = "1";

if (%classid == 2)
$playerClass = "2";

%this.spawnPlayer(%this);
}
</code>

In player.cs:
<code>

datablock PlayerData(PlayerBody2)
{
renderFirstPerson = false;
shapeFile = "~/data/shapes/player/player2.dts";

className = Armor; // Apply armor class to all bot and player
}

datablock PlayerData(PlayerBody)
{
renderFirstPerson = false;
shapeFile = "~/data/shapes/player/player.dts";

className = Armor; // Apply armor class to all bot and player
}

</code>

In commands.cs:
<code>

function serverCmdJoinPlayerClass(%client, %classid)
{
%client.joinPlayerClass(%classid);
}

function joinclass(%classid)
{
commandtoserver('JoinPlayerClass', %classid);
//Canvas.popDialog(ClassSelectDlg); //Hide the dialog once selection was made
}

</code>