Login | Register  
Latest 20 PostsMinimize
04 Sep 2010 05:25 PM
28 Aug 2010 08:51 PM
RE: MONO - Fastalanasa
28 Aug 2010 01:51 AM
RE: MONO - Taliesen
28 Aug 2010 01:31 AM
RE: MONO - Fastalanasa
27 Aug 2010 04:10 PM
RE: MONO - Taliesen
27 Aug 2010 03:16 PM
RE: MONO - Fastalanasa
27 Aug 2010 09:26 AM
RE: MONO - Karak
27 Aug 2010 05:04 AM
RE: MONO - Taliesen
25 Aug 2010 04:00 PM
RE: MONO - Fastalanasa
25 Aug 2010 04:49 AM
RE: MONO - Taliesen
23 Aug 2010 04:19 AM
RE: MONO - Fastalanasa
23 Aug 2010 02:57 AM
23 Aug 2010 02:54 AM
RE: MONO - Taliesen
23 Aug 2010 02:52 AM
RE: MONO - Fastalanasa
23 Aug 2010 02:36 AM
RE: MONO - Fastalanasa
23 Aug 2010 02:13 AM
RE: Stat System - Fastalanasa
23 Aug 2010 01:57 AM
23 Aug 2010 01:34 AM
23 Aug 2010 01:32 AM
23 Aug 2010 01:30 AM
ForumsMinimize
Effects: Stacking / Non-Stacking
Last Post 01 Jul 2009 01:20 AM byFastalanasa. 13 Replies.
Printer Friendly
Sort:
PrevPrev NextNext
You are not authorized to post a reply.
AuthorMessages
KarakUser is Offline
Locutus of WheelMUD
Advanced Member
Advanced Member
Send Private Message
Posts:501
Avatar

--
09 May 2009 06:54 AM  

Allowing a player to circumvent a bad effect by gaining a weaker effect of the same kind is clearly a problem.

Directly modifying the entity's stats is probably dangerous overall.  It seems games tend to have a "base" stat and a "current" stat, the latter being a throw-away-value that is recalculated from scratch as needed.  IMO this should apply not only for numeric stats, but things like the "enabled" bools for senses as well.

As for stackable/non-stackable buffs:  there are situations where both are useful, even more so based on underlying game system where for instance, two strength-boosting spells may or may not be stackable.

One solution I see is building the application of effects in a way that both are possible and work together (but any given system might chose to use only one methodology).  What I'm thinking this would look like would be:

* All modifiable Sats and Senses values will all gain a "current" value like Senses[SensoryType.Hearing].currentlyEnabled or Stats["strength"].currentValue.

* These will not be modified directly by random code;  they will be recalculated at specific times to determine what the current value should be.  For instance, when a StatEffect is added or removed from an entity, the StatsManager would iterate through the entity's current list of effects, looking for StatEffects, and recalculating the current value of each stat.  Same thing for the SenseManger recalculating the current senses whenever a sensory effect is added/removed. (Aside: generalize SensoryEffect instead of just DeafEffect etc?)

* The managers' recalculation methods would also be called any time the Real values change; such as stats gained permanently via levelling up.

* During the iteration of effects, the total modifiers would be tracked independently for 4 categories: 

-- highest positive modifier for non-stacking effects (ie the biggest "str boost" spell)

-- lowest negative modifier for non-stacking effects (ie the worst "str sapping" spell)

-- total accumulation of stackable postive effects (ie a handful of different "str boost" effects)

-- total accumulation of stackable negative effects (ie a handful of different "str sapping" effects)

* Current value = Real value + MAX(the "highest positive non-stacking", "total accumulation of stacking")... thus we are treating all stacking effects as one accumulated effect for purposes of seeing if it overrides a non-stacking effect, in the event of there being both kinds of modifiers in this game system.

* Note that this totally removes the awkward "reduce the modifier to the biggest modifier it can be without setting the stat above the maximum" code since the post-recalculation would just set the "current" equal to max if it was greater than max.  Ditto for enforcing minimums.  This also totally fixes bugs that would have otherwise occurred around adding/removing effects in succession near the maximums and minimums.

