ID:151983
 
Well, i've been working on a new Project(Bleach, don't rant). I've been playing around with variables and stuff and just started the "combat" system. However, i'm a bit shakey on what the attack equation. I've got a somewhat "solid" one made, but i just feel that it's missing something and i can't figure out what it is.

This is what i currently have:
mob
verb
Combat()
set hidden = 1
for(var/mob/M in get_step(usr,usr.dir))
if(! (M) || !(attackable(M) )) return
// using line breaks so the equation is a little bit easier to read
var/damage=max(0, min(M.health.value,\
usr.str.value * (max (1, usr.tempvars["strbonus"]) + ( (usr.rei.value * max( 1, usr.tempvars["reibonus"]) * usr.strd) /4)\
- ( M.def.value * max(1, usr.tempvars["defbonus"]) + ( (M.rei.value * max( 1, M.tempvars["reibonus"]) * M.reid) /4)))))


strd/reid : I currently have an option to set how much of your reiatsu you want to use towards attacking / defending.

Any Suggestions?
e=mc2
In response to BLACK ST4R
No, E=mc2. But that's irrelevant.

Axerob, I can't tell what's wrong in your equation, because I don't know what's right in it. What results are you expecting, and how are they different from what you get?
1. usr.tempvars["defbonus"]? I think you mean M.tempvars["defbonus"].

2. I think you should add the ability for M to dodge, block and counter-attack.
In response to DivineO'peanut
DivineO'peanut wrote:
No, E=mc2. But that's irrelevant.

Axerob, I can't tell what's wrong in your equation, because I don't know what's right in it. What results are you expecting, and how are they different from what you get?

There really isn't anything *wrong* with my equtaion, it's just that it was missing something.

I've added in some neat little "Basic" skills such as Hand to hand, Blocking, and evading.

mob
verb
Combat()
set hidden = 1
for(var/mob/M in get_step(usr,usr.dir))
if(! (M) || !(attackable(M) )) return
// using line breaks so the equation is a little bit easier to read
var/damage=max(0, min(M.health.value,\
(! (usr.tempvars["weapon"]) ? 0 : usr.Skill("Basic","Hand_To_Hand","power") * (log (2 ** rand (5,10)))) + \
usr.str.value * (max (1, usr.tempvars["strbonus"]) + ( (usr.rei.value * max( 1, usr.tempvars["reibonus"]) * usr.strd) /4)\
- ( M.def.value * max(1, M.tempvars["defbonus"]) + ( (M.rei.value * max( 1, M.tempvars["reibonus"]) * M.reid) /4)))))
if(prob(max (0, min (100, (M.Skill("Basic","Block","power")-usr.Skill("Basic","Block","power")) / rand(1,10)))))
spawn()Damage(M,"Block")
M.Skill_Exp_Add("Basic","Block")
return
if(prob(max (0, min (100, ( M.Skill ("Basic","Evade","power") - usr.Skill ("Basic","Evade","power")) / rand(1,10)))))
spawn()Damage(M,"Evade")
M.Skill_Exp_Add("Basic","Evade")
return
if(! (usr.tempvars["weapon"]))
M.Skill_Exp_Add("Basic","Hand_To_Hand")


I thin i'm going to have an option that if you have the chance to "Block", you could choose to counter.
In response to Axerob
That's not what I meant. I'm asking you what do you need help with? How is your damage formula different from what you had in mind? Are you getting incorrect results? Are they too high? Too low? "Missing something" is too abstract.
In response to Axerob
Axerob wrote:
> mob
> verb
> Combat()
> set hidden = 1
> for(var/mob/M in get_step(usr,usr.dir))
> if(! (M) || !(attackable(M) )) return
> // using line breaks so the equation is a little bit easier to read
> var/damage=max(0, min(M.health.value,\
> (! (usr.tempvars["weapon"]) ? 0 : usr.Skill("Basic","Hand_To_Hand","power") * (log (2 ** rand (5,10)))) + \
> usr.str.value * (max (1, usr.tempvars["strbonus"]) + ( (usr.rei.value * max( 1, usr.tempvars["reibonus"]) * usr.strd) /4)\
> - ( M.def.value * max(1, M.tempvars["defbonus"]) + ( (M.rei.value * max( 1, M.tempvars["reibonus"]) * M.reid) /4)))))
> if(prob(max (0, min (100, (M.Skill("Basic","Block","power")-usr.Skill("Basic","Block","power")) / rand(1,10)))))
> spawn()Damage(M,"Block")
> M.Skill_Exp_Add("Basic","Block")
> return
> if(prob(max (0, min (100, ( M.Skill ("Basic","Evade","power") - usr.Skill ("Basic","Evade","power")) / rand(1,10)))))
> spawn()Damage(M,"Evade")
> M.Skill_Exp_Add("Basic","Evade")
> return
> if(! (usr.tempvars["weapon"]))
> M.Skill_Exp_Add("Basic","Hand_To_Hand")


