Combat Overhaul

So I'm hoping to overhaul my combat system a little and was wondering if anyone wanted to offer some insight. I have SOME ideas but this line of programming is still a little beyond my scope of knowledge (out of range :P ).
Here's the...
Global TurnScript "attacking_player"

if (not game.notarealturn) {
  foreach (o, GetDirectChildren(player.parent)) {
    if (GetBoolean(o, "attacking_player")) {
      if (o.health > 1) {
        if (HasScript(o, "specialattack")) {
          if (RandomChance(5)) {
            do (o, "specialattack")
          }
          else {
            do (o, "attackplayer")
          }
        }
        else {
          do (o, "attackplayer")
        }
      }
    }
  }
}
if (not game.notarealturn) {
  game.turncount = game.turncount + 1
}
game.notarealturn = False

So this is pretty straight forward, it checks to see if the enemy is attacking and if the next player action is using a real turn or not. A real turn would constitute preforming an in-game action, while a non-real turn would be like checking the enemy description or their own description, inventory etc.


This next part is an Object Type --- so all monsters that fall into this type have the attacking_player turn-script. My problem with this particular section is that it causes A LOT of misses. So sometimes combat can drag on and it makes enemies very tough to defeat because the player misses 50% of the time.
Here's the code.

if (this.health > 0) {
  if (player.equipped = null) {
    bonus = - this.defense
    damage = player.strength / 2
  }
  else {
    bonus = player.equipped.damagebonus - this.defense
    if (HasString(player.equipped, "damage")) {
      damage = DiceRoll(player.equipped.damage)
    }
    else {
      damage = player.equipped.damage
    }
  }
  if (RandomChance(player.intelligence + 10)) {
    critical = true
    damage = damage * 2
  }
  else {
    critical = false
  }
  if (RandomChance(15 + 5 * bonus)) {
    if (critical) {
      msg ("<br/><font color\"dedede\">You got a critical hit!</font color><br/>")
    }
    this.health = this.health - damage
    if (this.health > 0) {
      PrintOrRun (this, "attackhit")
      msg ("[" + damage + " damage done, " + this.health + " health remaining]")
    }
    else {
      PrintOrRun (this, "attackkill")
      msg ("[" + damage + " damage done]")
      this.listalias = "<span style=\"color: red;\">" + this.alias + "</span>"
    }
  }
  else {
    PrintOrRun (this, "attackmissed")
  }
}
else {
  msg ("It is already dead!")
}

I'm hoping to set it up so that strength affects the player dice.
if (HasString(player.equipped, "damage")) {
damage = DiceRoll(player.equipped.damage)
}

And that agility affects how often the player is hit in combat.

and intelligence affects critical stike chances and causes double damage; Typical RPG stuff.

and defense reduces damage etc.

I'd also like to keep it as simple as it can be. I think ideally it would be nice if the player hit 80% of the time, and that the enemy also hits 80% of the time (although reduces percentage with player.agility).

Here is the enemies attack script.

bonus = this.damagebonus - player.agility / 2
damage = this.damage - player.defense / 3
if (damage < 1) {
  if (RandomChance(50)) {
    damage = 1
  }
  else {
    damage = 0
  }
}
if (RandomChance(40 + bonus * 5)) {
  msg (this.attackplayerhit)
  player.health = player.health - damage
}
else {
  msg (this.attackplayermissed)
}

Am I just wishing against fate :O !? Basically first, I just need to know if what I want can be done.

Anonynn.


This is still all strange and new to me. I have yet to figure out what Damageatt and Attackatt (damage attribute and attack attribute) connect to in my games/The Pixie's code.

What is this?

    bonus = - this.defense

What are you subtracting?

To hit 80% or so, of the time, you adjust some of the variables/functions...

And question.
Why do you have 2 critical hit functions?

if (RandomChance(player.intelligence + 10)) {
    critical = true
    damage = damage * 2
  }
