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?
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?
About the author
Lead Developer for MediaBreeze Multimedia
#2
02/07/2010 (2:46 pm)
wow.... and all of that can happen in a split second during real time?
#3
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:
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
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:
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.
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 valThen 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
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.
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
thanks for the feedback. I love this engine. and Torque3D got even better.
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.
#8
02/08/2010 (11:14 am)
Good idea :P.
#9
I add those code in my TGE_1_5_2\example\starter.fps\server\scripts\game.cs file.
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
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>
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>
Associate Steve Acaster
[YorkshireRifles.com]
I think everything you need is in game.cs.