Ok... NOW I'm sad.
On other news, I think I've nailed the attribmod library, I'm tackling the Powers & Effects (restricted to attribmod effects, discarding the summon, setmode etc...) one, but that one is hairy, especially the "Ignore buffs&debuffs" flag on powers >_>
|
There's the "ignore outside buffs" flag on powers that still allows enhancements slotted in the power to work, but ignores outside strength buffs.
There's the "ignore buffs and enhancements" flag on individual attribmod/effects that ignores ALL strength buffs, even ones that come from slotted enhancements.
There's also the "list of attributes to disallow buffing" on the power, where if you put say, Recharge or Range in that list, the entire power will ignore all strength buffs to that particular attribute, whether they're from enhancements or outside buffs.
Don't forget there's multiple versions of that flag.
There's the "ignore outside buffs" flag on powers that still allows enhancements slotted in the power to work, but ignores outside strength buffs. |
There's the "ignore buffs and enhancements" flag on individual attribmod/effects that ignores ALL strength buffs, even ones that come from slotted enhancements. |
There's also the "list of attributes to disallow buffing" on the power, where if you put say, Recharge or Range in that list, the entire power will ignore all strength buffs to that particular attribute, whether they're from enhancements or outside buffs. |
WE ARE HEROES. THIS IS WHAT WE DO.
City et moi, �a colle !
So... how 'bout them Steelers?
The Alt Alphabet ~ OPC: Other People's Characters ~ Terrific Screenshots of Cool ~ Superhero Fiction
hmmm where is that used for instance ? Because that could be implemented as flagging each involved power effects with the previous (Effect-scale) flag on each effect that gets hit by this (power-scale) flag. So I don't see why it exists, but it does, you say ? So on which power ?
|
Recharge Strength is not taken into account inside an attribmod, ever. Well it may be, but in the end it's not, because recharge mods are generally (always?) [ignore buffs and enhancements].
WE ARE HEROES. THIS IS WHAT WE DO.
City et moi, �a colle !
WE ARE HEROES. THIS IS WHAT WE DO.
City et moi, �a colle !
C++ still lacks the amount of standard (but poorly implemented as you said) things that Java has, allowing fast prototyping.
|
Anyway, I'm letting the thread get back to its original, intended tangent at this point. :P
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
Which was exactly my point. I think the reason C++ lacks them is that it's harder to distribute and integrate well-crafted services than in Java because of design decisions around memory management.
Anyway, I'm letting the thread get back to its original, intended tangent at this point. :P |
I also only had time to test (and debug, don't forget debug, debug takes time, especially when you coded tired, tired code is a hive of bug) the paragonwiki brute Energy resistance case.
I was in the process of making damage tests afterward, if somebody wills to add them to the main and do the test themselves as curiosity (I don't even know if it's going to work !) just do another effect with a negative scale (if someone here think damages are a positive thing ...!) modifying the Abs aspect of the Energy attribute. This is hardwired to modify the health's Abs, but leverages the general formulas to get the resistances and strength of the damage type.
The Effects are basic, and the attribmod effects code is meant to work only for one-shots right now, the DoesNotStackFromSameCaster clause is not handled right now because I need to register them on the Entity, but the formulas are done and should work (as always when programming, if you forget the bugs :P).
WE ARE HEROES. THIS IS WHAT WE DO.
City et moi, �a colle !
I had to look. First off, kudos for being the first C++ programmer I've ever met who uses .hpp for C++ headers
So all the formulas are implemented in the Effects class?
Why is the target void* and not Entity*?
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
I had to look. First off, kudos for being the first C++ programmer I've ever met who uses .hpp for C++ headers
So all the formulas are implemented in the Effects class? Why is the target void* and not Entity*? |
Some formulas are in Effect, others in Attribs*, and you've got to look at Aspect to understand them. Also, they are also used by encapsulation in Entity (to make a single call to an entity's method is single-pass as the layout of the aspects in an entity is fixed thanks to the use of arrays and enums)
The target is void* because it could be a Location in case of powers that summoned entities. Well, it could also be an Entity, created at power launch time, but empty, and then modified by the power effect, similarly to fork/exec. Actually, that would prevent the headache of making the power location-aware, that would also carry out the current buffs and debuffs, and then you only have to ignore them in case of ignoreBuffs&Enhancements and apply the summoning power's enhancements to the entity... I like it! If I have to implement the Summon kind of Effects, I'd definitely do that.
Also, you may notice that there seem to be an awful lot of functions involved to just modify a mod once you know the value and attrib and aspect targeted. But it should be optimized out because of inlining and templates, it just doesn't show in the debug because there is no optimization. I wouldn't be against a rewrite either if it keeps the optimality.
*: Especially the special cases and Aspect clamped value caching (val is the clamped, abs_val is the unclamped value for modification). Had to do that in Attribs because it's another or two other aspects that sometimes dictate the range of an aspect, like Min and Max limit Abs (and are involved in the calculation of Cur), and MaxMax restricts Max, and then Str and Res are also limited. So it only makes sense when you have all the aspects.
WE ARE HEROES. THIS IS WHAT WE DO.
City et moi, �a colle !
Thanks for the transition, here is the calculator source code, disclaimer: IT'S OF NO USE TO NON-PROGRAMMERS, it's in C++, it's ugly, but it comes optimized a bit. Normally. Comes also with code stubs, follow the main to find only the useful bits.
I also only had time to test (and debug, don't forget debug, debug takes time, especially when you coded tired, tired code is a hive of bug) the paragonwiki brute Energy resistance case. I was in the process of making damage tests afterward, if somebody wills to add them to the main and do the test themselves as curiosity (I don't even know if it's going to work !) just do another effect with a negative scale (if someone here think damages are a positive thing ...!) modifying the Abs aspect of the Energy attribute. This is hardwired to modify the health's Abs, but leverages the general formulas to get the resistances and strength of the damage type. The Effects are basic, and the attribmod effects code is meant to work only for one-shots right now, the DoesNotStackFromSameCaster clause is not handled right now because I need to register them on the Entity, but the formulas are done and should work (as always when programming, if you forget the bugs :P). |
I'm also concerned about this sort of thing:
//keep Cur, Abs and Max in Sync template <> inline const val_type mod<Aspects::Abs>(Attribs::Type& attrib, const val_type valmod){ attrib.aspects[Aspects::Abs].abs_val = attrib.aspects[Aspects::Abs].abs_val + valmod; register val_type val = attrib.aspects[Aspects::Abs].abs_val; register val_type max = attrib.aspects[Aspects::Max].val; register val_type min = attrib.aspects[Aspects::Min].val; attrib.aspects[Aspects::Abs].val = (val>max)?max:(val<min)?min:val; attrib.aspects[Aspects::Cur].abs_val = val / max; attrib.aspects[Aspects::Cur].val = attrib.aspects[Aspects::Abs].val / max; return valmod;
//Cur modding is just a syntactic sugar for things such as heal X% of inspirations
One other thing:
//"Resistance resists resistible resistance debuffs" //this requires buffs to register specifically as buffs //the less computationnaly expensive way is to test sign at data load.
"You DON'T make resistible resist buffs... period"
This is ironically a case where you're making it harder than it needs to be, or would be if you handled resistance as the game engine does.
It is also not a good idea to "test sign" to determine what is a buff and what is a debuff. Mez protection buffs are negative for example. You're rolling the dice that a lot of your simplifications won't break something important somewhere.
Here's my first test of the attribmod engine. Take the Brute and the Corruptor and shoot the Brute with Scream. What happens?
[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.)
Here's my first test of the attribmod engine. Take the Brute and the Corruptor and shoot the Brute with Scream. What happens? |
Sorry couldn't resist, especially since this thread started with someone asking for a my brute type of program and now its focused on simulating a software bugs, quirks and all.
He puts his hands over his ears and yells "STOP THAT" ?
Sorry couldn't resist, especially since this thread started with someone asking for a my brute type of program and now its focused on simulating a software bugs, quirks and all. |
If you prefer, to eliminate the question of unintended delay, I can rephrase the question as calculating what happens when a target is hit by Shriek, and then three seconds later is hit by Fire Blast.
A significant amount of the complexity of the attribmod system is in the fact that attribmods can have durations and activation periods. An attribmod calculating engine must be able to handle those, or its not an attribmod calculator, its a calculator.
[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.)
The reason I mention Objective-C is because, for the most part, MMOs are written with static game engines and dynamic but conceptually encapsulated data. Many was the college student who came onto the boards thinking the Freakshow was a C++ class of which Dreck was an instance. Not only is that not done, there's no really advantage to doing it.
But in a language like Objective-C (or Smalltalk, or most other object-based runtime bound environments) there is the crazy-but-interesting idea of converting data to objects at runtime dynamically and using the environment itself as a part of the game engine. A game engine written in Smalltalk or LISP wouldn't need special Requires expression handlers, it could just meta Eval them. Attribmods would convert to methods, and attribmod stacks would just be method stacks. Powers and entities could be redefined on the fly and all interactions would rebind automatically through dynamic dispatch.
The problem is, of course, you lose some control over the engine to the environment. You've probably made something a little less like City of Heroes, and a little more like Corewars.
For the record, not a fan of templates.
[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.)
[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.)
He puts his hands over his ears and yells "STOP THAT" ? |
Scream's behavior is not a bug. As I explained above, the reference to "My Brute" wasn't intended to imply tremendous oversimplification, but rather eliminating all of the surrounding effort required to create a 3D engine, mapservers, and all of the other trappings surrounding the core engine that correctly computes what happens when a set of entities N activate a set of powers P over time.
|
A significant amount of the complexity of the attribmod system is in the fact that attribmods can have durations and activation periods. An attribmod calculating engine must be able to handle those, or its not an attribmod calculator, its a calculator. |
Father Xmas - Level 50 Ice/Ice Tanker - Victory
$725 and $1350 parts lists --- My guide to computer components
Tempus unum hominem manet
Thanks ArcanaVille !
At first glance, there seems to be issues with this being a true attribmod calculation engine. It appears to be more of an attribmod calculation toolbox. The main loop explicitly creates effects, which in and of itself is fine because any incomplete engine has to inject those somehow, but then also *explicitly* calls functions to compute the things you know are changing: resolve(brutesResistance, &brute, &brute); resolve(brutesResistanceBuf, &brute, &brute); for example.
|
I'm also concerned about this sort of thing: Code:
//keep Cur, Abs and Max in Sync template <> inline const val_type mod<Aspects::Abs>(Attribs::Type& attrib, const val_type valmod){ attrib.aspects[Aspects::Abs].abs_val = attrib.aspects[Aspects::Abs].abs_val + valmod; register val_type val = attrib.aspects[Aspects::Abs].abs_val; register val_type max = attrib.aspects[Aspects::Max].val; register val_type min = attrib.aspects[Aspects::Min].val; attrib.aspects[Aspects::Abs].val = (val>max)?max:(val<min)?min:val; attrib.aspects[Aspects::Cur].abs_val = val / max; attrib.aspects[Aspects::Cur].val = attrib.aspects[Aspects::Abs].val / max; return valmod; Code:
//Cur modding is just a syntactic sugar for things such as heal X% of inspirations |
One other thing: Code:
//"Resistance resists resistible resistance debuffs" //this requires buffs to register specifically as buffs //the less computationnaly expensive way is to test sign at data load. |
Code:
"You DON'T make resistible resist buffs... period" This is ironically a case where you're making it harder than it needs to be, or would be if you handled resistance as the game engine does. |
IIRC, the Original MoG did what ? It was a, irresistible +100% res heal (or more, to cut heals), +100% irresistible heal mod (to remove any damage), -75% irresistible heal mod after a 0,1sec delay (to put you at low health from full health), -10000% cur regen (to cut regen), and insane amounts of def and res, why would it need to have resistible *resist* buffs ? I'm at a loss here
It is also not a good idea to "test sign" to determine what is a buff and what is a debuff. Mez protection buffs are negative for example. You're rolling the dice that a lot of your simplifications won't break something important somewhere. |
Here's my first test of the attribmod engine. Take the Brute and the Corruptor and shoot the Brute with Scream. What happens? |
WE ARE HEROES. THIS IS WHAT WE DO.
City et moi, �a colle !
Originally Posted by Arcanaville
My biggest problem with C++ is that everyone does, for everything. C++ is a language, but saying you code in C++ is like saying you speak in syllables. Any real project large enough to require more than one programmer starts to get into serious coordination issues unless the programmers are clones. Its actually easier in direct C for everyone to do their own thing and meet in the middle than C++.
|
blame the poor habits, not the language (again, no language does prevent its users from making stupidities)
I am in fact a student of programming languages. If you are a compile-time type-checking fan, you'll like templates. If you prefer runtime binding, and if you're using Objective-C and you don't like runtime binding you're insane, templates are usually a redundancy.
|
The reason I mention Objective-C is because, for the most part, MMOs are written with static game engines and dynamic but conceptually encapsulated data. Many was the college student who came onto the boards thinking the Freakshow was a C++ class of which Dreck was an instance. Not only is that not done, there's no really advantage to doing it. But in a language like Objective-C (or Smalltalk, or most other object-based runtime bound environments) there is the crazy-but-interesting idea of converting data to objects at runtime dynamically and using the environment itself as a part of the game engine. A game engine written in Smalltalk or LISP wouldn't need special Requires expression handlers, it could just meta Eval them. Attribmods would convert to methods, and attribmod stacks would just be method stacks. Powers and entities could be redefined on the fly and all interactions would rebind automatically through dynamic dispatch. The problem is, of course, you lose some control over the engine to the environment. You've probably made something a little less like City of Heroes, and a little more like Corewars. |
And again, I'd like to apologize for only making an attribmod calculator, I thought it was only that, that was asked, not an attribmod engine. But basically, you just need to put that in a loop to make it an engine. And you also need to feed the loop, but I simply refuse to do that without the City of Data's generator as reference, as ugly and as incomplete as it may be considered by its genitors
WE ARE HEROES. THIS IS WHAT WE DO.
City et moi, �a colle !
I actually remembered something about inspirations being somewhat of normal powers, but the problem is you always need 4 small insps to get full health, even with Max health buffs.
|
If duration X is >0s, there is a cancellation effect that is spawned and set to be resolved X later. But that requires a full power/effect engine (especially registering current effects on an entity). |
It does because resistible effects and irresistible effects are mutually exclusive, and each effect is applied separately. "Resistible" only means you have to apply the target's resistance (or target's resistance buffs in case of resistance) value before applying the mod. I think. |
(Note I did write "Resistible RESIST buffs, all other buffs can be resistible, does that answer your concern ?) IIRC, the Original MoG did what ? It was a, irresistible +100% res heal (or more, to cut heals), +100% irresistible heal mod (to remove any damage), -75% irresistible heal mod after a 0,1sec delay (to put you at low health from full health), -10000% cur regen (to cut regen), and insane amounts of def and res, why would it need to have resistible *resist* buffs ? I'm at a loss here |
Well, as I said, since it's a one-shot calculator only at the moment, and (as you can see on the City of Data) since the damage is listed first before the resistible resistance debuff, should the power resolution method (not written at the moment) resolve effects in their order, the first tick of damage is not under the influence of the debuffs, but all the other ticks (resolved laters) are. |
I'm still not sure what you mean by "power resolution method" vs attribmod calculation. The order in which attribmod effects are computed is a necessary requirement for the attribmod engine to function properly.
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)
That's not really what I was talking about at all, but in any event, that's about 1% of the work of the entire combat engine. So: assuming I'm looking at about 10 hours of work, with testing and debugging, at this rate about a thousand hours of work and you'll have something maybe close to the complete engine done.
[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.)
Well, as I said, since it's a one-shot calculator only at the moment, and (as you can see on the City of Data) since the damage is listed first before the resistible resistance debuff, should the power resolution method (not written at the moment) resolve effects in their order, the first tick of damage is not under the influence of the debuffs, but all the other ticks (resolved laters) are.
|
So don't depend on city of data being accurate for the exact order that the engine applies effects in, as it intentionally lies about that in some cases.
So, what I get from this fascinating discussion is:
1) It is possible to write an engine that does something with all the powers data in City of Heroes; and
2) writing an engine that does exactly what CoX does with the powers data is much more time consuming than being lax about it
Faced with the possibility of complete extinction, my 20,000ft read is that people would be pretty happy with anything even if it wasn't completely faithful to CoX's behaviors and edge cases. And yes, before Arcanaville stomps on me for it, I'm aware that many of the engine differences would lead to broken power sets and/or unbeatable combos, but then CoX itself had its share of those at launch.
That said, I've always felt that even Arcanaville's estimates were low. Maybe that's because most programmers I've met are less productive than I imagine most of the programmers in this conversation to be. It took me at least two years to do this, and that's a significantly smaller project than building a full MMO. Based on that experience my estimate for CoX would be closer to 8-10 developer-years of effort.
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
Further thoughts...
One of the early hurdles CoX faced was legal rather than technical. If some other entity than Paragon Studios took up the mantle, someone would have to look into the legalities surrounding hero-themed IP and what steps a new game would have to take to protect its creators and even users from lawsuits.
Beyond that, though, it would be really fascinating to see a community-developed MMO. I don't know that any such thing has existed before, at least in quite this form (some early MUDs were open source, and of course the Mission Architect blurred a few lines). With a decent project manager at the lead, you might be able to factor the problem such that a large number of people could work on it in parallel. I'm thinking you could split the project along these lines and allow them to operate somewhat independently:
1) Combat engine and powers
2) Client/server communication, protocols
3) Character creation, costumes, and crafting
4) Critter AI
5) World creation and 3D assets
6) Mission and story authoring
7) 2D UI
8) Chat, registration, and user management
9) Legal and business development
Somewhere in there would be database/persistence management, but it might be split among several teams. And of course once launched you'd also need support staff, both technical and moderation. There may be other pieces I'm missing.
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
OK, I really should be doing other things, but my mind just started going crazy with this.
Suppose this new MMO supported user-generated creative goods: costume pieces, missions and story lines, etc. Suppose further that users could sell them to each other, and the role of the main coordinators was to provide a store for these goods, taking a cut off the top. Would such a model be sufficient to keep the game running? I don't know how to answer that, but it's a tempting answer to the problem of never-ending content in a game that has minimal direct funding for development.
There are previous models for this, such as 2nd Life, but I think CoX has an edge in that it is an actual game and not just an empty playground.
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
OK, I really should be doing other things, but my mind just started going crazy with this.
Suppose this new MMO supported user-generated creative goods: costume pieces, missions and story lines, etc. Suppose further that users could sell them to each other, and the role of the main coordinators was to provide a store for these goods, taking a cut off the top. Would such a model be sufficient to keep the game running? I don't know how to answer that, but it's a tempting answer to the problem of never-ending content in a game that has minimal direct funding for development. There are previous models for this, such as 2nd Life, but I think CoX has an edge in that it is an actual game and not just an empty playground. |
Except if Objective-C has found a way to code an Oracle, it's just the same algorithm as in boost::shared_ptr, as these are also reference counting, and it's still vulnerable to circle-referencing. In boost you have weak pointers for that at least. But I never used that yet, never needed to. I prefer to see the ownerships of things and clear creation such as deep copies and shallow copies.
On other news, I think I've nailed the attribmod library, I'm tackling the Powers & Effects (restricted to attribmod effects, discarding the summon, setmode etc...) one, but that one is hairy, especially the "Ignore buffs&debuffs" flag on powers >_> I need that to "handle how Combat Training: Offensive buffs itself" (which it does at the moment) and resistance toggles. and a whole other bunch of things, with real entities. I could do it quick & dirty but it wouldn't be nice.
WE ARE HEROES. THIS IS WHAT WE DO.
City et moi, �a colle !