(fixed) Combat balance
Moderator: Sophia
Forum rules
Please read the Forum rules and policies before posting.
Please read the Forum rules and policies before posting.
(fixed) Combat balance
After a lot of fighting (at low level) I must say that something bother me :
A lot (really a lot) of attacks (whatever the method) miss at low level.
I don't mind them being very low damage, but fighting for ten minutes and dealing zero damage 9 times in 10 is really boring. It's the same for warcry and others "misc" attack. I would prefer higher idle time and higher chances of dealing at least minor damage / short timed fear effect.
I would slightly improve the chance of dealing 1 or 2 damage for every methods. That would be more balanced, since early on, throwing all the inventory in the face of monster seems to be much more efficient than just fighting with weapons or bare hands. And killing a monster by throwing a shirt is just stupid (most clothes should deal no damage at all).
To even this fact, I would also increase the chance of monster to deal a very low damage.
For now, it seems they are also often failing their attacks, and when they succeed, it's generally a major blow...
A lot (really a lot) of attacks (whatever the method) miss at low level.
I don't mind them being very low damage, but fighting for ten minutes and dealing zero damage 9 times in 10 is really boring. It's the same for warcry and others "misc" attack. I would prefer higher idle time and higher chances of dealing at least minor damage / short timed fear effect.
I would slightly improve the chance of dealing 1 or 2 damage for every methods. That would be more balanced, since early on, throwing all the inventory in the face of monster seems to be much more efficient than just fighting with weapons or bare hands. And killing a monster by throwing a shirt is just stupid (most clothes should deal no damage at all).
To even this fact, I would also increase the chance of monster to deal a very low damage.
For now, it seems they are also often failing their attacks, and when they succeed, it's generally a major blow...
What Is Your Quest ?
- Sophia
- Concise and Honest
- Posts: 4240
- Joined: Thu Sep 12, 2002 9:50 pm
- Location: Nowhere in particular
- Contact:
Hmm, this could be one of two issues:
A cursory examination of the CSBwin code doesn't reveal any huge discrepancies between DSB's algorithm and the one used there, but I'm sure I don't fully understand what's going on.
- You have an issue with the DM mechanics. In this case, we can talk about making small changes (especially ones that seem to be what the designers intended, but just didn't do due to program bugs or technical limitations)-- but I'm not sure if I want to change things too drastically.
- I made a mistake in porting the DM mechanics to DSB. In this case, it's more clear-cut, and I can correct my mistake.
A cursory examination of the CSBwin code doesn't reveal any huge discrepancies between DSB's algorithm and the one used there, but I'm sure I don't fully understand what's going on.
Maybe that's just an impression I had because of reincarnated character.
I have to check but I thought the first levels where quite faster to obtain...
I still think the whole combat doesn't give enough result at low level, even if it is not a bug. So I would go for solution one among your two answers.
I have to check but I thought the first levels where quite faster to obtain...
I still think the whole combat doesn't give enough result at low level, even if it is not a bug. So I would go for solution one among your two answers.
What Is Your Quest ?
- Paul Stevens
- CSBwin Guru
- Posts: 4318
- Joined: Sun Apr 08, 2001 6:00 pm
- Location: Madison, Wisconsin, USA
Using CSBwin as a benchmark for party
attacks and party level progression may
not be too wise.
When I first translated the Atari code
to create CSBwin I made quite extensive
use of the Atari emulator. I forget which
one it was but the source code was available
and I could run the emulator using the
Visual C++ debugger and thereby step through
the Atari code. It could have been WinSTon
I modified the emulator to write 'event' files.
Then I modified CSBwin to write 'event' files.
Then I ran the two programs and compared
the 'event' files. If they were different in any
way I fixed CSBwin and tried again. But
things like combat were difficult to test.
So I am afraid that combat did not get tested
as well as (for example) monster actions and
monster attacks.....which required no mouse or
keyboard input. I simply stood still and
got myself killed.
So...It may be that I did not get party attacks
as wll tested as I would have liked.
Here is what I suggest. If you can get a hold
of an emulator and, as far as possible, recreate
the same conditions as a game using CSBwin and
you can demonstrate that there is quite a large
difference in the way they work, then I am 100%
willing to go back and see what might be causing
such differences.
attacks and party level progression may
not be too wise.
When I first translated the Atari code
to create CSBwin I made quite extensive
use of the Atari emulator. I forget which
one it was but the source code was available
and I could run the emulator using the
Visual C++ debugger and thereby step through
the Atari code. It could have been WinSTon
I modified the emulator to write 'event' files.
Then I modified CSBwin to write 'event' files.
Then I ran the two programs and compared
the 'event' files. If they were different in any
way I fixed CSBwin and tried again. But
things like combat were difficult to test.
So I am afraid that combat did not get tested
as well as (for example) monster actions and
monster attacks.....which required no mouse or
keyboard input. I simply stood still and
got myself killed.
So...It may be that I did not get party attacks
as wll tested as I would have liked.
Here is what I suggest. If you can get a hold
of an emulator and, as far as possible, recreate
the same conditions as a game using CSBwin and
you can demonstrate that there is quite a large
difference in the way they work, then I am 100%
willing to go back and see what might be causing
such differences.
Just out of interest, what were you trying to attack with the low level characters?
If it was something well armoured, instead of default screamers and mummies of DM, then you might find the misses are due to that intead. And do you gain less experience for ineffective attacks? So it could be the low level model is right aslong as you are attacking low level monsters
If it was something well armoured, instead of default screamers and mummies of DM, then you might find the misses are due to that intead. And do you gain less experience for ineffective attacks? So it could be the low level model is right aslong as you are attacking low level monsters
I used Stamm reincarnated.
Basic enemies like : mummy, screamers, rockpiles, trollins.
I kill them with a few thrown objects (except rockpiles), while in close combat
(even with the axe)
I deal low damage (less than 10) and only once every 10 or 15 attacks at most !
I played PC DM to see for my self, and it goes the other way : reincarnated stamm deals as much as 30 damage once every two or three attacks.
All that with no fighter level.
Basic enemies like : mummy, screamers, rockpiles, trollins.
I kill them with a few thrown objects (except rockpiles), while in close combat
(even with the axe)
I deal low damage (less than 10) and only once every 10 or 15 attacks at most !
I played PC DM to see for my self, and it goes the other way : reincarnated stamm deals as much as 30 damage once every two or three attacks.
All that with no fighter level.
What Is Your Quest ?
Yes, and punching was not efficient either.
I could kill the first monsters only because of the collision damage... so I just threw a lot of things.
Usually, one or two hits with a thrown axe are enough, but again it's not logical since chopping with an axe should do more damage than throwing it !
It makes the first wasp at level 3 quite deadly !
PaulS: Actually, as far as Conflux is concerned, the party attack balance in CSBWin is ok. I would have to test with original DM in order to get a fair comparison though.
But I think that for something as contrived as the party attack mechanics in DM, the best is to go for a simple (as much as possible), balanced solution.
I'll come up with some ideas on how damage should be dealt with.
(next post...)
I could kill the first monsters only because of the collision damage... so I just threw a lot of things.
Usually, one or two hits with a thrown axe are enough, but again it's not logical since chopping with an axe should do more damage than throwing it !
It makes the first wasp at level 3 quite deadly !
PaulS: Actually, as far as Conflux is concerned, the party attack balance in CSBWin is ok. I would have to test with original DM in order to get a fair comparison though.
But I think that for something as contrived as the party attack mechanics in DM, the best is to go for a simple (as much as possible), balanced solution.
I'll come up with some ideas on how damage should be dealt with.
(next post...)
What Is Your Quest ?
- Paul Stevens
- CSBwin Guru
- Posts: 4318
- Joined: Sun Apr 08, 2001 6:00 pm
- Location: Madison, Wisconsin, USA
So, what I saw, opening the methods.lua is that :
- failure gives a binary result, so it's almost always 0 or full damage.
- the way success is computed (with luck, quickness, etc.) looks very contrived.
- damage is also a complex result (not to say contrived calculus)
I didn't detail everything :
First remark : In DM, the luck stat is not static.
It increase at every failure and decrease at every succes, with boundaries.
It was done because the Atari ST / Amiga had no complex number generator and no way to get complex mathematical function for probability.
I have no problem with that BUT, what I would do is a less binary and contrived way of taking the luck result, that is :
- failure gives a binary result, so it's almost always 0 or full damage.
- the way success is computed (with luck, quickness, etc.) looks very contrived.
- damage is also a complex result (not to say contrived calculus)
I didn't detail everything :
Code: Select all
HIT IF :
character_quickness - monster_quickness - random(31) > 0
OR
25 % chance
OR
luck_calculus (complex, dependant on the attack method "chance")
DAMAGE =
method_power/32 * [ weapon_power + random(weapon_power/2) ]
- monster_def (= xp_fact + monster_armor + random(31) )
+ weapon_def_reduce
+ weapon_bonus
if DAMAGE < 2
75 % chance to fail ( ! )
else
...more contrived stuff I won't detail !
It increase at every failure and decrease at every succes, with boundaries.
It was done because the Atari ST / Amiga had no complex number generator and no way to get complex mathematical function for probability.
I have no problem with that BUT, what I would do is a less binary and contrived way of taking the luck result, that is :
Code: Select all
- Luck Result (function of luck stat, monster and character quickness, method luck etc.) between 0 and 100 % = LR
- 5% > LR, critical failure, increasing the idleness time by a given factor.
- 25 % > LR > 5 %, failure, no damage
- 75 % > LR > 25 %, moderate success, damage factored by LR
- 95 % > LR > 75 %, success, full damage
- LR > 95 %, critical success, damage increased by a given factor
Last edited by Joramun on Sat Nov 17, 2007 5:20 pm, edited 1 time in total.
What Is Your Quest ?
- Paul Stevens
- CSBwin Guru
- Posts: 4318
- Joined: Sun Apr 08, 2001 6:00 pm
- Location: Madison, Wisconsin, USA
Sophia:
If it would help, I can step through
a couple of STAMM's Chop attacks and
write down the intermediate results
so that you can do a comparison with
the DSB results. Something probably
got minimized rather than maximized
or ????.
Edit:
I forgot....CSBwin has an 'Attack Trace'.
Here is the trace from my first Screamer
meeting (37 and 47 damage):
If it would help, I can step through
a couple of STAMM's Chop attacks and
write down the intermediate results
so that you can do a comparison with
the DSB results. Something probably
got minimized rather than maximized
or ????.
Edit:
I forgot....CSBwin has an 'Attack Trace'.
Here is the trace from my first Screamer
meeting (37 and 47 damage):
Code: Select all
PAUL attacks from 01(03,0d) to 01(04,0d)
Attack type = 2 = CHOP
Skill number required = 06
Byte20046[attackType=2 ] = 8
staminaCost = Byte20046[attackType=2 ] + Random(1) = 8
experiencedGained = Byte20178[attackType=2 ] = 10
Enter AttackWithPhysicalForce (attackType=2, skillNumber=6)
D6W=Byte20002[attackType=2 ]=48
D7W=Byte19958[attackType=2 ]=48
Calling PhysicalAttack(character, monster, D5W-1, D6W, D7W, skillNumber)
Entering PhysicalAttack(char=0,monster,P4=0,P7=48,P8=48,skillNumber=6)
levelDifficulty = 1
pi26 word2 &0x40 == 0 or vorpalOrDisrupt
Entering function to determine character's Quickness
quickness = (Dexterity=40) + (random(8)=5) --> 45
About to compute Maximum load
Loading effect=(quickness/2)*(load=105)/(maxload=480)-->4
Subtract loading effect from quickness -->41
Low Limit = random(8) + 1 --> 8
High Limit = 100-random(8) --> 97
Final quickness = 20
character's quickenss = 20
required quickness = (pi26.uByte8[4 ]=5) + (random(32)=17) + (levelDifficulty=1) - 16 = 7
Attack was successful because Character's quickness is great enough
D7W = Throwing distance=52
D7W = D7W+random(D7W/2+1) = 77
D7W = D7W*(P8=48)/32 = 115
D4W = (i26->uByte8[0 ]=5) + (levelDifficulty=1) + (random(32)=2) = 8
D7W = D7W + (random(32)=21) - (D4W=8) = 128
D6W = D7W = 128
Divide D7W by 2 --> 64
D0W=random(D7W) --> 28
D7W += (random(4)=0) + (D0W=28) --> 92
D7W += (random(D7W)=41)--> 133
Divide D7W by 4 --> 33
D7W += (random(4)=3) + 1 --> 37
Enter DetermineMastery(hero=PAUL, skill=6)
Extract two flags from skill number.
flag8000 = skill&0x8000 --> 0
flag4000 = skill&0x4000 --> 0
SkillNumber = 6
Mastery = log2(Experience=18) --> 1
Mastery of skill 6 is 1
D0W = ((D7W=37) * (Bits8_11(i26.word16)=0)/16) + 3 --> 3
AdjustSkills((skill=6), (D0W=3))
Decrement Stamina by random(4)+4 = 4
w_2 = DamageMonster() --> 37
PhysicalAttack returning D7W = 37
Word20264 = Result of calling PhysicalAttack = 37
Return 1
PAUL attacks from 01(03,0d) to 01(04,0d)
Attack type = 2 = CHOP
Skill number required = 06
Byte20046[attackType=2 ] = 8
staminaCost = Byte20046[attackType=2 ] + Random(1) = 8
experiencedGained = Byte20178[attackType=2 ] = 10
Enter AttackWithPhysicalForce (attackType=2, skillNumber=6)
D6W=Byte20002[attackType=2 ]=48
D7W=Byte19958[attackType=2 ]=48
Calling PhysicalAttack(character, monster, D5W-1, D6W, D7W, skillNumber)
Entering PhysicalAttack(char=0,monster,P4=0,P7=48,P8=48,skillNumber=6)
levelDifficulty = 1
pi26 word2 &0x40 == 0 or vorpalOrDisrupt
Entering function to determine character's Quickness
quickness = (Dexterity=40) + (random(8)=3) --> 43
About to compute Maximum load
Loading effect=(quickness/2)*(load=105)/(maxload=480)-->4
Subtract loading effect from quickness -->39
Low Limit = random(8) + 1 --> 8
High Limit = 100-random(8) --> 95
Final quickness = 19
character's quickenss = 19
required quickness = (pi26.uByte8[4 ]=5) + (random(32)=13) + (levelDifficulty=1) - 16 = 3
Attack was successful because Character's quickness is great enough
D7W = Throwing distance=49
D7W = D7W+random(D7W/2+1) = 71
D7W = D7W*(P8=48)/32 = 106
D4W = (i26->uByte8[0 ]=5) + (levelDifficulty=1) + (random(32)=23) = 29
D7W = D7W + (random(32)=24) - (D4W=29) = 101
D6W = D7W = 101
Divide D7W by 2 --> 50
D0W=random(D7W) --> 43
D7W += (random(4)=3) + (D0W=43) --> 96
D7W += (random(D7W)=84)--> 180
Divide D7W by 4 --> 45
D7W += (random(4)=1) + 1 --> 47
Enter DetermineMastery(hero=PAUL, skill=6)
Extract two flags from skill number.
flag8000 = skill&0x8000 --> 0
flag4000 = skill&0x4000 --> 0
SkillNumber = 6
Mastery = log2(Experience=25) --> 1
Mastery of skill 6 is 1
D0W = ((D7W=47) * (Bits8_11(i26.word16)=0)/16) + 3 --> 3
AdjustSkills((skill=6), (D0W=3))
Decrement Stamina by random(4)+4 = 7
w_2 = DamageMonster() --> 47
PhysicalAttack returning D7W = 47
Word20264 = Result of calling PhysicalAttack = 47
Return 1
I found something peculiar in the "have_luck" function :
I changed it to the more reasonable :
Which gives better results... once in a while.
Code: Select all
if got_luck < 10 then got_luck = 0 end
Code: Select all
if got_luck < 10 then got_luck = 10 end
What Is Your Quest ?
That's not suprising, since Luck is internally ten times the "real world" value, so all you did was change it from "if luck is less than 1, make it 0" to "if luck is less than 1, make it 1".Which gives better results... once in a while
*Edit* --Actually, I take that back, I was reading it wrong (and discovered what Sophia points out below, that luck is being multiplied by 10 twice).
With Paul's breakdown, I can point out a couple of discrepencies about required_quickness - DSB sets it too high (I don't know whether this is made up for by DSB's other "if-then's to success" though).
CSBwin
Code: Select all
required quickness = (pi26.uByte8[4 ]=5) + (random(32)=17) + (levelDifficulty=1) - 16 = 7
Code: Select all
local req_quickness = monster_arch.quickness + dsb_rand(0, 31)
Also, DSB's calc_quickness is off:
DSB (utils.lua::313: (calc_quickness))
Code: Select all
q = q - (loadval / dsb_get_maxload(who))
Code: Select all
(quickness) = (quickness) - Loading effect=(quickness/2)*(load=105)/(maxload=480)
I'm looking into the damage calculations now...
Last edited by Remy on Sat Nov 17, 2007 9:13 pm, edited 2 times in total.
- Sophia
- Concise and Honest
- Posts: 4240
- Joined: Thu Sep 12, 2002 9:50 pm
- Location: Nowhere in particular
- Contact:
After some playing around, I found two problems and started getting a lot better hit rates and damage.
- The "damage" value of the weapon (uByte2) was never actually entered into objects.lua. The formulas made reference to it (base_tpower) but the small values that were in place made it seem more like tweaks than a value important to the calculation-- or something. I actually don't totally remember what I was doing. But, I've fixed this, and the power went up immediately.
- A successful hit accidentally set your luck to an obscenely high value. This would help you, except, sys_update knocks your luck way down if it goes over the max (to simulate the capriciousness of luck)-- in normal play, this would happen rarely. In this case, it was happening every single time you scored a hit, resulting in bad luck rolls all the time. After doing this, the hit rate went up.
Now calc_tpower (the DSB version of CSBwin's DetermineThrowingDistance) will return much higher power levels. I'll need to rebalance object throwing and shooting to compensate-- I kind of winged thrown object damage because it was so paltry in DM-- but things are looking a lot better now.
EDIT:
Ok, thanks, Remy.
Two more changes:
After the "local req_quickness" stuff, I've added:
The first three lines of calc_quickness are now:
- The "damage" value of the weapon (uByte2) was never actually entered into objects.lua. The formulas made reference to it (base_tpower) but the small values that were in place made it seem more like tweaks than a value important to the calculation-- or something. I actually don't totally remember what I was doing. But, I've fixed this, and the power went up immediately.
- A successful hit accidentally set your luck to an obscenely high value. This would help you, except, sys_update knocks your luck way down if it goes over the max (to simulate the capriciousness of luck)-- in normal play, this would happen rarely. In this case, it was happening every single time you scored a hit, resulting in bad luck rolls all the time. After doing this, the hit rate went up.
Now calc_tpower (the DSB version of CSBwin's DetermineThrowingDistance) will return much higher power levels. I'll need to rebalance object throwing and shooting to compensate-- I kind of winged thrown object damage because it was so paltry in DM-- but things are looking a lot better now.
EDIT:
Ok, thanks, Remy.
Two more changes:
After the "local req_quickness" stuff, I've added:
Code: Select all
local req_quickness = monster_arch.quickness + dsb_rand(0, 31)
req_quickness = req_quickness + difficulty - 16
Code: Select all
local q = (dsb_get_stat(who, STAT_DEX) + dsb_rand(0,70)) / 10
local loadval = ((q/2) * dsb_get_load(who)) / dsb_get_maxload(who)
q = q - loadval