I'm not going to comment on the nutty damage equation, or the strange prob() tests that follow, but whatever happened to simple if-else logic? I've noticed this type of behavior a lot in the sources to ripped Anime games, so I'm going to assume Anime game programmers either dislike or don't know how to use the else structure? Essentially, this:
// Confusing:
if(x)
blah
return
if(y)
blah
return
blah


// Simple:
if(x)
blah
else if(y)
blah
else
blah


I just thought your verb might be more logical in a fashion such as this:
mob
verb
Combat()
set hidden = 1
for(var/mob/M in get_step(usr, dir))
if(attackable(M))
var/damage = 0 // substitute with the first wtf equation

if(prob(max(0, min(100, (M.Skill("Basic","Block","power")-usr.Skill("Basic","Block","power"))/rand(1,10)))))
spawn Damage(M, "Block")
M.Skill_Exp_Add("Basic", "Blcok")

else if(prob(max(0, min(100, (M.Skill("Basic","Evade","power")-usr.Skill("Basic","Evade","power"))/rand(1,10)))))
spawn Damage(M, "Evade")
M.Skill_Exp_Add("Basic", "Evade")

else if(!usr.tempvars["weapon"])
M.Skill_Exp_Add("Basic", "Hand_To_Hand")


As for the equation missing something, I can't imagine what that would be. It already has everything, and then some.
In response to Kuraudo
I would think a better evasion calculation would be Edefender/(Eattacker+Edefender), that ratio being the chance the defender has to evade. Thus:

if(rand() * (attacker.evade + defender.evade) < defender.evade)
// evade succeeded


The idea behind that would be to keep the combatants more or less matched while always having a rare chance for evasion to succeed against a quick opponent or fail against a slow one.

You can also shift the probability toward or away from the extremes by raising each value to a power. I.e., Ed2/(Ea2+Ed2) would move the formula closer to 0 or 1. Ed0.5/(Ea0.5+Ed0.5) would move it toward 0.5. Raising to the 0.5 power (the same as a square root) changes an advantage of 4:1 to 2:1, or from 9:1 to 3:1; this makes combat more interesting without really eliminating the benefits of better stats.

Lummox JR
In response to Axerob
Suggestions:

