Ok... NOW I'm sad.
[Guide to Defense] [Scrapper Secondaries Comparison] [Archetype Popularity Analysis]
In one little corner of the universe, there's nothing more irritating than a misfile...
(Please support the best webcomic about a cosmic universal realignment by impaired angelic interference resulting in identity crisis angst. Or I release the pigmy water thieves.)
Correct me if I'm wrong in this, but that's just a player front conceptualization on what Mez Resistance ends up doing.
My guestimation is that Mez Resistance is instead just accelerating the mez-wear-out timer while it's active. |
In fact, I can think of no other reasonable way to manage resistable duration than with decrementers.
[Guide to Defense] [Scrapper Secondaries Comparison] [Archetype Popularity Analysis]
In one little corner of the universe, there's nothing more irritating than a misfile...
(Please support the best webcomic about a cosmic universal realignment by impaired angelic interference resulting in identity crisis angst. Or I release the pigmy water thieves.)
So much attention has been focused on the data tables in the piggs that not many people have looked elsewhere, to find those elusive missing bits of info that are compiled in through auto-generated headers.
Also... I see things missing here. There is a Max to Max (a MaxMax), a Max and MinRes, and a MaxStr too. Those maybe aren't in the attributes, so where are they ? the MaxMax health gets recalculated everytime there is a Max modification ? The MaxStr is too, or is it fixed ? Is Maxresistance an entity-independant constant ?
|
Things that are defined there apply to every entity that belongs to its class, whether it's a player archetype or a NPC class. They are.
Per-class attribute info
(these exist once and are static across all levels)
AttribMin
AttribBase -- the starting value for the attribute
StrengthMin
ResistanceMin
AttribDimin[Str|Cur|Res][In|Out] (PvP diminishing returns)
Per-level attribute info
(these are still per-class, but come in a table form that defines values for levels 1-50 for players and 1-55 for NPCs)
AttribMax -- the starting value for the attribute's Max aspect
AttribMaxMax
StrengthMax
ResistanceMax
I have absolute confirmation Cur is used for most defense buffs: the dived data everyone who is capable of diving attribmod data can see, and I should point out that I did contract powers work for the dev team for I18, which should draw the logical conclusion there.
|
it has gone from unconscionable to downright appalling that we have no way of measuring our characters' wetness.
|
[Guide to Defense] [Scrapper Secondaries Comparison] [Archetype Popularity Analysis]
In one little corner of the universe, there's nothing more irritating than a misfile...
(Please support the best webcomic about a cosmic universal realignment by impaired angelic interference resulting in identity crisis angst. Or I release the pigmy water thieves.)
Begone with your insider knowledge and logic! Pics or it didn't happen!
|
(my hand was shaking more than I remember)
[Guide to Defense] [Scrapper Secondaries Comparison] [Archetype Popularity Analysis]
In one little corner of the universe, there's nothing more irritating than a misfile...
(Please support the best webcomic about a cosmic universal realignment by impaired angelic interference resulting in identity crisis angst. Or I release the pigmy water thieves.)
Did you ever say which system you were consulted on, or is that covered under NDA?
If I had to guess, I'd say Archvillain scaling by league size. I can't think of any other mechanics introduced around then that would require heavy mathematical analysis to get right.
MaxMax, et al aren't attributes in the same sense of the word. They aren't maintained on a per-entity basis like the 5 aspects are (possibly 4 if Abs is a pseudo-aspect). Those are defined in the class tables and are static data that never changes. There's no such thing as a MaxMax buff.
Things that are defined there apply to every entity that belongs to its class, whether it's a player archetype or a NPC class. They are. Per-class attribute info (these exist once and are static across all levels) AttribMin AttribBase -- the starting value for the attribute StrengthMin ResistanceMin AttribDimin[Str|Cur|Res][In|Out] (PvP diminishing returns) Per-level attribute info (these are still per-class, but come in a table form that defines values for levels 1-50 for players and 1-55 for NPCs) AttribMax -- the starting value for the attribute's Max aspect AttribMaxMax StrengthMax ResistanceMax |
That's really where all my time last night went: digging up that info and writing the import code, plus structuring it:
# entity class class CoHBlaster: name = '' attribmodStack = [] def applyAttribmod(attribmodId, powerId, entityId, triggerTime, trueScale): expireTime = triggerTime + AttribmodDB[attribmodId][kduration] nextAct = triggerTime attribmodStack.append([attribmodId, powerId, entityId, triggerTime, trueScale, expireTime, nextAct]) # stub to read in one archetype of data f = open("C:/coh/analyses/engine/Class_Blaster.csv",'r') archetype_data = f.readlines() f.close() archetype_data = map(lambda x: x.strip(),archetype_data) CoHBlaster.name = archetype_data[0] attribute_names = archetype_data[1].split(',') attribute_count = len(attribute_names) # min, base, strmin, resmin, strdimA, strdimB, curdimA, curdimB, resdima, resdimb CoHBlaster.min = map(lambda x: float(x), archetype_data[3].split(',')) CoHBlaster.base = map(lambda x: float(x), archetype_data[5].split(',')) CoHBlaster.strmin = map(lambda x: float(x), archetype_data[7].split(',')) CoHBlaster.resmin = map(lambda x: float(x), archetype_data[9].split(',')) CoHBlaster.strdimA = map(lambda x: float(x), archetype_data[11].split(',')) CoHBlaster.strdimB = map(lambda x: float(x), archetype_data[13].split(',')) CoHBlaster.curdimA = map(lambda x: float(x), archetype_data[15].split(',')) CoHBlaster.curdimB = map(lambda x: float(x), archetype_data[17].split(',')) CoHBlaster.resminA = map(lambda x: float(x), archetype_data[19].split(',')) CoHBlaster.resminB = map(lambda x: float(x), archetype_data[21].split(',')) CoHBlaster.max = [0] * attribute_count CoHBlaster.maxmax = [0] * attribute_count CoHBlaster.strmax = [0] * attribute_count CoHBlaster.resmax = [0] * attribute_count # max, maxmax, strmax, resmax for loop in xrange(0,attribute_count): CoHBlaster.max[loop] = archetype_data[23+loop].split(',') CoHBlaster.maxmax[loop] = archetype_data[139+loop].split(',') CoHBlaster.strmax[loop] = archetype_data[255+loop].split(',') CoHBlaster.resmax[loop] = archetype_data[371+loop].split(',') CoHBlaster.named = {} # named tables for loop in xrange(0,(len(archetype_data)-486)/2): CoHBlaster.named[archetype_data[486+loop*2]] = archetype_data[487+loop*2].split(',') CoHBlaster.Cur = copy.copy(CoHBlaster.base)
[Guide to Defense] [Scrapper Secondaries Comparison] [Archetype Popularity Analysis]
In one little corner of the universe, there's nothing more irritating than a misfile...
(Please support the best webcomic about a cosmic universal realignment by impaired angelic interference resulting in identity crisis angst. Or I release the pigmy water thieves.)
Ooh, Python. I wrote my first bin file parser in Python. Love it for quick prototyping. It worked, but was painfully slow.
Eventually redid it in C++. With templates. Because I had never really used them before, and STL uses them extensively, so they must be good, right? Might as well learn.
Yeah... won't be doing that again.
Did you ever say which system you were consulted on, or is that covered under NDA?
If I had to guess, I'd say Archvillain scaling by league size. I can't think of any other mechanics introduced around then that would require heavy mathematical analysis to get right. |
The NDA on that work expired long ago, beyond the permanent non-disclose on things like internal data, but I didn't mention it prior to now by mutual agreement that harping on it served no useful purpose to the game (it was actually my idea to not discuss it; the devs did not initially ask me to do that although they concurred with the reasoning). It can't hurt anymore to discuss it, and if the game is saved I doubt anyone's going to care.
[Guide to Defense] [Scrapper Secondaries Comparison] [Archetype Popularity Analysis]
In one little corner of the universe, there's nothing more irritating than a misfile...
(Please support the best webcomic about a cosmic universal realignment by impaired angelic interference resulting in identity crisis angst. Or I release the pigmy water thieves.)
Ooh, Python. I wrote my first bin file parser in Python. Love it for quick prototyping. It worked, but was painfully slow.
|
Oh, and in a moment of sheer brain-dead I decided to make one parser that could read all builds rather than multiple parsers that could read one build each, so I could have two different builds in memory simultaneously for cross-build computation. Forty build differences later, that's a 9.2 on the stupid-o-meter.
[Guide to Defense] [Scrapper Secondaries Comparison] [Archetype Popularity Analysis]
In one little corner of the universe, there's nothing more irritating than a misfile...
(Please support the best webcomic about a cosmic universal realignment by impaired angelic interference resulting in identity crisis angst. Or I release the pigmy water thieves.)
I think it was actually the "iterate through each field and print it out" part that was slow -- reading the files into a buffer was fine, and parsing wasn't too bad, but writing every field from a large tree structure like powers or costumes into a text file took a couple minutes. The C++ version runs in a few seconds. However the compile time and resulting executable size is a lot higher than I'd like; mostly because of the template use. That's one important thing I learned from that project -- templates == massive codegen bloat.
If I was going to do it again, I'd use straight C.
The other reason I went with C++ was actually very similar to one of your goals; I wanted it to support every build with only one code base, so that I could write a comparison engine to see exactly what changed with each patch. So having the various versions of the schema derive from each other made sense at the time. All in all I'd say it ended up like most programming projects, not perfect by any means, but functional and useful despite any small warts that might bother me.
The other reason I went with C++ was actually very similar to yours; I wanted it to support every build with only one code base, so that I could write a comparison engine to see exactly what changed with each patch. So having the various versions of the schema derive from each other made sense at the time. All in all I'd say it ended up like most programming projects, not perfect by any means, but functional and useful despite any small warts that might bother me.
|
Although just to show you how crazy I am, the thought had crossed my mind to stop writing parsers, and write an expert system that could perform parsing as well as I could. Because tracing the client code was just too easy I guess.
[Guide to Defense] [Scrapper Secondaries Comparison] [Archetype Popularity Analysis]
In one little corner of the universe, there's nothing more irritating than a misfile...
(Please support the best webcomic about a cosmic universal realignment by impaired angelic interference resulting in identity crisis angst. Or I release the pigmy water thieves.)
In this case, however, we lucked out that the devs used the same client build for development, so it's fully capable of loading the data from the source text files instead of the bins. I imagine that's for quick changes since they apparently used a local mapserver pointed at the same data files.
Even before that, ent_types was easy at least. They helpfully included the source files with the client for twenty issues.
This is more a what if question regarding mez resistance and magnitude. One of the things that I just didn't like in the game was how the seperate stats of mez resistance and function of magnitude and protection.
To me it would seem nicer (for lack of a better word atm) if there was just mez resistance by type. That is fire based mez, psychic based mez (which could cover fears and holds etc...), and so on.
Then those sets that carry that type of mez protection would be switched over to simply carry the equivelent mez reistance. So Tank Fiery Aura would have that rare 100% (+) Fire mez resistance. Should a mez attack land on a target, the attack would go against whatever mez resistance was present. Kind of like how damage and damage resistane works. Whatever is left over, is the amount of strength that mez has left.
Theoretical example: Crushing damage based hold with base mez of 50% enhanced to 80% strength lands on a target with 75% crushing resistance. The hold takes effect, but is only at 5% strength. The base duration of 10 seconds enhanced to 16 seconds at 5% strength = .8 seconds.
Also, sets could layer resistance and mez resistance. So a set like Invuln would have its resistance to varius types of damage, and have in Unyielding additional mez resistance. This would also be applicable for sets reliant on defense. IO sets with mez resistance would be more valuable for everyone as well.
Courtesy of Matt Miller's twitter: http://twitter.com/MMODesigner/statu...361857/photo/1
(my hand was shaking more than I remember) |
it has gone from unconscionable to downright appalling that we have no way of measuring our characters' wetness.
|
I think it was actually the "iterate through each field and print it out" part that was slow -- reading the files into a buffer was fine, and parsing wasn't too bad, but writing every field from a large tree structure like powers or costumes into a text file took a couple minutes. The C++ version runs in a few seconds. However the compile time and resulting executable size is a lot higher than I'd like; mostly because of the template use. That's one important thing I learned from that project -- templates == massive codegen bloat.
|
WE ARE HEROES. THIS IS WHAT WE DO.
City et moi, �a colle !
Concerning the whole Cur vs Abs and defense case, I think there is something fishy here, and blatantly, I could go with the curious Cur + Abs implementation we seem to have in the game right now.
I still have two assumptions I would like to have verified, which if they were true, make me differ permanently from your point of view, Arcanaville. So please (anybody) debunk:
There are permanent mods (to cur or abs) only for Health, Endurance, Meter, Damage (which redirect to health) and maybe to knockup/back/repel status effects values (which could get degraded to the current protection value as soon as the movement engine has applied the effect, or by itself after a duration).
There is no permanent mod (to cur or abs) to Defense nor any of the attributes not cited in the first assumption.
Please, shoot counterexamples at me, as I have the feeling we are missing something here (or maybe just me missing to learn to shut the ficus up ^^) I'm willing to get over it and have cur and abs being two scalar values and percent-based effects being handled otherwise, but if my assumptions are true, computationally, you only need abs or cur in any attrib mod, and their meaning changes according to the very Attribute they are in. So if both exist where only one field could be sufficient, there must be a reason.
WE ARE HEROES. THIS IS WHAT WE DO.
City et moi, �a colle !
I just decided this post wasn't worth it.
As you were.
And for a while things were cold,
They were scared down in their holes
The forest that once was green
Was colored black by those killing machines
Concerning the whole Cur vs Abs and defense case, I think there is something fishy here, and blatantly, I could go with the curious Cur + Abs implementation we seem to have in the game right now.
I still have two assumptions I would like to have verified, which if they were true, make me differ permanently from your point of view, Arcanaville. So please (anybody) debunk: There are permanent mods (to cur or abs) only for Health, Endurance, Meter, Damage (which redirect to health) and maybe to knockup/back/repel status effects values (which could get degraded to the current protection value as soon as the movement engine has applied the effect, or by itself after a duration). There is no permanent mod (to cur or abs) to Defense nor any of the attributes not cited in the first assumption. Please, shoot counterexamples at me, as I have the feeling we are missing something here (or maybe just me missing to learn to shut the ficus up ^^) I'm willing to get over it and have cur and abs being two scalar values and percent-based effects being handled otherwise, but if my assumptions are true, computationally, you only need abs or cur in any attrib mod, and their meaning changes according to the very Attribute they are in. So if both exist where only one field could be sufficient, there must be a reason. |
Cur and Abs never show up simultaneously in a single attribmod normally. Every attribmod has an Aspect value which is either Cur, Abs, Str, Res, MaxMax, or a few other rarer values.
To be very precise, because I know there are some internals that say otherwise, the devs are only capable of setting an attribmod's Aspect Cur or Abs (or one of the others) and not both. I'm unaware of a method the devs have for setting an attribmod to make both a Cur and an Abs modification simultaneously. I'm not sure why you believe I thought this was possible, if that is what you are implying.
[Guide to Defense] [Scrapper Secondaries Comparison] [Archetype Popularity Analysis]
In one little corner of the universe, there's nothing more irritating than a misfile...
(Please support the best webcomic about a cosmic universal realignment by impaired angelic interference resulting in identity crisis angst. Or I release the pigmy water thieves.)
Cur and Abs never show up simultaneously in a single attribmod normally. Every attribmod has an Aspect value which is either Cur, Abs, Str, Res, MaxMax, or a few other rarer values.
To be very precise, because I know there are some internals that say otherwise, the devs are only capable of setting an attribmod's Aspect Cur or Abs (or one of the others) and not both. I'm unaware of a method the devs have for setting an attribmod to make both a Cur and an Abs modification simultaneously. |
I'm not sure why you believe I thought this was possible, if that is what you are implying. |
You seem to be stripping all functionality out of the attribmod calculation engine except AttrValue = Min(Max[(AttrValue + [Attribmod(Abs) + Attribmod(Cur)] * (1 - Res)),AttrMin],AttrMax)
|
So, we have:
- Attribmods have exactly one target attribute, exactly one target aspect to mod, no more, no less
- Attribmobs have a duration or have none. Normally attribmods to an attribute's abs are permanent (no duration), and attribmods to Cur are bound to expire (finite duration) but there are exceptions. So the attribmod's duration is independant to the target aspect.
Now, considering only the 'Cur' and 'Abs' attribmods out there, in the game, but completely ignoring which of the two aspects it is, what are the attribmods in the game, that in the end (that is considering the code that gets executed on them), temporarily affect Endurance, Health, Meter or maybe knocks/repel ? What are the attribmods that permanently affect the other attributes ? (I'm thinking def, other status, recov/regen, perception and stealth, others may still fall in this category or the one of health/end etc)
I hope you understand I'm just trying to get this piece of information for 3 questions already, I'm sorry to everybody to flooding, but especially to you, whom I'm bugging to no end. I'm bad at asking questions it seems.
As far as I'm aware, besides the ones you've named the only other attribute for which I believe Cur modifiers are (theoretically) permanent is Absorb. I would not be at all surprised to learn that the dev macros are hard-coded to flag Cur as permanent for the first twenty five attribmods. |
WE ARE HEROES. THIS IS WHAT WE DO.
City et moi, �a colle !
Interesting, I would have said that absorb is not permanent, but that's because I didn't read the description enough.
|
Now, considering only the 'Cur' and 'Abs' attribmods out there, in the game, but completely ignoring which of the two aspects it is, what are the attribmods in the game, that in the end (that is considering the code that gets executed on them), temporarily affect Endurance, Health, Meter or maybe knocks/repel ? What are the attribmods that permanently affect the other attributes ? (I'm thinking def, other status, recov/regen, perception and stealth, others may still fall in this category or the one of health/end etc) |
Technically speaking its possible the engine could support a temporary Cur buff on Hitpoints, but there's circumstantial evidence to support the notion that even if it can, the dev tools prohibited such usage. The IWill bug where Castle accidentally set a Res to a Cur supports the notion that in the absence of any other changes, Hitpoints-based Cur buffs are always permanent.
Aside: zero progress tonight. I got caught up in thinking about the question of server-side event overflow, aka server-side lag. On the plus-side, I now have an integrated load monitor.
[Guide to Defense] [Scrapper Secondaries Comparison] [Archetype Popularity Analysis]
In one little corner of the universe, there's nothing more irritating than a misfile...
(Please support the best webcomic about a cosmic universal realignment by impaired angelic interference resulting in identity crisis angst. Or I release the pigmy water thieves.)
Templates are tricky. If you take my attribmod calculator, I already have only 2 megs of binary code, and thats mainly because I have Attribs::NUMBER*Aspects::NUMBER methods of accessing the attributes and maintain an array to access the corresponding method from the Attribute and Aspect.
|
Static code is powerful, and memory is plentiful nowadays, so it doesn't matter, complexity is king now, so use it, I say, but sometimes it get even over that... During my internship, I did perfectly legal template metaprogramming, but code generation went over the 6 gigs of my computer... Yeah, there was a hell of a lot of data, too bad it didn't work it would have been blazingly fast though :') |
That's why these days my default optimization level is -Os. In my admittedly somewhat limited testing, being able to fit more code (and as a result, data) into the cache significantly outstrips the benefit of things like loop unrolling in the average case.
Using "resources are plentiful" as an excuse to be inefficient is the reason that the Windows 2008 server admin tools are so painfully slow. I peeked at one with a debugger once and cringed at the sheer bulk of the many dozens of .NET assemblies it was loading, just to view the event log...
My guestimation is that Mez Resistance is instead just accelerating the mez-wear-out timer while it's active.
Pseudocode example:
Same goes for recharge buffs vs power recharge.
Again, this is a guess, it's how my abandoned attack chain calculator evaluated both these effects (and recovery and regeneration ticks.)