Jump to content

Papyrus: How to verify Player's Whiterun Thaneship Status


Recommended Posts

Posted

Feel free to check the code below

Spoiler
Bool Function thaneImmunity()
    Quest DragonRisingQuest = Game.GetFormFromFile(0x02610C, "Skyrim.esm") as Quest; Dragon Rising
    Quest WhiterunThaneQuest = Game.GetFormFromFile(0x0A2C9E, "Skyrim.esm") as Quest; Thane of Whiterun
    Quest WinterholdThaneQuest = Game.GetFormFromFile(0x0A34D7, "Skyrim.esm") as Quest; Thane of Winterhold
    Quest RiftenThaneQuest = Game.GetFormFromFile(0x065BDF, "Skyrim.esm") as Quest; I Done Got Thaned!
    Quest ReachThaneQuest = Game.GetFormFromFile(0x0A2C86, "Skyrim.esm") as Quest; Thane of the Reach
    Quest PaleThaneQuest = Game.GetFormFromFile(0x0A34D4, "Skyrim.esm") as Quest; Thane of the Pale
    Quest HjaalmarchThaneQuest = Game.GetFormFromFile(0x0A34CE, "Skyrim.esm") as Quest; Thane of Hjaalmarch
    Quest HaafingarThaneQuest = Game.GetFormFromFile(0x0A2C9B, "Skyrim.esm") as Quest; Thane of Haafingar
    Quest FalkreathThaneQuest = Game.GetFormFromFile(0x0A34DE, "Skyrim.esm") as Quest; Thane of Falkreath
    Quest EastmarchThaneQuest = Game.GetFormFromFile(0x0A2CA6, "Skyrim.esm") as Quest; Thane of Eastmarch

    if DragonRisingQuest.IsCompleted() && !WhiterunThaneQuest.IsRunning() || WhiterunThaneQuest.IsCompleted()
        return true
    elseIf WinterholdThaneQuest.IsCompleted() && IsInLocation(WinterholdHoldLocation)
        return true
    elseIf RiftenThaneQuest.IsCompleted() && IsInLocation(RiftHoldLocation)
        return true
    elseIf ReachThaneQuest.IsCompleted() && IsInLocation(ReachHoldLocation)
        return true
    elseIf PaleThaneQuest.IsCompleted() && IsInLocation(PaleHoldLocation)
        return true
    elseIf HjaalmarchThaneQuest.IsCompleted() && IsInLocation(HjaalmarchHoldLocation)
        return true
    elseIf HaafingarThaneQuest.IsCompleted() && IsInLocation(HaafingarHoldLocation)
        return true
    elseIf FalkreathThaneQuest.IsCompleted() && IsInLocation(FalkreathHoldLocation)
        return true
    elseIf EastmarchThaneQuest.IsCompleted() && IsInLocation(EastmarchHoldLocation)
        return true
    endIf
    return false
EndFunction

bool Function IsInLocation(Location akLocation)
	if licenses.currLoc == None
		return false
	else
		return akLocation.IsChild(licenses.currLoc) || licenses.currLoc == akLocation
	endif
endFunction

 

 

Evidently, this code is flawed, which is why I need some help. Unlike other Holds in Skyrim, Whiterun's Thane condition is a special: if Dragon Rising is completed, there is no Thane quest as player is automatically bequeathed Thaneship. However, should Balgruuf be deposed, the player loses Thaneship until they finish the Thane of Whiterun quest (the actual equivalent Thane quest of the other Holds). Given these special conditions, I wonder if anyone has figured out how to cancel player Thane status in their own scripts. This issue is further complicated by the fact that the quest which deposes Balgruuf, Battle for Whiterun, is a Radiant Quest with ID CWSiegeObj. This means I can't just check for the related quest's completion status.

Posted
1 hour ago, Gyra said:

Feel free to check the code below

  Hide contents
