44#include < filesystem>
55#include < map>
66#include < d3d9.h>
7+ #include < bitset>
78
89class 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+
521591void 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
11511271CEXP void InitializeASI ()
0 commit comments