Did I explain that well?  Does that seem viable?

~ Karak

FastalanasaUser is Offline
Grumpy Half-Elf
Advanced Member
Advanced Member
Send Private Message
Posts:705
Avatar

--
09 May 2009 05:48 PM  
I think we also need to introduce precedence with effects. The new deafen effect is a good example of what I want to work with. In meatspace, when somebody is deafened, no other deafened effects can occur, because the sensory apparatus is already overwhelmed, meaning that it is turned off and can't receive additional sensory information. This is one mechanism that could also be used for stats, just one of many.

"Directly modifying the entity's stats is probably dangerous overall. It seems games tend to have a "base" stat and a "current" stat, the latter being a throw-away-value that is recalculated from scratch as needed. IMO this should apply not only for numeric stats, but things like the "enabled" bools for senses as well.

* All modifiable Sats and Senses values will all gain a "current" value like Senses[SensoryType.Hearing].currentlyEnabled or Stats["strength"].currentValue."

That's exactly how the previous code incarnation handled it. That way the entity had what was persisted, and a calculated game value.

One thing that I don't see in code right now, maybe I just don't know where it is, is a sort of Heartbeat/Tick system. That system will send a MUD-wide announcement that a heartbeat happened and to process whatever is needed. That's what the TickElapsed is for (at least that's what it was used for in the previous system).
KarakUser is Offline
Locutus of WheelMUD
Advanced Member
Advanced Member
Send Private Message
Posts:501
Avatar

--
09 May 2009 09:29 PM  
Sounds like we're on a good track here. When we get to chosing what effecs to add to the entity or not, we still have to consider if people can "cheat" by getting "weak" versions of any given detriment type just to avoid a more major version... but I would probably be ok with sometimes chosing not to add a weaker versions of an Effect when you have one of the same type that is stronger and longer-lasting, or with logic that sometimes upgrades an existing Effect with a new stronger and longer-lasting one that is applied. Basically, I've seen a MUD back in the day where if you didn't intentionally, constantly go get yourself poisoned with a minor (but ideally long-lasting) poison on purpose, you were "doing it wrong." This feels akin to catching a minor cold so that you could safely wade through the Bubonic Plague at every turn. Quite silly IMO :)
ShabubuUser is Offline
New Member
New Member
Send Private Message
Posts:92
Avatar

--
10 May 2009 04:36 AM  
Posted By Fastalanasa on 05/09/2009 10:48 AM
One thing that I don't see in code right now, maybe I just don't know where it is, is a sort of Heartbeat/Tick system. That system will send a MUD-wide announcement that a heartbeat happened and to process whatever is needed. That's what the TickElapsed is for (at least that's what it was used for in the previous system).


Just as an aside, as it is now, TickElapsed in the Effects is when the effect wears off.  It is not a regular heartbeat.

I'm having to play around making a DOT poison effect with the TickElapsed calling the same class's Apply method.  Kind of fun, but a seperate HeartBeat or Tick would be nice. :)

ShabubuUser is Offline
New Member
New Member
Send Private Message
Posts:92
Avatar

--
10 May 2009 04:43 AM  
Posted By Karak on 05/08/2009 11:54 PM

(Aside: generalize SensoryEffect instead of just DeafEffect etc?)

Without knowing how the whole thing works, I was afraid of making it a generalized effect.

A deaf and a blind might stack, but two SensoryEffects might not.  Also, bit arraying them together makes more code - which isn't needed until the design is all finalized. 

It'll be easy once this system gets finalized to condense it all down to one if there is no reason to have them apart.

But, without more work, an eyedrop item that cures blindness, might also cure the deaf if they're just one general effect.

ShabubuUser is Offline
New Member
New Member
Send Private Message
Posts:92
Avatar

--
10 May 2009 05:07 AM  
The problem with some might be stackable and other's aren't is that we now might have to do a classification system.

