Game Development Community

Developing a Battle System (discussion)

by Infinitum3D · in Torque Game Engine · 05/06/2009 (9:45 am) · 67 replies

I have TGE 1.5.2

The way I see it, there are three types of battles;
1. melee
2. ranged
3. magic

Torque has a basic 'ranged' battle system in effect.

I'm looking at player.cs and crossbow.cs first.

player.cs has datablock PlayerData(PlayerBody)
with the definition "maxDamage = 100;" which is commonly referred to as 'hit points'.

further down;
function Armor::onImpact applies damage %obj.damage()

and function Armor::damage applies damage
%obj.applyDamage(%damage);

and function Armor::onDamage does 3 things:
1.checks to see if player is dead
2.'flashes' the screen to show damage being done
3. plays an audio (pain) file

There are also the onEnterLiquid damage switch for Lava and finally the function Player::kill which looks like it assigns 10000 points damage to the player.


Crossbow.cs uses datablock ProjectileData(CrossbowProjectile)
which has the definitions
directDamage=20;
radiusDamage=20;

and further down
function CrossbowProjectile::onCollision()
which applies damage to ShapeBaseObjectTypes

So, what is my question?

Obviously this all applies to a 'ranged' battle system.

Would anyone care to comment on how they've adapted this to fit their game?

Are modifiers added through script, or are engine changes used? For example, if I wanted a more powerful (or less powerful) crossbow projectile, I could simple increase (or decrease) tthe directDamage variable.

But what I'm looking for is a discussion on various ways to modify this inherent battle system in TGE.

I know a 'melee' system resource exists (I've already added it), but for now, maybe we can just discuss 'ranged' modifications?

Any comments?

Tony
Page «Previous 1 2 3 4 Last »
#1
05/06/2009 (11:05 am)
In the case i understood you:

You are thinking about a system to apply a damage-value to a object caused by another object. Right?
Currently i am thinking about the same "problem" like you.

Quote:
Are modifiers added through script, or are engine changes used? For example, if I wanted a more powerful (or less powerful) crossbow projectile, I could simple increase (or decrease) tthe directDamage variable.

As far as i know you can not modify a value of a datablock. They are static.

Example: You have five different types of weapons and one type of AIBot. Each of these five weapons has a different damage-value for AIBots.

%projectile = new Projectile()
{
   datablock = something;
   damage = %currentWeapon.getDamage(); // your own method
   // and so on...
};

function AProjectileDatablock::onCollision(%this,%obj,%col,%fade,%pos,%normal)
{
   if (%col.getClassName $= "AIBotClass") // something like this
   {
      %col.setHealth(%col.getHealth()-%obj.getDamageValue());
      // the methods setHealth, getHealth and getDamage are defined by you
   }
}

A smart way would be to create a simple datastructure where previously defined damage-values are stored. I dont like the damage-system of TGE. A own implementation is more elegant.
#2
05/06/2009 (12:38 pm)
"...can not modify a value of a datablock..."

Hmmm... I don't think that's right. Isn't that the whole purpose of a datablock? To assign values so that they *can* be modified?



#3
05/06/2009 (12:45 pm)
Hmm, The whole point of a datablock is to act as a template for creating objects, they are static and only sent from the server to the client once, so cannot be modified as changes on the server would not affect the client.

When you have created an object from a datablock, you can change the values that it has inherited from the datablock, but these only affect a single object.
#4
05/06/2009 (12:46 pm)
Datablocks are like a template with basic values for a object.
They are transferred to all clients before a mission starts to save bandwidth.

Edit: Ups, Matt was faster then me.
#5
05/06/2009 (1:07 pm)
What sort of modifications do you want to talk about? I'm planning, and have already implemented, quite a few changes to the Projectile and ShapeBaseImage classes. Most of them you can find here as resources.

However, I think the most 'battle system'-changing modification I'm planning is locational damage and damage tracking. So locational damage gives you different damage effects for different locations - if your leg's crippled you'll limp, but if your head's crippled, you'll die :P. The system is heavily based on pen/paper RPGs in a few regards.
Damage tracking, on the other hand, will record damage done by clients to other objects. When this other object dies, it 'releases' the damage done to it to the server, which analyses all the data. I plan to use this for achievement tracking purposes, and maybe for performance analysis of players, if it gets that far.

But I really don't understand what you're getting at with the question ;P.
#6
05/06/2009 (1:14 pm)
@Daniel: You have implemented a hit-zone-system? Is it possible to use it with AIPlayer?

Where can i find this resource?
#7
05/06/2009 (1:37 pm)
Heh, not yet. That's just in the planning stages. It will be a resource*, though, and yes, since it's planned to be part of the Player class, it naturally inherits to AIPlayer.

*Though the resource probably won't include all the features I mentioned^, since some of them are parts of other systems, not the damage model. Like limping ties in to the animation system rather than damage.

^That said, I do plan to release most of my stuff as resources at some point.
#8
05/06/2009 (1:39 pm)
Perfect. :-)
#9
05/06/2009 (2:47 pm)
I guess my 'Datablocks' comment was confusing.

What I meant was, the values that are set in the datablock can be pulled into a function, and modified there, correct?

Player speed for example is set in a datablock, but I can use that value in a function, multiply it by two, and make the player move twice as fast by calling that function. I don't directly change the datablock, but I change the value temporarily.

