Game Development Community

Scripted Experience and Attribute (stats) system

by Will Brown · 06/07/2007 (11:12 am) · 37 comments

Greetings community,

I would first like to say that this community is awesome, and I have learned more here in the last two months than I did working with the Unreal Engine for about a year. I think that it is wonderful that there are so many talented people here that are willing to share what they know and have learned with the rest of the community.

When Nick and I were working on programming with TGE for the RPG we are working on we had noticed that there were TONS of wonderful resources available in the community, but we haven't found any functional systems for experience points or attributes. Although there are definitely some that touch up on these subjects.

The functionality in this resource was created by Nick Helton and Will Brown.

Without further ado...

So we want to have an experience system in our game. Wait a minute, what about attributes for the player? We need to have those too to make it believable right?

Do not worry, this will walk you through the entire process.

First we will do the initializing of the variables for the player in the game.cs class.

in "~\server\game.cs"
...
function GameConnection::createPlayer(%this, %spawnPoint)
{
   if (%this.player > 0)  {
      // The client should not have a player currently
      // assigned.  Assigning a new one could result in 
      // a player ghost.
      error( "Attempting to create an angus ghost!" );
   }

   // Create the player object
   %player = new Player() {
      dataBlock = PlayerBody;
      client = %this;
   
      [b]// HERE IS WHERE WE WILL BE GIVING OUR PLAYER SOME EXTRA STATS
      experience = 0;
      level = 0;

      //base attributes
      STR = 10;
      STA = 10;	
      AGI = 10;
      INT = 10;
      SPR = 10;

      //extended attributes
      HP = 0; 		// player's amount of life
      maxHP = 0; 	// player HP when fully healed
      MP = 0; 		// player's amount of mana
      maxMP = 0; 	// player's MP when fully replenished[/b]
   };
   MissionCleanup.add(%player);

   // Player setup...
   %player.setTransform(%spawnPoint);
   %player.setShapeName(%this.name);
   
   // Starting equipment
   %player.setInventory(Crossbow,1);
   %player.setInventory(CrossbowAmmo,10);
   %player.mountImage(CrossbowImage,0);

   // Update the camera to start with the player
   %this.camera.setTransform(%player.getEyeTransform());

   // Give the client control of the player
   %this.player = %player;
   %this.setControlObject(%player);
}

This code will set our player up to have 5 attributes or stats.

Strength is STR
Stamina is STA
Agility is AGI
Intellect is INT
Spirit is SPR

You can alter these to whatever will work best with the game you are creating. You will also notice some variables for tracking current and maximum HP and MP. We are using these for calculations that we will make later for increasing the maximum health and magic on the fly.

Now we need the bulkier bits of this resource. Time to delve into the player class.

in "~\server\player.cs"
...
//----------------------------------------------------------------------------

function Player::playDeathAnimation(%this)
{
   if (%this.deathIdx++ > 11)
      %this.deathIdx = 1;
   %this.setActionThread("Death" @ %this.deathIdx);
}

function Player::playCelAnimation(%this,%anim)
{
   if (%this.getState() !$= "Dead")
      %this.setActionThread("cel"@%anim);
}


//----------------------------------------------------------------------------

[b]//***************************************************************************

// added function to award experience to the player
function Player::awardExp(%this, %cl, %amount)
{
   %this.experience += %amount;

   //we got some points lets see if we gained a level
   %nextLevel = %this.level + 1;

   //This formula can be changed to your liking
   if(%this.experience >= %nextLevel * %nextLevel * 100)
   {
      commandToServer('awardLevel', %cl);
      commandToServer('updateAttributes', %cl);
   }
   else
   {
      // no level but xp points are good and we'll let you know it
      DisplayScreenMessage(%cl, "You got" SPC %amount SPC "xp.");
      echo("You got" SPC %amount SPC "XP!");
   }
  
}

