Research:Player Craft Skills: Difference between revisions
(Fixing top level headings.) |
(→Alchemy: Added full mechanic for potions and wortcraft.) |
||
Line 65: | Line 65: | ||
==Alchemy== | ==Alchemy== | ||
===Potions=== | |||
{{Formula | {{Formula | ||
|On potion creation | |On potion creation | ||
|Uses [[Research:Magic#Magic effects|magic effect flags]]. | |||
| | | | ||
|{{StatusCol|orange|Requires regression testing}}}} | |||
|{{StatusCol| | |||
<syntaxhighlight lang="python"> | |||
consume ingredients on both success and failure | |||
x = pcAlchemy + 0.1 * pcIntelligence + 0.1 * pcLuck | |||
roll 100 vs x, succeed if roll <= x | |||
x *= mortarQuality * fPotionStrengthMult | |||
for each ingredient: | |||
for each effect in ingredient: | |||
if effect.id == -1: continue | |||
magicEffect = lookupEffect(effect.id) | |||
check magicEffect for match with effects in all other ingredients: | |||
effect.id should match | |||
if magicEffect.flags & TARGET_SKILL: effect.targetSkill should match | |||
if magicEffect.flags & TARGET_ATTR: effect.targetAttribute should match | |||
if effect is matched: | |||
if magicEffect is not in effectList, add it | |||
if effectList is empty: return with failure | |||
for each magicEffect in effectList: | |||
if not magicEffect.flags & NO_MAGNITUDE: | |||
if not magicEffect.flags & NO_DURATION: | |||
magnitude = (x / fPotionT1MagMult) / magicEffect.baseCost | |||
duration = (x / fPotionT1DurMult) / magicEffect.baseCost | |||
if not magicEffect.flags & NEGATIVE: | |||
if retort and calcinator: (magnitude, duration) += 2*retort + calcinator | |||
if only retort: (magnitude, duration) += retort | |||
if only calcinator: (magnitude, duration) += calcincator | |||
else: | |||
if alembic and calcinator: (magnitude, duration) /= 2*alembic + 3*calcinator | |||
if only alembic: (magnitude, duration) /= 1 + alembic | |||
if only calcinator: (magnitude, duration) += calcinator | |||
else: | |||
magnitude = (x / fPotionT1MagMult) / magicEffect.baseCost | |||
duration = 1 | |||
if not magicEffect.flags & NEGATIVE: | |||
if retort and calcinator: magnitude += 2/3 * (retort + calcinator) + 0.5 | |||
if only retort: magnitude *= retort + 0.5 | |||
if only calcinator: magnitude *= calcincator + 0.5 | |||
else: | |||
if alembic and calcinator: magnitude /= 2*alembic + 3*calcinator | |||
if only alembic: magnitude /= 1 + alembic | |||
if only calcinator: magnitude *= calcinator + 0.5 | |||
else: | |||
if not magicEffect.flags & NO_DURATION: | |||
magnitude = 1 | |||
duration = (x / fPotionT1DurMult) / magicEffect.baseCost | |||
if not magicEffect.flags & NEGATIVE: | |||
if retort and calcinator: duration += 2/3 * (retort + calcinator) + 0.5 | |||
if only retort: duration *= retort + 0.5 | |||
if only calcinator: duration *= calcincator + 0.5 | |||
else: | |||
if alembic and calcinator: duration /= 2*alembic + 3*calcinator | |||
if only alembic: duration /= 1 + alembic | |||
if only calcinator: duration *= calcinator + 0.5 | |||
else: | |||
magnitude = 1 | |||
duration = 1 | |||
magnitude = floor(magnitude + 0.5) | |||
duration = floor(duration + 0.5); | |||
if magnitude > 0 and duration > 0: add potionEffect(magicEffect, magnitude, duration) else nullify effect | |||
if all effects are nullified: return with failure | |||
* | price = int(iAlchemyMod * x) | ||
weight = sum of ingredient weights / total ingredients added | |||
visual = roll { 'Bargin', 'Cheap', 'Exclusive', 'Fresh', 'Quality', 'Standard' } | |||
pick model/icon { m/misc_potion_{visual}_01.nif, m/tx_potion_{visual}_01.tga } | |||
exercise alchemy skill (potion creation) | |||
</syntaxhighlight> | </syntaxhighlight> | ||
====Comments==== | |||
It is notable how effective a calcinator becomes when combined with a retort or alembic. One of the few mechanics unaffected by fatigue. Each code path is slightly different; the most common (effects with magnitude and duration) acts differently enough with only a calcinator that it may be consider a bug. GMSTs fPotionMinUsefulDuration, fPotionT4BaseStrengthMult, fPotionT4EquipStrengthMult are unused. | |||
===Wortcraft=== | |||
{{Formula | |||
|On eating a raw ingredient | |||
|Uses [[Research:Magic#Magic effects|magic effect flags]]. Uses common term [[Research:Common_Terms#fatigueTerm|fatigueTerm]]. | |||
| | |||
|{{StatusCol|green|Verified}}}} | |||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
magicEffect is the first effect of ingredient eaten | |||
< | x = (pcAlchemy + 0.2 * pcIntelligence + 0.1 * pcLuck) * fatigueTerm | ||
roll 100, succeed if roll <= x | |||
y = roll / min(x, 100) | |||
y *= 0.25 * x | |||
if not magicEffect.flags & NO_DURATION: | |||
duration = int(y) | |||
else: | |||
duration = 1 | |||
if not magicEffect.flags & NO_MAGNITUDE: | |||
if not magicEffect.flags & NO_DURATION: | |||
magnitude = int((0.05 * y) / (0.1 * baseCost)); | |||
else: | |||
magnitude = int(y / (0.1 * baseCost)) | |||
magnitude = max(1, magnitude) | |||
else: | |||
magnitude = 1 | |||
apply effect(magicEffect, magnitude, duration) | |||
exercise alchemy skill (ingredient use) | |||
</syntaxhighlight> | </syntaxhighlight> | ||
Revision as of 20:26, 3 September 2012
Enchanting
Actions affected | On PC enchant attempt |
Description | |
Implementation status | |
Analysis status | Self-enchanting formula ignores fatigue and some GMSTs |
Self-enchanting
for a constant effect item:
chance = Enchant + 0.125 * Intelligence + 0.25 * Luck - 5 * [enchantment points]
note: last term in above formula is solved for default GMSTs, full version is:
7.5/(fEnchantmentChanceMult*fEnchantmentConstantChanceMult) * [enchantment points]
Enchanted item recharge
Actions affected | On soulgem use |
Description | Recharging with a filled soulgem. Uses common term fatigueTerm. |
Implementation status | |
Analysis status | Verified |
luckTerm = 0.1 * luck
if luckTerm < 1 or luckTerm > 10: luckTerm = 1
intelligenceTerm = 0.2 * intelligence
if intelligenceTerm > 20: intelligenceTerm = 20
if intelligenceTerm < 1: intelligenceTerm = 1
x = (pcEnchant + intelligenceTerm + luckTerm) * fatigueTerm
roll 100, success if roll < x
on success restore charge: soulgem charge * (roll / x)
Comments
Recharging for most characters has a good chance of wasting a soul gem, as the enchant skill is the dominant term used for success. You would require enchant skill of over 65 with average stats to have a 100% success rate. The amount restored is a uniform random percentage of the soul gem, except if you have over a 100% success rate, in which case you will never get the full charge range out of a gem. The missing range increases as your skill does, but the lost charge is no more than 25% at the natural stat limit. Finally, note the strange luck term capping behaviour.
Armorer
Actions affected | On using a repair item |
Description | |
Implementation status | |
Analysis status | Verified, but original contains bugs |
fatigueTerm = fFatigueBase - fFatigueMult*(1 - normalisedFatigue)
where normalisedFatigue is a function of fatigue. empty fatigue bar -> 0.0, full fatigue bar -> 1.0
x = (0.1 * pcStrength + 0.1 * pcLuck + armorerSkill) / fatigueTerm
roll 100, if roll <= x then repair continues
y = int(fRepairAmountMult * hammerQuality * roll)
y = max(1, y)
repair item by y points
Comments
Bug in original game: Being more tired makes it easier to repair an item. The game should have multiplied by fatigueTerm instead of dividing by it.
Alchemy
Potions
Actions affected | On potion creation |
Description | Uses magic effect flags. |
Implementation status | |
Analysis status | Requires regression testing |
consume ingredients on both success and failure
x = pcAlchemy + 0.1 * pcIntelligence + 0.1 * pcLuck
roll 100 vs x, succeed if roll <= x
x *= mortarQuality * fPotionStrengthMult
for each ingredient:
for each effect in ingredient:
if effect.id == -1: continue
magicEffect = lookupEffect(effect.id)
check magicEffect for match with effects in all other ingredients:
effect.id should match
if magicEffect.flags & TARGET_SKILL: effect.targetSkill should match
if magicEffect.flags & TARGET_ATTR: effect.targetAttribute should match
if effect is matched:
if magicEffect is not in effectList, add it
if effectList is empty: return with failure
for each magicEffect in effectList:
if not magicEffect.flags & NO_MAGNITUDE:
if not magicEffect.flags & NO_DURATION:
magnitude = (x / fPotionT1MagMult) / magicEffect.baseCost
duration = (x / fPotionT1DurMult) / magicEffect.baseCost
if not magicEffect.flags & NEGATIVE:
if retort and calcinator: (magnitude, duration) += 2*retort + calcinator
if only retort: (magnitude, duration) += retort
if only calcinator: (magnitude, duration) += calcincator
else:
if alembic and calcinator: (magnitude, duration) /= 2*alembic + 3*calcinator
if only alembic: (magnitude, duration) /= 1 + alembic
if only calcinator: (magnitude, duration) += calcinator
else:
magnitude = (x / fPotionT1MagMult) / magicEffect.baseCost
duration = 1
if not magicEffect.flags & NEGATIVE:
if retort and calcinator: magnitude += 2/3 * (retort + calcinator) + 0.5
if only retort: magnitude *= retort + 0.5
if only calcinator: magnitude *= calcincator + 0.5
else:
if alembic and calcinator: magnitude /= 2*alembic + 3*calcinator
if only alembic: magnitude /= 1 + alembic
if only calcinator: magnitude *= calcinator + 0.5
else:
if not magicEffect.flags & NO_DURATION:
magnitude = 1
duration = (x / fPotionT1DurMult) / magicEffect.baseCost
if not magicEffect.flags & NEGATIVE:
if retort and calcinator: duration += 2/3 * (retort + calcinator) + 0.5
if only retort: duration *= retort + 0.5
if only calcinator: duration *= calcincator + 0.5
else:
if alembic and calcinator: duration /= 2*alembic + 3*calcinator
if only alembic: duration /= 1 + alembic
if only calcinator: duration *= calcinator + 0.5
else:
magnitude = 1
duration = 1
magnitude = floor(magnitude + 0.5)
duration = floor(duration + 0.5);
if magnitude > 0 and duration > 0: add potionEffect(magicEffect, magnitude, duration) else nullify effect
if all effects are nullified: return with failure
price = int(iAlchemyMod * x)
weight = sum of ingredient weights / total ingredients added
visual = roll { 'Bargin', 'Cheap', 'Exclusive', 'Fresh', 'Quality', 'Standard' }
pick model/icon { m/misc_potion_{visual}_01.nif, m/tx_potion_{visual}_01.tga }
exercise alchemy skill (potion creation)
Comments
It is notable how effective a calcinator becomes when combined with a retort or alembic. One of the few mechanics unaffected by fatigue. Each code path is slightly different; the most common (effects with magnitude and duration) acts differently enough with only a calcinator that it may be consider a bug. GMSTs fPotionMinUsefulDuration, fPotionT4BaseStrengthMult, fPotionT4EquipStrengthMult are unused.
Wortcraft
Actions affected | On eating a raw ingredient |
Description | Uses magic effect flags. Uses common term fatigueTerm. |
Implementation status | |
Analysis status | Verified |
magicEffect is the first effect of ingredient eaten
x = (pcAlchemy + 0.2 * pcIntelligence + 0.1 * pcLuck) * fatigueTerm
roll 100, succeed if roll <= x
y = roll / min(x, 100)
y *= 0.25 * x
if not magicEffect.flags & NO_DURATION:
duration = int(y)
else:
duration = 1
if not magicEffect.flags & NO_MAGNITUDE:
if not magicEffect.flags & NO_DURATION:
magnitude = int((0.05 * y) / (0.1 * baseCost));
else:
magnitude = int(y / (0.1 * baseCost))
magnitude = max(1, magnitude)
else:
magnitude = 1
apply effect(magicEffect, magnitude, duration)
exercise alchemy skill (ingredient use)