Skip to content

Commit 584065f

Browse files
Merge pull request #749 from absol89/dev
Bugfix: Prevent players from recruiting pets on public servers and cause crashes
2 parents 01dd4e4 + 138e14d commit 584065f

File tree

4 files changed

+230
-0
lines changed

4 files changed

+230
-0
lines changed
3.56 KB
Binary file not shown.
4.91 KB
Binary file not shown.
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
Scriptname PetFramework_ParentQuestScript extends Quest
2+
{Get/Set functions for pet count and limit checks. All other shared controls are in PetFramework_PetScript.}
3+
;rvogel 9/2017
4+
5+
GlobalVariable Property PetFramework_MaxPets Auto ;Max number of pets who can follow at once, default is 2
6+
7+
;RefAliases to fill from DLC at runtime
8+
9+
ReferenceAlias Property DLC2SeverinManorEnableMarker Auto
10+
ReferenceAlias Property HomeMarkerDLC2SeverinManor Auto
11+
12+
ReferenceAlias Property BYOH01DoorLakeviewManor Auto
13+
ReferenceAlias Property BYOH02DoorWindstadManor Auto
14+
ReferenceAlias Property BYOH03DoorHeljarchenHall Auto
15+
16+
ReferenceAlias Property HomeMarkerLakeviewManor Auto
17+
ReferenceAlias Property HomeMarkerWindstadManor Auto
18+
ReferenceAlias Property HomeMarkerHeljarchenHall Auto
19+
20+
Faction Property PetFramework_PetFaction Auto
21+
Faction Property PlayerFaction Auto
22+
23+
Faction Property CWSonsFaction Auto
24+
Faction Property CWImperialFaction Auto
25+
26+
; Setting start CurrentPetCount over the Max so the player cannot dismiss 2 pets and recruit new ones while online. Hypothetically.
27+
Int Property CurrentPetCount = 4 Auto Hidden ;Current count of pets, this is manipulated by pet ESPs/ESLs using the functions below
28+
29+
Event OnInit()
30+
debug.trace("Setting pet and player relationship to ally")
31+
PetFramework_PetFaction.SetAlly(PlayerFaction)
32+
33+
;Prevent CW actors from becoming hostile to pets
34+
PetFramework_PetFaction.SetAlly(CWSonsFaction)
35+
PetFramework_PetFaction.SetAlly(CWImperialFaction)
36+
EndEvent
37+
38+
Int Function GetCurrentPetCount()
39+
{Called by 'child' pet ESPs/ESLs to get current count and limit}
40+
Return CurrentPetCount
41+
EndFunction
42+
43+
Int Function GetMaxPets()
44+
{Called by 'child' pet ESPs/ESLs to get max pets}
45+
Return PetFramework_MaxPets.GetValue() as Int
46+
EndFunction
47+
48+
Function IncrementPetCount()
49+
{Called by 'child' pet ESPs/ESLs to update active pet count}
50+
CurrentPetCount += 1
51+
EndFunction
52+
53+
Function DecrementPetCount()
54+
{Called by 'child' pet ESPs/ESLs to update active pet count}
55+
If(CurrentPetCount > 0)
56+
CurrentPetCount -= 1
57+
EndIf
58+
EndFunction
59+
60+
Bool Function HasMaxPets()
61+
{Called to check if the player has the maximum pets allowed}
62+
63+
If(GetCurrentPetCount() == GetMaxPets())
64+
Return True
65+
Else
66+
Return False
67+
EndIf
68+
69+
EndFunction
70+
71+
72+
Function FillRefAliasesFromDLC()
73+
{Called from first stage of quest to fill aliases from DLC that are unreachable by Update.esm}
74+
75+
;Dragonborn Refs (Marker and Chest used to check ownership)
76+
ObjectReference DLC2SeverinManorEnableRef = (Game.GetFormFromFile(0x040396D0, "dragonborn.esm") as ObjectReference)
77+
ObjectReference DLC2SeverinManorMarkerRef = (Game.GetFormFromFile(0x0403BD35, "dragonborn.esm") as ObjectReference)
78+
79+
;Hearthfire Refs (Doors)
80+
ObjectReference DoorLakeviewManorRef = (Game.GetFormFromFile(0x03003221, "hearthfires.esm") as ObjectReference)
81+
ObjectReference DoorWindstadManorRef = (Game.GetFormFromFile(0x0300B852, "hearthfires.esm") as ObjectReference)
82+
ObjectReference DoorHeljarchenHallRef = (Game.GetFormFromFile(0x03010DDF, "hearthfires.esm") as ObjectReference)
83+
84+
;Hearthfire Refs (Markers)
85+
ObjectReference MarkerLakeviewManorRef = (Game.GetFormFromFile(0x0300309B, "hearthfires.esm") as ObjectReference)
86+
ObjectReference MarkerWindstadManorRef = (Game.GetFormFromFile(0x0301205C, "hearthfires.esm") as ObjectReference)
87+
ObjectReference MarkerHeljarchenHallRef = (Game.GetFormFromFile(0x03016E05, "hearthfires.esm") as ObjectReference)
88+
89+
;Fill the refs
90+
DLC2SeverinManorEnableMarker.ForceRefTo(DLC2SeverinManorEnableRef)
91+
HomeMarkerDLC2SeverinManor.ForceRefTo(DLC2SeverinManorMarkerRef)
92+
93+
BYOH01DoorLakeviewManor.ForceRefTo(DoorLakeviewManorRef)
94+
BYOH02DoorWindstadManor.ForceRefTo(DoorWindstadManorRef)
95+
BYOH03DoorHeljarchenHall.ForceRefTo(DoorHeljarchenHallRef)
96+
97+
HomeMarkerLakeviewManor.ForceRefTo(MarkerLakeviewManorRef)
98+
HomeMarkerWindstadManor.ForceRefTo(MarkerWindstadManorRef)
99+
HomeMarkerHeljarchenHall.ForceRefTo(MarkerHeljarchenHallRef)
100+
101+
EndFunction
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
Scriptname PetFramework_PetQuest extends Quest Conditional
2+
{Manages the pet's home location, commands, etc. Some functions are called from the pet actor script.}
3+
4+
PetFramework_ParentQuestScript Property PetFramework_ParentQuest Auto
5+
Message Property PetFramework_PetDismissMessage Auto
6+
Message Property PetFramework_PetMaxReachedMessage Auto
7+
Faction Property PetFramework_PetFollowingFaction Auto
8+
Faction Property PlayerFaction Auto
9+
Faction Property PetFramework_PetFaction Auto
10+
ReferenceAlias Property PetHomeMarker Auto
11+
ReferenceAlias Property PetRefAlias Auto
12+
ReferenceAlias Property PetDynamicHomeMarker Auto
13+
Bool Property MovingTogglePackageOn = False Auto Conditional Hidden ;Hearthfire adoption/move trick - turn on a temporary package
14+
15+
Function MakePetAvailableToPlayer()
16+
{Called when the quest meets the criteria for the pet to be available, i.e. purchase, rescue, whatever scenario. Without this the pet cannot be talked to or recruited.}
17+
PetRefAlias.GetActorReference().SetFactionRank(PetFramework_PetFaction, 1)
18+
;PetRefAlias.GetActorReference().AddToFaction(PlayerFaction)
19+
EndFunction
20+
21+
Function MakePetUnavailableToPlayer()
22+
{If for some reason we want to make the pet unavailable to player, i.e. sell it someone else, etc. this function will do that}
23+
PetRefAlias.GetActorReference().SetFactionRank(PetFramework_PetFaction, 0)
24+
;PetRefAlias.GetActorReference().RemoveFromFaction(PlayerFaction)
25+
EndFunction
26+
27+
Function FollowPlayer(Bool snapIntoInteraction = False)
28+
{Called when the player recruits the pet via dialogue.}
29+
30+
If(PetFramework_ParentQuest.HasMaxPets())
31+
PetFramework_PetMaxReachedMessage.Show()
32+
Else
33+
PetFramework_PetDismissMessage.Show()
34+
return ; STR players ignore the pets.
35+
debug.trace("Pet Framework: " + PetRefAlias.GetActorReference() + " setting to following player")
36+
debug.trace("Pet Framework: " + PetRefAlias.GetActorReference() + " PetFollowingFactionRank: " + PetRefAlias.GetActorReference().GetFactionRank(PetFramework_PetFollowingFaction))
37+
38+
;If the pet was waiting for the player, clear the actor value (no need to check just run it)
39+
WaitForPlayer(False)
40+
41+
;Set the rank to 1, which will enable dialogue commands, etc. (used by shared pet framework)
42+
PetRefAlias.GetActorReference().SetFactionRank(PetFramework_PetFollowingFaction, 1)
43+
44+
debug.trace("Pet Framework: " + PetRefAlias.GetActorReference() + " PetFollowingFactionRank: " + PetRefAlias.GetActorReference().GetFactionRank(PetFramework_PetFollowingFaction))
45+
46+
;Some animals have very long idles they get 'stuck' which feels like recruiting them didn't do anything
47+
If(snapIntoInteraction)
48+
PetRefAlias.GetReference().Disable()
49+
PetRefAlias.GetReference().Enable()
50+
EndIf
51+
52+
PetFramework_ParentQuest.IncrementPetCount()
53+
debug.trace("Pet Count: " + PetFramework_ParentQuest.GetCurrentPetCount())
54+
55+
;Re-evaluate the package stack based on our new conditions
56+
PetRefAlias.GetActorReference().EvaluatePackage()
57+
58+
EndIf
59+
60+
EndFunction
61+
62+
Function WaitForPlayer(Bool doWait = True)
63+
{True/False: Pet will wait for the player or continue to follow.}
64+
65+
DEBUG.TRACE("WaitForPlayer called with value: " + doWait)
66+
67+
If(doWait == True)
68+
debug.trace("PetFramework Setting pet to wait for player")
69+
PetRefAlias.GetActorReference().SetAV("WaitingForPlayer", 1)
70+
Else
71+
debug.trace("PetFramework Setting pet to stop waiting for player")
72+
PetRefAlias.GetActorReference().SetAV("WaitingForPlayer", 0)
73+
EndIf
74+
75+
;Re-evaluate the package stack based on our new conditions
76+
PetRefAlias.GetActorReference().EvaluatePackage()
77+
78+
EndFunction
79+
80+
Function SetHomeToCurrentLocation()
81+
{Makes the "Home" of the pet right where they stand, so they will dismiss and sandbox the area (house mods, camping, etc.)}
82+
83+
;Move the xmarker to where the pet is standing
84+
PetDynamicHomeMarker.GetReference().MoveTo(PetRefAlias.GetReference())
85+
PetDynamicHomeMarker.GetReference().SetAngle(0,0,0)
86+
87+
;Set the home idle marker to the dynamic marker
88+
SetNewHome(PetDynamicHomeMarker, True)
89+
90+
EndFunction
91+
92+
Function SetNewHome(ReferenceAlias newLocation, Bool dismiss = True, Bool doWarp = False)
93+
94+
debug.trace("Set New Home called from actor proxy")
95+
96+
;Clear the waiting flag
97+
WaitForPlayer(False)
98+
99+
;Turn on the temporary package while we change the ref alias data for their idle package - trick from Hearthfire adoption
100+
MovingTogglePackageOn = True ;"Hold"AI package looks at this quest var
101+
PetRefAlias.GetActorReference().EvaluatePackage()
102+
103+
;Set the ref alias to be the pet's new home
104+
PetHomeMarker.ForceRefTo(newLocation.GetReference())
105+
106+
;Remove them from current following faction so they actually go to their new home
107+
If(dismiss)
108+
PetRefAlias.GetActorReference().SetFactionRank(PetFramework_PetFollowingFaction, 0)
109+
EndIf
110+
111+
Utility.Wait(0.1)
112+
113+
MovingTogglePackageOn = False
114+
PetRefAlias.GetActorReference().EvaluatePackage()
115+
116+
If(doWarp)
117+
Utility.Wait(0.01)
118+
PetRefAlias.GetReference().MoveTo(newLocation.GetReference(), 0,0,0,False)
119+
EndIf
120+
121+
PetFramework_PetDismissMessage.Show()
122+
PetFramework_ParentQuest.DecrementPetCount()
123+
124+
debug.trace("Pet Count: " + PetFramework_ParentQuest.GetCurrentPetCount())
125+
126+
EndFunction
127+
128+
129+

0 commit comments

Comments
 (0)