Skip to content

Commit 01bc3d1

Browse files
committed
shadows update
1 parent 0dc8bdf commit 01bc3d1

File tree

3 files changed

+135
-8
lines changed

3 files changed

+135
-8
lines changed

data/plugins/GTAIV.EFLC.FusionFix.ini

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ RecoilFix = 1
66
DefinitionFix = 1
77
EmissiveShaderFix = 1
88
AimingZoomFix = 1
9-
FlickeringShadowsFix = 1
9+
10+
[SHADOWS]
11+
FlickeringShadowsFix = 1 // known issue: disables player's shadow from headlights
12+
ExtraDynamicShadows = 1 // 1: restores some missing shadows | 2: also adds vegetation shadows | 3: forces all shadows to appear
13+
DynamicShadowForTrees = 0
1014
1115
[FRAMELIMIT]
1216
FpsLimitPreset = 0 // used by main menu toggle, do not modify
@@ -22,4 +26,7 @@ DefaultCameraAngleInTLAD = 0
2226
PedDeathAnimFixFromTBOGT = 1
2327
DisableCameraCenteringInCover = 1
2428
MouseFix = 1
25-
ScreenFilter = 5 // used by main menu toggle, do not modify
29+
ScreenFilter = 5 // used by main menu toggle, do not modify
30+
31+
[BudgetedIV]
32+
VehicleBudget = 0 // may cause issues, set to e.g. 260000000 to increase budget limit

source/dllmain.cpp

Lines changed: 125 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <filesystem>
55
#include <map>
66
#include <d3d9.h>
7+
#include <bitset>
78

89
class CSettings
910
{
@@ -518,6 +519,75 @@ void* __cdecl sub_8C4CF0(char* a1, char* a2)
518519
return injector::cstd<void* (char*, char*)>::call(CFileMgrOpenFile, a1, a2);
519520
}
520521

