ToME: the Tales of Maj'Eyal

Everything about ToME
It is currently Tue Nov 19, 2019 10:52 pm

All times are UTC




Post new topic Reply to topic  [ 1 post ] 
Author Message
PostPosted: Sun Aug 06, 2017 5:54 pm 
Offline
Wyrmic

Joined: Fri Sep 07, 2012 1:34 am
Posts: 260
For as long as sustains have existed, they have been subject to a major bug: many of them compute a value when first activated, and continue using that original value until deactivated, even when the value should have changed because the actor's spellpower/strength/talent category mastery/etc. changed, allowing all manner of abuses. This bug has also been known for as long as sustains existed, so I always assumed a fix was right around the corner. It's been about eight years, so I think that my assumption was not correct.
Therefore, I have compiled this list of sustains and passives currently in the game that suffer from this bug. I hope it's useful to both developers and players. I believe it is complete, but it's certainly possible that I've missed one.

Poorly chosen color codes:
Bad - The talent suffers from this problem and is affected by a stat that changes frequently, such as the 6 primary stats, defense, spellpower, luck, resistances, armor, and other things that are frequently affected by buffs or equipment. Example: Lucid Dreamer's saves scale with mindpower.
Bad If Players Get It - Like Bad, but the talent is "NPC-only" or old-saves-only, so it's rarely relevant (but still relevant because possessors exist).
Bad With Mastery Items - The talent suffers from this problem, but is only affected by talent level. Changes to talent level reset sustains...unless they come from, say, a mastery bonus on an item. So you can abuse this bug if you have a mastery item (or, in some cases, one of the few items that grants direct bonus talent levels), but not otherwise. Example: Arcane Feed.
This problem does not occur with passives, which do reset upon all mastery and talent level changes. Yes, you could fix these specific talents by making sustains restart upon mastery changes.
Bad With Mastery Items If Players Get It
Provisionally Fine - The talent is almost Bad With Mastery Items but it uses raw talent level instead of real talent level. If changed to use real talent level, it will become Bad With Mastery Items, so it is risky to leave it as-is. Example: Quicken Spells.
Worse - Like Bad, but additionally cannot safely be auto-restarted because restarting it would have side effects. Example: Saw Wheels does a bunch of attacks, and resets its damage bonus, when deactivated.

Bad, Bad With Mastery Items, and Worse are all urgently important to fix. They are differentiated here only for the benefit of players wishing to take advantage of the bugs.

The list
celestial/chants-chants
Chant of Fortitude
Chant of Fortress
Chant of Resistance
Chant of Light

celestial/combat
Weapon of Light (melee_project portion only, damage shield portion is fine)
Weapon of Wrath

celestial/crusader
Righteous Strength

celestial/eclipse
Darkest Light (this is more of an active, so there's an argument that it's not an issue)

celestial/guardian
Retribution

celestial/hymns-hymns
Hymn of Shadows
Hymn of Detection
Hymn of Perseverance

celestial/radiance
Searing Sight

celestial/sol
Solar Wind

chronomancy/matter
Matter Weaving

chronomancy/other
Quantum Feed
Entropic Field
Carbon Spikes

chronomancy/temporal-archery
Perfect Aim

chronomancy/temporal-hounds
Temporal Hounds

corruption/blight
Dark Ritual

corruption/blood
Blood Fury