Bool Function thaneImmunity()
    Quest DragonRisingQuest = Game.GetFormFromFile(0x02610C, "Skyrim.esm") as Quest; Dragon Rising
    Quest WhiterunThaneQuest = Game.GetFormFromFile(0x0A2C9E, "Skyrim.esm") as Quest; Thane of Whiterun
    Quest WinterholdThaneQuest = Game.GetFormFromFile(0x0A34D7, "Skyrim.esm") as Quest; Thane of Winterhold
    Quest RiftenThaneQuest = Game.GetFormFromFile(0x065BDF, "Skyrim.esm") as Quest; I Done Got Thaned!
    Quest ReachThaneQuest = Game.GetFormFromFile(0x0A2C86, "Skyrim.esm") as Quest; Thane of the Reach
    Quest PaleThaneQuest = Game.GetFormFromFile(0x0A34D4, "Skyrim.esm") as Quest; Thane of the Pale
    Quest HjaalmarchThaneQuest = Game.GetFormFromFile(0x0A34CE, "Skyrim.esm") as Quest; Thane of Hjaalmarch
    Quest HaafingarThaneQuest = Game.GetFormFromFile(0x0A2C9B, "Skyrim.esm") as Quest; Thane of Haafingar
    Quest FalkreathThaneQuest = Game.GetFormFromFile(0x0A34DE, "Skyrim.esm") as Quest; Thane of Falkreath
    Quest EastmarchThaneQuest = Game.GetFormFromFile(0x0A2CA6, "Skyrim.esm") as Quest; Thane of Eastmarch

    if DragonRisingQuest.IsCompleted() && !WhiterunThaneQuest.IsRunning() || WhiterunThaneQuest.IsCompleted()
        return true
    elseIf WinterholdThaneQuest.IsCompleted() && IsInLocation(WinterholdHoldLocation)
        return true
    elseIf RiftenThaneQuest.IsCompleted() && IsInLocation(RiftHoldLocation)
        return true
    elseIf ReachThaneQuest.IsCompleted() && IsInLocation(ReachHoldLocation)
        return true
    elseIf PaleThaneQuest.IsCompleted() && IsInLocation(PaleHoldLocation)
        return true
    elseIf HjaalmarchThaneQuest.IsCompleted() && IsInLocation(HjaalmarchHoldLocation)
        return true
    elseIf HaafingarThaneQuest.IsCompleted() && IsInLocation(HaafingarHoldLocation)
        return true
    elseIf FalkreathThaneQuest.IsCompleted() && IsInLocation(FalkreathHoldLocation)
        return true
    elseIf EastmarchThaneQuest.IsCompleted() && IsInLocation(EastmarchHoldLocation)
        return true
    endIf
    return false
EndFunction

bool Function IsInLocation(Location akLocation)
	if licenses.currLoc == None
		return false
	else
		return akLocation.IsChild(licenses.currLoc) || licenses.currLoc == akLocation
	endif
endFunction

 

 

Evidently, this code is flawed, which is why I need some help. Unlike other Holds in Skyrim, Whiterun's Thane condition is a special: if Dragon Rising is completed, there is no Thane quest as player is automatically bequeathed Thaneship. However, should Balgruuf be deposed, the player loses Thaneship until they finish the Thane of Whiterun quest (the actual equivalent Thane quest of the other Holds). Given these special conditions, I wonder if anyone has figured out how to cancel player Thane status in their own scripts. This issue is further complicated by the fact that the quest which deposes Balgruuf, Battle for Whiterun, is a Radiant Quest with ID CWSiegeObj. This means I can't just check for the related quest's completion status.

 

Looking at related dialogue conditions (usually for guard dialogues), they are always checking for stage completed on the quests.  For instance, Riften wants quest stage 200.  Sounds like that might fix the CWSiegeObj issue as well.
 

Beyond that, this might be a case where a controller quest looks up status on every change of Hold location and stores that result rather than have to go through this kind of scripting every time.

Posted
1 hour ago, DarkBlade13 said:

For me that means once you obtained thane status you keep it.

 

He explained pretty clearly in the original post why that won't work.

 

That also won't function for other locations, since being thane is separate from owning property.

Posted (edited)
Spoiler
Scriptname BM_Licenses_Utility extends Quest  

BM_Licenses Property licenses auto
FavorJarlsMakeFriendsScript Property FJMF auto
Location Property WhiterunHoldLocation auto
Location Property WinterholdHoldLocation auto
Location Property RiftHoldLocation auto
Location Property ReachHoldLocation auto
Location Property PaleHoldLocation auto
Location Property HjaalmarchHoldLocation auto
Location Property HaafingarHoldLocation auto
Location Property FalkreathHoldLocation auto
Location Property EastmarchHoldLocation auto
Faction Property CWImperialFaction auto
Faction Property CWSonsFaction auto
ReferenceAlias Property playerRef auto
ReferenceAlias Property guardRef auto