function Player::awardLevel(%this, %cl)
{

   %this.level++;

   //these attributes always go up 2
   %this.STR += 2;
   %this.STA += 2;
   %this.AGI += 2;
   %this.INT += 2;
   %this.SPR += 2;

   DisplayScreenMessage(%cl, "You gained a level!" NL "You are now level: "@%this.level);
   echo("You gained a level!");
   echo("You are now level: "@%this.level);
}

function Player::updateAttributes(%this, %cl)
{
   // here we are updating all the stats the player
   // for example making sure that player maxHP = STA * 10
   // this will most likely be called at spawn and when gaining a level
   %this.maxHP = %this.STA * 10;
   %this.maxMP = %this.INT * 10;

   //you gained a level, have full health and mana!
   %this.HP = %this.maxHP;
   %this.MP = %this.maxMP;
}

// we should eventually put these somewhere else but this works for now
function serverCmdawardExp(%client, %amount)
{
   %client.player.awardExp(%client, %amount);
}

function serverCmdupdateAttributes(%client)
{
   %client.player.updateAttributes(%client);
}

function serverCmdawardLevel(%client)
{
   %client.player.awardLevel(%client);
}

//****************************************************************************************************
[/b]
function Player::playDeathCry( %this )
{
   %this.playAudio(0,DeathCrySound);
}
...

That will cover everything as far as setting up the commands and functions to level up and make the stats alter the player in some way, shape or form. Next we will do what we need to for the enemies. Please note that this was created with the AIGUARD resource in mind. We are using this resource as our base class for our enemies, and have decided to incorporate the bit about when the enemy dies into this class.

To do things as follows please go to www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=6773 and install it. You won't regret it.

You back already? wow that was quick, Ok, now to continue. Let's go into the aiguard.cs class and alter one simple function to award the experience.

In "~\server\scripts\aiguard.cs"
[b]// At the top with the other global variables..
$AI_GUARD_XP_PER_KILL = 50;[/b]
...
function GuardPlayer::OnDamage(%this, %obj, %delta)
{
   		
	if(%delta < 0) //we are repairing, DON'T get stuck in a "defending" loop
		return;
		
      if (obj.action !$="GetHealth")
   	{
   			%obj.action = "Defending";
   	}
   	
   	[b]if(%obj.getstate() $="Dead") 
   	{
         %obj.action="Dead";
            //************************************************************************************************************
         //you killed that guy, have some experience points
         %client = ClientGroup.getObject(0);
         echo("We killed the mob, /joy");
         commandToServer('awardExp', $AI_GUARD_XP_PER_KILL);
   	}[/b]
   		
   	if(%obj.getState() $= "Dead" && %obj.respawn == true)
      {
         %obj.delaybeforerespawn(%obj.botname, %obj.marker);
         %this.player=0;
      }
}
...

*Edit* I added a variable initialization for the global used for determining the experience gained per kill. The changes are indicated in bold

That one was simple wasn't it?

That should be all you need for the back end of this stuff running, but now how do we know that it is working? We can visually see it happening much better if we have some sort of GUI to go by. Ok, let's create it.

This is the bonus portion with the statsGui.gui file. This one won't require too many changes. First let's go to the new file that you will be working with, of which, I will provide an example. Please also note that this example was highly inspired by the Inventory Gui resource.

Copy the following into a new .gui file and save it as statsGui.gui

