Moving a variable outside the datablock?
by Dreamer · in Torque Game Engine · 05/01/2005 (11:03 am) · 11 replies
Hello, I have managed to move the MaxDamage value out of the PlayerData datablock and created 2 console methods and a new member variable, setMaxDamage, getMaxDamage and mMaxDamage. Then I removed all refferences in code to mDatablock->MaxDamage and replaced them with mMaxDamage.
Here is the most relevant snippits
This new system seems to work really well, and I would like to create similar functionality for Energy and ShapeFile, I think with Energy the change will be really straightforward, however before I start, trying to do this with the ShapeFile, I would like to find out if there are any possible repurcussions in the engine. Like for instance, what considerations if any would I need to make, to keep the engine from crashing if I changed the shapefile? The purpose of changing the shapefile would of course be to allow the player to cast a spell and change his body shape, without needing to change datablocks.
Anyways, any caveats or advice would be greatly appreciated. Thanks!
Here is the most relevant snippits
void ShapeBase::setMaxDamage(int maxdamage){
mMaxDamage = maxdamage;
updateDamageLevel();
}
int ShapeBase::getMaxDamage(){
return(mMaxDamage);
}
ConsoleMethod( ShapeBase, setMaxDamage, void, 3, 3, "(int Max Damage)")
{
object->setMaxDamage(dAtoi(argv[2]));
}
ConsoleMethod(ShapeBase, getMaxDamage, S32,2,2,"(no params returns int)"){
return object->getMaxDamage();
}This new system seems to work really well, and I would like to create similar functionality for Energy and ShapeFile, I think with Energy the change will be really straightforward, however before I start, trying to do this with the ShapeFile, I would like to find out if there are any possible repurcussions in the engine. Like for instance, what considerations if any would I need to make, to keep the engine from crashing if I changed the shapefile? The purpose of changing the shapefile would of course be to allow the player to cast a spell and change his body shape, without needing to change datablocks.
Anyways, any caveats or advice would be greatly appreciated. Thanks!
#2
Datablocks are shared on both the server and the client (after being downloaded), and therefore if you change objectXXX->mDatablock->someValue, it will change for everyone that references that datablock.
05/01/2005 (12:57 pm)
@Ian: Actually, that is not true. If you change a datablock value, it will change for every object that uses that datablock.Datablocks are shared on both the server and the client (after being downloaded), and therefore if you change objectXXX->mDatablock->someValue, it will change for everyone that references that datablock.
#3
Changing a datablock's value during a game is not a good idea:
(a) It will not be persisted to the clients, so the datablocks will be out of sync.
(b) It won't affect objects which already exist, only newly created ones.
My point is that he shouldn't bother taking the values out of the datablock: they're doing absolutely no harm there, and taking things out that aren't doing any hard simply causes work later on, it's a proven fact of indie dev.
What he wants to do is change some values dynamically on an already spawned object. What datablocks do is initialise values. There is no intersection between these two things, and thus he shouldn't be messing around with the later while implementing the former.
At least, that's my take :)
Ian
05/01/2005 (1:11 pm)
No, don't agree. Sure, if you change a datablock value when the game isn't running it will affect all objects of that type, but then just leave those values default.Changing a datablock's value during a game is not a good idea:
(a) It will not be persisted to the clients, so the datablocks will be out of sync.
(b) It won't affect objects which already exist, only newly created ones.
My point is that he shouldn't bother taking the values out of the datablock: they're doing absolutely no harm there, and taking things out that aren't doing any hard simply causes work later on, it's a proven fact of indie dev.
What he wants to do is change some values dynamically on an already spawned object. What datablocks do is initialise values. There is no intersection between these two things, and thus he shouldn't be messing around with the later while implementing the former.
At least, that's my take :)
Ian
#4
If you modify a value in a datablock accessor method called within Object1, and then check that value from another object of the same datablock name, the change will have happened since both of the accessors will be referencing the same block of memory space: both of the objects will point to the same mDataBlock memory.
I originally thought datablocks were simply initializers as well, but they are only instantiated once, and then are shared.
If someone can show the code that proves this false, I'd certainly like to see it!
05/01/2005 (1:23 pm)
@Ian: Based on information from GG (I haven't traced this through myself to be honest), when you create a new object with a datablock name, it simply sets the object's mDataBlock pointer to the currently existing copy of the datablock object in memory.If you modify a value in a datablock accessor method called within Object1, and then check that value from another object of the same datablock name, the change will have happened since both of the accessors will be referencing the same block of memory space: both of the objects will point to the same mDataBlock memory.
I originally thought datablocks were simply initializers as well, but they are only instantiated once, and then are shared.
If someone can show the code that proves this false, I'd certainly like to see it!
#5
Try adding this funciton in ShapeBase.cc
Create 2 players both using the PlayerBody datablock.
1138 is the first client
1139 is the second client.
1138.Player.setMaxDamage(100);
1139.Player.setMaxDamage(50);
echo("First player's MaxDamage is"@1138.Player.MaxDamage);
FirstPlayers MaxDamage is50
This would only happen is the value is being refferenced from the most recent change to the datablock. In short datablocks are convenient places to store static data which must be shared across multiple instances.
So if for instance I had 2 teams, Orcs and Elves, and I all the sudden wanted ALL the elves to get sick and lose 50 percent of thier max hitpoints. Just refference one elf.
%targetObject.Player.setMaxDamage(%targetObject.Player.MaxDamage /2);
And all the sudden all elves loose 1/2 of thier damage recieving capabilities.
05/01/2005 (1:34 pm)
Here is my proof...Try adding this funciton in ShapeBase.cc
void ShapeBase::setMaxDamage(int damage){
mDataBlock->maxDamage = damage;
updateDamageLevel();
}
ConsoleMethod( ShapeBase, setMaxDamage, void, 3, 3, "(int MaxDamage)")
{
object->setMaxDamage(dAtoi(argv[2]));
}Create 2 players both using the PlayerBody datablock.
1138 is the first client
1139 is the second client.
1138.Player.setMaxDamage(100);
1139.Player.setMaxDamage(50);
echo("First player's MaxDamage is"@1138.Player.MaxDamage);
FirstPlayers MaxDamage is50
This would only happen is the value is being refferenced from the most recent change to the datablock. In short datablocks are convenient places to store static data which must be shared across multiple instances.
So if for instance I had 2 teams, Orcs and Elves, and I all the sudden wanted ALL the elves to get sick and lose 50 percent of thier max hitpoints. Just refference one elf.
%targetObject.Player.setMaxDamage(%targetObject.Player.MaxDamage /2);
And all the sudden all elves loose 1/2 of thier damage recieving capabilities.
#6
Ian
05/01/2005 (1:36 pm)
Right, gotcha. Looking at MaxEnergy etc the player class does call the datablock directly, so I'm wrong on that count. I guess what I think he should be doing is to change all references to mDatabock->maxEnergy to mMaxEnergy, fill mMaxEnergy from the dataBlock in onNewDataBlock, then access that directly.Ian
#7
What I need to know is if there are any possible repurcussions to this, like for instance, I would think that this new value needs to be handed off to the client somewhere via PackUpdate and UnPackUpdate, but I'm not seeing where to stick it.
Strangely though, this change seems to have propegated it's self automagically.
05/01/2005 (1:43 pm)
Well what I wound up doing is initializing mMaxDamage to 100 (for safety sake) at about the same place as mDamage is declared.MPLEMENT_CO_NETOBJECT_V1(ShapeBase);
ShapeBase::ShapeBase()
{
mTypeMask |= ShapeBaseObjectType;
mDrag = 0;
mBuoyancy = 0;
mWaterCoverage = 0;
mLiquidType = 0;
mLiquidHeight = 0.0f;
mControllingClient = 0;
mControllingObject = 0;
mGravityMod = 1.0;
mAppliedForce.set(0, 0, 0);
mTimeoutList = 0;
mDataBlock = NULL;
mShapeInstance = 0;
mShadow = 0;
mGenerateShadow = false;
mEnergy = 0;
mRechargeRate = 0;
[b]mMaxDamage = 100;[/b]
mDamage = 0;
mRepairRate = 0;What I need to know is if there are any possible repurcussions to this, like for instance, I would think that this new value needs to be handed off to the client somewhere via PackUpdate and UnPackUpdate, but I'm not seeing where to stick it.
Strangely though, this change seems to have propegated it's self automagically.
#8
I have looked everywhere for a good place to post this, and this seems to be it, so here we go. I want to add a dynamic variable to the Player class, called mJumpCharge (values being 0-1) that modifies the mDataBlock->jumpForce variable by taking a percentage of it. Originally, I added the following to player.h
Then in player.cc under Player::Player() I added
Next in player.cc under Player::updateMove(const Move* move) I changed this
To this:
Is there anything else I need to do to get this working right, so I can change the value of mJumpCharge in script?
I experimented with added read and write lines to packUpdate and unpackUpdate, but to no avail.
05/03/2005 (1:48 pm)
Hey all,I have looked everywhere for a good place to post this, and this seems to be it, so here we go. I want to add a dynamic variable to the Player class, called mJumpCharge (values being 0-1) that modifies the mDataBlock->jumpForce variable by taking a percentage of it. Originally, I added the following to player.h
ActionState mState; ///< What is the player doing? @see ActionState bool mFalling; ///< Falling in mid-air? [b]F32 mJumpCharge; ///< percent to be multiplied by jumpForce (0-1) - AB [/b] S32 mJumpDelay; ///< Delay till next jump
Then in player.cc under Player::Player() I added
mFalling = false; mContactTimer = 0; [b]mJumpCharge = 0; [/b] mJumpDelay = 0;
Next in player.cc under Player::updateMove(const Move* move) I changed this
F32 impulse = mDataBlock->jumpForce / mMass;
To this:
//modified to account for charged jump F32 impulse = (mJumpCharge * mDataBlock->jumpForce) / mMass;
Is there anything else I need to do to get this working right, so I can change the value of mJumpCharge in script?
I experimented with added read and write lines to packUpdate and unpackUpdate, but to no avail.
#9
I have looked everywhere for a good place to post this, and this seems to be it, so here we go. I want to add a dynamic variable to the Player class, called mJumpCharge (values being 0-1) that modifies the mDataBlock->jumpForce variable by taking a percentage of it. Originally, I added the following to player.h
Then in player.cc under Player::Player() I added
Next in player.cc under Player::updateMove(const Move* move) I changed this
To this:
Is there anything else I need to do to get this working right, so I can change the value of mJumpCharge in script?
I experimented with added read and write lines to packUpdate and unpackUpdate, but to no avail.
05/03/2005 (2:37 pm)
Hey all,I have looked everywhere for a good place to post this, and this seems to be it, so here we go. I want to add a dynamic variable to the Player class, called mJumpCharge (values being 0-1) that modifies the mDataBlock->jumpForce variable by taking a percentage of it. Originally, I added the following to player.h
ActionState mState; ///< What is the player doing? @see ActionState bool mFalling; ///< Falling in mid-air? [b]F32 mJumpCharge; ///< percent to be multiplied by jumpForce (0-1) - AB [/b] S32 mJumpDelay; ///< Delay till next jump
Then in player.cc under Player::Player() I added
mFalling = false; mContactTimer = 0; [b]mJumpCharge = 0; [/b] mJumpDelay = 0;
Next in player.cc under Player::updateMove(const Move* move) I changed this
F32 impulse = mDataBlock->jumpForce / mMass;
To this:
//modified to account for charged jump F32 impulse = (mJumpCharge * mDataBlock->jumpForce) / mMass;
Is there anything else I need to do to get this working right, so I can change the value of mJumpCharge in script?
I experimented with added read and write lines to packUpdate and unpackUpdate, but to no avail.
#10
Look at method 2
You can access the data in scripts easily. Modify it in the way you want.
05/06/2005 (7:38 pm)
Http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=7453Look at method 2
You can access the data in scripts easily. Modify it in the way you want.
#11
05/07/2005 (12:37 pm)
Thanks a lot.. That is exactly what i needed.
Associate Ian Omroth Hardingham
Mode 7 Games
On to your real question: it won't be just as simple as changing the shapefile, you will need to do a bit of setting up. But look through shapebase::onNewDatablock and you should see what you need to do.
Ian