Bool Function ThaneImmunity()
    Debug.Notification("Running ThaneImmunity")
    Actor playerActor = playerRef.GetActorRef()
    Actor guardActor = guardRef.GetActorRef()
    licenses.currLoc = playerActor.GetCurrentLocation()
    if IsInLocation(WhiterunHoldLocation) && ((FJMF.WhiterunImpGetOutofJail != 0 && guardActor.IsInFaction(CWImperialFaction)) || (FJMF.WhiterunSonsGetOutofJail != 0 && guardActor.IsInFaction(CWSonsFaction)))
        return true
    elseIf IsInLocation(WinterholdHoldLocation) && ((FJMF.WinterholdImpGetOutofJail != 0 && guardActor.IsInFaction(CWImperialFaction)) || (FJMF.WinterholdSonsGetOutofJail != 0 && guardActor.IsInFaction(CWSonsFaction)))
        return true
    elseIf IsInLocation(RiftHoldLocation) && ((FJMF.RiftImpGetOutofJail != 0 && guardActor.IsInFaction(CWImperialFaction)) || (FJMF.RiftSonsGetOutofJail != 0 && guardActor.IsInFaction(CWSonsFaction)))
        return true
    elseIf IsInLocation(ReachHoldLocation) && ((FJMF.ReachImpGetOutofJail != 0 && guardActor.IsInFaction(CWImperialFaction)) || (FJMF.ReachSonsGetOutofJail != 0 && guardActor.IsInFaction(CWSonsFaction)))
        return true
    elseIf IsInLocation(PaleHoldLocation) && ((FJMF.PaleImpGetOutofJail != 0 && guardActor.IsInFaction(CWImperialFaction)) || (FJMF.PaleSonsGetOutofJail != 0 && guardActor.IsInFaction(CWSonsFaction)))
        return true
    elseIf IsInLocation(HjaalmarchHoldLocation) && ((FJMF.HjaalmarchImpGetOutofJail != 0 && guardActor.IsInFaction(CWImperialFaction)) || (FJMF.HjaalmarchSonsGetOutofJail != 0 && guardActor.IsInFaction(CWSonsFaction)))
        return true
    elseIf IsInLocation(HaafingarHoldLocation) && ((FJMF.HaafingarImpGetOutofJail != 0 && guardActor.IsInFaction(CWImperialFaction)) || (FJMF.HaafingarSonsGetOutofJail != 0 && guardActor.IsInFaction(CWSonsFaction)))
        return true
    elseIf IsInLocation(FalkreathHoldLocation) && ((FJMF.FalkreathImpGetOutofJail != 0 && guardActor.IsInFaction(CWImperialFaction)) || (FJMF.FalkreathSonsGetOutofJail != 0 && guardActor.IsInFaction(CWSonsFaction)))
        return true
    elseIf IsInLocation(EastmarchHoldLocation) && ((FJMF.EastmarchImpGetOutofJail != 0 && guardActor.IsInFaction(CWImperialFaction)) || (FJMF.EastmarchSonsGetOutofJail != 0 && guardActor.IsInFaction(CWSonsFaction)))
        return true
    endIf
    return false
EndFunction

bool Function IsInLocation(Location akLocation)
	if licenses.currLoc == None
		return false
	else
		return akLocation.IsChild(licenses.currLoc) || licenses.currLoc == akLocation
	endif
endFunction

 

 

This is what I've ended up with. Rather than depending on Jarls, I'm just going to piggyback on how the vanilla game checks Thane status given vanilla Skyrim doesn't even have an explicit variable for checking Thaneship. In other words, Thane checking will solely be between player and a guard NPC.

 

All vanilla game actually does to benefit a player Thane is give a Get Out of Jail card. The vanilla FavorJarlsMakeFriends script has a comment that says as much. So, I made a new quest to fill a quest reference alias with Closest Guard. 

 

Edit: I forgot to also mention: Player thaneship soft resets when a Hold is taken over by a new Jarl. Even though player just needs to talk with the new Jarl to regain thaneship should they have already completed the thane quest, the act of talking to the new Jarl is still neccessary to activate Thaneship. This makes any method depending on the Jarl NPC or quest really complicated.

Edited by Gyra

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

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