1. Evasion: prob( Target's Evasion / ( Attacker's Evasion(or Accuracy) + Target's Evasion) * 100 )

2. Same thing with Block.

3. Try to evade before trying to block.

4. Once you evaded the attack (melee), try to counter-attack.

5. While/After attacking (melee), your evasion rate will be temporarily lowered for a few ticks.
In response to Kuraudo
Kuraudo wrote:
I'm not going to comment on the nutty damage equation, or the strange prob() tests that follow, but whatever happened to simple if-else logic? I've noticed this type of behavior a lot in the sources to ripped Anime games, so I'm going to assume Anime game programmers either dislike or don't know how to use the else structure? Essentially, this:
// Confusing:
> if(x)
> blah
> return
> if(y)
> blah
> return
> blah
>
>
> // Simple:
> if(x)
> blah
> else if(y)
> blah
> else
> blah


I am more than well aware on else if statements. However, this is just an experiment for the real damage foruma i'm going to do, so i kind of half-assed the whole thing.

TO Lummox: That is a great way to do things like that since everything is stat based. So i have adjusted the Blocking/Evading equation as such.

                if( ( rand() * usr.Skill("Basic",BLOCK,"Power") + M.Skill("Basic",BLOCK,"Power")) < M.Skill("Basic",BLOCK,"Power"))
spawn()Damage(M,"Block")
M.Skill_Exp_Add("Basic","Block")
if( ( rand() * M.Skill("Basic",BLOCK,"Power") + usr.Skill("Basic",BLOCK,"Power")) < usr.Skill("Basic",BLOCK,"Power"))
....


There is one question i do have, what exactly does rand() do with empty arguments?

[edit]
I have also made the other version, using exponents.

                if( prob(M.Skill("Basic",EVADE,"power") ** 0.5) / ( (usr.Skill("Basic",EVADE,"power") + M.Skill("Basic",EVADE,"power")) ** 0.5))
spawn()Damage(M,"Block")
M.Skill_Exp_Add("Basic","Block")
if( prob(usr.Skill("Basic",EVADE,"power") ** 0.5) / ( (M.Skill("Basic",EVADE,"power") + usr.Skill("Basic",EVADE,"power")) ** 0.5))


I am going to get a buddy and help me test this out to see which one I think suits the equation the best.
In response to Axerob
You've actually got the opening parenthesis in the wrong spot in your formula--the parentheses should be around the Ea+Ed terms so it's rand()*(Ea+Ed), not (rand()*Ea+Ed).

The call to rand() without arguments produces a random number from 0 to just less than 1.

Lummox JR
In response to Lummox JR
Lummox JR wrote:
You've actually got the opening parenthesis in the wrong spot in your formula--the parentheses should be around the Ea+Ed terms so it's rand()*(Ea+Ed), not (rand()*Ea+Ed).

The call to rand() without arguments produces a random number from 0 to just less than 1.

Lummox JR

Ah i see, that can be quite useful, thanks.

I've tested it out and using the second formula is much better to use for what i wanted.

mob
verb
Combat()
for(var/mob/M in get_step(usr,usr.dir))
if(! (M) || !(attackable(M) )) break

var
damage1=(usr.tempvars["weapon"] ? 0 : usr.Skill("Basic",HAND,"power") * log(2 ** rand(5,10)))

damage2 = usr.str.value * max(1, usr.tempvars["strbonus"])+ ( (usr.rei.value * max(1, usr.tempvars["reibonus"]) * usr.strd) /4)

damage3 = M.def.value * max(1, M.tempvars["defbonus"]) + ( (M.rei.value * max(1, M.tempvars["reibonus"]) * M.reid) /4)

damage = damage1 + (damage2 - damage3)

if( prob(M.Skill("Basic",EVADE,"power") ** 0.5) / ( (usr.Skill("Basic",EVADE,"power") + M.Skill("Basic",EVADE,"power")) ** 0.5))
spawn()Damage(M,"Evade")
world<<"EVADE"
M.Skill_Exp_Add("Basic",EVADE)
if( prob(usr.Skill("Basic",EVADE,"power") ** 0.5) / ( (M.Skill("Basic",EVADE,"power") + usr.Skill("Basic",EVADE,"power")) ** 0.5))
spawn()
Damage(usr,damage)
damage(usr,damage,M)


else if( prob(M.Skill("Basic",BLOCK,"power") ** 0.5) / ( (usr.Skill("Basic",BLOCK,"power") + M.Skill("Basic",BLOCK,"power")) ** 0.5))
spawn()Damage(M,"Block")
M.Skill_Exp_Add("Basic",BLOCK)



else
if(! (usr.tempvars["weapon"]))
usr.Skill_Exp_Add("Basic",HAND)
spawn()
Damage(M,damage)
damage(M,damage,usr)
Lock("Combat",usr.othervars["attackd"])


If you're wondering why i split up the damage equation into 3 parts, it was because i had made quite a few errors with my parenthesis placements. It's also a bit easier to decypher it this way aswell.
In response to Axerob
Bear in mind, prob() is based on percentages, so you need to scale up those ratios by 100 for them to work right with prob(). That's why I used rand(), because that method doesn't worry about percentages.

Lummox JR