corruption/bone
Bone Shield (The number of bones isn't subject to this bug, but the regeneration rate of the bones is.)

corruption/demon-seeds
Corrosive Slashes
Shadowmeld
Blood Shield


corruption/demonic-strength
Abyssal Shield

corruption/rot
Infestation

corruption/sanguisuge
Absorb Life (why does this even exist?)

corruption/shadowflame
Flame of Urh'Rok

corruption/torment
Willful Tormentor (why isn't this passive?)
Overkill
Blood Vengeance

cunning/lethality
Blade Flurry (again, though, more of an active)

cunning/shadow-magic
Shadow Feed

cunning/stealth
Stealth

cunning/tactical
Exploit Weakness

cursed/endless-hunt
Surge

golem/arcane
Reflective Skin

psionic/augmented-mobility
Skate

psionic/dream-forge
Forge Shield (the Forge Armor bonuses)

psionic/dreaming
Lucid Dreamer

psionic/kinetic-mastery
Deflect Projectiles

psionic/nightmare
Night Terror

psionic/other
Beyond the Flesh (very specific: gems/mindstars combined with Finer Energy Manipulation mastery items).
Thought-form: Bowman
Thought-form: Warrior
Thought-form: Defender

psionic/psi-fighting
Augmentation

psionic/trance
Trance of Purity
Trance of Well-Being
Trance of Focus

race/shalore
Secrets of the Eternals

race/yeti
Resilient Body

spell/acid-alchemy
Acid Infusion

spell/aegis
Shielding
Arcane Shield

spell/aether
Pure Aether

spell/air
Feather Wind

spell/arcane
Arcane Power
Disruption Shield

spell/conveyance
Probability Travel

spell/divination
Keen Senses

spell/earth
Stone Skin

spell/eldritch-shield
Eldritch Infusion

spell/energy-alchemy
Lightning Infusion
Living Lightning (movement speed only)

spell/enhancement
Fiery Hands
Shock Hands
Inner Power

spell/fire-alchemy
Flame Infusion
Body of Fire (resistance and on_melee_hit only)

spell/frost-alchemy
Frost Infusion
Ice Core

spell/grave
Will o' the Wisp
Vampiric Gift

spell/ice
Uttercold

spell/meta
Spellcraft
Quicken Spells

spell/necrosis
Blurred Mortality

spell/other
Frost Hands
Necrotic Aura

spell/phantasm
Blur Sight
Phantasmal Shield
Invisibility

spell/shades
Frostdusk

spell/staff-combat
Defensive Posture

spell/stone
Body of Stone
Crystalline Focus

spell/storm
Tempest

spell/temporal
Essence of Speed

spell/wildfire
Burning Wake
Wildfire

steamtech/avoidance
Automated Cloak Tesselation

steamtech/battlefield-management
Saw Wheels
Grinding Shield

steamtech/butchery
Overheat Saws
Tempest of Metal

steamtech/furnace
Furnace

steamtech/other
Rocket Boots
Steam Powered Armour

steamtech/thoughts-of-iron
Molten Iron Blood

technique/2hweapon-offense
Berserker

technique/agility
Rapid Shot

technique/battle-tactics
True Grit has the bizarre property of updating its effects in callbackOnActBase, which still means they'll be incorrect (in the user's detriment) for most of a turn in which they take more than one instance of damage. Doesn't really fit into any of the classifications above, but seems bad.

technique/combat-techniques-active
Precise Strikes

technique/field-control
Slow Motion

technique/grappling
Grappling Stance

technique/magical-combat
Arcane Feed

technique/other
Precision
Momentum
Incendiary Ammunition (Alloyed Munitions penetration bonus only)
Piercing Ammunition (Penetration bonus only)

technique/shield-defense
Shield Wall
Last Stand

technique/sniper
Concealment
Aim

technique/strength-of-the-berserker
Berserker Rage updates every time the player acts, but their strength/dexterity could change more often than that, which is very slightly relevant if they have retaliating melee attacks as a possessor or adventurer.

technique/superiority
Onslaught (not that there's any reason to use it anyway)
Shattering Impact

technique/thuggery
Total Thuggery

technique/tireless-combatant
Pace Yourself

technique/unarmed-other
Striking Stance

wild-gift/antimagic
Antimagic Shield

wild-gift/call-of-the-wild
Meditation

wild-gift/cold-drake
Icy Skin

wild-gift/corrosive-blades
Corrosive Nature (acid resistance only)
Acidic Soil

wild-gift/eyals-fury
Nature's Defiance

wild-gift/fungus
Wild Growth

wild-gift/harmony
Elemental Harmony

wild-gift/mindstar-mastery
Psiblades

wild-gift/oozing-blades
Natural Acid (nature resistance only)
Unstoppable Nature

wild-gift/slime
Acidic Skin

wild-gift/summon-advanced
Master Summoner





Class summary
Finally, for the benefit of players, here's a summary of classes, coloured by the worst-bugged sustain or passive that they have. For example, Sun Paladin has Retribution, whereas the worst one Temporal Warden has is Temporal Hounds, and Doomed has no talents that suffer from this bug.
Categories that every class can get without escorts (Staff Combat, Mindstar Mastery, Harmony, Survival) are excluded for the purposes of this list.

Berserker
Bulwark
Archer
Arcane Blade
Brawler

Rogue
Shadowblade
Marauder
Skirmisher

Alchemist
Archmage
Necromancer

Summoner
Wyrmic
Oozemancer
Stone Warden

Sun Paladin
Anorithil

Reaver
Corruptor
Doombringer
Demonologist

Cursed
Doomed

Paradox Mage
Temporal Warden (but really Temporal Warden because nobody in their right mind takes temporal hounds)

Mindslayer
Solipsist
Possessor

Adventurer

Sawbutcher
Gunslinger
Psyshot

For addon developers: how to avoid and how to fix this bug
The game currently tries to (rather lazily) get around this issue by making sustains and passives reactivate every time something relevant changes. As you can see from the list above, this has not been successful, and furthermore no matter how much you increase the number of things that reactivate talents, it is fundamentally untenable because of interactions between sustains/passives and other sustains/passives. For example, Arcane Power affects spellpower, which in turn affects dozens of other sustains. So the order in which sustains reactivate matters, and players are incentivized to control it!
(Currently sustains reactivate whenever a change is made in the levelup menu, and passives reactivate whenever that happens or when mastery changes.)

Fixing this bug requires individually rewriting each affected sustain and passive. Some can be fixed by using existing features alone (mainly callbacks). Others would need to be fixed by adding new callbacks or special-casing them elsewhere (e.g. Armour Training has specific code in Combat:combatArmor() in order to make it work). Doing that might be the most practical solution; there aren't that many sustains in the game. By adding callbackOnGetResist, callbackOnGetArmor, etc. you wouldn't have to special-case many of the talents at all. And callbacks already support priority, so you don't need to worry about undefined order anymore.

It's hard not to notice that the common thread of suck between almost all bugged sustains and passives is the usage of Actor:addTemporaryValue() or Actor:talentTemporaryValue() to apply their effect. For example, Reflective Skin:
Code:
tmpid = self:addTemporaryValue("reflect_damage", (t.getReflect(self, t)))
It computes the reflect_damage bonus once, when activated, and never again until reactivated. What we need is for it to compute the reflect_damage value every time it's needed. Strictly, in this specific case, you could do this by recomputing it and re-applying the temporary value every time the actor's spellpower changes. Some sustains do this sort of thing already with callbackOnStatChange. However, it'd be much more maintainable to simply recalculate the value every time the actor's reflect_damage attribute is queried. Perhaps then Actor:addTemporaryValue() would be refactored to take a function as its second argument, which would be called to get the attribute bonus every time it's needed. None of the relevant attributes are indexed often enough for replacing them with functions to be a performance issue.
However, this would be a significant refactoring so lots of things could go wrong. Additionally, it makes it easy to accidentally introduce a circular dependency between attributes. I would suggest instead deprecating these two functions for passives and sustains entirely.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 1 post ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group