Some effect giving potions, might give more than one effect (Prismatic?)...it might be an intelligent boost, dex boost, +2 str boost.

Someone casts Strength of Bull on same person...which could give an unstackable +3 str boost.
Do we undo part of the potion's effects? Or just say that Str of Bull cannot be applied? Or unapply all of the potion's effects, arguably the worst case scenario, even though Str of Bull has a higher bonus in one stat.

Do we classify Spell effects differently than Potion and Skill effects, so they can be separate in our effect checks?

There are tons of ways to do this, hopefully we find a way that isn't a list per effect that trumps known effects. :)

If we're trying to make this non-ruleset specific, wouldn't we have to take all these possibilities into account?
KarakUser is Offline
Locutus of WheelMUD
Advanced Member
Advanced Member
Send Private Message
Posts:501
Avatar

--
10 May 2009 05:45 AM  
On the other hand, if you have a spell that "cleanses all detrimental sensory effects" then the code for that would have to find DeafnessEffect, BlindnessEffect, BlockTremorsenseEffect, ... Maybe there should actually be a SensoryEffect but then the DeafnessEffect inherits from it and we get the identification benefits of both types of needs?

I think with your example, the potion can apply 3 Effects instead of just one. If we needed to go the other direction, like with a Magic Dispel, then the effects could be tied together with an ID in case the whole package needs to go away? *shrug* A set of effects is probably what we'll want for equipment and the like with essentially non-expiring effects that only go away when you remove the equipment. We probably wouldn't want a seperate Effect file to have to be built for every combination of effects like for goggles that add +2 Int but also +20 to your Sight sense. Might as well use the same approach for potions with multiple effects as with equipment that have multiple effects?
ShabubuUser is Offline
New Member
New Member
Send Private Message
Posts:92
Avatar

--
10 May 2009 05:59 AM  
Posted By Karak on 05/09/2009 10:45 PM
On the other hand, if you have a spell that "cleanses all detrimental sensory effects" then the code for that would have to find DeafnessEffect, BlindnessEffect, BlockTremorsenseEffect, ... Maybe there should actually be a SensoryEffect but then the DeafnessEffect inherits from it and we get the identification benefits of both types of needs?

I think with your example, the potion can apply 3 Effects instead of just one. If we needed to go the other direction, like with a Magic Dispel, then the effects could be tied together with an ID in case the whole package needs to go away? *shrug* A set of effects is probably what we'll want for equipment and the like with essentially non-expiring effects that only go away when you remove the equipment. We probably wouldn't want a seperate Effect file to have to be built for every combination of effects like for goggles that add +2 Int but also +20 to your Sight sense. Might as well use the same approach for potions with multiple effects as with equipment that have multiple effects?


Good idea, I'll make a SensoryEffect and then inherit from that.  Perhaps a StatChangeEffect that is inherited will be a good idea too?  StatChangeEffect -> IntModifier.

I'm wasn't thinking along the lines of a new effect that does 3 seperate things, but of an item that applies 3 seperate effects.  So, we're in agreement on that.  In the end, we probably only need a handful of effects that do all we need.

But, my question still stands with this further clarification. :)

slowreflexUser is Offline
Forum Wraith
Basic Member
Basic Member
Send Private Message
Posts:171
Avatar

--
13 May 2009 08:06 AM  
For handling stackable effects you have quite a few choices that I can think of:

1. Each stack of the effect resets the duration timer

2. The stack of the effect increases the effect but uses the original effects existing timer

3. Each stack takes the average of the existing stack timer and the new timer. Example: Example: Say there are four stacked effects with a current average duration of 10 seconds. If another effect is cast with a duration of 30 seconds, the new average duration would be (1 X 10 + 1 X 30)/2 which is 20 seconds.

4. You do a weighted average. Example: Say there are four stacked effects with a current weighted duration of 10 seconds. If another effect is cast with a duration of 30 seconds, the weighted average duration would be (4 X 10 + 1 X 30)/5 which is 14 seconds.

5. Each effect in the stack has a separate timer

