Dynamic Vars added to engine, but not working.
by J · in Torque Game Engine · 04/17/2008 (2:16 pm) · 10 replies
I'm working on cleaning up an AI attacking script, because its using a ton of global variables for each enemy's additional values that I need:.
using [url="http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=7080"]this resource[/url]; I added four variables to the shapebase class:
It recompiled just fine...
So I added the values at the end of my AIPlayer datablock
Then when I run my game...
I can't get them to show any value...
either when I run my AI script or if I'd just echo it...
returns blank...
but I can go Imp.setFieldValue(sightRange,70);
and the imp chases just like he should....
I don't understand the shapebase additions I made for the dynamic variables... should it work like that? or is there something I missed to get it to operate like I want it to?
Which is...just setup those variables in the Imp datablock, I then run a container search for a %targetObject...then call %targetObject.getFieldValue(sightRange)); to determine the distance they can "see" the player and chase.
Any ideas? or do I need to do things differently to get the desired results?
Any help is greatly appreciated!!!
GOD BLESS!
J
using [url="http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=7080"]this resource[/url]; I added four variables to the shapebase class:
sightRange; attackRange; equipedWeapon; colDamage;
It recompiled just fine...
So I added the values at the end of my AIPlayer datablock
upMaxSpeed = 80; upResistSpeed = 25; upResistFactor = 0.3; //Additional Variables [b]sightRange = 70; attackRange = 5; equipedWeapon = 1; colDamage = 1;[/b] }; //------------------------------------------------------------------------------ //END IMP DATABLOCK END //------------------------------------------------------------------------------
Then when I run my game...
I can't get them to show any value...
either when I run my AI script or if I'd just echo it...
echo(Imp.getFieldValue(sightRange));
returns blank...
but I can go Imp.setFieldValue(sightRange,70);
and the imp chases just like he should....
I don't understand the shapebase additions I made for the dynamic variables... should it work like that? or is there something I missed to get it to operate like I want it to?
Which is...just setup those variables in the Imp datablock, I then run a container search for a %targetObject...then call %targetObject.getFieldValue(sightRange)); to determine the distance they can "see" the player and chase.
Any ideas? or do I need to do things differently to get the desired results?
Any help is greatly appreciated!!!
GOD BLESS!
J
About the author
I used to be obsessed with building my own open-ended RPG and a 3D Side Scroller RPG. But the job/house/girlfriend got in the way. I know, I know. Now I concentrate on doing architectural renderings (with the help of T3D of course) and VBA programming.
#2
Nevermind, didn't make a difference.
So maybe this isn't setting up a variable like I'm thinking it should.
I just want a few variables I can access with getFieldValue...that is unique to each enemies datablock. Should I go about this a different way?
04/18/2008 (6:31 am)
Just seen part of my problem...S32 on initiating it and then F32 in addfield...I'll fix that and recompileNevermind, didn't make a difference.
So maybe this isn't setting up a variable like I'm thinking it should.
I just want a few variables I can access with getFieldValue...that is unique to each enemies datablock. Should I go about this a different way?
#3
04/18/2008 (8:21 am)
I was confused why the fields were added to shapebase. Every tree and building and human player now has them?
#4
Looking back at the topic flow, I think you are confusing dynamic fields with persistent fields.
Dynamic fields are created and used only in script, and never accessed in C++ directly in common use. getFieldValue only exists for the compiler and editors to use, and is not something that you should expect to use in "normal" TorqueScript.
Persistent fields on the other hand (which is what you are creating with your code above), are designed explicitly to allow access from both C++ and TorqueScript, and have no need for getFieldValue at all--you simply use the %objectID.persistentField syntax.
04/18/2008 (8:22 am)
I'm honestly not sure where this use of GetFieldValue has snuck in to common use--it's not an expected use in normal game logic programming for persistent fields, which is what you have created.Looking back at the topic flow, I think you are confusing dynamic fields with persistent fields.
Dynamic fields are created and used only in script, and never accessed in C++ directly in common use. getFieldValue only exists for the compiler and editors to use, and is not something that you should expect to use in "normal" TorqueScript.
Persistent fields on the other hand (which is what you are creating with your code above), are designed explicitly to allow access from both C++ and TorqueScript, and have no need for getFieldValue at all--you simply use the %objectID.persistentField syntax.
#5
@ Matthew
I wanted to just set them up for the player datablock...but the resource I used to originally learn how to set the variables up just did it in shapebase.cc/h; But now I do have it in the Player.cc/h
@Stephen
I did figure that out from a different thread here I didn't understand how that was supposed to work. I did try it like
%targetObject.sightRange..but I got null... so i didn't know for sure what was correct.
Now, After messing with this...I placed my three new variables in void Player::consoleInit() with addField.
I can now get a 0 sightRange and colDamage and a wierd number for attackRange.
So I'm trying to figure out where I need to designate a value for them.
I currently have it at the bottom of PlayerData::PlayerData()
That is where the values for everything else is defined. Is that right?
I followed a few threads: this is the exact same problem I'm having.Here
And just to be specific (hope I'm not repeating myself), but I want to have the same fields/variables in each datablock. Then I can set a value those fields when I setup a new enemy datablock and those values will be unique to each player so I can use them.
Maybe I'm going about this all wrong.
Thank you for you help guys I really appreciate it.
God Bless!
J
04/18/2008 (8:47 am)
Sorry If I'm confusing...I don't know C++ very well at all...@ Matthew
I wanted to just set them up for the player datablock...but the resource I used to originally learn how to set the variables up just did it in shapebase.cc/h; But now I do have it in the Player.cc/h
@Stephen
I did figure that out from a different thread here I didn't understand how that was supposed to work. I did try it like
%targetObject.sightRange..but I got null... so i didn't know for sure what was correct.
Now, After messing with this...I placed my three new variables in void Player::consoleInit() with addField.
I can now get a 0 sightRange and colDamage and a wierd number for attackRange.
So I'm trying to figure out where I need to designate a value for them.
I currently have it at the bottom of PlayerData::PlayerData()
That is where the values for everything else is defined. Is that right?
I followed a few threads: this is the exact same problem I'm having.Here
And just to be specific (hope I'm not repeating myself), but I want to have the same fields/variables in each datablock. Then I can set a value those fields when I setup a new enemy datablock and those values will be unique to each player so I can use them.
Maybe I'm going about this all wrong.
Thank you for you help guys I really appreciate it.
God Bless!
J
#6
::consoleInit is for global script variables, not object associated variables.
Player::initPersistFields() is for variables associated with a specific Player, not a specific Player DataBlock.
04/18/2008 (8:55 am)
They should be in PlayerData::initPersistFields(), but since you actually put the variable declarations in your shapeBase class, it would be more appropriate to put them in ShapebaseData::initPersistfields().::consoleInit is for global script variables, not object associated variables.
Player::initPersistFields() is for variables associated with a specific Player, not a specific Player DataBlock.
#7
You need to access the field on the datablock, not the player object:
04/18/2008 (9:18 am)
Quote:%targetObject.sightRange..but I got null... so i didn't know for sure what was correct.
You need to access the field on the datablock, not the player object:
%targetObject.getDataBlock().sightRange;
#8
New fields in the PlayerData datablock, fields defined in PlayerData::initPersistFields, the initial values in the PlayerData::PlayerData (C++ constructor) (default values used if not found later in the datablock script).
Access _datablock_ variables with %objectID.getDataBlock().field syntax. Maybe, if you mistakenly use %objectID.newField syntax it creates a new dynamic field for the object?
Be aware that unless you do more coding, these variables are only available for the Server scripts, not for remote clients. (You can send these C++ added fields across to the client, but often this isn't needed so it is done only on a case-by-case basis. Since this is for AI use that is code run on the server, you likely won't need to do that. For other people/problems, if you need fields transferred, look through the PlayerData class, etc., for examples.)
04/18/2008 (10:12 am)
Make sure you put all these advices (is that a word? ;) ) together. New fields in the PlayerData datablock, fields defined in PlayerData::initPersistFields, the initial values in the PlayerData::PlayerData (C++ constructor) (default values used if not found later in the datablock script).
Access _datablock_ variables with %objectID.getDataBlock().field syntax. Maybe, if you mistakenly use %objectID.newField syntax it creates a new dynamic field for the object?
Be aware that unless you do more coding, these variables are only available for the Server scripts, not for remote clients. (You can send these C++ added fields across to the client, but often this isn't needed so it is done only on a case-by-case basis. Since this is for AI use that is code run on the server, you likely won't need to do that. For other people/problems, if you need fields transferred, look through the PlayerData class, etc., for examples.)
#9
When I set everything up the first time with the resource in shapebase.cc/h... I left the variable declarations in the shapebase.h file...deleted it, compiled, and it worked fine...Great!!!
Thank you guys for all your help and fast responses, I really appreciate it!
Lesson in Review:
#1
#2
#3
#4
#5
#6
#7
Thanks again guys!
God Bless!
J
04/18/2008 (1:48 pm)
Geez...what a dumb move on my part....When I set everything up the first time with the resource in shapebase.cc/h... I left the variable declarations in the shapebase.h file...deleted it, compiled, and it worked fine...Great!!!
Thank you guys for all your help and fast responses, I really appreciate it!
Lesson in Review:
#1
-Declare the field/variable- In [i]Player.h[/i] under [b]struct PlayerData: public ShapeBaseData[/b] example: [i]F32 newVariable;[/i]
#2
-Give it a default value- In [i]Player.cc[/i] under [b]PlayerData::PlayerData()[/b] example: [i]newVariable = x;[/i]
#3
-Define it-
In [i]Player.cc[/i] under
[b]void PlayerData::initPersistFields()[/b]
example: [i]addField("newVariable", TypeF32, Offset(newVariable, PlayerData));[/i]#4
-Write it- In [i]Player.cc[/i] under [b]void PlayerData::packData(BitStream* stream)[/b] example: [i]stream->write(newVariable);[/i]
#5
-Read it- In [i]Player.cc[/i] under [b]void PlayerData::unpackData(BitStream* stream)[/b] example: [i]stream->read(&newVariable);[/i]
#6
-Set it up in script- In [i]Player.cs[/i] under [b]datablock PlayerData(PlayerBody)[/b] example: [i]newVariable = 25;[/i]
#7
-Access it or use it in game/script- In your console or in your script: [i]%player.getDataBlock().newVariable;[/i]
Thanks again guys!
God Bless!
J
#10
For example if you are adding a flag, say canShoot. You would (obviously) declare it as:
Using the proper write/read methods of the BitStream will lead to the best network efficiency. As a final note, remember that the order that fields are written and read in the packData and unpackData functions are massively important.
Good summary!
04/18/2008 (2:23 pm)
Just to ensure things are clear, I would point out that the "type" portion of the addField call as well as the function called in packData to write into and in unpackData to read from the stream is dependent on the type of variable being added.For example if you are adding a flag, say canShoot. You would (obviously) declare it as:
bool canshoot;That goes in the header, in initPersistFields:
addField("canShoot", [b]TypeBool[/b], Offset(canShoot, PlayerData));and in the networking functions[b]void PlayerData::packData(BitStream* stream)[/b] stream->writeFlag(canShoot); [b]void PlayerData::unpackData[/b] canShoot = stream->readFlag();
Using the proper write/read methods of the BitStream will lead to the best network efficiency. As a final note, remember that the order that fields are written and read in the packData and unpackData functions are massively important.
Good summary!
Associate Kyle Carter