522+
int32_t bExtraDynamicShadows;
523+
bool bDynamicShadowForTrees;
524+
std::string curModelName;
525+
injector::memory_pointer_raw CModelInfoStore__allocateBaseModel = nullptr;
526+
void* __cdecl CModelInfoStore__allocateBaseModelHook(char* modelName)
527+
{
528+
curModelName = modelName;
529+
std::transform(curModelName.begin(), curModelName.end(), curModelName.begin(), [](unsigned char c) { return std::tolower(c); });
530+
return injector::cstd<void* (char*)>::call(CModelInfoStore__allocateBaseModel, modelName);
531+
}
532+
injector::memory_pointer_raw CModelInfoStore__allocateInstanceModel = nullptr;
533+
void* __cdecl CModelInfoStore__allocateInstanceModelHook(char* modelName)
534+
{
535+
curModelName = modelName;
536+
std::transform(curModelName.begin(), curModelName.end(), curModelName.begin(), [](unsigned char c) { return std::tolower(c); });
537+
538+
if (bDynamicShadowForTrees) {
539+
static std::vector<std::string> treeNames = {
540+
"ag_bigandbushy", "ag_bigandbushygrn", "ag_tree00", "ag_tree06", "azalea_md_ingame",
541+
"azalea_md_ingame_05", "azalea_md_ingame_06", "azalea_md_ingame_2", "azalea_md_ingame_3",
542+
"azalea_md_ingame_4", "bholly_md_ingame", "bholly_md_ingame_2", "bholly_md_s_ingame",
543+
"bholly_md_s_ingame_2", "beech_md_ingame_2", "c_apple_md_ingame", "c_apple_md_ingame01",
544+
"c_apple_md_ingame_2", "c_fern_md_ingame", "c_fern_md_ingame_2", "c_fern_md_ingame_3",
545+
"elm_md_ingame", "elm_md_ingame_2", "h_c_md_f_ingame", "h_c_md_f_ingame_2", "l_p_sap_ingame_2",
546+
"liveoak_md_ingame", "liveoak_md_ingame_2", "londonp_md_ingame", "londonp_md_ingame_2",
547+
"mglory_c_md_ingame", "mglory_c_md_ingame_2", "pinoak_md_ingame", "pinoak_md_ingame_2",
548+
"scotchpine", "tree_beech1", "tree_beech2", "w_birch_md_ingame", "w_birch_md_ingame2",
549+
"w_birch_md_ingame_2", "w_r_cedar_md_ingame", "w_r_cedar_md_ing_2", "scotchpine2", "scotchpine4",
550+
"tree_redcedar", "tree_redcedar2"
551+
};
552+
if (std::any_of(std::begin(treeNames), std::end(treeNames), [](auto& i) { return i == curModelName; }))
553+
return injector::cstd<void* (char*)>::call(CModelInfoStore__allocateBaseModel, modelName);
554+
}
555+
556+
return injector::cstd<void* (char*)>::call(CModelInfoStore__allocateInstanceModel, modelName);
557+
}
558+
559+
std::vector<std::string> modelNames = {"track", "fence", "rail", "pillar", "post"};
560+
injector::memory_pointer_raw CBaseModelInfo__setFlags = nullptr;
561+
void __cdecl CBaseModelInfo__setFlagsHook(void* pModel, int dwFlags, int a3)
562+
{
563+
if (bExtraDynamicShadows)
564+
{
565+
enum
566+
{
567+
flag0, flag1, alpha, flag3, flag4, trees, flag6, instance, flag8,
568+
enable_bone_anim, enable_uv_animation, model_hidden_shadow_casting,
569+
flag12, no_shadow, flag14, flag15, flag16, dynamic, flag18, flag19,
570+
flag20, no_backface_cull, static_shadow_1, static_shadow_2,
571+
flag24, flag25, enable_specialattribute, flag27, flag28,
572+
flag29, flag30, flag31
573+
};
574+
575+
auto bitFlags = std::bitset<32>(dwFlags);
576+
if (bitFlags.test(no_shadow))
577+
{
578+
if (bExtraDynamicShadows >= 3 || std::any_of(std::begin(modelNames), std::end(modelNames), [](auto& i) { return curModelName.contains(i); }))
579+
{
580+
bitFlags.reset(no_shadow);
581+
bitFlags.reset(static_shadow_1);
582+
bitFlags.reset(static_shadow_2);
583+
dwFlags = static_cast<int>(bitFlags.to_ulong());
584+
}
585+
}
586+
}
587+
588+
return injector::cstd<void(void*, int, int)>::call(CBaseModelInfo__setFlags, pModel, dwFlags, a3);
589+
}
590+
521591
void Init()
522592
{
523593
CIniReader iniReader("");
@@ -530,7 +600,9 @@ void Init()
530600
bool bEmissiveShaderFix = iniReader.ReadInteger("MAIN", "EmissiveShaderFix", 1) != 0;
531601
bool bHandbrakeCamFix = iniReader.ReadInteger("MAIN", "HandbrakeCamFix", 0) != 0;
532602
int32_t nAimingZoomFix = iniReader.ReadInteger("MAIN", "AimingZoomFix", 1);
533-
bool bFlickeringShadowsFix = iniReader.ReadInteger("MAIN", "FlickeringShadowsFix", 1) != 0;
603+
bool bFlickeringShadowsFix = iniReader.ReadInteger("SHADOWS", "FlickeringShadowsFix", 1) != 0;
604+
bExtraDynamicShadows = iniReader.ReadInteger("SHADOWS", "ExtraDynamicShadows", 1);
605+
bDynamicShadowForTrees = iniReader.ReadInteger("SHADOWS", "DynamicShadowForTrees", 0) != 0;
534606

535607
//[FRAMELIMIT]
536608
nFrameLimitType = iniReader.ReadInteger("FRAMELIMIT", "FrameLimitType", 2);
@@ -1110,10 +1182,6 @@ void Init()
11101182
}
11111183
}; injector::MakeInline<CreatePixelShaderHook>(pattern.get_first(0), pattern.get_first(9));
11121184