"~\client\ui\statsGui.gui"
//--- OBJECT WRITE BEGIN ---
new GuiControl(StatsGUI) {
   profile = "GuiDefaultProfile";
   horizSizing = "right";
   vertSizing = "bottom";
   position = "0 0";
   extent = "640 480";
   minExtent = "8 2";
   visible = "1";

   new GuiWindowCtrl(StatsWindow) {
      profile = "GuiWindowProfile";
      horizSizing = "right";
      vertSizing = "bottom";
      position = "2 -2";
      extent = "621 476";
      minExtent = "8 2";
      visible = "1";
      text = "Stats";
      maxLength = "255";
      resizeWidth = "1";
      resizeHeight = "1";
      canMove = "1";
      canClose = "1";
      canMinimize = "1";
      canMaximize = "1";
      minSize = "50 50";
      CloseCommand = "Canvas.PopDialog(StatsGUI);";
     
    [b]new GuiObjectView(StatsItemView) {
	profile = "GuiDefaultProfile";
	horizSizing = "relative";
	vertSizing = "relative";
	position = "0 0";
	extent = "400 400";
	minExtent = "8 2";
	visible = "1";
	helpTag = "0";
	cameraZRot = "0";
	forceFOV = "0";
      };[/b]
      new GuiScrollCtrl() {
         profile = "GuiScrollProfile";
         horizSizing = "right";
         vertSizing = "bottom";
         position = "410 30";
         extent = "200 400";
         minExtent = "8 2";
         visible = "1";
         willFirstRespond = "1";
         hScrollBar = "alwaysOn";
         vScrollBar = "alwaysOn";
         constantThumbHeight = "0";
         childMargin = "0 0";

         new GuiTextListCtrl(StatsListView) {
            profile = "GuiTextArrayProfile";
            horizSizing = "right";
            vertSizing = "bottom";
            position = "2 2";
            extent = "178 2";
            minExtent = "8 2";
            visible = "1";
            enumerate = "0";
            resizeCell = "1";
            columns = "0";
            fitParentWidth = "1";
            clipColumnText = "0";
         };
      };
   };
};
//--- OBJECT WRITE END ---

function toggleStatsGUI(%val)
{
	if(%val)
      StatsGUI.toggle();
}

function StatsGUI::OnWake(%this)
{
	UpdateStatsListView();
}

//This function updates the StatsListView
function UpdateStatsListView()
{
	StatsListView.clear();	

	echo("Updating the players Stats...");
	
	%client = ClientGroup.getObject(0);
	
	//Health and Mana
	StatsListView.addRow(0,"Health:" SPC %client.player.maxHP);
	StatsListView.addRow(1,"Mana :" SPC %client.player.maxMP);

	//Experience and level
	StatsListView.addRow(2,"Experience:" SPC %client.player.experience);
	StatsListView.addRow(3,"Level :" SPC %client.player.level);
	
	//Attributes
	StatsListView.addRow(4,"STR :" SPC %client.player.STR);
	StatsListView.addRow(5,"STA :" SPC %client.player.STA);
	StatsListView.addRow(6,"AGI :" SPC %client.player.AGI);
	StatsListView.addRow(7,"INT :" SPC %client.player.INT);
	StatsListView.addRow(8,"SPR :" SPC %client.player.SPR);
	
	StatsListView.setSelectedRow(0);
	StatsListView.scrollVisible(0);
}

function StatsGUI::toggle(%this)
{
    if (%this.isAwake())
      Canvas.popDialog(%this);
    else
      Canvas.pushDialog(%this);
}

[b]function StatsListView::OnSelect( %this, %id, %text )
{
	%client = ClientGroup.getObject(0);
   
	StatsItemView.setEmpty();
        //Change the location of this dts to whatever you are using
	StatsItemView.setObject("player","starter.fps/data/shapes/player/player.dts","", 0);
}[/b]

[Edit]
If you have the guiObjectView.cc and guiObjectView.h files as part of your codebase please disregard this portion.

Please note that the items in bold above do not need to be implemented. If you want to pull this off with only scripting this will help you ascertain such a thing. If you don't have guiObjectView, or are trying to do this via scripting only, simply leave out the items that are marked in bold

If you would like to have the avatar, please go here and implement the guiObjectView files:
www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=4063

After including them in your codebase, and re-compiling, linking and building the game engine, you should be good to go.

[/Edit]

Now that we have the GUI created, we need to set it up so that we can view the stats of this player at our choosing. To do this, we need to make some new commands to view it.

Add the following to your "~\client\scripts\default.bind.cs"
...
//Allows us to view our stats
moveMap.bind(keyboard,  c,          toggleStatsGUI);
...

Please also be sure to exec() this newly created GUI class wherever your other classes are being executed.

in "~\client\init.cs"
...
   //Character Stat/Exp sheet
   exec("./ui/statsGui.gui");