Is that right?

I don't know if anyone knows anything about Visual Basic, but in VB you 'declare' your values, and then use those values in functions. I've always looked at datablocks like that; as Declarations of baseline data.

Am I wrong?

Thanks.
Tony
#10
05/06/2009 (3:02 pm)
If you have the book "The Game Programmers Guide to Torque" look at page 132.

Quote:
Remember that datablocks are SimObjects, and we can access (read) their fields like any other object. However, changing a datablock field after the datablock is created and transmitted to all clients will have no effect on the client copies of the field(s) you have changed.
You may only get useful results from changing datablock fields in a singleplayer game, because both the client and the server are sharing the same datablock. In all other scenarios, you should consider the datablock object to be a read-only object.
#11
05/06/2009 (5:36 pm)
Hard to believe I've been using Torque for 3 years and still don't understand datablocks...

OK, so by default Crossbow.cs does directDamage = 20;

If I wanted a SuperCrossbow that does directDamage = 100; How would I do this? Do I need an entirely separate datablock for SuperCrossbow, or is there a way to pull this value from directDamage = 20; and change it to 100 in script? According to the previous post quoting the book, it's not possible.

Thanks!

Tony
#12
05/06/2009 (11:34 pm)
Yes, ideally you'd create a new weapon datablock. Or, in tis case, you'd just have to make a new projectile type (SuperCrossbowProjectile), since that's where damage is defined. Then get the Crossbow weapon to fire SuperCrossbowProjectiles. If you want to have both normal and super projectiles being fired, then you would need to create a new weapon image. Or, you could add a member to the existing CrossbowImage such as 'firesSuperProjectiles', and check that in onFire to see whether to spawn a normal or super projectile.
#13
05/06/2009 (11:55 pm)
You have two possibilities:

1.
Create the different damage-values as additional dynamic fields in your Projectile ( not your ProjectileData Datablock ).

2.
Create a separate datablock for each type of projectile.

But i think case 2 would be better because now you can define separate explosions, debris, decals and particle effects for each type of projectile.
#14
05/07/2009 (12:11 am)
Topic: "Datablocks are read-only (Multiplayer)"

I thought about it. When you modify a property of a datablock, only one client would be affected (mostly the host itself). But what happens when i use this code?

function clientCmdChangeDatablock(%datablock, %property, %value)
{
   %datablock @ "." @ %property = %value;
}

function ChangeDatablock(%datablock, %property, %value)
{
   %clCount = clientGroup.getCount();
   for (%i=0; %i<%clCount; %i++)
   {
      %clientConn = clientGroup.getObject(%i);
      commandToClient(%clientConn, "ChangeDatablock", %datablock, %property, %value);
   }
}

I am not sure but it could be a possibility.
#15
05/07/2009 (1:38 am)
I think that something like that would work, yes. Not the exact code you've written, but the same principle - you can correct client-side inaccuracies when you update the server.

However, you should *never* have a need to change datablock values, it's against the concept of the whole system. The only time you'd do it would be as a hack, workaround, or if you wanted real-time datablock editing (hey...).
#16
05/07/2009 (1:44 am)
Yes, your are right. I will never do that. It was only a line of thought. Nothing more.

Datablocks exist, because the need of saving bandwidth.
#17
05/07/2009 (1:51 am)
I thought there was also a function to re-send datablocks to the client. It might be possible to copy this functionality to update a specific datablock. Now I'm getting into the realm of real-time editing, being able to change your datablocks on the fly to test things without having to reload the game.
#18
05/07/2009 (2:53 am)
A repeated exec(Scriptfile); after each modifikation should do the trick.
#19
05/07/2009 (5:01 am)
"Create a separate datablock for each type of projectile"

So Datablocks must have an extremely low overhead, because a completed game must have thousands of datablocks.

That also makes programming (or rather, scripting) much easier, because everything is kept separate. But on the other hand, its more confusing, because you have to keep track of all those datablocks.

If I want 10 different crossbow projectile types, its not so bad. But if I want a hundred different types, it gets kinda messy.


OK, here's another question!
This goes back to my original 'battleSystem' concept...

If I want something like a sword to have variable damage based on a player's attributes and skill level:

for example, a level 1 player with a 10 strength and a baseline swordDirectDamage = 10;

compared to a level 2 player with 11 strength and a baseline swordDirectDamage = 10;

Same sword. Player reaches a point in the game where he "levels up" from level one to two, and gains 1 strength point at that time...

The sword would need a dynamic field (?) to keep track of the damage? Since datablocks are static, how does a changing value happen? Where do I keep track of the change?

%swordDirectDamage = (playerLevel x playerStrength x swordDirectDamage) ???

Thanks,
Tony
#20
05/07/2009 (5:36 am)
I would simply give the player only a few dynamic fields.
On the server side you can create a list of global variables. Something like this would be useful:

$swordType1Damage = 10;
$swordType2Damage = 13;
$fireballType1Damage = 30;
$fireballType2Damage = 56;

And each player has a dynamic field called... maybe... skill.

Now, the result damage at onCollision or onFire or onSomething would be...

%attackedEnemy.health -= %thePlayer.skill * $swordType2Damage; 
// assumed $swordType2 ist the current weapon
// the formula is only a example
Page «Previous 1 2 3 4 Last »