Closed Aldriana closed 13 years ago
I'll take this on over gettext any day. Should have it roughed out by late tomorrow.
Have we ever encountered a proc effect that procced from spell periodical damage but not physical? I believe they do exist in the game, although perhaps not of interest to us, so I intend to split these up.
And a couple more - for "other" procs like unheeded warning and the tier bonus, what do you want to be able to do to get information about them? Is the logic going to have to go all in the calculator? Should there be get_all_other_procs() that returns procs with a Proc.description of what they do along with the usual duration, icd, etc?
For damage procs, do you want to know damage type? High-low damage or just average? These should be another sub class I think.
Re: periodic spell vs periodic physical (aka bleeds). I'm not aware of any, but then, I pay roughly no attention to caster loot so I couldn't say for sure. If you feel there's value in splitting them, by all means do so. If you'd prefer to wait until there's need for such a thing, that's fine too.
For all damaging effects, I'm only going to worry about average damage. I really don't see any point to worrying about min and max damage. When and if someone is writing a model that does care about it, we can worry about it then. I don't expect that to happen anytime soon.
Damage procs could either be a subclass or just a class of procs of type "physical_damage" or "spell_damage" (as appropriate) and no duration. I think either way is fine.
For special procs like the ones you note (and Tiny Abom, and so forth) there's basically no way around the fact that they will need to be special-cased in the model. For stat procs having a general framework is good so new procs can be added without needing to adjust the model; but there's no point trying to do that for procs where every instance of them will be unique. With that in mind, I don't feel that there's a particular need for a general "get all wierd procs" function - I think it's fine to make the user check for each one individually.
I guess my inclination would be to make wierd procs available on procs.proc_name (i.e., self.stats.procs.unheeded_warning) - calling this returns False if they don't exist, or a proc object containing as much information as makes sense - i.e., for unheeded warning, it reports the proc rate, duration, triggering effects, etc. Anything that doesn't make sense can just be set to None (or whatever) because it won't be called anyway.
I'm not totally committed to that design - if it doesn't fit with what you're planning by all means feel free to adjust - but the general notion that the modeler should be able to a) check whether the proc is present and b) retrieve general proc rate information and the like seem like good goals.
P.S. There probably is some value in having a get_all_stat_procs function in addition to the getters for each stat - or perhaps a get_procs_for_stat(stat=None) function that returns all procs with the specified stat, or all stat procs if None is passed. I'm still thinking through the implementation details, but I can imagine wanting to grab all stat procs for some manner of preprocessing rather than splitting out by stat.
As a further aside, it might make sense to make the proc type field match up with the stat names, so you can use getattr and setattr with them to match them up to their base stat. Not a huge deal, but possibly a slight convenience.
Some wild questions/observations (hopping I make some kind of sense): I need to ask how are things like 4T11 going to be modeled. My instinct tells me we'll run the modeler once, figure how many evis/env are casted, how many of those are crits, and then have some rogue_t11_4pc_crit_bonus function return a new evis/env crit rate to feed the modeler in a second run. If that is the case, I imagine that this particular proc could live in stats.py just fine (like 2t11 does). Only thing is that the crit bonus is dynamic (it scales with gear that is; actually this one will downgrade rather than scale as we get more crit).
With that in mind I think having some sort of dynamic_proc sub class (or a new object, since those would have to be two subclasses actually: ppm based and % based) could make sense. It would have methods to compute the actual bonus if we pass the correct numbers along.
TAiaJ behaves much like DMC-hurricane: it's a proc based strike. Only thing is that it dynamicaly updates with your weapon. Unheeded warning is a little easier to deal with: it could be called directly from the modeler to figure it's impact.
What I'm trying to get across is that they are not that weird: their impact just happens to be updated constantly with our gear. Now, I have no idea of how to code this, just wanted to brainstorm a bit.
On a rather unrealted note: some procs may change their own proc rate when they proc. Take haste procs for instance: haste indirectly increases the number of instants (through energy regen) and hence modify the proc rate of any ppm related proc. Is there a way to model this appart from running the modeler multiple times untill the proc rate increase aproaches cero?. I remember this issue (it was crit procs by then, those that affected our energy regen) bugged me in the former spreadsheets and I never got to figure how those were handled.
I think the key point to this discussion is as follows: different modelers may approach these procs in different ways, so we shouldn't tie the architecture of the proc object to any particular modeling technique. That's sort of the point of the design. If we write it specifically towards how I'm currently planning to model procs, it may or may not work with how I model them when and if I rewrite my module for better proc handling, and even if it supports both of those it might not do well when someone comes along and writes a simulator with this framework.
In terms of modeling uptime for behavior-modifying procs (i.e., procs that change your rate of energy or combo point generation), the general spreadsheet approach was to iterate to convergence. That's more or less what I'm initially planning here as well. However, I do have some ideas for handling these better via massively interweaved conditional probabilities, but as that's going to be quite hard to do I figure it can wait until we have a basic model working for all specs.
I think we're good on this for now, so closing.
I think we want a little more detailed proc handling than we currently have - there's basically three things about the current setup that I'm finding a bit cumbersome to work with.
1) First and foremost, pulling stuff out of a five-tuple isn't the clearest and easiest way to do business. Keeping track of what entry is what requires a lot of flipping back and forth between sections of code - I think it'd be nicer if there was a proc object that would allow you to just read the relevant attributes off proc.value, prod.duration, proc.icd, and so forth.
2) There's a couple proc properties not well supported by the current framework - the notable ones that spring to mind are PPM and stacking procs (i.e Fluid Death). This could be fixed by adding still more things to the tuple (i.e., more named variables per point 1), but it might also make sense to subclass the proc object. Then you can have PPMProc (or whatever it winds up being called) take weapon speed as an argument to proc_rate() as opposed to just returning a static percentage.
Edit: I suppose only PPM really requires subclassing, as a regular proc can probably be handled as a stacking proc with max_stacks = 1.
3) The current triggering rules aren't really that useful for actually figuring out how many procs you're going to get. I think it'd be nicer if the proc exposed a set of booleans for each type of triggering effect, so you can call proc.procs_off_autoattacks and it'll return True or False. You probably wind up needing something like 5 different categories (autoattacks, strikes, debuff application (i.e. rupture), spells, and periodic damage), plus a toggle for crits only. I could do that classification in the model, I suppose, but I think it makes more sense to have proc object itself be smart enough to tell you those things.
So, basically, what I'm envisioning is: you have a set of Proc objects that define these sorts of useful quantities, and then the current Procs object is basically just a container for these that's smart enough to map a list of proc strings to the corresponding procs, and has methods to return all procs for a given stat. It's probably not ideal to have the classes be called Proc and Procs, but you get the idea.
I'm going to need this before I get too much further on the modeling front, so if you're interested in doing this please let me know - otherwise I'll probably work on implementing it sometime Sunday or Monday.