Jump to content

[LE] Detecting difficulty setting via script


EPHHall

Recommended Posts

I'd just like to know whether or not it is possible to detect what difficulty setting (novice, apprentice, etc.) the player is currently playing on in Skyrim using Papyrus and, if it is, how to do it. I've been searching the internet for a little while now, and will continue to do so, but I haven't found anything yet. Any help would be greatly appreciated.

Edited by EPHHall
Link to comment
Share on other sites

Ishara Meridan, thank you. However, I'm having a new problem now. Regardless of what difficulty I select, Utility.GetINIInt("iDifficulty") always equals 0. Do you have any idea why that could be? Here's my script:

Scriptname DangerousHallucinationsSpell extends activemagiceffect  
{Target loses a portion of their max health periodically for as long as the effect lasts}

float property PercentDamage auto
actor property SpellTarget auto
int property UpdateTime auto
float property Damage auto
float property DamageIfNovice auto
float property DamageIfApprentice auto
float property DamageIfAdept auto
float property DamageIfExpert auto
float property DamageIfMaster auto
float property DamageIfLegendary auto
float property damageMult auto
float property PreviousConf auto


event OnEffectStart (Actor Target, Actor Caster)
	
	SpellTarget = Target
	Damage = Caster.getav("Illusion") * damageMult
	Debug.Notification("Current game difficulty is "+Utility.GetINIInt("iDifficulty"))
	registerforsingleupdate(UpdateTime)

endEvent

event OnUpdate()

	if Utility.GetINIInt("iDifficulty") == 0
		debug.messagebox("In Novice")
		PercentDamage = Damage * DamageIfNovice
	endIf	
	
	if Utility.GetINIInt("iDifficulty") == 1
		debug.messagebox("In Apprentice")
		PercentDamage = Damage * DamageIfApprentice
	endIf	
	
	if Utility.GetINIInt("iDifficulty") == 2
		debug.messagebox("In Adept")
		PercentDamage = DamageIfAdept
	endIf	

	if Utility.GetINIInt("iDifficulty") == 3
		debug.messagebox("In Expert")
		PercentDamage = Damage * DamageIfExpert
	endIf	

	if Utility.GetINIInt("iDifficulty") == 4
		debug.messagebox("In Master")
		PercentDamage = Damage * DamageIfMaster
	endIf	

	if Utility.GetINIInt("iDifficulty") == 5
		debug.messagebox("In Legendary")
		PercentDamage = Damage * DamageIfLegendary
	endIf	

	SpellTarget.damageAV ("Health", percentDamage)	

	registerforsingleupdate (UpdateTime)

endEvent

Link to comment
Share on other sites

Apologies, this is completely unrelated to the question, but I had some time to stop and think about your script, and I was wondering what the values for your multipliers are. If the idea behind the multipliers is to scale it somehow, then depending on the type of scaling, it might be possible use just a single scaling multiplier in a single property.

 

For example something like this (in Python for testing):

 

 

 

#!/usr/bin/python3

import math


def damage_test():

    # properties
    CasterSkillMult = 0.002
    DifficultyMult = 0.1

    # actor illusion skill
    IllusionSkill = 60

    # damage based on skill and base mult
    Damage = IllusionSkill * CasterSkillMult

    # final damage calculations in the update event
    for Difficulty in range(0, 6):
        print('difficulty {}, percent {:.3f}'.format(
            Difficulty,
            math.pow(Damage, 1 - (Difficulty - 2) * DifficultyMult)
        ))


if __name__ == '__main__':
    damage_test()
 

 

 

 

Which would produce this:

 

 

 

difficulty 0, percent 0.079
difficulty 1, percent 0.097
difficulty 2, percent 0.120
difficulty 3, percent 0.148
difficulty 4, percent 0.183
difficulty 5, percent 0.227

 

 

 

And could look a bit like this in Papyrus:

 

 

 

ScriptName YourPrefix_DangerousHallucinationsSpell Extends ActiveMagicEffect
{Target loses a portion of their max health periodically for as long as the effect lasts}

Float Property CasterSkillMult Auto ; for example 0.002
Float Property DifficultyMult Auto ; for example 0.1
Float property UpdateInterval Auto

Actor TargetActor
Float Damage

Event OnEffectStart(Actor akTarget, Actor akCaster)
    TargetActor = akTarget
    Damage = akCaster.GetActorValue("Illusion") * CasterSkillMult
    RegisterForSingleUpdate(UpdateInterval)
EndEvent

Event OnUpdate()
    Int Difficulty = Utility.GetINIInt("iDifficulty:GamePlay") ; <-- as suggested by IsharaMeradin
    Float DamagePercent = Math.Pow(Damage, 1 - (Difficulty - 2) * DifficultyMult)
    Debug.MessageBox("DifficultyLevel (" + Difficulty + "), DamagePercentApplied (" + DamagePercent + ")")
    TargetActor.DamageActorValue("Health", DamagePercent)
    RegisterForSingleUpdate(UpdateInterval)
EndEvent

 

 

 

That is just one unrelated thought, and I have not tested the Papyrus one. Just something to think about if you ever need to cut down on the number of properties. But then again, if your scaling needs necessitate all the different multipliers, then you just have to keep them, of course. :smile:

Edited by Contrathetix
Link to comment
Share on other sites

If your modifiers are somewhat arbitrary it would still probably be better to store them in an array (and you can still fill them in the CK). I would also do as many calculations as possible early.

ScriptName YourPrefix_DangerousHallucinationsSpell Extends ActiveMagicEffect
{Target loses a portion of their max health periodically for as long as the effect lasts}

Float property UpdateInterval Auto

Float Property CasterSkillMult Auto

Float[] Property DifficultyMult Auto
{Fill with 6 values for Novice (0) through Legendary (5).}

Actor TargetActor
Float Damage

Event OnEffectStart(Actor akTarget, Actor akCaster)
    TargetActor = akTarget
    Float DamageBySkill = akCaster.GetActorValue("Illusion") * CasterSkillMult
    Int Difficulty = Utility.GetINIInt("iDifficulty:GamePlay")
    ;Float Damage = Math.Pow(DamageBySkill, 1 - (Difficulty - 2) * DifficultyMult)
    Float Damage = DamageBySkill * DifficultyMult[Difficulty]
    Debug.MessageBox("DifficultyLevel (" + Difficulty + "), DamagePercentApplied (" + DamagePercent + ")")
    RegisterForSingleUpdate(UpdateInterval)
EndEvent

Event OnUpdate()
    TargetActor.DamageActorValue("Health", Damage)
    RegisterForSingleUpdate(UpdateInterval)
EndEvent
Link to comment
Share on other sites

Yes, as cdcooley mentioned, avoiding unnecessary processing should definitely be something to try and achieve. However in this case, if a user has difficulty level set to legendary, someone casts that spell on the player character, and the user lowers difficulty level to novice after acquiring the spell effect, the damage applied would probably not update to reflect the difficulty level change if all the calculations have already been done at the beginning. Maybe. Other than that, moving the calculations to the beginning definitely is a great idea.

 

Edit: Assuming people would notice that the damage would not change. If people do not notice it, then it does not matter, now that I think of it... :happy:

Edited by Contrathetix
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...