|
|
#1 |
|
Lovely SK
Join Date: Oct 2003
Location: Neriak
Age: 33
Posts: 673
Rep Power: 20 ![]() |
Melee Attack Pseudocode
This is a sort of attempt to outline what goes on when you press attack and your weapon starts to flail. Comments and remarks will be marked by \\. I am attempting to write this so that it can be followed for both a mob, and for a player. Not really sure what this is good for, aside from head scratching value. No, the goal is not to plug this into a compiler and let it rip. I suppose I just want to help establish a framework in which all the other melee understandings can be looked at.
Code:
Initialize Auto Attack cycle.
Delay Cycle Begin
\\This is the timestamped, official 'when' of combat
Target Determination
\\For mobs, this is the point at which they decide who they will attack. Top
\\of modified Aggro list determines. Special Case NPC Rampage Success: Top
\\of modified Rampage list. Special Case PC Rampage: Within AoE / Already
\\Rampaged.
Call Process Effect Subfunction.
Process Effect Sub Function.
Weapon Proc Check. If yes, resolve cast, end subfunction
Weapon Augment Proc Check. If yes, resolve cast, end subfunction.
Buff Proc Check. If yes, resolve cast.
End subfunction.
Dual wield check - If no, end function.
\\Only appropriate to offhand weapon.
Call Subfunction Multiattack.
Subfunction Multiattack.
Attacks=1.
Check Double attack. If yes, attacks=attacks+1
If attacks=2, check Triple attack. If yes, attacks=attacks+1.
Check Punishing Blade / Speed of the Knight. If yes, attacks = Attacks +1.
Check Flurry. If 1, attacks = attacks +1, if 2, attacks = attacks +2
while attacks > 1
Target Valid Object Check- If no, end cycle, return error.
\\For PC, checks attackable NPC, relative PK flags. For NPC, checks valid NPC
\\target, checks valid PC target.
Target Living Check - If no, end cycle, return error.
Target Range Check - no, end cycle, return error.
call Subfunction Hit Resolution.
attacks = attacks -1,
loop while
Subfunction Hit Resolution.
If defender NPC, assign aggro generation.
Check Defender Dodge. If yes, call Subfunction Strikethrough
Check Defender Parry. If yes, call Subfunction Strikethrough
Check Defender Block. If yes, call Subfunction Strikethrough
Check Defender Riposte. If yes, call Subfunction Strikethrough
Check Defender Invulnerability. If yes, end Subfunction, return Invuln.
\\DA, DB, Magic weapons, bane presence.
Subfunction Strikethrough
Check Attacker Strikethrough
If yes, end subfunction.
If no, end subfunction hit resolution, return calling check.
\\Subfunction Strikethrough has 5 possible results: Strike through successful,
\\continue Hit Resolution. Strikethrough Unsuccessful, return Dodge, Parry,
\\Block, Riposte.
Compare attacker accuracy, defender evasion.
Generate random number.
Locate hit/miss on Class to-hit table.
If hit, call Subfunction Damage Resolution.
If miss, End Subfunction.
Subfunction Damage Resolution.
Compare attacker penetration, defender mitigation.
Generate Random Number(1-20).
If Mob, then damage = DB + RNG(DI)
If PC, then reference PC damage tables (With subtables?)
Final Damage = Damage - Damage Absorbance. (includes BoVie subcode).
If Final Damage = 0, return 'magical skin absorbs attack'.
If Damage Absorbance < Damage, then resolve buff fade.
\\This is the rune/Vie check. End of rune/Vie is likely resolved here.
Target HP = Target HP - Final Damage.
Check & Resolve True Innate Process(Mob only).
\\This includes Flurry, Rampage, normal mob procs.
Resolve Target Death - If yes, broadcast end auto-attack, return death.
End subfunction.
End Function.
I'm quite sure stuff is missing above, please feel free to point it out. ... SoE needs to sell old server boxes to SETI.
__________________
Arathena Sa'Riik Scourge Knight of Poison Arrow |
|
|
|
|
|
#2 |
|
Veteran User
Join Date: Apr 2003
Posts: 584
Rep Power: 21 ![]() |
Hola-
Worked on something like this a long time ago, as a logic table instead of pseudocode tho; bunch of effects have changed/been added since then, I'll have to dig it up and compare it to what you've coded. A couple of partially-remembered observations: -the order of dodge/block/parry/riposte checks can be determined by frequency analysis vs. base skill. -you can proc on a miss, but cannot proc on an "impossible" hit; apparently could at one time, but since modified. Some annecdotal evidence of procing on invalid targets (like corpses), but SoE has changed the "types" of invalid targets now (new type invunerable NPCs, etc.) -some trickyness determining hits, as to when avoidance is determined. makes a difference for defensive responses (i.e. riposting misses, damage shield damage assignment). -also some complexity determining when damage is assigned, tho I don't remember the details offhand. -assigning damage from both regular and reverse damage shields is somewhere in there, after target and hit determination, but dunno if before or after defensive response. -the player and mob "combat" code is almost certainly very similar, but different in small but significant ways (i.e. there is no "invalid target" for mobs, instead it forces a target change + possible movement; also need to include checks for cast vs. melee, summon, etc.). Would be very interesting to figure out the exact sequence of checks and assignments, could be quite useful to determine the relative worth of some avoidance modifiers. Basically, the EQ "random number" generator is VERY streaky and at least one component of it has a short (one or few ticks) persistence. That, plus the empirical observation that most checks are "high = success, low = fail" means that the ORDER that the checks are made in has a stronger impact on the outcome than you might otherwise expect... Good stuff. RdT. |
|
|
|
|
|
#3 |
|
Veteran User
Join Date: Jun 2003
Posts: 63
Rep Power: 20 ![]() |
Just like to add in the Process Effect Sub Function. You might wanna add a line about bard procs cause bards have a song Katta's somethingyamajig which adds a proc that lowers the targets dex and it shows up in the bard song box. Yes it stacks with spell proc (pestilenece shock, Call of the Sky, Soul Claw, Potions of Draconic Rage) and yes i have had 6 procs going before 2 on each weapons, Proc off Potion of draconic rage AND katta's
|
|
|
|
|
|
#4 |
|
Veteran User
Join Date: Jun 2003
Location: LI NY
Posts: 1,291
Rep Power: 21 ![]() |
Um... I will read it carefully soon as I get back from the store but there has to be some psudo code differance between mobs and PCs on procs. We can (or could) proc on a miss. Mobs cant. So a mobs proc check has to happen after the To Hit (and I think PDR) checks.
__________________
Guthammer Dwarf Warrior of Silver Hand |
|
|
|
|
|
#5 |
|
Registered User
Join Date: Jun 2004
Posts: 2
Rep Power: 0 ![]() |
In EverQuest NPCs can proc on a riposte whereas PCs cannot.
|
|
|
|
|
Advertisement
|
|
|
|
#6 |
|
EQ Developer
Join Date: Dec 2003
Posts: 20
Rep Power: 0 ![]() |
NPCs' innate proc checks occur on every swing. So an NPC can technically proc 4 times on a quad attack. Weapon procs (both player and NPC) only check once per round, as you have above.
- Kavhok, SOE |
|
|
|
|
|
#8 |
|
Veteran User
Join Date: Jun 2003
Location: LI NY
Posts: 1,291
Rep Power: 21 ![]() |
!!
And since the code tag adds scoll bars so you can't see it all at once: Initialize Auto Attack cycle. Delay Cycle Begin \\This is the timestamped, official 'when' of combat Target Determination \\For mobs, this is the point at which they decide who they will attack. Top \\of modified Aggro list determines. Special Case NPC Rampage Success: Top \\of modified Rampage list. Special Case PC Rampage: Within AoE / Already \\Rampaged. Call Process Effect Subfunction. Process Effect Sub Function. Weapon Proc Check. If yes, resolve cast, end subfunction Weapon Augment Proc Check. If yes, resolve cast, end subfunction. Buff Proc Check. If yes, resolve cast. End subfunction. Dual wield check - If no, end function. \\Only appropriate to offhand weapon. Call Subfunction Multiattack. Subfunction Multiattack. Attacks=1. Check Double attack. If yes, attacks=attacks+1 If attacks=2, check Triple attack. If yes, attacks=attacks+1. Check Punishing Blade / Speed of the Knight. If yes, attacks = Attacks +1. Check Flurry. If 1, attacks = attacks +1, if 2, attacks = attacks +2 while attacks > 1 Target Valid Object Check- If no, end cycle, return error. \\For PC, checks attackable NPC, relative PK flags. For NPC, checks valid NPC \\target, checks valid PC target. Target Living Check - If no, end cycle, return error. Target Range Check - no, end cycle, return error. call Subfunction Hit Resolution. attacks = attacks -1, loop while Subfunction Hit Resolution. If defender NPC, assign aggro generation. Check Defender Dodge. If yes, call Subfunction Strikethrough Check Defender Parry. If yes, call Subfunction Strikethrough Check Defender Block. If yes, call Subfunction Strikethrough Check Defender Riposte. If yes, call Subfunction Strikethrough Check Defender Invulnerability. If yes, end Subfunction, return Invuln. \\DA, DB, Magic weapons, bane presence. Subfunction Strikethrough Check Attacker Strikethrough If yes, end subfunction. If no, end subfunction hit resolution, return calling check. \\Subfunction Strikethrough has 5 possible results: Strike through successful, \\continue Hit Resolution. Strikethrough Unsuccessful, return Dodge, Parry, \\Block, Riposte. Compare attacker accuracy, defender evasion. Generate random number. Locate hit/miss on Class to-hit table. If hit, call Subfunction Damage Resolution. If miss, End Subfunction. Subfunction Damage Resolution. Compare attacker penetration, defender mitigation. Generate Random Number(1-20). If Mob, then damage = DB + RNG(DI) If PC, then reference PC damage tables (With subtables?) Final Damage = Damage - Damage Absorbance. (includes BoVie subcode). If Final Damage = 0, return 'magical skin absorbs attack'. If Damage Absorbance < Damage, then resolve buff fade. \\This is the rune/Vie check. End of rune/Vie is likely resolved here. Target HP = Target HP - Final Damage. Check & Resolve True Innate Process(Mob only). \\This includes Flurry, Rampage, normal mob procs. Resolve Target Death - If yes, broadcast end auto-attack, return death. End subfunction. End Function.
__________________
Guthammer Dwarf Warrior of Silver Hand |
|
|
|
|
|
#9 | |
|
knows too much
Join Date: Mar 2003
Posts: 1,047
Rep Power: 22 ![]() |
Quote:
__________________
Fitemore Mystique "You see he stand 'bout six foot four All the downtown ladies call him 'Treetop Lover' All the mens just call him 'Sir' " -Jim Croce |
|
|
|
|
|
|
#10 |
|
Lovely SK
Join Date: Oct 2003
Location: Neriak
Age: 33
Posts: 673
Rep Power: 20 ![]() |
I'd edit out my code tags, but I don't seem to be able to. Oh well. =p
Big oops I noticed, the while loop should run while Attacks > 0, not attacks >1. On procs, the big difference between PC and NPC in this pseudocode comes from what I've termed the 'True Innate Proc'. This is the only process effect that exists in the 'Determine damage' subroutine. I suspect that the reason is the throttling of the PC proc against the streaky RNG, combined with coding effeciency. By isolating the PC proc from the 'to-hit' routine, they can control the proc per minute much more effectively, as well as spare the cycles to check the weapon every single swing. It might not seem as much, but considering that 40%+ of a high end character's attacks are likely multi-attacks, it's exponentially less ugly. By not isolating the NPC proc, Reparm is born. I suspect that there's an 'if Final Damage > 0, then NPC proc check' that I forgot to slip in there as well. The relevant subfunction then becomes: Subfunction Damage Resolution. Compare attacker penetration, defender mitigation. Generate Random Number(1-20). If Mob, then damage = DB + RNG(DI) If PC, then reference PC damage tables Final Damage = Damage - Damage Absorbance. \\Damage Absorbance refers to Rune, Vie, etc. May, in the case of some NPC \\debuffs, theoretically become a negative value. If Final Damage = 0, return 'magical skin absorbs attack'. If Damage Absorbance < Damage, then resolve buff fade. \\This is the rune/Vie check. End of rune/Vie is likely resolved here. If Final Damage > 0, then { Target HP = Target HP - Final Damage. Check & Resolve True Innate Process(Mob only). } \\This includes Flurry, Rampage, normal mob procs. Resolve Target Death - If yes, server broadcast end auto-attack, return death. End subfunction. I -think- most of Casai's concerns should be taken care of not by the explicit instructions of the code, but by the implications of instruction order. My dodge/parry/block/riposte order is a big, fat, assumption, justified only by order of skill reception. Resolution of the process subfunction will be a function of the spell engine - Putting it anywhere else is recoding the wheel. AI decisions such as 'chase, summon, target switch' are also not going to be handled here for the most part: the AI will be handed a return code stating Invulnerable, Out of Range, Dead, Attack Attempt Successful, etc, and it will act based on the return code. My strikethrough subroutine seems very, very, very sloppy to me. Can anyone point out a more elegant way of doing it? Edit (DOH!)
__________________
Arathena Sa'Riik Scourge Knight of Poison Arrow |
|
|
|
|
Advertisement
|
|
|
|
#11 |
|
EQ Developer
Join Date: Dec 2003
Posts: 20
Rep Power: 0 ![]() |
Yes, NPC innate procs only go off if the NPC does not miss and isn't blocked, dodged, etc. So it would be more accurate to say it checks on every actual hit.
- Kavhok, SOE |
|
|
|
|
|
#12 | |
|
The Brigitte Bardot of TSW
Join Date: May 2003
Location: Boston
Age: 64
Posts: 3,774
Rep Power: 24 ![]() |
Quote:
Many of the original software random generators used in games twenty-five years ago were based on a Linear feedback shift register method outlined by Don Lancaster in CMoS Cookbook and a Byte magazine article. A variety of primitive methods have been known and employed to ensure short term compliance with expected results utilizing previous results. There are two major known weakness with these methods. First, post manipulation of the value returned by the LFSR pseudo-random generator using seemingly benign operations return less random results. Secondly, short term compliance with expected result is a local effect - no matter how many other players are generating random numbers, I don't expect to ever fail a trivial combine 5 times in a row. In the last few years, new linear RNG's like the Mersenne Twister exhibit more uniform distribution and a higher periodicy. I suppose that either a spectral test or weighted spectral test could "ride herd" on such an RNG and "corrective measures" taken - but I seriously doubt the EQ progamers have employed such sophistication. I hope they aren't uising the standard C function rand() for a variety of reason. I also am very doubtful that they are using either previous results nudging from the olden days or running spectral tests. So, I really don't know what your comment is saying and I fear I have a lack of knowledge you could clear up. BB |
|
|
|
|
|
|
#13 |
|
Veteran User
Join Date: Jun 2003
Location: LI NY
Posts: 1,291
Rep Power: 21 ![]() |
Hey BB, just curious, but how computational intesive are the new RNG's?
Only because EQ seems to use SO many of them. I would imagine over a thosand a second on your typical raid.
__________________
Guthammer Dwarf Warrior of Silver Hand |
|
|
|
|
|
#14 | |
|
Lovely SK
Join Date: Oct 2003
Location: Neriak
Age: 33
Posts: 673
Rep Power: 20 ![]() |
Quote:
__________________
Arathena Sa'Riik Scourge Knight of Poison Arrow |
|
|
|
|
|
|
#15 |
|
The Brigitte Bardot of TSW
Join Date: May 2003
Location: Boston
Age: 64
Posts: 3,774
Rep Power: 24 ![]() |
To answer the question,
I haven't looked in years. But Don Lancaster's is 8-10 lines of code and just shirfts and adds, so its fast as heck. MT and rand() are about the same speed and something like 20ish lines of code for rand(). There's a nasty way to avoid having to run the code everytime someone wants a random number. Since for a given individual of mob we're talking human speed, you can add the RNG to the keyboard Interrupt hander (as I recall, it's been awhile), let the Int generate a new random, and just have your override of rand() return the random value. Sure, you might return the same value 100's of time, but since we're talking 10ths of seconds or less, no human speed event will end up with the same number as far as any one user is concerned. BB |
|
|
|
|
Advertisement
|
|
![]() |
| Thread Tools | |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| OoW AA | Nymeria | The Arena | 56 | 08-23-2004 08:00 PM |
| Taunt and Higher Level MOBs (GoD+) | Symgharyl | The Arena | 11 | 06-03-2004 02:57 PM |