if (RandomChance(15 + 5 * bonus)) {
    if (critical) {
      msg ("<br/><font color\"dedede\">You got a critical hit!</font color><br/>")
    }

This would, it seems, make it so that 15 percent of 10+ of the time, the critical hit message runs correctly?

The enemy's attack script seems completely fine, though.


The critical hit code looks sensible enough to me. Depends what the range of your intelligence stat is, though; the probability of a critical hit looks quite low, unless stats can be quite large numbers.

If combat has too many misses, I'd think it's just a chance of adjusting the probabilities.
RandomChance(15 + 5 * bonus) seems to be your chance of hitting, if I'm reading that right.
So to have a 50% chance of hitting, your weapon's damagebonus would have to be 7 higher than the enemy's defense.

I think the code is good. If you feel like the player is missing too often, then adjust the 15 and the 5 in that line to different numbers. If the damagebonus of weapons available (assuming player.equipped is their current weapon) at any point is 10-15 points higher than the defense of enemies you'll encounter at that stage in the game, I'd expect that to be fine. If the difference is less, maybe make the hit chance RandomChance(15 + 7 * bonus) or something. Or if damagebonus and defense are likely to be similar numbers at each stage of the game, RandomChance(45 + 5 * bonus) might work better.

I think your code is good; it's just a case of tweaking the numbers, which may take a little experimentation until the length of battles feels right.


you can always research/use other games' mechanics/equations/formulas, either for help/ideas or directly using, if you're having trouble on your own creation of game mechanics (and balancing). It's a lot of trial and error and slowly getting experience/creating-a-system.

I am in the same predicament, as I never tried doing any of this either, never done any D&D table-top/dice-games, so no experience with game mechanics and balancing, as well as hating/not-being-good-at math, lol.


for a critical hit, I just use a 'luck' stat (Integer or Double Attribute: 0 to 100 or 0.0 to 100.0):

(using a Function for example scripting)

// scripting examples:

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

// katana.damage = 50

// player.right_hand = katana
// player.strength = 100
// player.luck = 100

player.damage = (player.right_hand.damage + (player.right_hand.damage * (player.strength / 100))) * critical_function
// player.damage = (50 + (50 * (100/100))) * 2 = (50 + (50 * 1)) * 2 = (50 + 50) * 2 = 100 * 2 = 200

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

// unarmed.damage = 1

// player.right_hand = unarmed
// player.strength = 0
// player.luck = 0

player.damage = (player.right_hand.damage + (player.right_hand.damage * (player.strength / 100))) * critical_function
// player.damage = (1 + (1 * (0/100))) * 1 = (1 + (1 * 0)) * 1 = (1 + 0) * 1 = 1 * 1 = 1

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

// scimitar.damage = 20

// player.right_hand = scimitar
// player.strength = 50
// player.luck = 0

player.damage = (player.right_hand.damage + (player.right_hand.damage * (player.strength / 100))) * critical_function
// player.damage = (20 + (20 * (50/100))) * 1 = (20 + (20 * 1/2)) * 1 = (20 + 10) * 1 = 30 * 1 = 30

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

<function name="critical_function" type="INTEGER_OR_DOUBLE_CHOOSE_ONE">
  if (RandomChance (player.luck)) {
    modifier = 2 // or: 1.5
  } else {
    modifier = 1 // or: 1.0
  }
  return (modifier)
</function>

for example of ideas, take a look at some of TES:Morrowind's mechanics:

ht.tp://en.uesp.net/wiki/Morrowind:Combat (scroll down to find the formulas/equations)

and look up other games as well, such as Diablo series and various other RPGs (computer, NES, SNES, PS1, etc consoles):

ht.tp://www.bigd-online.com/JG/JGFrame.html (jarulf's guide for diablo 1)

ht.tps://diablo2.diablowiki.net/Item_Generation_Tutorial (diablo 2's item-drop generation/selection)


also, you can take a look at my combat system for some ideas, though it's old and the code is bad, but it's got some kinda neat stuff that can help or give ideas for you:

ht.tps://textadventures.co.uk/forum/quest/topic/3348/noobie-hks-help-me-thread#22483
ht.tps://textadventures.co.uk/forum/quest/topic/3348/noobie-hks-help-me-thread#22485 (Pertex' download file of a cleaned up version of my code, not sure if it works/if-is-still-available, though...)
ht.tps://textadventures.co.uk/forum/quest/topic/3348/noobie-hks-help-me-thread#22486 (the key/legend for my code, as I stupidly used abrevs, I've learned never to do that ever again, lol)

ask if you got any questions on anything, or if you need help/explanation of anything as well.


I think there are just about as many ways to do RPG/DnD combat and damage as there are adventure game players...
And everyone of them is "correct" for their game...
I have Ali Baba and the Forty Thieves for my Atari (Had, I remember I saved a game on the master disk and killed it :( )
It had a simple system...
Roll to hit based on Dex (if I remember correctly)
Then damage was Weapon damage*2-target armor
Then it would Beep for every point of damage done, with a comment about how hard the hit was...


What is this?

    bonus = - this.defense

What are you subtracting?
That is bonus of the player attack subtracting from the enemy's defense.

As for the critical hit functions, I'm not sure why there are two. Good question! I removed one.

It's now this. The player certainly misses a lot less (thankfully). I'll see what everyone says about it during the next release and balance it further from there.

if (this.health > 0) {
  if (player.equipped = null) {
    bonus = - this.defense
    damage = player.strength / 2
  }
  else {
    bonus = player.equipped.damagebonus - this.defense
    if (HasString(player.equipped, "damage")) {
      damage = DiceRoll(player.equipped.damage)
    }
    else {
      damage = player.equipped.damage
    }
  }
  if (RandomChance(player.intelligence + 10)) {
    critical = true
    damage = damage * 2
  }
  else {
    critical = false
  }
  if (RandomChance(45 + 5 * bonus)) {
    this.health = this.health - damage
    if (this.health > 0) {
      PrintOrRun (this, "attackhit")
      msg ("[" + damage + " damage done, " + this.health + " health remaining]")
    }
    else {
      PrintOrRun (this, "attackkill")
      msg ("[" + damage + " damage done]")
      this.listalias = "<span style=\"color: red;\">" + this.alias + "</span>"
    }
  }
  else {
    PrintOrRun (this, "attackmissed")
  }
}
else {
  msg ("It is already dead!")
}

Thanks so much! Coming up next after I finish all of Chapter 1 will be the Skill tree I need to add to this thing. xD

Anonynn.


As for the critical hit functions, I'm not sure why there are two. Good question! I removed one.
It's now this. The player certainly misses a lot less (thankfully). 

Ah. That's a relief! One of those rare times I'm right.

bonus = - this.defense

But shouldn't that be....

bonus = player.attack - this.defense

But shouldn't that be....

bonus = player.attack - this.defense

I don't think it has to because this is an object type which is tied to the enemy object. I think it would just be redundant. But I'm not 100% sure.

Anonynn.


Do you want the chance of hitting an enemy to depend on the player's stats?

As it stands, your chance of hitting depends on the weapon's "damagebonus" and the enemy's "defense". If the enemy's defense is 9 higher than the weapon's damagebonus, the attack will always miss; and if the damagebonus is 11 higher then every attack will hit.

In the case that the player is unarmed, their fists (I assume) have a damage bonus of 0, so they will always miss an enemy whose defense is 9 or higher.


just to add to mrangel's post:

usually games force this:

min = 5%
max = 95%

so, you can (5% is low chance of course) always hit and to prevent you from always hitting as well (95% instead of 100%)

and, the minimum damage is forced to be '1', so you can kill stuff...

also, lots of games separate the 'to hit / accuracy' chance from the amount of damage done:

check 'to hit / accuracy ... (usually vs target's 'armor class')', if successful, then determine how much damage is done (usually damage vs target's 'defense/resistance')


all of these things prevents your game from getting stuck... for example... if you hit for no/zero damage but the target/monster can't kill you either, you're stuck in that battle forever... (unless you got an 'escape' choice and it can be successful, again forcing not having a 0% chance), but if you (and/or target/monster) hit for at least 1 damage... eventually... you (or the target/monster) will win the battle...


This topic is now closed. Topics are closed after 60 days of inactivity.

Support

Forums