Skip to content

Commit 683ec29

Browse files
Merge pull request #752 from tiltedphoques/dev
V1.7.1
2 parents 02ec3a4 + 299f208 commit 683ec29

File tree

12 files changed

+384
-4
lines changed

12 files changed

+384
-4
lines changed

.github/workflows/windows-playable-build.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ jobs:
3232
git submodule sync --recursive
3333
git submodule update --init --force --recursive --depth=1
3434
35+
- name: Checkout master on tag push
36+
if: github.ref_type == 'tag'
37+
# Checkout only if the tag was pushed to master
38+
run: (git rev-parse HEAD) -eq (git rev-parse origin/master) -and (git checkout master)
39+
3540
- name: Cache xmake dependencies
3641
uses: actions/cache@v4
3742
with:

Code/client/Services/Generic/InputService.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,14 @@ LRESULT CALLBACK InputService::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPAR
400400
}
401401
ProcessKeyboard(virtualKey, scancode, KEYEVENT_CHAR, false, false);
402402
}
403+
// If the player tabs out/in with UI visible, this WndProc doesn't run during mouse or keyboard events.
404+
// When player tabs in, force the UI state
405+
else if (uMsg == WM_SETFOCUS && s_pOverlay->GetActive())
406+
{
407+
TiltedPhoques::DInputHook::Get().SetEnabled(true);
408+
s_pOverlay->SetActive(true);
409+
pRenderer->SetCursorVisible(true);
410+
}
403411
else if (uMsg == WM_INPUTLANGCHANGE)
404412
{
405413
s_currentACP = GetRealACP();

Code/immersive_launcher/TargetConfig.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ static constexpr TargetConfig CurrentTarget{
2525
L"Skyrim Special Edition",
2626
489830, 0x40000000, 35410264};
2727
#define TARGET_NAME L"SkyrimSE"
28+
#define TARGET_NAME_A "SkyrimSE"
2829
#define PRODUCT_NAME L"Skyrim Together"
2930
#define SHORT_NAME L"Skyrim Special Edition"
3031

Code/immersive_launcher/stubs/FileMapping.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ std::wstring s_OverridePath;
2626
DWORD(WINAPI* RealGetModuleFileNameW)(HMODULE, LPWSTR, DWORD) = nullptr;
2727
DWORD(WINAPI* RealGetModuleFileNameA)(HMODULE, LPSTR, DWORD) = nullptr;
2828
HMODULE(WINAPI* RealGetModuleHandleW)(LPCWSTR) = nullptr;
29-
HMODULE(WINAPI* RealGetModuleHandleA)(LPSTR) = nullptr;
29+
HMODULE(WINAPI* RealGetModuleHandleA)(LPCSTR) = nullptr;
3030
NTSTATUS(WINAPI* RealLdrLoadDll)(const wchar_t*, uint32_t*, UNICODE_STRING*, HANDLE*) = nullptr;
3131
NTSTATUS(WINAPI* RealLdrGetDllHandle)(PWSTR, PULONG, PUNICODE_STRING, PVOID*) = nullptr;
3232
NTSTATUS(WINAPI* RealLdrGetDllFullName)(HMODULE, PUNICODE_STRING) = nullptr;
@@ -87,6 +87,28 @@ bool IsLocalModulePath(HMODULE aHmod)
8787
return buf.find(s_OverridePath) != std::wstring::npos;
8888
}
8989

90+
// some mods do GetModuleHandle("SkyrimSE.exe") for some reason instead of GetModuleHandle(nullptr)
91+
HMODULE WINAPI TP_GetModuleHandleW(LPCWSTR lpModuleName)
92+
{
93+
constexpr auto pTarget = TARGET_NAME L".exe";
94+
auto targetSize = std::wcslen(pTarget);
95+
96+
if (lpModuleName && std::wcsncmp(pTarget, lpModuleName, targetSize) == 0)
97+
lpModuleName = nullptr;
98+
return RealGetModuleHandleW(lpModuleName);
99+
}
100+
101+
// some mods do GetModuleHandle("SkyrimSE.exe") for some reason instead of GetModuleHandle(nullptr)
102+
HMODULE WINAPI TP_GetModuleHandleA(LPCSTR lpModuleName)
103+
{
104+
constexpr auto pTarget = TARGET_NAME_A ".exe";
105+
constexpr auto targetSize = sizeof(TARGET_NAME_A ".exe");
106+
107+
if (lpModuleName && std::strncmp(pTarget, lpModuleName, targetSize) == 0)
108+
lpModuleName = nullptr;
109+
return RealGetModuleHandleA(lpModuleName);
110+
}
111+
90112
// some mods do GetModuleHandle("SkyrimSE.exe") for some reason instead of GetModuleHandle(nullptr)
91113
NTSTATUS WINAPI TP_LdrGetDllHandle(PWSTR DllPath, PULONG DllCharacteristics, PUNICODE_STRING DllName, PVOID* DllHandle)
92114
{
@@ -300,6 +322,12 @@ void CoreStubsInit()
300322
// TODO(Vince): we need some check if usvfs already fucked with this?
301323
// MH_CreateHookApi(L"ntdll.dll", "LdrGetDllFullName", &TP_LdrGetDllFullName, (void**)&RealLdrGetDllFullName);
302324
VALIDATE(MH_CreateHookApi(L"ntdll.dll", "LdrLoadDll", &TP_LdrLoadDll, (void**)&RealLdrLoadDll));
325+
326+
// Starting with Windows 11 24H2 the call stack has changed and GetModuleHandle() no longer
327+
// downcalls to LdrGetDllHandleEx, so we have to hook this too.
328+
VALIDATE(MH_CreateHookApi(L"kernel32.dll", "GetModuleHandleW", &TP_GetModuleHandleW, (void**)&RealGetModuleHandleW));
329+
VALIDATE(MH_CreateHookApi(L"kernel32.dll", "GetModuleHandleA", &TP_GetModuleHandleA, (void**)&RealGetModuleHandleA));
330+
303331
VALIDATE(MH_EnableHook(nullptr));
304332
}
305333

Code/server_runner/main.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,16 +223,18 @@ int main(int argc, char** argv)
223223
}
224224
*/
225225

226-
ScopedCrashHandler _(true, true);
226+
//ScopedCrashHandler _(true, true);
227227

228-
RegisterQuitHandler();
228+
// Note(Vince): This started crashing on 1.7+ lets disable it for now.
229+
// RegisterQuitHandler();
229230

230231
// Keep stack free.
231232
const auto cpRunner{std::make_unique<DediRunner>(argc, argv)};
232233
if (bConsole)
233234
{
234235
cpRunner->StartTerminalIO();
235236
}
237+
236238
cpRunner->RunGSThread();
237239

238240
return 0;

Code/skyrim_ui/src/assets/i18n/tr.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
"ROOT": {
8282
"CONNECT": "Bağlan",
8383
"DISCONNECT": "Bağlantıyı Kopar",
84+
"REVEAL_PLAYERS": "Oyuncuları Göster",
8485
"RECONNECT": "Geri Bağlan",
8586
"PLAYER_MANAGER": "Oyuncu Yöneticisi",
8687
"SETTINGS": "Ayarlar",
@@ -177,4 +178,4 @@
177178
"PARTY_INVITE": "{{from}} parti daveti attı!"
178179
}
179180
}
180-
}
181+
}
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)