guiHealthBarHUD Advanced
by Dreamer · 11/18/2006 (11:33 am) · 4 comments
I made a promise a long time ago when I started the MMORPG Enhancement Kit, that any enhancements to the engine we made that could "stand-alone" would be released as free resources. This is me keeping that promise to the community.
I had a need to extend the existing guiHealthBarHUD by allowing it to display health on any player and yet not break existing installs.
You see the way the default guiHealthBarHUD works is by simply looking at the current connection, and obtaining the current control object i.e. player. This works great if you happen to be in control of your player at the moment, but if you go third person by pressing alt+c you loose all the information about your players current state, which makes it very hard to do a "click to move" setup. Also we use this for targeting feedback now too, so you can see the health of your target.
The changes aren't very substantial, and essentially involve adding 2 new variables to the code and script.
mPlayer (exposed to script as Player)
mPlayerBound (exposed to script as PlayerBound)
mPlayer is simply a pointer to the player you want to track, so as not to break existing installs, we have it always default to the current player being controlled and you can override this at anytime easily, by calling GuiHealthBarHUD.player = %player;
mPlayerBound is a little tricky to understand, but basically it forces the gui to track the current control object, it does this by setting mPlayer to 0 which tells the code that mPlayer is unset, and therefore to go back into original mode. I use this on the guiHealthBarHud, I have for tracking my own player, so that when he dies and respawns the gui starts tracking him and not his corpse :)
Ok so now here's the code, you can just drop this on top of your current engine/game/fps/guihealthbarhud.cc and recompile!
Now if you want to use this for creating a targetingGUI, it would be extremely trivial, just create a new instance of guiHealthBarHud and in the constructor (or at any time really), just pass in the object you are wanting to target.
If you had a whole team and you were keeping track of them in a simset you could display your entire team with something like this...
Ok I hope that explains this sufficiently, it's a really cool little mod that I hope you will have lots of fun with.
If you own the MMOKit, this code is in SVN and will be put into the next Patch, which will likely occur before this resource gets approved :)
Regards,
Dreamer
I had a need to extend the existing guiHealthBarHUD by allowing it to display health on any player and yet not break existing installs.
You see the way the default guiHealthBarHUD works is by simply looking at the current connection, and obtaining the current control object i.e. player. This works great if you happen to be in control of your player at the moment, but if you go third person by pressing alt+c you loose all the information about your players current state, which makes it very hard to do a "click to move" setup. Also we use this for targeting feedback now too, so you can see the health of your target.
The changes aren't very substantial, and essentially involve adding 2 new variables to the code and script.
mPlayer (exposed to script as Player)
mPlayerBound (exposed to script as PlayerBound)
mPlayer is simply a pointer to the player you want to track, so as not to break existing installs, we have it always default to the current player being controlled and you can override this at anytime easily, by calling GuiHealthBarHUD.player = %player;
mPlayerBound is a little tricky to understand, but basically it forces the gui to track the current control object, it does this by setting mPlayer to 0 which tells the code that mPlayer is unset, and therefore to go back into original mode. I use this on the guiHealthBarHud, I have for tracking my own player, so that when he dies and respawns the gui starts tracking him and not his corpse :)
Ok so now here's the code, you can just drop this on top of your current engine/game/fps/guihealthbarhud.cc and recompile!
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "dgl/dgl.h"
#include "gui/core/guiControl.h"
#include "console/consoleTypes.h"
#include "game/gameConnection.h"
#include "game/shapeBase.h"
//-----------------------------------------------------------------------------
/// A basic health bar control.
/// This gui displays the damage value of the current PlayerObjectType
/// control object. The gui can be set to pulse if the health value
/// drops below a set value. This control only works if a server
/// connection exists and it's control object is a PlayerObjectType. If
/// either of these requirements is false, the control is not rendered.
class GuiHealthBarHud : public GuiControl
{
typedef GuiControl Parent;
bool mShowFrame;
bool mShowFill;
bool mDisplayEnergy;
bool mFlipped;
bool mPlayerBound;
ColorF mFillColor;
ColorF mFrameColor;
ColorF mDamageFillColor;
S32 mPulseRate;
F32 mPulseThreshold;
F32 mValue;
ShapeBase* mPlayer;
public:
GuiHealthBarHud();
void onRender( Point2I, const RectI &);
static void initPersistFields();
DECLARE_CONOBJECT( GuiHealthBarHud );
};
//-----------------------------------------------------------------------------
IMPLEMENT_CONOBJECT( GuiHealthBarHud );
GuiHealthBarHud::GuiHealthBarHud()
{
mShowFrame = mShowFill = true;
mFlipped = mDisplayEnergy = false;
mFillColor.set(0, 0, 0, 0.5);
mFrameColor.set(0, 1, 0, 1);
mDamageFillColor.set(0, 1, 0, 1);
mPulseRate = 0;
mPulseThreshold = 0.3f;
mValue = 0.2f;
mPlayer = 0;
mPlayerBound = 0;
}
void GuiHealthBarHud::initPersistFields()
{
Parent::initPersistFields();
addGroup("Colors");
addField( "fillColor", TypeColorF, Offset( mFillColor, GuiHealthBarHud ) );
addField( "frameColor", TypeColorF, Offset( mFrameColor, GuiHealthBarHud ) );
addField( "damageFillColor", TypeColorF, Offset( mDamageFillColor, GuiHealthBarHud ) );
endGroup("Colors");
addGroup("Pulse");
addField( "pulseRate", TypeS32, Offset( mPulseRate, GuiHealthBarHud ) );
addField( "pulseThreshold", TypeF32, Offset( mPulseThreshold, GuiHealthBarHud ) );
endGroup("Pulse");
addGroup("Misc");
addField( "flipped", TypeBool, Offset( mFlipped, GuiHealthBarHud ) );
addField( "showFill", TypeBool, Offset( mShowFill, GuiHealthBarHud ) );
addField( "showFrame", TypeBool, Offset( mShowFrame, GuiHealthBarHud ) );
addField( "displayEnergy", TypeBool, Offset( mDisplayEnergy, GuiHealthBarHud ) );
addField( "playerBound", TypeBool, Offset( mPlayerBound, GuiHealthBarHud ) );
addField( "player", TypeSimObjectPtr, Offset( mPlayer, GuiHealthBarHud ) );
endGroup("Misc");
}
//-----------------------------------------------------------------------------
/**
Gui onRender method.
Renders a health bar with filled background and border.
*/
void GuiHealthBarHud::onRender(Point2I offset, const RectI &updateRect)
{
/*
// Must have a connection and player control object
GameConnection* conn = GameConnection::getConnectionToServer();
if (!conn)
return;
ShapeBase* control = conn->getControlObject();
*/
if(mPlayerBound){
mPlayer =0; //We do this to force it to look for the current playerObject on the connection
//when used as a typical HealthBar, otherwise if we die the GUI doesn't update
}
if(mPlayer == 0){
GameConnection* conn = GameConnection::getConnectionToServer();
if (!conn)
return;
mPlayer = conn->getControlObject();
}
if (!mPlayer || !(mPlayer->getType() & PlayerObjectType))
return;
if(mDisplayEnergy)
{
mValue = mPlayer->getEnergyValue();
}
else
{
// We'll just grab the damage right off the control object.
// Damage value 0 = no damage.
mValue = 1 - mPlayer->getDamageValue();
}
// Background first
if (mShowFill)
dglDrawRectFill(updateRect, mFillColor);
// Pulse the damage fill if it's below the threshold
if (mPulseRate != 0)
{
if (mValue < mPulseThreshold)
{
F32 time = Platform::getVirtualMilliseconds();
F32 alpha = mFmod(time,mPulseRate) / (mPulseRate / 2.0);
mDamageFillColor.alpha = (alpha > 1.0)? 2.0 - alpha: alpha;
}
else
mDamageFillColor.alpha = 1;
}
// Render damage fill %
RectI rect(updateRect);
if(mBounds.extent.x > mBounds.extent.y)
{
if(mFlipped)
{
S32 bottomX = rect.point.x + rect.extent.x;
rect.extent.x = (S32)(rect.extent.x * mValue);
rect.point.x = bottomX - rect.extent.x;
}
else
{
rect.extent.x = (S32)(rect.extent.x * mValue);
}
}
else
{
if(mFlipped)
{
rect.extent.y = (S32)(rect.extent.y * mValue);
}
else
{
S32 bottomY = rect.point.y + rect.extent.y;
rect.extent.y = (S32)(rect.extent.y * mValue);
rect.point.y = bottomY - rect.extent.y;
}
}
dglDrawRectFill(rect, mDamageFillColor);
// Border last
if (mShowFrame)
dglDrawRect(updateRect, mFrameColor);
}Now if you want to use this for creating a targetingGUI, it would be extremely trivial, just create a new instance of guiHealthBarHud and in the constructor (or at any time really), just pass in the object you are wanting to target.
%myBar = new GuiHealthBarHud(){
Player = %myTarget;
}If you had a whole team and you were keeping track of them in a simset you could display your entire team with something like this...
for(%x = 0; %x < MyTeamSimSet.getCount(); %x++){
%myBar = new GuiHealthBarHud(){
player = MyTeamSimSet.getObject(%x);
}
DoSomethingWithIt(%myBar);
}Ok I hope that explains this sufficiently, it's a really cool little mod that I hope you will have lots of fun with.
If you own the MMOKit, this code is in SVN and will be put into the next Patch, which will likely occur before this resource gets approved :)
Regards,
Dreamer
#2
to
07/25/2007 (1:39 pm)
to allow the healthbar to display the health of any object not just playerobject time (example other buildings and vehicles) change the code (all in onRender method)if (!mPlayer || !(mPlayer->getType() & PlayerObjectType))
return;to
if (!mPlayer)
return;
#3
01/22/2008 (8:23 am)
What I looking for :)
#4
10/09/2009 (9:51 pm)
i like the pulsing healthbar, good stuff, thanks... 
Torque 3D Owner Kevin Rogers