...

That should do it, you should now have attributes or stats, experience points, and a level. You should also be able to hit the 'c' key to view your stats at any time.

This can definitely be expanded on, and we plan on eventually taking things to the C++ engine route as we progress forward. We both had agreed that this is a wonderful starting point and wanted to share it with the rest of the community.

[edit]
Oh yes, don't forget to also map it in your optionsDlg.cs class.

In "~\client\scripts\optionsDlg.cs"
...
$RemapName[$RemapCount] = "Toggle Stats Dialog";
$RemapCmd[$RemapCount] = "toggleStatsGUI";
$RemapCount++;
...

Add this with the rest of the Interface Keys here and you should be good to go.

About the author

Recent Blogs

Page «Previous 1 2
#1
06/06/2007 (8:20 pm)
I hope you all find this useful. If there is anything that you would like to see changed in it just let me know and I will do what I can.

Thanks,
Will
#2
06/07/2007 (2:41 pm)
Looks good.
#3
06/08/2007 (5:56 am)
Nice demonstration of script capability and flexibility =). Useful and instructional, good work!

#4
06/11/2007 (11:06 am)
Looks fantastic! Thanks for the excellent writeup!
#5
06/12/2007 (3:08 pm)
Couple of notes I'd have on this.

First of all, it's not multi-player compatible. Anywhere you are calling 'ClientGroup.getObject(0)' you are automatically choosing the first client to connect -- usually that's going to be the client that's hosting the server. Also, you are trying to access server-sidse objects, such as ClientGroup, from various client-side methods intertwined with the GUI stuff. That will also cause it to fail when attempting to use it multi-player, I believe.

Finally, during my own implementation of player stats, I found that if I wanted a statistic to affect player movement and physics somehow, such as having stronger characters jump higher, etc...I needed to implement it in C++ and make sure to ghost it to the client. For example, I put the equivalent of strength, agility and 'endurance' in C++ and ghosted them, but left other stats not related to player movement in any way defined in script alone. Implementing them in C++ and ghosting them to the client allowed me to easily refer to the stat in the C++ methods that affect movement.
#6
06/12/2007 (3:36 pm)
Brian does bring forth some interesting points to look at if you decide to use this as a starting base for your game.

First do know that this scripted set up is not multiplayer compatible, it is designed for a single player game set up. As Brian had mentioned we are referring to the client that is hosting the server (in our case the only player). I'm sure that someone could implement these simple examples of the system in such a way that it could be multi-player, but how it is set up currently it would not work.

As a second note, I agree that it would be much easier to have the attributes affect the player's movement speed, physics, and much much more by implementing a system changing the C++ source code. This example was only to guide people to a starting point for a scripted experience and/or attribute system. Eventually we will get our system plugged into our game via C++, and we will submit another resource at that time.

I do appreciate the feedback and suggestions you all have made.
#7
06/13/2007 (12:11 pm)
Nice looking resource, and it looks like a very good basis to do a lot of nice things from.

A few comments, not so much on your coding but in your thinking. Reading over your scripting it's as if you were trying to emulate a similar system to say World of Warcraft. I want to offer this philosophy to you to think about. And maybe not so much for you as for some other people that may want to read this article in trying also to emulate a game system similar to that one's for a multiplayer game.


The key philosophy to Wow and some of the other large MMORPGs is that the entire game is an inventory tracking system. Forget about client/server for a minute and just think about that simple fact. Everything you do, get or receive is an inventory item. Some are kept in your inventory such as you receive a coin, others are handled and dealt with such as you receive information that PlayerA has hit PlayerB for so much damage.

The first case is easy to see the philosophy in, but not so much the second. But in the second case you are receiving the information to update your clients current inventory of what it says PlayerB has for health, and you take it from his inventory.


I'll use Wow as an example but it applies to the others.