Personally, I like #3 or 4. #1 is too overpowered. #2 is too underpowered. #5 is good as well, but probably harder to code/more mem. However, if you are trying to make a powerful server that is customizable, you would program all five options and have the choice per spell effect. :)

If an effect isn't stackable then you would likely just overwrite it if the new effect is stronger or last longer than the existing effect.
NostradamusUser is Offline
New Member
New Member
Send Private Message
Posts:27
Avatar

--
29 Jun 2009 09:48 PM  
I know that many Discworld-derived MUDs have an (optional) merge_effect method called if it is already present on the target. This allows each effect to decide how it merges - if not defined, the latter effect would replace the former.
e.g. this old LPC sample:

mixed merge_effect( object player, int time1, int time2 ) { ... }

Might you also want to have a check in the EffectsManager to see if the effect is allowed to be added?
e.g. public virtual bool IsAllowed(IThing host, IThing creator) { return true; } in EffectBase

This is not necessarily about merging, but could prevent effects from taking place under certain circumstances, e.g. someone with a "wet" effect might not be vulnerable to a "boiling oil" effect.
FastalanasaUser is Offline
Grumpy Half-Elf
Advanced Member
Advanced Member
Send Private Message
Posts:705
Avatar

--
30 Jun 2009 06:47 AM  
Interesting! I didn't know that Discworld had that. Unfortunately, I've only worked with TMI 2, Nightmare, and LimaBean. My background is mostly MudOS with TrekLib (by Zortek). I've played around with DeadSouls, but not as much as the other mudlibs.

You do make a good point about the EffectsManager. We've talked about this exact scenario in the recent past. We are still working on some low level crap, so we haven't got there yet. However, why don't you submit a patch in the meantime? Then we could have this as a placeholder, for when we get to work on that area.
NostradamusUser is Offline
New Member
New Member
Send Private Message
Posts:27
Avatar

--
30 Jun 2009 02:22 PM  
Thanks - I will do so once I get home from work.

(Though I am not sure that DW itself has that, but my old MUD's codebase was derived from the DW skylib base, and we had that logic. The beauty of the "mixed" datatype was that you could actually pass anything to merge_effect for the "old" and "new" arguments as long as you were consistent all the way through.)
NostradamusUser is Offline
New Member
New Member
Send Private Message
Posts:27
Avatar

--
30 Jun 2009 11:05 PM  
When merging effects, one of the key problems would be the treatment of the senses.

Currently, senses are enabled or not. What this means is that you couldn't combine a long-term deafness (maybe a cursed item) with a short-term deafness (Thunderclap-type spells) without either:

a) Preventing stacking of sensory effects - this could leverage the changes I'll be submitting as a patch.
b) Some form of custom merging logic to determine an increased duration.

However, you could easily facilitate this logic by holding each sense as an counter rather than a boolean. To deafen (for example), your effect would do something like:

this.Host.Senses[SensoryType.Hearing]--;

And to restore it, conversely:

this.Host.Senses[SensoryType.Hearing]++;

With you needing to have 1+ in a sense to use it.

This would allow you to stack the effects quite easily, as long as you balance the increment and decrement calls!

Nos.
FastalanasaUser is Offline
Grumpy Half-Elf
Advanced Member
Advanced Member
Send Private Message
Posts:705
Avatar

--
01 Jul 2009 01:20 AM  
Hmm, I thought I had added a CurrentLevel to the Sense class, but I guess I forgot to add it. Senses can be calibrated using the HighThreshold and LowThreshold properties, then the CurrentLevel will tell the framework how well it is working. So as the value gets closer to LowThreshold, the worse it degrades. On the other hand, the closer the value gets to HighThreshold, the better it works. Anything over the HighThreshold, means that this sense is getting overloaded. Just imitating Mother Nature. My biology classes did come in handy after all. ;)
You are not authorized to post a reply.

Active Forums 4.2
Copyright 2007-2010 by WheelMUD  | Terms Of Use | Privacy Statement
Google Analytics Alternative