1113-
1114-
pattern = hook::pattern("8D A4 24 00 00 00 00 8B 40 04 8B 54 24 28");
1115-
static auto ptr = pattern.get_first(0);
1116-
11171185
pattern = hook::pattern("A1 ? ? ? ? 52 8B 08 50 89 15 ? ? ? ? FF 91 ? ? ? ? 8B 44 24 10");
11181186
static auto pD3DDevice = *pattern.get_first<IDirect3DDevice9**>(1);
11191187
struct SetPixelShaderHook
@@ -1146,6 +1214,58 @@ void Init()
11461214
}
11471215
}; injector::MakeInline<SetPixelShaderHook>(pattern.get_first(0));
11481216
}
1217+
1218+
if (bExtraDynamicShadows || bDynamicShadowForTrees)
1219+
{
1220+
auto pattern = hook::pattern("E8 ? ? ? ? EB 11 8D 44 24 54");
1221+
CModelInfoStore__allocateBaseModel = injector::GetBranchDestination(pattern.get_first(0));
1222+
injector::MakeCALL(pattern.get_first(0), CModelInfoStore__allocateBaseModelHook, true);
1223+
pattern = hook::pattern("E8 ? ? ? ? 8B F0 83 C4 04 8D 44 24 6C");
1224+
CModelInfoStore__allocateInstanceModel = injector::GetBranchDestination(pattern.get_first(0));
1225+
injector::MakeCALL(pattern.get_first(0), CModelInfoStore__allocateInstanceModelHook, true);
1226+
pattern = hook::pattern("D9 6C 24 0E 56");
1227+
CBaseModelInfo__setFlags = injector::GetBranchDestination(pattern.get_first(5));
1228+
injector::MakeCALL(pattern.get_first(5), CBaseModelInfo__setFlagsHook, true);
1229+
1230+
std::vector<std::string> vegetationNames = {
1231+
"bush", "weed", "grass", "azalea", "bholly", "fern", "tree"
1232+
};
1233+
1234+
if (bExtraDynamicShadows == 2)
1235+
modelNames.insert(modelNames.end(), vegetationNames.begin(), vegetationNames.end());
1236+
1237+
//sway
1238+
if (bDynamicShadowForTrees)
1239+
{
1240+
static auto dw1036C00 = *hook::get_pattern<float*>("F3 0F 5C 2D ? ? ? ? F3 0F 10 35", 4);
1241+
static auto dw1036C04 = dw1036C00 + 1;
1242+
static auto dw1036C08 = dw1036C00 + 2;
1243+
static auto dw11A2948 = *hook::get_pattern<float*>("C7 05 ? ? ? ? ? ? ? ? 0F 85 ? ? ? ? 6A 00", 2);
1244+
pattern = hook::pattern("8B 80 ? ? ? ? FF 74 24 20 8B 08 53 FF 74 24 20");
1245+
struct SetVertexShaderConstantFHook
1246+
{
1247+
void operator()(injector::reg_pack& regs)
1248+
{
1249+
regs.eax = *(uint32_t*)(regs.eax + 0x11AC);
1250+
auto pD3DDevice = (IDirect3DDevice9*)(regs.eax);
1251+
auto StartRegister = *(UINT*)(regs.esp + 0x18);
1252+
auto pConstantData = (float*)regs.ebx;
1253+
auto Vector4fCount = *(UINT*)(regs.esp + 0x20);
1254+
1255+
if (StartRegister == 51 && Vector4fCount == 1) {
1256+
if (pConstantData[0] == 1.0f && pConstantData[1] == 1.0f && pConstantData[2] == 1.0f && pConstantData[3] == 1.0f) {
1257+
static float arr[4];
1258+
arr[0] = *dw1036C00;
1259+
arr[1] = *dw1036C04;
1260+
arr[2] = *dw1036C08;
1261+
arr[3] = *dw11A2948;
1262+
pD3DDevice->SetVertexShaderConstantF(233, &arr[0], 1);
1263+
}
1264+
}
1265+
}
1266+
}; injector::MakeInline<SetVertexShaderConstantFHook>(pattern.count(2).get(1).get<void*>(0), pattern.count(2).get(1).get<void*>(6));
1267+
}
1268+
}
11491269
}
11501270

11511271
CEXP void InitializeASI()

0 commit comments

Comments
 (0)