When you learn a new ability it gets added to your spellbook. An item is added to your inventory. If you try to use a spell, your inventory is checked to see if you have it, as well as your mana is high enough (mana itself is an inventoried item that you posess). If you do then you send a message to the server saying "I'm starting such and such spell..." The server can check to see who's nearby or grouped with you that needs to see this information and forwards it out. Everyone receives a message saying "SoandSo begins casting SpellX" And everyone's client starts the appropriate animation. If you interrupt the spell you send a message saying such and the other people around receive one. These types of messages arent stored per se, but it is a matter of you sending and everyone nearby receiving something. In this instance the incoming item is information and not something semi-tangible as xp or loot.

Lets say you finish casting your spell though, your client looks at your stats, and makes a determination of how effective your spell will be and determines how many overall points of damage the spell will do. Then your machine sends the message to the server that shuffles that similar message and damage value to the other clients. This allows for random attack values to be had but keeps everyone in synch because your client picks the random number, and then everyone else just reacts to your number.


This allows the client to handle the load of checking bonuses etc... your character might have, and frees the server up to handle just messages.

Plus these messages could be made very small. Reducing your packet size to and from the server.

(For those thinking deeply, you'll see why having your combat system like this in scripting and not hardcoded could be very bad....)

Like I said, it's a philosophy. But when you simplify it and look at most aspects of the game you'll see that by thinking of everything in terms of adding or taking it away from someone's inventory you'll see how to make your game multi-user and how to free up a load of server time, because all it has to handle is passing messages and not having to do much else. Add to that limiting who receives messages by zone, group or proximity and you have the ability to cut down on your traffic on your server, rather than having to send messages to people who don't need them.

Again, I may be stating the obvious to some, but I hope this information does help someone in terms of thinking about how to manage a large-scale multiplayer game better.
#8
06/18/2007 (10:17 am)
I modified the stats and the GUI a little bit, but when I wanted to modify the text on the GUI, the console says toggleStatsGUI: Unknown Command. Does anyone know how I can fix this, this is a very nice resource by the way.
#9
06/18/2007 (1:03 pm)
@ Barak
I am not sure where to begin helping you, as I'm not sure what you modified.

The problem sounds like it is stemming from the GUI file itself. I will start by explaining how it works a little, to see if it clears anything up. One of the most noticable differences is the use of the SPC command rather than the @ command.

This:
StatsListView.addRow(0,"Health:" [b]SPC[/b] %client.player.maxHP);

is the same thing as:
StatsListView.addRow(0,"Health:" [b]@[/b] %client.player.maxHP);

the basic logic to this is:

ListView.addRow(RowN, TextToDisplay);

Where :
- ListView is the name of the GuiTextListCtrl you will be using for displaying the attributes
- RowN is the number of the row you want to alter (ie: 0,1,2,3,4,...n)
- TextToDisplay is the text that you want to display, here you can display something hardcoded, a variable, or both.

I hope this helps, if it doesn't, try displaying some of your source, and I will see what I can do to walk you through it.

@ Mark
I agree with your philosophy, except I think that everything is nothing more than a record in a database, or a field in an array. Thanks for sharing, as I think your idea's will help many get a strong foot hold on creating a good RPG. The attributes were losely based on WoW, only because I thought that with so many people playing it, it would click better for them. The game that we are working on has a bit more complicated of a system.
#10
06/18/2007 (5:18 pm)
[Edit] I fixed my problem... it was a really stupid problem... In the init, since I use tutorial.base and not starter.fps, I didnt change the path to the GUI, so it didnt load anything up. (I fixed the not finding the function too). Thanks a lot.
#11
06/19/2007 (6:53 am)
It's pretty good all of that but how do he suppose to put particule on hand when player cast magic? It's just cause im doing a rpg N it's been a week i try to find a solution. I mount a shapebaseimage to my player but i can't instantiate the particule some1 can help me?

this is the code :

datablock ShapeBaseImageData(dummy1Img)
{
shapeFile = "~/data/shapes/player/dummy.dts";
offset = "0.1 0.1 -0.9";
mountPoint = 1;
emap = true;

className = "WeaponImage";
};


and on the player creation

// Create the player object

%player = new Player(){
datablock = PlayerShape;
client = %this;
};

MissionCleanup.add(%player);

// Player setup...
%player.setTransform(%spawnPoint);
%player.setShapeName(%this.name);

// Starting equipment
%player.mountImage(dummy0Img,0);
%player.mountImage(dummy1Img,1);

// Update the camera to start with the player
%this.camera.setTransform(%player.getEyeTransform());

// Give the client control of the player
%this.player = %player;
%this.setControlObject(%player);
$player = %player;
}

