Game Development Community

Hook-up player datablock / variable in gui

by elvince · in Torque 3D Professional · 06/23/2009 (12:07 am) · 9 replies

All,

I would like to use the "variable" attribute of Guitxtctrl to reflect some player stats/variable in a gui.

I tought I might use : variable="%client.player.dataBlock.MyVar" or variable="%client.player.getDataBlock().MyVar"
But I can't make it work.

Do I need to use variables $Myvar or change the text by code on the event "onwake"?
What's the best approach?

Thanks for your help.

#1
06/23/2009 (1:43 am)
I don't know exactly how the variable field works, but are you sure you are using a client side variable? I mean, you are using %client.***, but usually it is defined server side, in the GameConnection functions indeed it is a local variable ... oh wait, have you written it in the variable field of the gui control? if so, it surely doesn't work, the engine cannot know %client, since it is a local variable. You have to store your value in a global variable, like $MyVar, but again, be sure to store it in a client side defined variable, otherwise when you'll join a remote server it won't work anymore.
#2
06/23/2009 (8:31 am)
You want to display a datablock attribute on the HUD or something like that?

First of all, GUIs are not network-aware. They exist solely on the client, and while you can perform GUI manipulation and have GUI scripts access server stuff during local connections, that will fail completely in a network environment.

In order to do that you need to transmit information from the server to the clients via commandToClient and in the corresponding client function you modify the gui. Example:

Server script:
function updateClientInfos()
{
  for (%i=0; %i<ClientGroup.getCount(); %i++)
  {
     %client = ClientGroup.getObject(%i); 
     %info = %client.player.getDataBlock().myVar;    
     
     commandToClient(%client, 'UpdateInfo', %info);          
  }
}

Client script:
function clientCmdUpdateInfo(%info)
{
   $clientMyVar = %info;   
}

Your GuiTextCtrl:
variable = $clientMyVar;
(The "variable" field ONLY works with globals, it cannot evaluate code)

Now a few extra pointers:
1) Datablocks are meant to be immutable. I assume you're not changing the value of myVar during execution.

2) Custom fields in datablocks are not automagically sent via network, so they don't exist in clients unless you send them manually via commandToClient().
#3
06/23/2009 (10:39 am)
Thanks for the answer, not it's clear on how I will put my stuff in place.

@Manoel,
On your extra comments, when you said Datablock are meant to be immuable, that's mean that once load, you should have to change it, even if you can?

So it's better to add new variables on the "class" that will support the datablock, than the datablock itself, am I right?

To be clear, if I want to add a experience variable to a player I should not add it to the player datablock but more on the player class.

means during :player = new Player() {..}
and not in datablock PlayerData(DefaultPlayerData)

What is the downside of using datablock to store non static data?

#4
06/23/2009 (11:05 am)
Because the datablock is supposed to be shared among several object instances and hold data that is common to those instances. If you reach a point where each single Player has an unique datablock, you have a design problem: you should modify your Player and PlayerData to move the unique fields from the datablock to the instance, and reduce the number of needed datablocks.

Experience is something that should be stored in the player. If your player can die (and thus be deleted), then you should store it in the client that controls the player. But not on the datablock, because there could be two players using the same datablock.
#5
06/23/2009 (11:12 am)
Thanks for the clarification.

I'm starting with Torque and I'm learning a lot by reading some post, but sometime I miss some basic stuff.

FYI, I find this ressource that allow to hook and show some variables directly from function/variable of a object.
http://www.garagegames.com/community/resource/view/16287/2#comments
#6
06/23/2009 (1:04 pm)
I looked at the resource. While it does allow you to display fields and even method results, be aware that you still cannot simply access server objects from the client by name alone.

When running a local connection you have two sets of objects: the server objects and the ghosts for those objects. Clients connected to a server only have the ghosts. The ghosts are the ones that get rendered on the screen, and only server objects are named (this is done so to prevent you from accidentally accessing a ghost in a localconnection's server scripts).

So, if you want to read an object property health, or velocity, or something like that to display in a GUI, the network-correct way to do it is by accessing the ghost. For that, you need to have the server convert an object ID to a client ghost ID, send that to the client, and have the client convert that ghost ID back into an object ID. However, this only applies to properties that are ghosted via network (aka: most C++ stuff). Dynamic script-only fields like experience and score are server-only unless you make sure to tell the clients about them via commandToClient().
#7
06/23/2009 (2:46 pm)
Thanks again for the clarification.

If fact, I'm using %client.getGhostId(%client.player) to send the object in servercmdand ServerConnection.resolveGhostID(%shape) to get the correct id on client side. I think this is it.

As you said, it's working fine for C++ stuffs and not dynamic script only fields.
I will look at the bet way to send the information (C++ or commandtoclient).

Question:
In term of network traffic, what should be the best approach for getting those information? Does C++ information is more compressed than information send vie commandtoclient?
As most of the information I want to show do not change a lot during a game session, what should be the best approach?

#8
06/23/2009 (3:22 pm)
Script info is sent basically as strings, I think. With C++ (the class' packupdate/unpackupdate methods) you have better control of how many bits you're sending, but it takes more code and you need to take care to write and read in the correct order. You might also need to create masks for information that is only sent sometimes, but not always.

But if you're only sending a couple fields to a single client during special events, like when the player picks an item, kills something, accomplishes an objective, or anything that isn't happening every second or so, do it using script for easier management.
#9
06/23/2009 (11:09 pm)
I will do first in script and if I need to optimize later on, I know that there are some area by moving stuff from script to c++.