-
Posts
126 -
Joined
-
Hey now EK, that was a good idea, and perfect realization. It's not your only one, but this one, I can't stop me from tipping my hat to. Never realized the mustaches were so close to the gaulish ones.
-
You're too funny
All your crazy are belong to you.
-
Devouring earth. Pure and simple.
My main, a Dark/SR Brute, was a demigod, even +4x8, even before the incarnates. Then, a simple quartz was spawned.
That mindless shard just always got me as nude as a MasterMind without pets, but with taunt. -
Quote:J'allais dire ça, mais avec 999,5 ans de moins ^^Non y'a plus d'espoir. Par contre va sur le forum du titan network. Y'a un utilitaire pour sauvegarder ton perso complet (sentinel plus) au cas où le titan network fasse un remake pirate qui prendra mille ans à faire.
Désolé de pas être plus présent, à mon boulot, "la mmmde a atteint le ventilateur", comme disent les anglais, et ça sentait vraiment pas bon. En plus, je préfère bosser pour sauver le jeu ou le recoder que vous tenir au courant, désolé.
Mais ne perdez pas espoir, NC fait la forte tête, mais ils ne peuvent pas ignorer Paragon Studios et des investisseurs bien longtemps. On les aura, même s'il faut recoder le jeu. -
Quote:Like Hide in the stalker secondary, blaster and tanks first secondary (defiance 2.0 shoot through mez and Bruising). But actually those two were simple to "fix" (make Hide an inherent, and leave the first powers special). Then you would have needed a way to prevent the game from letting the player choose 2 primary or 2 secondary as first powers, and from these two situations, only the one where the player had no offensive power was bad.The dev team did look into that. It would have resulted in fundamental game-breaking issues, unfortunately. Not as in game imbalance. I mean as in it would cause things to explode break-wise, as the game makes fundamental assumptions on how powers are assigned.
-
I do remember proposing, long long ago, Electric Control to BaBs, and it had a sort of "polarize" power that used a Repel, but with negative value, that should have done the trick (ie clumping instead of dispersing). I wonder whether that's what they did with this water vortex power.
It was on the 15 July, 2008. -
Quote:Saw the poster of the film on imdb and the ship had a positive memory reaction. It looks like it. Thank you so much ! This thing has been driving me nuts since the internet came and I've been unable to remember the name of that one !Sounds a little like "The Shape of Things to Come" the bad one with Jack Palance not "Things to Come" by Cameron Menzies, that's arguably one of the greatest movies of all time.
Barry Morse and the moon scenes might have made you think of space 1999
Edit: This is definitely it, the alternate name in France is "Cosmos 2050" while Space 1999 is known in France as "Cosmos 1999", so I did not hallucinate. This is so great, thank you again, I would never have been able to find it myself !
Tanker, Controller, Dominator, Blaster... Tanker got Martial Arts not so recently. Dominator and Blaster got Martial assault/Manipulation more recently... Martial/Ki control ? -
Quote:Since we are on that, I wanted to ask some gurus of the 80s, but possibly either early 90s or even back to the 60s. The robot picture reminded me.Hmm, I guess that works. Although I suppose this also works a little:
- You are ALL grey to me.
I remember a film where a robot, sent against the protagonists, was destroyed and got reconstructed, he ressembled Robby the Robot, the bubble arms and round glass head, but wasn't quite like it. There was a dark and red corridor at the beginning also. Then, an asteroid came down on the base, then all I remember was seeing something that ressembled Moonbase alpha from Space 1999, from which the heroes (a family or something like that) took off in a saucer+Enterprise tail ship, then they found another planet they explored in the saucer only part of their ship.
That's all I can remember of the film, I thought I labeled the VHS "Space 2000" but I can't quite really remember, but for reasons unknown, I took the VHS apart to see how it was functionning. I was 8 or so at the time, so it's quite old and doesn't make any sense.
Could you help me put a title on that ? Thank you ! -
Quote:Boost is templates.Heh, my generic bin file dumper that handles most builds back to I18-ish weighs in at about 3MB, which in my opinion is about 2.5MB too big for what it does. That's a x86-64 release build, stripped of debug info. When I dug into it, I found that most of that bulk is static initializers from STL containers, and the umpteen different versions of them that got instantiated from all the possible classes that could be stored in them. Boost is a hog as well, as nifty as some of the metaprogramming you can do with it is.
Quote:Memory is plentiful until you use it all up. Also, don't forget that while CPUs are very fast, memory bus bandwidth has not scaled upward as quickly and is lagging behind. So you have a ton of memory, and a ton of CPU resources, but a relatively small bottleneck to load data from that memory. In practice, performance is limited by the CPU's L1 cache, and to a lesser extent, the L2 cache.
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.
Quote: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... -
Quote:Okay, you've not exactly answered what I asked because I'm expressing myself funnily, but that's conforting to know another, less suspicious assumption, but an assumption none the less, was true.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.
Quote:I'm not sure why you believe I thought this was possible, if that is what you are implying.
Quote: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.
Quote: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. -
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. -
Quote: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 :')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.
-
Quote:Yeah I understood that. But what's the point of knowing this powers's duration or magnitude is resisted, when it's irresistible ? =) But you need another bit anyway. I want ternary computer =)Technically the engine has separate flags for whether resistance (and combat mods) affect magnitude or duration.
Quote:Practically, and this is something I went back and forth with Arcana on a while back, it seems that these flags are automatically assigned by whatever tools the devs used to compile the data. So effectively it is based on the type of the effect.
Quote:IIRC, based on datamining, I determined that there is a fourth option -- if a Constant type effect is resistible, both its magnitude and duration will be resisted.
Constant attribmods are ones where the Scale is not used at all; instead the base Magnitude and Duration from the power definition is used. They're fairly rare, however, and almost always use one of the 'special' Attribs that isn't really an attrib at all, like GrantPower.
Quote:It's the Type field of the attribmod. I don't know of any way to directly determine that in-game, though real numbers gives you some clues based on how it formats the numbers.
Quote:CurAbs is just an alias for Abs. I have no idea how often it's used, as we only have the binary representation of the data, not the source text files that it's compiled from.
Many of the constants in the game engine are prefixed with 'k'. That doesn't really mean anything, it's just a convention that they used for some of the constants. Probably because all of them go into a giant global hash table, and it's to try to prevent the inevitable namespace collisions.
Here's the binary representations that are defined for attribmod type:
kCurrent=0x00000000
kMaximum=0x00000004
kStrength=0x00000008
kResistance=0x0000000C
kAbsolute=0x00000010
kCurrentAbsolute=0x00000010
kCur=0x00000000
kMax=0x00000004
kStr=0x00000008
kRes=0x0000000C
kAbs=0x00000010
kCurAbs=0x00000010
Quote:You'll notice these are separated by 4. The normal attribs themselves are as well. For attribs, the ID number also doubles as an index into the memory block where the attributes are stored (32-bit single precision floats). My theory is that on the server side, it keeps a separate copy of that block for each aspect, so the server keeps 2300 bytes worth of data on hand to describe the combat state of every entity. That's 115 attributes * 4 bytes = 460 bytes * 5 aspects = 2300.
Quote:Meter (aka kMeter) is an attrib just like HitPoints or Endurance. The client uses it to draw the 'tertiary bar' for things like Fury or Domination. It's one of the few attribs that is kept in sync between the client and the server, because it's used for the UI.
'Rage' is the attrib that is actually granted by things like Brute and Dominator attacks. Brutes have an inherent power that on every tick gives them Meter based on how much Rage they have. IIRC, the damage buff is based on the current value of Meter, forming a kind of feedback loop (which the inherent power that handles Fury decay takes advantage of). -
Quote:Neat, so there is still only one resistance and one strengh for an entity attribute and it does become "Magnitude resistance/strengh" or "duration resistance/strengh" because the effect is flagged to be magnitude-resisted or the other, and this flag is a boolean. Also, one same attribute can be duration or magnitude at the same type in different powers, so no hard coding that in the "modification" of the value when the effect is resistible. Actually, that makes it a 3-value flag whether the effect is to be duration-resisted, magnitude resisted, or not at all. Makes me wonder if there isn't a fourth possibility.That's technically not true. Technically speaking, Magnitude Resistance decreases magnitude using the Scale * (1 - Res) formula. Duration Resistance decreases duration using the Scale / (1 + Res) formula.
Which one you use is based on the type of the attribmod. This is another important feature of the game engine. Strength and Resistance all affect the net scale value of the effect. But whether that net scale value is the magnitude or the duration of the effect depends on a type flag. Virtually all mez powers have their mez effects typed "Duration" and that's why slotting enhancements into them increases their duration. Damage effects are typed "Magnitude" and thus enhancements boost the magnitude of those effects, not duration. Its not baked into the attribute type nor the enhancements how this works: its keyed off a type field.
Interestingly, mez protection buffs are often typed magnitude, not duration. That means in theory if you could slot them with mez enhancement, your protection would get higher. You can't do that, so you can't see this effect. But you *can* see this effect if you have someone Benumb you in PvP: that will cause your mez protection magnitude to actually go down, because those debuffs affect mez strength, and that strength reduction in turn makes your mez protection pulses drop in magnitude, because they are typed magnitude.
About buffs to status and status protection, get a character with power boost and Tactics or any Leadership power that protects against status. I'd do it if I wasn't at work.
Quote:In any case, this is just an informative tangent. The obvious reason why 10,000% equals confused dev is because someone put "100" into the powers spreadsheet for that resistance, thinking "100% resistance" when the correct thing to do was to put in "1.0" which is 100% resistance. This error was never corrected, because there's no obvious sign of a problem when you make this error: both make you absolutely immune to all (except unresistable) knockback. Because knockback effects are generally typed "Magnitude."
The rule is: Strength and Resistance can only affect Magnitude or Duration, not both, and both always affect the same thing. So if slotting enhancements into KB powers increases the mag of the KB, KB resistance reduces the mag of those same powers. They go together because of a fundamental property of the way the game engine handles scale values of powers.
Quote:Coincidentally I was just starting to write some code for my attribmod engine and was thinking about that specific issue. Because for efficiency sake, it makes no sense to push around all the data for the attribmods; in a practical sense attribmods are static and all you need is to use pointers to them. That's almost certainly what the actual game engine does. But you do need to pass one piece of information around: the effective scale value of the attribmod when its instantiated. And that's because it will be modified by the entity's tables (usually) and the entity's strength. But you can precompute that because an attribmod's net scale value is immutable upon creation. It can be affected by variable target resistance, but not by variable caster strength.
Quote:Thus, you end up with something like this:
Code:def applyAttribmod(attribmodId, powerId, entityId, triggerTime, trueScale): expireTime = triggerTime + AttribmodDB[attribmodId][kduration] nextAct = triggerTime attribmodStack.append([attribmodId, powerId, entityId, triggerTime, trueScale, expireTime, nextAct])
In my idea of implementation, you should keep time like that until this power is the next one to resolve on this entity, when it's really needed to keep track of the "delay remaining".
Quote:After 1.5 hours of coding, I have a data import routine for archetype tables, some class stuff for entities, and the definitions for basic attribmods. In terms of actual code that does something, here's what I got:
Code:while True: # this increments the clock by 1/30th of a second with alignment if clock % 100 == 0: clock = clock + 34 else: clock = clock + 33 if clock > endtime: break
Also, I already thought of all that, it is sorted out, I just wanted to have sorted out the formulas before I went forward. If it's just a matter of adding variables to structures, it's not a problem. If you have to code new functions for new cases, it's another matter.
Quote:71 actual lines of code, ~90 minutes. Going to try to tackle Abs, Str, and Res tomorrow. I have an idea on how to manage Cur without having to track a lot of funky exceptions, but that will require more algorithmic thought.
Also, you didn't answer my question about whether you did have evidence Cur is used for time-limited attribmods, or Cur is the time-limited attribmods-dedicated storage value because it is. Is that going to be answered any day or are you keeping your sources a secret ? I'm a scepticist, so I need evidence. At least answer what line (in powers.bin ?) did say defense buffs were Cur mods, without modifying the wording (as Codewalker said "kCurAbs", and I saw kMeter...
oh shucks.
isn't kCurAbs a sort of pointer/flag to designate which of Abs or Cur is gonna be moded ? like kMeter could be a pointer to a meter/attribute, and these variables/aliases are part of the attribmod attributes ??
Please, Codewalker, could I have a look at Mids and City of Data interpreters of powers.bin ? This could answer so much. -
Quote:Answer is, we want to have the unresisted effect. So my implementation is (going to) be incorrect. Well was, because I know that I need to correct this.Just to get a pictured case, and a test case in AE, what do we want to happen when this happens ?:
Brute has 40% res to energy, brute gets hit by thermal radiation.melt armor, brute toggles off its defensive toggle, melt armor expires.
We want to brute to get back to 0% res. But what happens during the time the melt armor is the only remaining effect ? is it the full debuff or the resisted debuff ?
Against melt armor mobs in AE, my resistance went 33.38,18.99 then -21.6 then 0. So they *do* recalculate everything everytime res or unresisted res gets modified, so you've got to store the applied value and delay the cancellation value computation until, well, the cancellation. -
Quote:Just to get a pictured case, and a test case in AE, what do we want to happen when this happens ?:No good. If you have an effect on the target that is resistable, and then the *resistance* expires, you have to recalculate all of the resistable effects. In the general case, you have to recalculate the attribmods for every tick of time in which its theoretically possible for resistance to expire, and dealing with this with special cases just makes things more complex. It makes more sense to recalculate attribmods on every tick of the clock. Otherwise, you're just asking for problems. And I haven't really fully thought about whether there are other failure modes besides expiring resistance, because it would never occur to me to take this short cut in the first place, because its already known to be broken.
Brute has 40% res to energy, brute gets hit by thermal radiation.melt armor, brute toggles off its defensive toggle, melt armor expires.
We want to brute to get back to 0% res. But what happens during the time the melt armor is the only remaining effect ? is it the full debuff or the resisted debuff ?
Quote:Endurance has both Abs and Cur applied to it. And in fact, Cur modifications on Endurance are permanent. Which actually creates an unanswered question for me: are endurance cur effects flagged to be permanent, or does the game engine presume Cur effects on Endurance are permanent automatically? Both are theoretically possible at the moment, although I suspect its the latter that is true due to a bug that occurred several issues ago that demonstrated what the game engine does when you apply a Cur to health with a duration inadvertently. I would personally code it that way without direct evidence to the contrary.
Quote:The game engine doesn't deal in percentages at all. 1 def would be 1.0 def, which would in effect be 100% defense, but the game engine calls that 1.0. For reference, Focused Fighting offers a base 0.13875 buff to Melee_Attack Cur. To be more precise, it offers 1.85 Scale buff to Melee_Attack Cur, using the Melee_Buff_Def table. For Scrappers, that table contains 0.075 for all levels. So Focused Fighting offers a net 1.85 * 0.075 = 0.13875 buff to Melee_Attack Cur, which we players call "13.875%"
Quote:A Cur buff is Scale * Max in value.
Quote:I don't think it is, for the game engine to work in the general case. I believe the special case logic required to do anything else would not make the alternative significantly faster without breaking things.
Quote:Attribmods are time dependent effects, and there is no such thing as an effect separate from attribmods in the City of Heroes game. Attribmods are effects: Attrib-mod: Attribute-Modifier. They are the only mechanism for producing an effect in the game.
Quote:I'm aware of all that, but my comment stands. Based on what I've seen, there's no way to extrapolate this effort into a full combat engine in four weekends of work; there's no way to extrapolate this effort into even just a full attribmod calculator in four weekends of work: I'm dubious its even possible to extrapolate this into a stripped down version of an attribmod calculator that excludes extensions such as expression evaluation and entity spawning in four weekends. I still believe you're vastly underestimating the scope of the problem, and your code is doing much to narrow down the margin for error that exists for how fast you could possibly do it.
I don't see the point here. Status resistance decreases duration, not magnitude (another special case ? Yes, I have to code that) -
Quote:When you apply a resistible debuff/buff, you're modifying the resistible value of the mod with (1-res) and apply this mod directly to the result... as if it was irresistible ! Right ? So you (well my code at least) fall back to this case. And what do you do to cancel an irresistible mod ? You use an irresistible mod with opposite value ? Yes ! That's what I made, well, actually set up only, in my attribmod code (you must have found funny that my functions returned a value instead of nothing, and also, applying an Effect returns an Executable instead of void). Why, do you ask ? That's the raw cancellation effect that you would need to apply if the effect had a duration. You (nearly) have the result on hand, even if the effect is of no duration (such as heal or damage), it takes nearly nothing to leave it on the stack, so I put that as the signature of the method. This was how I would have tackled the "engine" part, leave the cancellation on a stack to apply later on or upon removal of the effect.Originally Posted by ArcanavilleEven if you punt the actual mechanics of the clocking, the code doesn't seem to even have any hooks for clocking. It applies effects in a way that makes it difficult for them to expire in random order, because the effects are entangled with resistances. You could create an expiration queue to basically apply the inverse effect upon expiration, but you have to be very careful to honor intermediate floors and ceilings when you do that. It seems very likely that this code doesn't just omit clocking, it isn't trivially extensible to being clocked.
Let's suppose you are right, you in fact do have Cur that sums the duration-based effects and Abs the others. You anyway need to have a timer on hand for each effect in order to know when to cancel them, and what amount to cancel each effect individually, or you need to reconstruct from adding all the remaining effects, which is the same amount of data but plain computationally inefficient. Something that takes as much or less space and calculation is to keep the list of "timer & cancellation value" per applying effect instance, and you don't need store each sum separately, because "Abs+(Cur-Cancellation)" is "Abs+Cur-Cancellation". So it's more effective to store the total in either Cur or Abs as the result, and apply cancellations over it.
Also, I didn't find any duration-infinite status effect, Regen, Recovery or Recharge buff or debuff. Only damage, health and endurance modification are "infinite" and "absolute" modification (or am I missing something ?). And those don't have duration-finite modification to their Value (Spectral Wound's damage gets couteracted by a heal, not negative damage). In fact, I didn't find any attribute that needs both of them.
Also, about flooring and ceilings, you may have found that in my code I have a 'val' and an 'abs_val' fields in every Aspects. That's because "getters" are reading the val that is floored&ceiled version of the abs-val that is the blunt sum of all mods, and val gets updated when the Aspect gets modified (I was supposing you had far more reads than mods, so I opted for this "caching". But that's quickly changed if the contrary is proven)
Quote:Mezzes, and by extension mez protection powers, are Cur effects with a limited duration. As are defense buffs, movement speed, and just about everything except for damage, come to think of it.
Cur applying as a percentage of anything seems to be a quirk of the implementation and as far as I can tell only applies for certain attrib types (damage, endurance, hitpoints). The Cur effects for defense powers certainly don't end up adding a percentage of the defense cap for that level.Quote:All of them are. Movement buffs are sometimes Cur. Defense buffs almost always are.
So, what is Cur ? The only thing I find making sense is an old post from Arcanaville about Cur being something like (Abs-Min)/(Max-Min), meaning that with an attribute being in between 0 and a max, it's the normalized value of Abs to the Max.
Quote:Yes and no. The way the server works, the engine does an unresistable pass and computes intermediate results for resistance. Then it does a resistible pass and computes all other values given the intermediate resistance. In other words, lets say you have a target with 80% resistance (to something) and it gets hit with a -30% unresistable resistance debuff and a -20% resistable resistance debuff. The game engine calculates the target's intermediate resistance based on all unresistable effects, and gets 80-30=50%. Then it calculates the effects of all resistable effects given that resistance: the -20% debuff is reduced to -10% because of the effective resistance at that moment, and the final resistance drops to 50-10 = 40%.
Quote:However, one clock later, the server starts over.
Quote:I did say that, but being able to calculate "moment by moment" is exactly what it sounds like. You don't need to implement a clock, but you should be able to state what the current attribute values are for a *given* moment. If I say "+1.2 seconds" the calculator should be able to say. But it can't, because its not just unclocked, its completely time-unaware. And a completely time-unaware scale summer is something I could do in a single afternoon: that's an extremely tiny component of the whole. Its so small I would never write it time-unaware, because of the strong possibility my code would not be extensible to a clocked environment.
Quote:I don't see how you are rationalizing it as part of the "powers" engine. The only thing that makes any sort of sense is you're thinking of making the attribmod equivalent of micro-ops and breaking down time-dependent attribmods into micro-attribmods and clocking them outside of the micro-attribmod engine. Which is fine, except that doesn't allow you to redefine the scope of the problem to be writing the micro engine, because that eliminates the bulk of the complexity of the problem.
Quote:No one says its impossible. What is true is all non-experts think they are far better than they actually are. In fact, most of the experts tend to think they are better than they actually are also.
Quote:That's a fair point. I'm working the next two weekends, so I'm going to try to steal some nights and write an attribmod calculation engine. My guess is that given the context we're talking about, that's about 40-50 hours of work for all except the expression engine, entity spawning, attribmod distance effects (basically, inner and outer radius), and boost templates (basically all attribmods will be assumed to be flagged to be powers not enhancements). Maybe some other little flags I'm not considering, like the set bonus ones.
Lets see how long it actually takes.
Enhancement are a different beast, I have an idea of how to implement them, but it's going to be Carte Blanche since I didn't see anything about how they could be handled by the server. But given how the Dual Pistols powers work, and how efficient it's going to need to be, I have this idea. But it'll come later.
I think entity spawning can be done by the movement engine, I mean, very basic entity spawning, like an empty shell, to pass to the power engine for such things as summoning pseudo- and full pets and so on. You could these empty shell for effects that would then only need to provide templates to these empty entity, transforming them into full-fledged Ice Storm and whatnot. Also, you could copy your attributes to them to buff their powers exactly as yours, or as default the movement engine creates clones of you as fork/exec does in UNIX. -
Did test with a crabspider, you're right. Great! So the question is, do we need (i.e. is there a power with) duration-limited +-X Cur effects ? (we do need one-shot Cur mods, that's not the question) But that's in the event that Cur is just a 0-100% representation of Abs in regard to Min and Max as you said in another thread. But I'm beginning to understand given your formula you wrote below that maybe in Cur are added resistible mods and in Abs the irresistible mods. Or in Cur time-restricted mods, and in Abs time-infinite (or one-shot) mods. So what is right ?
Quote:I don't see why. An attribmod calculation engine should be able to, given a list of attribmods, determine what is going on at time t, for all t. Otherwise, as I said, its not an attribmod calculator. Its just a calculator with a lot of rows.
Quote:I haven't had a chance to analyze the code completely yet, but what I meant was that resistable buffs are resisted by the resistance of the target after unresistable buffs are accounted for first.
Quote:You're going to special case resist modifiers separate from all other modifiers?
Quote:You can't rely on City of Data for order of operation.
Quote:But in any case, that's your explanation of the effect: I'm asking what your calculator says, not what you personally know.
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)
Quote:Honestly, I recommend you to spend just a single weekend writing as much of an attribmod calculator as you can. Not even an engine, just a calculator that can be given a set of attribmods and will calculate what the attribute values are for the entity that has them for the full duration of those attribmods, moment by moment. That's like at most 1/6th of a full combat engine. If you think you can write a full combat engine in four weekends, you should be able to do this in one without missing the NFL late game.
Just try it for even one hour and see how far you get. I can only assume you are dramatically underestimating the time necessary because you have no reference to compare to.
Quote: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.
But let's stop playing "that's what you said" "-No what I said", "That's not what I meant"... Someone earlier in this thread posted a link that basically said it's impossible to plan or estimate a plan effectively because there are so many unknowns, either that or you have an all-seeing eye and/or pure luck, or take excessive amounts of margin, and guess what, you and I are just trying to guesstimate the time it would take to code this. And I'm the only one to actually work to try to measure that, and you're the only one able, or at the very least the best fit, to evaluate this. You already corrected approximately 5 things I misunderstood or thought I knew, and I may have corrected myself to 3 or 4 on my own by looking at the Paragonwiki and City of Data, and Codewalker did some more. I think I did ridiculize myself quite well already, but I want more because my mind just can't stop thinking how to implement the thing. I guess it thinks it's a hero.
I think we have sufficiently derailed the thread here, in fact, it may already be overtaken. I would like to take this moment to (finally) apologize to Bill Z. Arcanaville, would you like to continue this project discussion/report/criticism in another thread, maybe in another forum ? (there is a city sunset category over at the Titan Network) -
Quote:Yet, everything is just prevented by actually *reading* the header, where the overloaded new operator is defined...Originally Posted by ArcanavilleMy 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)
Quote: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.
Quote: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 -
Thanks ArcanaVille !
Quote:Well, I didn't want to get into the power parsing part of the engine, because someone else already did it, so I only made the calculation toolbox, yes. The engine still lacks input this way, you are totally right.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.
Quote: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
Quote: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.
Quote: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
Quote: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.
Quote:Here's my first test of the attribmod engine. Take the Brute and the Corruptor and shoot the Brute with Scream. What happens? -
Quote:I've had problems with geany (a lightweight IDE) not properly recognizing .h as C++ headers but as C headers instead, making it unable to parse the file properly and I had to change the document's language by hand each time I opened a C++ .h header >_<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. -
Quote: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.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). -
-
Quote:I'm going to answer that myself. In melee powers for instance, you don't benefit from range boosting, obviously, and VIP Temp powers don't benefit from your Damage nor Recharge. In fact, these flags should only be for Damage, Recharge and Range, I think. Am I right ?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]. -
Quote:and debuffs. I'm talking about that one.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.
Quote:There's the "ignore buffs and enhancements" flag on individual attribmod/effects that ignores ALL strength buffs, even ones that come from slotted enhancements.
Quote: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.