and here the particule code :

//we create datablock for particules

datablock ParticuleData(Bleu)
{
textureName = "~/data/shapes/particles/spark";
dragCoefficient = 0.0;
windCoefficient = 0.0;
gravityCoefficient = 0.0; // rises slowly
inheritedVelFactor = 55;
lifetimeMS = 5000;
lifetimeVarianceMS = 1000;
useInvAlpha = false;
spinRandomMin = -90.0;
spinRandomMax = 90.0;

colors[0] = "1.000000 0.800000 0.000000 0.800000";
colors[1] = "1.000000 0.700000 0.000000 0.800000";
colors[2] = "1.000000 0.000000 0.000000 0.200000";

sizes[0] = 0.05;
sizes[1] = 0.1;
sizes[2] = 0.05;

times[0] = 0.0;
times[1] = 0.5;
times[2] = 1.0;
};

datablock ParticleEmitterData(BleuEmitter)
{
ejectionPeriodMS = 10;
periodVarianceMS = 10;

ejectionVelocity = 10;
velocityVariance = 3.00;
ejectionOffset = 2.0;

thetaMin = -180.0;
thetaMax = 180.0;
particles = "Bleu";
};

datablock ParticleEmitterNodeData(BleuNode)
{
timeMultiple = 1;
};
#12
06/19/2007 (8:52 am)
@ Fernand

This isn't relevant to this post, and should probably be asked in a forum somewhere, but I will attempt to stear you in the right direction.

If you have the AFX kit try these articles:
www.garagegames.com/mg/forums/result.thread.php?qt=63273
www.garagegames.com/mg/forums/result.thread.php?qt=62907

Also there are many examples of this within the AFX code as it is.

If you are not an AFX kit owner, try the following links:
www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=8621
www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=7584
www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=2955

www.garagegames.com/mg/forums/result.thread.php?qt=21220
www.garagegames.com/mg/forums/result.thread.php?qt=22697
www.garagegames.com/mg/forums/result.thread.php?qt=6395
www.garagegames.com/mg/forums/result.thread.php?qt=22069

All of those links are related to casting spells and placement of emitters. I hope these help you.
#13
06/23/2007 (2:08 pm)
Good job Will
#14
06/25/2007 (11:37 am)
Will,

First of all, welcome to the community. I've seen many posts from you recently, and it looks like you are well ahead of the average newcomer. Thanks for joining!


I've tried this resource, and I'm getting a console error:

Unable to instantiate non-conobject class GuiObjectView

I'm still a Torque beginner, and I have no C++ experience. How can I fix this error?

Thanks!

Tony
#15
06/25/2007 (12:36 pm)
@ Infinitum

Thanks for the compliment. It sounds to me like there is a problem with the creation of the following portion of the "~\client\ui\statsGui.gui" file:

new GuiObjectView(StatsItemView) {
	profile = "GuiDefaultProfile";
	horizSizing = "relative";
	vertSizing = "relative";
	position = "0 0";
	extent = "400 400";
	minExtent = "8 2";
	visible = "1";
	helpTag = "0";
	cameraZRot = "0";
	forceFOV = "0";
      };

I don't have access to TGE while I am at work, but I can dig into this deeper when I get home.

One thing that I would like you to check is to ensure that you have the following line in your "~/client/init.cs" file, as it is needed to properly load up the GUI file:

exec("./ui/StatsGui.gui");

Beyond that, I have found the following link:
www.garagegames.com/mg/forums/result.thread.php?qt=34669
stating that this could be a problem with VC2005 not including the guiObjectView.cc and guiObjectView.h files correctly.

