Getting a reference to my player object from scratch
by Drew Parker · in Torque Game Engine · 03/13/2004 (6:16 pm) · 15 replies
I'm new to Torque scripting, and while this question seems super simple, I haven't seem to come across an example, or if I did I missed it.
I want a reference to the player object so I can change the jump height for my player.
My learning activity is to setup a keypress which will set the player's jump height to super high, then move on to making that a power-up the player can pick up (like Unreal Tournament jump boots). I already know how to modify the jump height by changing the playerData datablock, but not how to modify it through script.
I see lots of player references from functions like %this.player.someFunc(), %obj.player.someFunc(), etc.... but none where you can pull it out of thin air, like with a global variable or something. So, if I'm creating a function from scratch which doesn't build on some other class, like inventory::pickup() or something, which might already have references to the player class indirectly, how can I get a reference to my player? Or, what's the best way to go about this?
My starting point has been in default.bind.cs, since that is where are the keypress code is located. Any ideas? Thanks!
I want a reference to the player object so I can change the jump height for my player.
My learning activity is to setup a keypress which will set the player's jump height to super high, then move on to making that a power-up the player can pick up (like Unreal Tournament jump boots). I already know how to modify the jump height by changing the playerData datablock, but not how to modify it through script.
I see lots of player references from functions like %this.player.someFunc(), %obj.player.someFunc(), etc.... but none where you can pull it out of thin air, like with a global variable or something. So, if I'm creating a function from scratch which doesn't build on some other class, like inventory::pickup() or something, which might already have references to the player class indirectly, how can I get a reference to my player? Or, what's the best way to go about this?
My starting point has been in default.bind.cs, since that is where are the keypress code is located. Any ideas? Thanks!
About the author
#2
I was wondering: Is there a way to change the jump height without C++ code? Like for instance, before I mentioned I changed the datablock jumpForce variable. And the datablock is used to make an object for each player, right? So is there a way I can just do
%cl.player.jumpForce = newJumpForce
or something like that? I'm trying to stay out of C++ code for now. I remember reading somewhere that game logic can be programmed in script... it seems like there should be a way to change the datablock object for a client's player without using c++? Of course, I'm keeping my fingers crossed. :)
03/13/2004 (7:41 pm)
Thanks a lot Dylan, that is really helpful info, and should keep me going for a while. :)I was wondering: Is there a way to change the jump height without C++ code? Like for instance, before I mentioned I changed the datablock jumpForce variable. And the datablock is used to make an object for each player, right? So is there a way I can just do
%cl.player.jumpForce = newJumpForce
or something like that? I'm trying to stay out of C++ code for now. I remember reading somewhere that game logic can be programmed in script... it seems like there should be a way to change the datablock object for a client's player without using c++? Of course, I'm keeping my fingers crossed. :)
#3
Dylan gave you the needed info to do so :-)
03/14/2004 (12:56 am)
As far as I know, you can only do this by changing the C++ code. To allow you to set it from script. Its not a method provided by the engine per default, so you'll have to do that yourself.Dylan gave you the needed info to do so :-)
#4
I found another function being called a lot in script, called getDataBlock(). I experimented with that, and discovered it returns the datablock for that class (tricky eh, since that's the name of the function :) Anyway, here's what I did:
And that changes the player's jump height to be super high! Alright! Jump boots on the way. So, altogether with Dylan's code for searching out player clients, we have:
Now I'm working on getting the jump to turn back to a normal height after a period of time, like Dylan mentioned. I'm using a %cl.player.schedule() function. Have to play around with it some more. Then I'll move on to making it a powerup.
Thanks again for the help everyone, that's really the last piece of the puzzle I needed to get me comfortable coding my own scripts. I was really impressed to see how fast questions are answered here on these forums. :)
03/14/2004 (9:02 am)
Ok, I found out how to do what I wanted from script. Probably I didn't make clear enough what I wanted to do in my post, so it seemed like maybe it couldn't be done with just script. I'll go ahead and lay out my process real quick for those who are new like me and might not know all the in's and out's of Torque lingo.I found another function being called a lot in script, called getDataBlock(). I experimented with that, and discovered it returns the datablock for that class (tricky eh, since that's the name of the function :) Anyway, here's what I did:
%myData = %cl.player.getDatablock();
%myData.jumpForce = 8.3 * 600;And that changes the player's jump height to be super high! Alright! Jump boots on the way. So, altogether with Dylan's code for searching out player clients, we have:
// This will cycle through the client's in the game and change their jump height
function toggleJump ()
{
for( %clientIndex = 0; %clientIndex < ClientGroup.getCount(); %clientIndex++ )
{
%cl = ClientGroup.getObject( %clientIndex );
//Do stuff here with the client... to acces the player object of
//this client, use %cl.player
// THIS WORKS ------------ Grabbing the jumpforce
// grab the Player class's datablock from the current client
%myData = %cl.player.getDatablock();
// echo it out to the console for good measure
echo ("cl.player.getDatablock() = " @ %myData);
echo ("cl.player.getDatablock().jumpForce = " @ %myData.jumpForce);
// make the jump height superhigh!
%myData.jumpForce = 8.3 * 600;
}
}Now I'm working on getting the jump to turn back to a normal height after a period of time, like Dylan mentioned. I'm using a %cl.player.schedule() function. Have to play around with it some more. Then I'll move on to making it a powerup.
Thanks again for the help everyone, that's really the last piece of the puzzle I needed to get me comfortable coding my own scripts. I was really impressed to see how fast questions are answered here on these forums. :)
#5
I suggest adding a "jumpMod" variable to the Player class and changing that, and having it affect the value fetched from the datablock in the C++ that is used in the jump force calculations. Similar to how the gravity mod resource works, you can then tweak the settings independently for each player object.
03/14/2004 (10:58 am)
The problem is that all your players probably share the same datablock. So changing the jumpForce on one changes it for all of them. And the changes may not get propagated across the network...I suggest adding a "jumpMod" variable to the Player class and changing that, and having it affect the value fetched from the datablock in the C++ that is used in the jump force calculations. Similar to how the gravity mod resource works, you can then tweak the settings independently for each player object.
#6
You did make it clear enough - we all understood what you wanted :-)
Unless you are making a single player game, then you are changing the jump force for all players in the game.
This is the public area, so I wont post code. But here is what you need to do
Try to go to the player.cc class. Find where the other ConsoleMethod declarations are. Copy paste one of them into a setJumpForce and getJumpForce, and simply take the variable send to the function and set the players jumpforce variable. It should be max 10 lines of code all in all, and you get what you need :-)
03/14/2004 (11:19 am)
What Ben says.You did make it clear enough - we all understood what you wanted :-)
Unless you are making a single player game, then you are changing the jump force for all players in the game.
This is the public area, so I wont post code. But here is what you need to do
Try to go to the player.cc class. Find where the other ConsoleMethod declarations are. Copy paste one of them into a setJumpForce and getJumpForce, and simply take the variable send to the function and set the players jumpforce variable. It should be max 10 lines of code all in all, and you get what you need :-)
#7
@Ben - Thanks, I'll check out the gravity mod to see what I can learn from that.
@Thomas - looks like I am still the one not clear about what I am doing. :)
So it looks like I still don't quite understand what I'm doing. I was thinking of a datablock like a C++ class, and a datablock object (ie PlayerData for different players) to be like instances of that class. But, even if I change a certain object's datablock, that will change all objects that use that datablock, meaning, all datablock references for a particular datablock actually point to the same thing in memory. Does that sound right?
So if player1 and player 2 share the same type of datablock....
And I did:
Then %player2Data.someVar would equal 10?
Hmmm, interesting. Just when I thought I was getting to understand datablocks. :)
03/15/2004 (1:16 pm)
Ahhhh, I see. :)@Ben - Thanks, I'll check out the gravity mod to see what I can learn from that.
@Thomas - looks like I am still the one not clear about what I am doing. :)
So it looks like I still don't quite understand what I'm doing. I was thinking of a datablock like a C++ class, and a datablock object (ie PlayerData for different players) to be like instances of that class. But, even if I change a certain object's datablock, that will change all objects that use that datablock, meaning, all datablock references for a particular datablock actually point to the same thing in memory. Does that sound right?
So if player1 and player 2 share the same type of datablock....
And I did:
%player1Data = %player1.getDatablock(); %player2Data = %player2.getDatablock(); %player1Data.someVar = 10;
Then %player2Data.someVar would equal 10?
Hmmm, interesting. Just when I thought I was getting to understand datablocks. :)
#8
If your datablock has a mVar = 10; in it, then all objects created from that datablock will have thier mVar variable set to 10. At runtime if you want to change mVar on a specific object, then you don't change the datablock, you change the mVar variable on the specific object instance you want to change. Unfortunately, most of those variables aren't exposed in script for per object changes so you have to expose them.
Does that make sense? There was another tpoic on datablocks that was posted recently where we explained this too. Maybe reading that will make it more clear. I'll see if I can fidn it.
03/15/2004 (1:22 pm)
Drew think of a DataBlock like a class definition in C++. You make a class definition in your header file, and every object of that class instantiated uses that definition. DataBlocks are a design time definition that you don't touch at runtime unless you really know what you're doing and want to change every instanced object based on that datablock..which you normally don't.If your datablock has a mVar = 10; in it, then all objects created from that datablock will have thier mVar variable set to 10. At runtime if you want to change mVar on a specific object, then you don't change the datablock, you change the mVar variable on the specific object instance you want to change. Unfortunately, most of those variables aren't exposed in script for per object changes so you have to expose them.
Does that make sense? There was another tpoic on datablocks that was posted recently where we explained this too. Maybe reading that will make it more clear. I'll see if I can fidn it.
#10
I understand your analogy of data blocks as a design time definition. I also get why I shouldn't touch them, then that will modifiy all instances that were created from it. So in a way, this is like what I thought initially. I thought what I was doing when I called %obj.getDatablock() was getting access to that object's *instance* of the datablock, but I was actually getting the original datablock and modifying it, which is not what I want to do.
So I guess what I need to know is, how can I change just the instance of the datablock I am working with, and not affect the actual datablock itself? And it sounds like from previous posts on this thread, I can't just access a datablock's instances from script, namely, I can't grab myPlayer.jumpForce. For whatever reason, the actual instance variables are not exposed in script. So I have to access them through the C++ code. Or write a C++ function to let me access them through script.
So is that the way it is for all datablocks? If I want to change an instance of the datablock, I have to do some tinkering in C++ to set that up?
03/15/2004 (1:56 pm)
Ah great, thanks John. Your post and that thread link was really helpful.I understand your analogy of data blocks as a design time definition. I also get why I shouldn't touch them, then that will modifiy all instances that were created from it. So in a way, this is like what I thought initially. I thought what I was doing when I called %obj.getDatablock() was getting access to that object's *instance* of the datablock, but I was actually getting the original datablock and modifying it, which is not what I want to do.
So I guess what I need to know is, how can I change just the instance of the datablock I am working with, and not affect the actual datablock itself? And it sounds like from previous posts on this thread, I can't just access a datablock's instances from script, namely, I can't grab myPlayer.jumpForce. For whatever reason, the actual instance variables are not exposed in script. So I have to access them through the C++ code. Or write a C++ function to let me access them through script.
So is that the way it is for all datablocks? If I want to change an instance of the datablock, I have to do some tinkering in C++ to set that up?
#11
DataBlock -> Instanced Object
What you need to do is modify the properites of that Instanced Object. To do that will require C++ side hooks, as those are generally not available out of the box. There is a resource around here somwhere on extending the Scripting side of things. It is REALLY simple, and will allow you to do what you want in 15 minutes.
In Psedua-code basically you'd create a new scripting funtion in C++:
ScriptFunction( setPlayerJumpValue, 2 /* 2 params, the instanced object and the value */, PlayerObject player, int value)
{
player.mJumpValue = value;
}
Then in script youd use it. Again pseudo In Script:
setPlayerJumpValue(%getPlayer, 100);
03/15/2004 (2:05 pm)
Pretty much you have your datablock which defines object. Instance of object is what you work on in script.DataBlock -> Instanced Object
What you need to do is modify the properites of that Instanced Object. To do that will require C++ side hooks, as those are generally not available out of the box. There is a resource around here somwhere on extending the Scripting side of things. It is REALLY simple, and will allow you to do what you want in 15 minutes.
In Psedua-code basically you'd create a new scripting funtion in C++:
ScriptFunction( setPlayerJumpValue, 2 /* 2 params, the instanced object and the value */, PlayerObject player, int value)
{
player.mJumpValue = value;
}
Then in script youd use it. Again pseudo In Script:
setPlayerJumpValue(%getPlayer, 100);
#12
Here
Time's like this i'm glad I always flag interesting resources :) Makes it so much easier to see.
BTW for those who don't know, if you just rate a resource 4 or a 5 (maybe 3 but not sure) then it gets added to your My Garage page under recommended resources. Makes it a handy way to bookmark or flag interesting resources for later followup.
03/15/2004 (2:07 pm)
Take a look at this resource:Here
Time's like this i'm glad I always flag interesting resources :) Makes it so much easier to see.
BTW for those who don't know, if you just rate a resource 4 or a 5 (maybe 3 but not sure) then it gets added to your My Garage page under recommended resources. Makes it a handy way to bookmark or flag interesting resources for later followup.
#13
Thanks a lot for taking some time to help me through this. :)
That last resource was super handy, that will get me coding new console functions in a jiffy. I can easily make a setJumpForce() function from there.
What would be great now would be for someone to make some kind of C++ modification that would let you always be able to access datablock instances without writing C++ code for each one. Or maybe there's not that many datablock variables that are worth being dynamic across instances anyway, guess I'll have to do more to find out what I think. Maybe I'll write one if I think people could use it. :)
Thanks John, thanks everybody for all the help.
03/15/2004 (2:45 pm)
John,Thanks a lot for taking some time to help me through this. :)
That last resource was super handy, that will get me coding new console functions in a jiffy. I can easily make a setJumpForce() function from there.
What would be great now would be for someone to make some kind of C++ modification that would let you always be able to access datablock instances without writing C++ code for each one. Or maybe there's not that many datablock variables that are worth being dynamic across instances anyway, guess I'll have to do more to find out what I think. Maybe I'll write one if I think people could use it. :)
Thanks John, thanks everybody for all the help.
#14
In worst case you could have cheaters hack your game. E.g. create a powerup effect themselves on a keypress or whatever. Or someone mods your game into something you dont want it to be.
With only exlicitly exposing single functions the engine writers can control what scripters can do "safely" without destroying the game.
(Extreme examples, but as I understand it, its by design made this way)
03/16/2004 (12:36 am)
Well - the issue is that you DONT want people to have access to all your datablocks (or for the matter individual instances) from script. Only the parts that you want to be "safely" accesible from script. In worst case you could have cheaters hack your game. E.g. create a powerup effect themselves on a keypress or whatever. Or someone mods your game into something you dont want it to be.
With only exlicitly exposing single functions the engine writers can control what scripters can do "safely" without destroying the game.
(Extreme examples, but as I understand it, its by design made this way)
#15
I guess I'm used to UT2003 modding, where almost everything "game-logic" wise, like player speed, jumpheight, etc, can be dynamically changed by script during runtime. With UT2003, there are other mechanisms in place to ensure this can't be used to cheat, etc... the server has to authorize any changes. The nice thing was, it was very easy to change game-logic variables however you wanted, without resorting to C++ coding.
On the flip side, with UT2003 modding, you *don't* have access to source code, you *can't* sell your mod, and if you wan't source you have to shell out like $200,000. So, for sure, Torque's gains far outweigh the losses to UT2003 scripting. I guess I just had to make a whole conceptual shift in my mind, as I'd spent a lot of time doing UT2003 scripting, and while Torque scripting is similiar, it's also different. Now that I'm starting to adjust, things are getting easier and making more sense.
I finished the jump boots example in C++. Made some changes, works like a charm over the network. The Torque engine really is awesome. I'm looking forward to learning more and more about it. And the community is really great and supportive too. I'll post the jumpboots as a tutorial / resource when I tweak them a bit. People with experience could do it in a snap, but maybe those learning like me will find it useful.
I saw a resource about being able to control the player mid-air with arrow keys, Quake style. I think I'll put that in now, so you can have more control jumping with the boots. :)
03/16/2004 (10:02 am)
That makes sense, you don't want the client to be able to do whatever they want without server authentication.I guess I'm used to UT2003 modding, where almost everything "game-logic" wise, like player speed, jumpheight, etc, can be dynamically changed by script during runtime. With UT2003, there are other mechanisms in place to ensure this can't be used to cheat, etc... the server has to authorize any changes. The nice thing was, it was very easy to change game-logic variables however you wanted, without resorting to C++ coding.
On the flip side, with UT2003 modding, you *don't* have access to source code, you *can't* sell your mod, and if you wan't source you have to shell out like $200,000. So, for sure, Torque's gains far outweigh the losses to UT2003 scripting. I guess I just had to make a whole conceptual shift in my mind, as I'd spent a lot of time doing UT2003 scripting, and while Torque scripting is similiar, it's also different. Now that I'm starting to adjust, things are getting easier and making more sense.
I finished the jump boots example in C++. Made some changes, works like a charm over the network. The Torque engine really is awesome. I'm looking forward to learning more and more about it. And the community is really great and supportive too. I'll post the jumpboots as a tutorial / resource when I tweak them a bit. People with experience could do it in a snap, but maybe those learning like me will find it useful.
I saw a resource about being able to control the player mid-air with arrow keys, Quake style. I think I'll put that in now, so you can have more control jumping with the boots. :)
Torque Owner Dylan Sale
You would need to change the player C++ code to allow for variable jump heights (through a ConsoleMethod). Then you could call this method in the ItemData::onUse script function (assuming your object is an Item) to change the jump height (force) of the player, as the player who is using the object is passed in as a parameter. Look in server/scripts/health.cs for an example, the player object is named %user.
You'd probably want to schedule a function that changes it back after a certain timeout as well.
In reguards to your other question, you can get all the currently connected clients by doing
for( %clientIndex = 0; %clientIndex < ClientGroup.getCount(); %clientIndex++ ) { %cl = ClientGroup.getObject( %clientIndex ); //Do stuff here with the client... to acces the player object of //this client, use %cl.player }This is because Torque is a multiplayer engine, thus usually there is more than one player. However, you could add a global variable to your player if you really wanted to. This would be done in the player creation code.. do a search for "new Player". The value returned could be placed in a global variable.