Research:Disposition and Persuasion

From OpenMW Wiki
Revision as of 20:01, 19 November 2015 by Hrnchamd (talk | contribs) (Added research navbox.)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search




Actions affected All disposition using functions
Description Recalculated every time effective disposition is required. Setting disposition assumes you are specifying the effective disposition, so the base disposition is adjust by the delta between the current and desired effective disposition.
Implementation status Implemented
Analysis status Verified

<syntaxhighlight lang="python"> x = baseDisposition (from npc reference) if pc and npc are the same race: x += fDispRaceMod x += fDispPersonalityMult * (pcPersonality - fDispPersonalityBase)

if pc and npc are the same faction and pc is not expelled:

   reaction = faction reaction for same faction
   rank = rank in shared faction, range [0..9]

else if npc has a faction:

   reaction = min(faction reactions for all pc factions) (most hated faction) (0 if no faction)
   rank = 0


   reaction = 0, rank = 0

x += (fDispFactionRankMult * rank + fDispFactionRankBase) * fDispFactionMod * reaction x -= fDispCrimeMod * pcBounty if pc has a disease: x += fDispDiseaseMod if pc has weapon drawn: x += fDispWeaponDrawn

effective disposition = int(x), normally clamped to [0..100] when used </syntaxhighlight>


Actions affected On persuade dialogue action
Description Persuasion options in the NPC dialogue menu.
Implementation status Implemented
Analysis status Verified


Successfully performing a Bribe, Admire, Taunt or Intimidate will raise your Speechcraft skill.

Shared terms[edit]

Per-actor terms: <syntaxhighlight lang="python"> persTerm = personality / fPersonalityMod luckTerm = luck / fLuckMod repTerm = reputation * fReputationMod levelTerm = level * fLevelMod fatigueTerm = fFatigueBase - fFatigueMult*(1 - normalisedFatigue)

  1. where normalisedFatigue is a function of fatigue. empty fatigue bar -> 0.0, full fatigue bar -> 1.0
  2. note fatigueTerm is normally 1.25 at full fatigue.

</syntaxhighlight> Using player stats: <syntaxhighlight lang="python"> playerRating1 = (repTerm + luckTerm + persTerm + speechcraft) * fatigueTerm playerRating2 = playerRating1 + levelTerm playerRating3 = (mercantile + luckTerm + persTerm) * fatigueTerm </syntaxhighlight> Using NPC stats (note structural differences; all terms are calculated from NPC stats): <syntaxhighlight lang="python"> npcRating1 = (repTerm + luckTerm + persTerm + speechcraft) * fatigueTerm npcRating2 = (levelTerm + repTerm + luckTerm + persTerm + speechcraft) * fatigueTerm npcRating3 = (mercantile + repTerm + luckTerm + persTerm) * fatigueTerm </syntaxhighlight> Opposing roll targets: <syntaxhighlight lang="python"> d = 1 - 0.02 * abs(npcDisposition - 50) target1 = d * (playerRating1 - npcRating1 + 50) target2 = d * (playerRating2 - npcRating2 + 50) target3 = d * (playerRating3 - npcRating3 + 50) + bribeMod where bribeMod is fBribe10Mod, fBribe100Mod or fBribe1000Mod </syntaxhighlight>


<syntaxhighlight lang="python"> target1 = max(iPerMinChance, target1) roll 100, win if roll <= target1 c = int(fPerDieRollMult * (target1 - roll)) x = max(iPerMinChange, c) on success, c on fail </syntaxhighlight>


<syntaxhighlight lang="python"> target2 = max(iPerMinChance, target2) roll 100, win if roll <= target2

if roll != target2:

   r = int(target2 - roll)


   r = 1

if roll <= target2:

   s = int(r * fPerDieRollMult * fPerTempMult)
   flee = max(iPerMinChange, s)
   fight = min(-iPerMinChange, -s)

c = -abs(int(r * fPerDieRollMult)) if success:

   if abs(c) < iPerMinChange:
       x = 0, y = -iPerMinChange    # bug, see comments
       x = -int(c * fPerTempMult), y = c

else fail:

   x = int(c * fPerTempMult), y = c



<syntaxhighlight lang="python"> target1 = max(iPerMinChance, target1) roll 100, win if roll <= target1

c = abs(int(target1 - roll))

if roll <= target1:

   s = c * fPerDieRollMult * fPerTempMult
   flee = min(-iPerMinChange, int(-s))
   fight = max(iPerMinChange, int(s))

x = int(-c * fPerDieRollMult)

if success and abs(x) < iPerMinChange:

   x = -iPerMinChange



<syntaxhighlight lang="python"> target3 = max(iPerMinChance, target3) roll 100, win if roll <= target3 c = int((target3 - roll) * fPerDieRollMult)

x = max(iPerMinChange, c) on success, c on fail </syntaxhighlight>

Disposition Change[edit]

For all persuasion actions there is a temporary and a permanent disposition change. The temporary one applies to the disposition meter you see in the dialogue window. The permanent one is applied when you say goodbye to the NPC; the NPC's disposition is reset to the disposition they had when you initiated the conversation, then the permanent disposition change is applied. You can see these values in the console by using ToggleDialogStats before persuading.

For all methods: <syntaxhighlight lang="python"> temporary disposition change = int(x * fPerTempMult) </syntaxhighlight>

except for Intimidate: <syntaxhighlight lang="python"> change = x </syntaxhighlight>

This may attempt to change actual disposition below/above 0/100. Disposition changes are clamped so as not to go past the caps, and the actual amount the disposition moved is used in the next function. <syntaxhighlight lang="python"> permanent disposition change = int(cappedDispositionchange / fPerTempMult) </syntaxhighlight>

except for Intimidate <syntaxhighlight lang="python"> change = -int(cappedDispositionchange/ fPerTempMult) on success y on fail </syntaxhighlight>

There may also be modifications to the NPC's flee and fight ratings. The flee and fight variables hold the amount those ratings are changed. They are also capped at 0 and 100.


The function is long and highly redundant, much of the same formulas are repeatedly calculated many times for no reason. It's just another poorly coded part of Morrowind. There is at least one bug with Intimidate, where if the calculated change is less than iPerMinChange, it fails to set x correctly (it should have the value y does). This is responsible for the disposition meter not moving on some Intimidate Success results.