First try doing a clean build with VC2005, or whatever IDE you are using to compile the engine. If this doesn't solve the problem try opening up VC2005 (or IDE of choice) and removing these files from the project, then re-adding them and recompile and build the executable.

[Edit]
you may want to check out this thread also:
www.garagegames.com/mg/forums/result.thread.php?qt=33025
#16
06/26/2007 (9:20 am)
It is exec'ed properly. It compiles into a .dso

I'm trying to rebuild now...

Thanks!
Tony

EDIT: I just did a search of my entire computer, including hidden files, and I don't have GuiObjectView.cc or GuiObjectView.h

Is that possible? I'm using v1.5.2...

EDIT2: OK, I found them in a ZIP file from Spock's Inventory Manager, which I previously installed. The Inventory Manager works, but guiObjectView.cc and .h are NOT in my Torque directory ANYWHERE? How does the Inventory Manager work then?

Anyways, I have the files, I just need to know where to put them before I do another Re-Build. Looks like they need to go in engine/ui, but I don't have engine/ui. I may try engine/gui/utility. Still looking.... Should I change the .mk? If so, how?

Thanks!

Tony
#17
06/26/2007 (1:15 pm)
Thank you all who have responded to this post. We really appreciate the feedback and are glad that we could help some people out. We are still learning as we are doing this and have learned a lot from the community and appreciate the chance to give back.

That being said here's something else to add to this that we have recently done.

You may have noticed that the HP that you gave the player in the game.cs doesn't actually mean anything yet although it will!
The reason is that the damage method is hard-coded in and is using the shapebase's MaxDamage rather than your HP. To fix this first follow this:
http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=9774

this will now allow you to dynamically change the individual players' HP for different types of creatures, leveling up and what not. If you follow that tutorial correctly you should now be able to set the player's maxDamage based on your HP when the player gains a level

In the updateAttributes functions below this
%this.maxHP = %this.STA * 10;

add this:

%this.setMaxDamage(maxHP);

if anyone is interested in adding a getMaxDamage console function I have already done this and would be willing to share that as well which will allow you to update the player's HP variable in the client when viewing the character sheet

Hope that helps
#18
06/26/2007 (1:34 pm)
@ Infinitum

Add the guiObjectView.cc and guiObjectView.h to the "~/engine/gui" directory.

I.E.:
"~/engine/gui/guiObjectView.cc"
"~/engine/gui/guiObjectView.h"

You also need to add these to your Visual Studio project, and then recompile. After doing this you should be able to view the GUI.

If you (or anyone else) doesn't have these files, please go here:
www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=4063
or somewhere else and install them. These files are required for the GUI to work correctly.

@ Nick

Thanks for posting this, as it really does help to expand the resource some more. When I get a few, I will go back and update the original to include these changes.

Oh yes, Nick, if you want to post a bit of code put it in [ code ] //source code here [ /code ] tags (without the spaces).
The same thing applies for URL's: [ url ] www.url.com [ /url ]
#19
06/26/2007 (2:39 pm)
OK, I've added the files to engine/gui/utilities and added them to my project and I'm rebuilding now.

I have two different guiObjectView.cc and .h files. I used the larger of the two, since they seem to be newer. Does it matter which version of guiObjectView.cc/.h I use?

The rebuild failed saying "cannot find gui/guiCanvas.h", so I went looking, and guiCanvas.h is in the gui/core folder, so I moved both guiObjectView files into that folder, and I'm rebuilding again. I'll let you know tomorrow if it works.

More to come...

Tony
#20
06/26/2007 (3:04 pm)
Quote:I.E.:
"~/engine/gui/guiObjectView.cc"
"~/engine/gui/guiObjectView.h"

Tony, they should go here.

[Edit]
Many times when you get a file that is a bit older, or even newer sometimes, you have to change the location of it's '#include'

A part of this is that things get moved around with diferent builds, and another part is that some people set up their Visual Studio folders differently.
Page «Previous 1 2