diff --git a/.vscode/compile_commands.json b/.vscode/compile_commands.json index f2389f3..15ffe8e 100755 --- a/.vscode/compile_commands.json +++ b/.vscode/compile_commands.json @@ -49,6 +49,11 @@ "arguments": ["/usr/bin/clang", "-c", "-Qunused-arguments", "-m32", "--target=i686-w64-windows-gnu", "-g", "-O0", "-std=c++23", "-include", "src/pch.h", "-include-pch", "build/.objs/ModelExtras/mingw/x86/debug/src/cxx/pch.h.pch", "-Iinclude", "-Iinclude/coreutils", "-I/m2/Code/plugin-sdk", "-I/m2/Code/plugin-sdk/plugin_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa/rw", "-I/m2/Code/plugin-sdk/shared", "-I/m2/Code/plugin-sdk/shared/game", "-I/m2/Code/plugin-sdk/injector", "-I/m2/Code/plugin-sdk/safetyhook", "-Isrc", "-Isrc/features", "-Ibuild/.gens/ModelExtras/mingw/x86/debug/platform/windows/idl", "-DPLUGIN_SGV_10US", "-DMODELEXTRAS_DEV", "-DGTASA", "-DRW", "--target=i686-w64-mingw32", "-fpermissive", "-fcommon", "-fms-extensions", "-Wno-microsoft-include", "-gdwarf-4", "-gstrict-dwarf", "-gcodeview", "-fdebug-macro", "-o", "build/.objs/ModelExtras/mingw/x86/debug/src/features/lights/base.cpp.obj", "src/features/lights/base.cpp"], "file": "src/features/lights/base.cpp" }, +{ + "directory": "/m2/Code/ModelExtras", + "arguments": ["/usr/bin/clang", "-c", "-Qunused-arguments", "-m32", "--target=i686-w64-windows-gnu", "-g", "-O0", "-std=c++23", "-include", "src/pch.h", "-include-pch", "build/.objs/ModelExtras/mingw/x86/debug/src/cxx/pch.h.pch", "-Iinclude", "-Iinclude/coreutils", "-I/m2/Code/plugin-sdk", "-I/m2/Code/plugin-sdk/plugin_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa/rw", "-I/m2/Code/plugin-sdk/shared", "-I/m2/Code/plugin-sdk/shared/game", "-I/m2/Code/plugin-sdk/injector", "-I/m2/Code/plugin-sdk/safetyhook", "-Isrc", "-Isrc/features", "-Ibuild/.gens/ModelExtras/mingw/x86/debug/platform/windows/idl", "-DPLUGIN_SGV_10US", "-DMODELEXTRAS_DEV", "-DGTASA", "-DRW", "--target=i686-w64-mingw32", "-fpermissive", "-fcommon", "-fms-extensions", "-Wno-microsoft-include", "-gdwarf-4", "-gstrict-dwarf", "-gcodeview", "-fdebug-macro", "-o", "build/.objs/ModelExtras/mingw/x86/debug/src/features/lights/headlight.cpp.obj", "src/features/lights/headlight.cpp"], + "file": "src/features/lights/headlight.cpp" +}, { "directory": "/m2/Code/ModelExtras", "arguments": ["/usr/bin/clang", "-c", "-Qunused-arguments", "-m32", "--target=i686-w64-windows-gnu", "-g", "-O0", "-std=c++23", "-include", "src/pch.h", "-include-pch", "build/.objs/ModelExtras/mingw/x86/debug/src/cxx/pch.h.pch", "-Iinclude", "-Iinclude/coreutils", "-I/m2/Code/plugin-sdk", "-I/m2/Code/plugin-sdk/plugin_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa/rw", "-I/m2/Code/plugin-sdk/shared", "-I/m2/Code/plugin-sdk/shared/game", "-I/m2/Code/plugin-sdk/injector", "-I/m2/Code/plugin-sdk/safetyhook", "-Isrc", "-Isrc/features", "-Ibuild/.gens/ModelExtras/mingw/x86/debug/platform/windows/idl", "-DPLUGIN_SGV_10US", "-DMODELEXTRAS_DEV", "-DGTASA", "-DRW", "--target=i686-w64-mingw32", "-fpermissive", "-fcommon", "-fms-extensions", "-Wno-microsoft-include", "-gdwarf-4", "-gstrict-dwarf", "-gcodeview", "-fdebug-macro", "-o", "build/.objs/ModelExtras/mingw/x86/debug/src/features/pedcols.cpp.obj", "src/features/pedcols.cpp"], diff --git a/compile_commands.json b/compile_commands.json index f2389f3..cfc230c 100755 --- a/compile_commands.json +++ b/compile_commands.json @@ -41,13 +41,63 @@ }, { "directory": "/m2/Code/ModelExtras", - "arguments": ["/usr/bin/clang", "-c", "-Qunused-arguments", "-m32", "--target=i686-w64-windows-gnu", "-g", "-O0", "-std=c++23", "-include", "src/pch.h", "-include-pch", "build/.objs/ModelExtras/mingw/x86/debug/src/cxx/pch.h.pch", "-Iinclude", "-Iinclude/coreutils", "-I/m2/Code/plugin-sdk", "-I/m2/Code/plugin-sdk/plugin_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa/rw", "-I/m2/Code/plugin-sdk/shared", "-I/m2/Code/plugin-sdk/shared/game", "-I/m2/Code/plugin-sdk/injector", "-I/m2/Code/plugin-sdk/safetyhook", "-Isrc", "-Isrc/features", "-Ibuild/.gens/ModelExtras/mingw/x86/debug/platform/windows/idl", "-DPLUGIN_SGV_10US", "-DMODELEXTRAS_DEV", "-DGTASA", "-DRW", "--target=i686-w64-mingw32", "-fpermissive", "-fcommon", "-fms-extensions", "-Wno-microsoft-include", "-gdwarf-4", "-gstrict-dwarf", "-gcodeview", "-fdebug-macro", "-o", "build/.objs/ModelExtras/mingw/x86/debug/src/features/lights/loader.cpp.obj", "src/features/lights/loader.cpp"], - "file": "src/features/lights/loader.cpp" + "arguments": ["/usr/bin/clang", "-c", "-Qunused-arguments", "-m32", "--target=i686-w64-windows-gnu", "-g", "-O0", "-std=c++23", "-include", "src/pch.h", "-include-pch", "build/.objs/ModelExtras/mingw/x86/debug/src/cxx/pch.h.pch", "-Iinclude", "-Iinclude/coreutils", "-I/m2/Code/plugin-sdk", "-I/m2/Code/plugin-sdk/plugin_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa/rw", "-I/m2/Code/plugin-sdk/shared", "-I/m2/Code/plugin-sdk/shared/game", "-I/m2/Code/plugin-sdk/injector", "-I/m2/Code/plugin-sdk/safetyhook", "-Isrc", "-Isrc/features", "-Ibuild/.gens/ModelExtras/mingw/x86/debug/platform/windows/idl", "-DPLUGIN_SGV_10US", "-DMODELEXTRAS_DEV", "-DGTASA", "-DRW", "--target=i686-w64-mingw32", "-fpermissive", "-fcommon", "-fms-extensions", "-Wno-microsoft-include", "-gdwarf-4", "-gstrict-dwarf", "-gcodeview", "-fdebug-macro", "-o", "build/.objs/ModelExtras/mingw/x86/debug/src/features/lights/lights.cpp.obj", "src/features/lights/lights.cpp"], + "file": "src/features/lights/lights.cpp" }, { "directory": "/m2/Code/ModelExtras", - "arguments": ["/usr/bin/clang", "-c", "-Qunused-arguments", "-m32", "--target=i686-w64-windows-gnu", "-g", "-O0", "-std=c++23", "-include", "src/pch.h", "-include-pch", "build/.objs/ModelExtras/mingw/x86/debug/src/cxx/pch.h.pch", "-Iinclude", "-Iinclude/coreutils", "-I/m2/Code/plugin-sdk", "-I/m2/Code/plugin-sdk/plugin_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa/rw", "-I/m2/Code/plugin-sdk/shared", "-I/m2/Code/plugin-sdk/shared/game", "-I/m2/Code/plugin-sdk/injector", "-I/m2/Code/plugin-sdk/safetyhook", "-Isrc", "-Isrc/features", "-Ibuild/.gens/ModelExtras/mingw/x86/debug/platform/windows/idl", "-DPLUGIN_SGV_10US", "-DMODELEXTRAS_DEV", "-DGTASA", "-DRW", "--target=i686-w64-mingw32", "-fpermissive", "-fcommon", "-fms-extensions", "-Wno-microsoft-include", "-gdwarf-4", "-gstrict-dwarf", "-gcodeview", "-fdebug-macro", "-o", "build/.objs/ModelExtras/mingw/x86/debug/src/features/lights/base.cpp.obj", "src/features/lights/base.cpp"], - "file": "src/features/lights/base.cpp" + "arguments": ["/usr/bin/clang", "-c", "-Qunused-arguments", "-m32", "--target=i686-w64-windows-gnu", "-g", "-O0", "-std=c++23", "-include", "src/pch.h", "-include-pch", "build/.objs/ModelExtras/mingw/x86/debug/src/cxx/pch.h.pch", "-Iinclude", "-Iinclude/coreutils", "-I/m2/Code/plugin-sdk", "-I/m2/Code/plugin-sdk/plugin_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa/rw", "-I/m2/Code/plugin-sdk/shared", "-I/m2/Code/plugin-sdk/shared/game", "-I/m2/Code/plugin-sdk/injector", "-I/m2/Code/plugin-sdk/safetyhook", "-Isrc", "-Isrc/features", "-Ibuild/.gens/ModelExtras/mingw/x86/debug/platform/windows/idl", "-DPLUGIN_SGV_10US", "-DMODELEXTRAS_DEV", "-DGTASA", "-DRW", "--target=i686-w64-mingw32", "-fpermissive", "-fcommon", "-fms-extensions", "-Wno-microsoft-include", "-gdwarf-4", "-gstrict-dwarf", "-gcodeview", "-fdebug-macro", "-o", "build/.objs/ModelExtras/mingw/x86/debug/src/features/lights/manager.cpp.obj", "src/features/lights/manager.cpp"], + "file": "src/features/lights/manager.cpp" +}, +{ + "directory": "/m2/Code/ModelExtras", + "arguments": ["/usr/bin/clang", "-c", "-Qunused-arguments", "-m32", "--target=i686-w64-windows-gnu", "-g", "-O0", "-std=c++23", "-include", "src/pch.h", "-include-pch", "build/.objs/ModelExtras/mingw/x86/debug/src/cxx/pch.h.pch", "-Iinclude", "-Iinclude/coreutils", "-I/m2/Code/plugin-sdk", "-I/m2/Code/plugin-sdk/plugin_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa/rw", "-I/m2/Code/plugin-sdk/shared", "-I/m2/Code/plugin-sdk/shared/game", "-I/m2/Code/plugin-sdk/injector", "-I/m2/Code/plugin-sdk/safetyhook", "-Isrc", "-Isrc/features", "-Ibuild/.gens/ModelExtras/mingw/x86/debug/platform/windows/idl", "-DPLUGIN_SGV_10US", "-DMODELEXTRAS_DEV", "-DGTASA", "-DRW", "--target=i686-w64-mingw32", "-fpermissive", "-fcommon", "-fms-extensions", "-Wno-microsoft-include", "-gdwarf-4", "-gstrict-dwarf", "-gcodeview", "-fdebug-macro", "-o", "build/.objs/ModelExtras/mingw/x86/debug/src/features/lights/components/strobe_light.cpp.obj", "src/features/lights/components/strobe_light.cpp"], + "file": "src/features/lights/components/strobe_light.cpp" +}, +{ + "directory": "/m2/Code/ModelExtras", + "arguments": ["/usr/bin/clang", "-c", "-Qunused-arguments", "-m32", "--target=i686-w64-windows-gnu", "-g", "-O0", "-std=c++23", "-include", "src/pch.h", "-include-pch", "build/.objs/ModelExtras/mingw/x86/debug/src/cxx/pch.h.pch", "-Iinclude", "-Iinclude/coreutils", "-I/m2/Code/plugin-sdk", "-I/m2/Code/plugin-sdk/plugin_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa/rw", "-I/m2/Code/plugin-sdk/shared", "-I/m2/Code/plugin-sdk/shared/game", "-I/m2/Code/plugin-sdk/injector", "-I/m2/Code/plugin-sdk/safetyhook", "-Isrc", "-Isrc/features", "-Ibuild/.gens/ModelExtras/mingw/x86/debug/platform/windows/idl", "-DPLUGIN_SGV_10US", "-DMODELEXTRAS_DEV", "-DGTASA", "-DRW", "--target=i686-w64-mingw32", "-fpermissive", "-fcommon", "-fms-extensions", "-Wno-microsoft-include", "-gdwarf-4", "-gstrict-dwarf", "-gcodeview", "-fdebug-macro", "-o", "build/.objs/ModelExtras/mingw/x86/debug/src/features/lights/components/indicator.cpp.obj", "src/features/lights/components/indicator.cpp"], + "file": "src/features/lights/components/indicator.cpp" +}, +{ + "directory": "/m2/Code/ModelExtras", + "arguments": ["/usr/bin/clang", "-c", "-Qunused-arguments", "-m32", "--target=i686-w64-windows-gnu", "-g", "-O0", "-std=c++23", "-include", "src/pch.h", "-include-pch", "build/.objs/ModelExtras/mingw/x86/debug/src/cxx/pch.h.pch", "-Iinclude", "-Iinclude/coreutils", "-I/m2/Code/plugin-sdk", "-I/m2/Code/plugin-sdk/plugin_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa/rw", "-I/m2/Code/plugin-sdk/shared", "-I/m2/Code/plugin-sdk/shared/game", "-I/m2/Code/plugin-sdk/injector", "-I/m2/Code/plugin-sdk/safetyhook", "-Isrc", "-Isrc/features", "-Ibuild/.gens/ModelExtras/mingw/x86/debug/platform/windows/idl", "-DPLUGIN_SGV_10US", "-DMODELEXTRAS_DEV", "-DGTASA", "-DRW", "--target=i686-w64-mingw32", "-fpermissive", "-fcommon", "-fms-extensions", "-Wno-microsoft-include", "-gdwarf-4", "-gstrict-dwarf", "-gcodeview", "-fdebug-macro", "-o", "build/.objs/ModelExtras/mingw/x86/debug/src/features/lights/components/side_light.cpp.obj", "src/features/lights/components/side_light.cpp"], + "file": "src/features/lights/components/side_light.cpp" +}, +{ + "directory": "/m2/Code/ModelExtras", + "arguments": ["/usr/bin/clang", "-c", "-Qunused-arguments", "-m32", "--target=i686-w64-windows-gnu", "-g", "-O0", "-std=c++23", "-include", "src/pch.h", "-include-pch", "build/.objs/ModelExtras/mingw/x86/debug/src/cxx/pch.h.pch", "-Iinclude", "-Iinclude/coreutils", "-I/m2/Code/plugin-sdk", "-I/m2/Code/plugin-sdk/plugin_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa/rw", "-I/m2/Code/plugin-sdk/shared", "-I/m2/Code/plugin-sdk/shared/game", "-I/m2/Code/plugin-sdk/injector", "-I/m2/Code/plugin-sdk/safetyhook", "-Isrc", "-Isrc/features", "-Ibuild/.gens/ModelExtras/mingw/x86/debug/platform/windows/idl", "-DPLUGIN_SGV_10US", "-DMODELEXTRAS_DEV", "-DGTASA", "-DRW", "--target=i686-w64-mingw32", "-fpermissive", "-fcommon", "-fms-extensions", "-Wno-microsoft-include", "-gdwarf-4", "-gstrict-dwarf", "-gcodeview", "-fdebug-macro", "-o", "build/.objs/ModelExtras/mingw/x86/debug/src/features/lights/components/allday_light.cpp.obj", "src/features/lights/components/allday_light.cpp"], + "file": "src/features/lights/components/allday_light.cpp" +}, +{ + "directory": "/m2/Code/ModelExtras", + "arguments": ["/usr/bin/clang", "-c", "-Qunused-arguments", "-m32", "--target=i686-w64-windows-gnu", "-g", "-O0", "-std=c++23", "-include", "src/pch.h", "-include-pch", "build/.objs/ModelExtras/mingw/x86/debug/src/cxx/pch.h.pch", "-Iinclude", "-Iinclude/coreutils", "-I/m2/Code/plugin-sdk", "-I/m2/Code/plugin-sdk/plugin_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa/rw", "-I/m2/Code/plugin-sdk/shared", "-I/m2/Code/plugin-sdk/shared/game", "-I/m2/Code/plugin-sdk/injector", "-I/m2/Code/plugin-sdk/safetyhook", "-Isrc", "-Isrc/features", "-Ibuild/.gens/ModelExtras/mingw/x86/debug/platform/windows/idl", "-DPLUGIN_SGV_10US", "-DMODELEXTRAS_DEV", "-DGTASA", "-DRW", "--target=i686-w64-mingw32", "-fpermissive", "-fcommon", "-fms-extensions", "-Wno-microsoft-include", "-gdwarf-4", "-gstrict-dwarf", "-gcodeview", "-fdebug-macro", "-o", "build/.objs/ModelExtras/mingw/x86/debug/src/features/lights/components/fog_light.cpp.obj", "src/features/lights/components/fog_light.cpp"], + "file": "src/features/lights/components/fog_light.cpp" +}, +{ + "directory": "/m2/Code/ModelExtras", + "arguments": ["/usr/bin/clang", "-c", "-Qunused-arguments", "-m32", "--target=i686-w64-windows-gnu", "-g", "-O0", "-std=c++23", "-include", "src/pch.h", "-include-pch", "build/.objs/ModelExtras/mingw/x86/debug/src/cxx/pch.h.pch", "-Iinclude", "-Iinclude/coreutils", "-I/m2/Code/plugin-sdk", "-I/m2/Code/plugin-sdk/plugin_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa/rw", "-I/m2/Code/plugin-sdk/shared", "-I/m2/Code/plugin-sdk/shared/game", "-I/m2/Code/plugin-sdk/injector", "-I/m2/Code/plugin-sdk/safetyhook", "-Isrc", "-Isrc/features", "-Ibuild/.gens/ModelExtras/mingw/x86/debug/platform/windows/idl", "-DPLUGIN_SGV_10US", "-DMODELEXTRAS_DEV", "-DGTASA", "-DRW", "--target=i686-w64-mingw32", "-fpermissive", "-fcommon", "-fms-extensions", "-Wno-microsoft-include", "-gdwarf-4", "-gstrict-dwarf", "-gcodeview", "-fdebug-macro", "-o", "build/.objs/ModelExtras/mingw/x86/debug/src/features/lights/components/day_light.cpp.obj", "src/features/lights/components/day_light.cpp"], + "file": "src/features/lights/components/day_light.cpp" +}, +{ + "directory": "/m2/Code/ModelExtras", + "arguments": ["/usr/bin/clang", "-c", "-Qunused-arguments", "-m32", "--target=i686-w64-windows-gnu", "-g", "-O0", "-std=c++23", "-include", "src/pch.h", "-include-pch", "build/.objs/ModelExtras/mingw/x86/debug/src/cxx/pch.h.pch", "-Iinclude", "-Iinclude/coreutils", "-I/m2/Code/plugin-sdk", "-I/m2/Code/plugin-sdk/plugin_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa/rw", "-I/m2/Code/plugin-sdk/shared", "-I/m2/Code/plugin-sdk/shared/game", "-I/m2/Code/plugin-sdk/injector", "-I/m2/Code/plugin-sdk/safetyhook", "-Isrc", "-Isrc/features", "-Ibuild/.gens/ModelExtras/mingw/x86/debug/platform/windows/idl", "-DPLUGIN_SGV_10US", "-DMODELEXTRAS_DEV", "-DGTASA", "-DRW", "--target=i686-w64-mingw32", "-fpermissive", "-fcommon", "-fms-extensions", "-Wno-microsoft-include", "-gdwarf-4", "-gstrict-dwarf", "-gcodeview", "-fdebug-macro", "-o", "build/.objs/ModelExtras/mingw/x86/debug/src/features/lights/components/night_light.cpp.obj", "src/features/lights/components/night_light.cpp"], + "file": "src/features/lights/components/night_light.cpp" +}, +{ + "directory": "/m2/Code/ModelExtras", + "arguments": ["/usr/bin/clang", "-c", "-Qunused-arguments", "-m32", "--target=i686-w64-windows-gnu", "-g", "-O0", "-std=c++23", "-include", "src/pch.h", "-include-pch", "build/.objs/ModelExtras/mingw/x86/debug/src/cxx/pch.h.pch", "-Iinclude", "-Iinclude/coreutils", "-I/m2/Code/plugin-sdk", "-I/m2/Code/plugin-sdk/plugin_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa/rw", "-I/m2/Code/plugin-sdk/shared", "-I/m2/Code/plugin-sdk/shared/game", "-I/m2/Code/plugin-sdk/injector", "-I/m2/Code/plugin-sdk/safetyhook", "-Isrc", "-Isrc/features", "-Ibuild/.gens/ModelExtras/mingw/x86/debug/platform/windows/idl", "-DPLUGIN_SGV_10US", "-DMODELEXTRAS_DEV", "-DGTASA", "-DRW", "--target=i686-w64-mingw32", "-fpermissive", "-fcommon", "-fms-extensions", "-Wno-microsoft-include", "-gdwarf-4", "-gstrict-dwarf", "-gcodeview", "-fdebug-macro", "-o", "build/.objs/ModelExtras/mingw/x86/debug/src/features/lights/components/spot_light.cpp.obj", "src/features/lights/components/spot_light.cpp"], + "file": "src/features/lights/components/spot_light.cpp" +}, +{ + "directory": "/m2/Code/ModelExtras", + "arguments": ["/usr/bin/clang", "-c", "-Qunused-arguments", "-m32", "--target=i686-w64-windows-gnu", "-g", "-O0", "-std=c++23", "-include", "src/pch.h", "-include-pch", "build/.objs/ModelExtras/mingw/x86/debug/src/cxx/pch.h.pch", "-Iinclude", "-Iinclude/coreutils", "-I/m2/Code/plugin-sdk", "-I/m2/Code/plugin-sdk/plugin_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa/rw", "-I/m2/Code/plugin-sdk/shared", "-I/m2/Code/plugin-sdk/shared/game", "-I/m2/Code/plugin-sdk/injector", "-I/m2/Code/plugin-sdk/safetyhook", "-Isrc", "-Isrc/features", "-Ibuild/.gens/ModelExtras/mingw/x86/debug/platform/windows/idl", "-DPLUGIN_SGV_10US", "-DMODELEXTRAS_DEV", "-DGTASA", "-DRW", "--target=i686-w64-mingw32", "-fpermissive", "-fcommon", "-fms-extensions", "-Wno-microsoft-include", "-gdwarf-4", "-gstrict-dwarf", "-gcodeview", "-fdebug-macro", "-o", "build/.objs/ModelExtras/mingw/x86/debug/src/features/lights/components/rear_lights.cpp.obj", "src/features/lights/components/rear_lights.cpp"], + "file": "src/features/lights/components/rear_lights.cpp" +}, +{ + "directory": "/m2/Code/ModelExtras", + "arguments": ["/usr/bin/clang", "-c", "-Qunused-arguments", "-m32", "--target=i686-w64-windows-gnu", "-g", "-O0", "-std=c++23", "-include", "src/pch.h", "-include-pch", "build/.objs/ModelExtras/mingw/x86/debug/src/cxx/pch.h.pch", "-Iinclude", "-Iinclude/coreutils", "-I/m2/Code/plugin-sdk", "-I/m2/Code/plugin-sdk/plugin_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa/rw", "-I/m2/Code/plugin-sdk/shared", "-I/m2/Code/plugin-sdk/shared/game", "-I/m2/Code/plugin-sdk/injector", "-I/m2/Code/plugin-sdk/safetyhook", "-Isrc", "-Isrc/features", "-Ibuild/.gens/ModelExtras/mingw/x86/debug/platform/windows/idl", "-DPLUGIN_SGV_10US", "-DMODELEXTRAS_DEV", "-DGTASA", "-DRW", "--target=i686-w64-mingw32", "-fpermissive", "-fcommon", "-fms-extensions", "-Wno-microsoft-include", "-gdwarf-4", "-gstrict-dwarf", "-gcodeview", "-fdebug-macro", "-o", "build/.objs/ModelExtras/mingw/x86/debug/src/features/lights/components/headlight.cpp.obj", "src/features/lights/components/headlight.cpp"], + "file": "src/features/lights/components/headlight.cpp" }, { "directory": "/m2/Code/ModelExtras", @@ -124,11 +174,6 @@ "arguments": ["/usr/bin/clang", "-c", "-Qunused-arguments", "-m32", "--target=i686-w64-windows-gnu", "-g", "-O0", "-std=c++23", "-include", "src/pch.h", "-include-pch", "build/.objs/ModelExtras/mingw/x86/debug/src/cxx/pch.h.pch", "-Iinclude", "-Iinclude/coreutils", "-I/m2/Code/plugin-sdk", "-I/m2/Code/plugin-sdk/plugin_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa/rw", "-I/m2/Code/plugin-sdk/shared", "-I/m2/Code/plugin-sdk/shared/game", "-I/m2/Code/plugin-sdk/injector", "-I/m2/Code/plugin-sdk/safetyhook", "-Isrc", "-Isrc/features", "-Ibuild/.gens/ModelExtras/mingw/x86/debug/platform/windows/idl", "-DPLUGIN_SGV_10US", "-DMODELEXTRAS_DEV", "-DGTASA", "-DRW", "--target=i686-w64-mingw32", "-fpermissive", "-fcommon", "-fms-extensions", "-Wno-microsoft-include", "-gdwarf-4", "-gstrict-dwarf", "-gcodeview", "-fdebug-macro", "-o", "build/.objs/ModelExtras/mingw/x86/debug/src/features/core/base.cpp.obj", "src/features/core/base.cpp"], "file": "src/features/core/base.cpp" }, -{ - "directory": "/m2/Code/ModelExtras", - "arguments": ["/usr/bin/clang", "-c", "-Qunused-arguments", "-m32", "--target=i686-w64-windows-gnu", "-g", "-O0", "-std=c++23", "-include", "src/pch.h", "-include-pch", "build/.objs/ModelExtras/mingw/x86/debug/src/cxx/pch.h.pch", "-Iinclude", "-Iinclude/coreutils", "-I/m2/Code/plugin-sdk", "-I/m2/Code/plugin-sdk/plugin_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa/rw", "-I/m2/Code/plugin-sdk/shared", "-I/m2/Code/plugin-sdk/shared/game", "-I/m2/Code/plugin-sdk/injector", "-I/m2/Code/plugin-sdk/safetyhook", "-Isrc", "-Isrc/features", "-Ibuild/.gens/ModelExtras/mingw/x86/debug/platform/windows/idl", "-DPLUGIN_SGV_10US", "-DMODELEXTRAS_DEV", "-DGTASA", "-DRW", "--target=i686-w64-mingw32", "-fpermissive", "-fcommon", "-fms-extensions", "-Wno-microsoft-include", "-gdwarf-4", "-gstrict-dwarf", "-gcodeview", "-fdebug-macro", "-o", "build/.objs/ModelExtras/mingw/x86/debug/src/features/core/fileconverter.cpp.obj", "src/features/core/fileconverter.cpp"], - "file": "src/features/core/fileconverter.cpp" -}, { "directory": "/m2/Code/ModelExtras", "arguments": ["/usr/bin/clang", "-c", "-Qunused-arguments", "-m32", "--target=i686-w64-windows-gnu", "-g", "-O0", "-std=c++23", "-include", "src/pch.h", "-include-pch", "build/.objs/ModelExtras/mingw/x86/debug/src/cxx/pch.h.pch", "-Iinclude", "-Iinclude/coreutils", "-I/m2/Code/plugin-sdk", "-I/m2/Code/plugin-sdk/plugin_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa", "-I/m2/Code/plugin-sdk/plugin_sa/game_sa/rw", "-I/m2/Code/plugin-sdk/shared", "-I/m2/Code/plugin-sdk/shared/game", "-I/m2/Code/plugin-sdk/injector", "-I/m2/Code/plugin-sdk/safetyhook", "-Isrc", "-Isrc/features", "-Ibuild/.gens/ModelExtras/mingw/x86/debug/platform/windows/idl", "-DPLUGIN_SGV_10US", "-DMODELEXTRAS_DEV", "-DGTASA", "-DRW", "--target=i686-w64-mingw32", "-fpermissive", "-fcommon", "-fms-extensions", "-Wno-microsoft-include", "-gdwarf-4", "-gstrict-dwarf", "-gcodeview", "-fdebug-macro", "-o", "build/.objs/ModelExtras/mingw/x86/debug/src/features/exhaust.cpp.obj", "src/features/exhaust.cpp"], diff --git a/resource/dist/ModelExtras.ini b/resource/dist/ModelExtras.ini index 6636871..e858dd4 100755 --- a/resource/dist/ModelExtras.ini +++ b/resource/dist/ModelExtras.ini @@ -7,9 +7,9 @@ // // Current Patrons: // -// Damix, SimBoRRis -// lemaze93, XG417 -// Clayton Morrison, Wei Woo, �Wishy, Alexander Alexander, Macc, Flaqko _GTA, MG45, spdfnpe, ID_not4ound +// SimBoRRis, Supercakes +// Keith Ferrell, XG417, Agha +// Marcos Reis, Flaqko _GTA, spdfnpe // // Help support the developer by becoming a patron! // https://www.patreon.com/c/grinch_ @@ -132,16 +132,12 @@ MaterialAmbientOff = 0.45 MaterialAmbientOn = 18.0 [CONFIG] -// Enables some developer specific features with MEDEV cheat (Patreon Only) // Also enables MERELOAD cheat (Reloads config data of current player vehicle) DeveloperMode = False // Version check for ModelExtras models (Recommended to keep it enabled) ModelVersionCheck = True -// Displays a warning message when an incompatible mod is detected -ShowIncompatibleWarning = True - // Log extra info in log, might cause performance issues (Useful for developers) VerboseLogging = False @@ -153,9 +149,6 @@ CoronaDistanceMul = 0.0 // Foglights will only turn on when headlights are active FoglightTiedToHeadlight = True -// The beam light effect of headlights -HeadLightBeams = True - // ImVehFt light height limit, set to 0.0 to disable LightHeightLimit = 0.5 diff --git a/src/ModelExtrasAPI.cpp b/src/ModelExtrasAPI.cpp index 4b8fab5..7e1cdaf 100755 --- a/src/ModelExtrasAPI.cpp +++ b/src/ModelExtrasAPI.cpp @@ -13,7 +13,7 @@ bool ME_IsFeatureAvail(ME_FeatureID featureId) { if (idx < 0 || idx >= static_cast(eFeatureMatrix::FeatureCount)) { return false; } - return ModelExtrasLoader::m_bEnabledFeatures.test(idx); + return ModelExtras::m_bEnabledFeatures.test(idx); } // Dummy function to show on crash logs diff --git a/src/ModelExtrasAPI.h b/src/ModelExtrasAPI.h index 2580935..3e3e024 100755 --- a/src/ModelExtrasAPI.h +++ b/src/ModelExtrasAPI.h @@ -1,5 +1,5 @@ /* - * API provided for ModelExtras v2.1 Release + * API provided for ModelExtras v3.0 Release */ #pragma once @@ -62,7 +62,7 @@ enum ME_FeatureID ME_FeatureCount }; -enum ME_MaterialID +enum ME_LightID { ME_HeadLightLeft, ME_HeadLightRight, @@ -118,21 +118,10 @@ extern "C" ME_WRAPPER bool ME_IsFeatureAvail(ME_FeatureID featureId); // Vehicle - ME_WRAPPER bool ME_GetVehicleLEDState(CVehicle *pVeh, ME_MaterialID ledID); - ME_WRAPPER void ME_SetVehicleLEDState(CVehicle *pVeh, ME_MaterialID ledID, bool state); - - ME_WRAPPER bool ME_GetVehicleLightState(CVehicle *pVeh, ME_MaterialID lightId); - ME_WRAPPER void ME_SetVehicleLightState(CVehicle *pVeh, ME_MaterialID lightId, bool state); - ME_WRAPPER unsigned int ME_GetExhaustCount(CVehicle *pVeh); ME_WRAPPER ME_ExhaustInfo ME_GetExhaustData(CVehicle *pVeh, int index); ME_WRAPPER void ME_SetExhaustData(CVehicle *pVeh, int index, ME_ExhaustInfo &data); - // Ped - ME_WRAPPER int ME_GetPedRemap(CPed *ped, int index); - ME_WRAPPER void ME_SetPedRemap(CPed *ped, int index, int num); - ME_WRAPPER void ME_SetAllPedRemaps(CPed *ped, int num); - #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/src/dllmain.cpp b/src/dllmain.cpp index 467a0fa..97a9f87 100755 --- a/src/dllmain.cpp +++ b/src/dllmain.cpp @@ -2,35 +2,8 @@ #include "defines.h" #include "loader.h" -std::vector donators = { - "Wei Woo", - "©Wishy", - "Alexander Alexander", - "Imad Fikri", - "ID_not4ound", - "Macc", - "lemaze93", - "XG417", - "Ruethy", - "Flaqko _GTA", - "MG45", - "Boris Ilincic", - "Damix", - "spdfnpe", - "Pol3 Million", - "Bubby Jackson", - "Keith Ferrell", - "Clayton Morrison", - "SimBoRRis", - "Agha" -}; - -void InitLogFile() +void InitLog() { - static bool initialized = false; - if (initialized) return; - initialized = true; - auto sink_cout = std::make_shared(AixLog::Severity::debug); auto sink_file = std::make_shared(AixLog::Severity::debug, std::string(MOD_NAME) + ".log"); AixLog::Log::init({sink_cout, sink_file}); @@ -48,15 +21,6 @@ void InitLogFile() st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute); header += timeBuf; - - if (!donators.empty()) - { - header += "Donators:\n"; - for (const auto& name : donators) - { - header += "- " + name + "\n"; - } - } LOG(INFO) << header; } @@ -66,52 +30,21 @@ BOOL WINAPI DllMain(HINSTANCE hDllHandle, DWORD nReason, LPVOID Reserved) { gVerboseLogging = gConfig.ReadBoolean("CONFIG", "VerboseLogging", false); - Events::initScriptsEvent.after += []() + Events::initGameEvent += []() { + InitLog(); if (!gVerboseLogging) { LOG(INFO) << "Enable 'VerboseLogging' in ModelExtras.ini to display model-related errors."; } - }; - - Events::initRwEvent.after += []() - { - bool cleo = GetModuleHandle("CLEO.asi"); - if (!cleo) + if (!GetModuleHandle("CLEO.asi")) { MessageBox(RsGlobal.ps->window, "CLEO Library 4.4 or above is required!", "ModelExtras", MB_OK); LOG(ERROR) << "CLEO Library 4.4 or above is required!"; } }; - - Events::initGameEvent += []() - { - bool ImVehFtInstalled = GetModuleHandle("ImVehFt.asi"); - bool ImVehFtFixInstalled = GetModuleHandle("ImVehFtFix.asi"); - bool AVSInstalled = GetModuleHandle("AdvancedVehicleSirens.asi"); - - InitLogFile(); - - if (gConfig.ReadBoolean("CONFIG", "ShowIncompatibleWarning", true) && (ImVehFtInstalled || ImVehFtFixInstalled || AVSInstalled)) - { - std::string str = "ModelExtras contain the functions of these plugins,\n\n"; - - if (ImVehFtInstalled) - str += "- ImVehFt.asi\n"; - if (ImVehFtFixInstalled) - str += "- ImVehFtFix.asi\n"; - if (AVSInstalled) - str += "- AdvancedVehicleSirens.asi\n"; - - str += "\nRemove them to continue playing the game."; - MessageBox(RsGlobal.ps->window, str.c_str(), "Incompatible plugins found!", MB_OK); - LOG(ERROR) << str; - exit(EXIT_FAILURE); - } - return TRUE; - }; - ModelExtrasLoader::Init(); + ModelExtras::Init(); } return TRUE; } \ No newline at end of file diff --git a/src/features/core/base.cpp b/src/features/core/base.cpp index 047561d..6238715 100755 --- a/src/features/core/base.cpp +++ b/src/features/core/base.cpp @@ -11,9 +11,9 @@ CBaseFeature::CBaseFeature(std::string name, std::string configSection, eFeature { if (IsActive()) { m_bActive = true; - ModelExtrasLoader::m_Features.push_back(this); + ModelExtras::m_Features.push_back(this); if (m_featureId <= eFeatureMatrix::FeatureCount) { - ModelExtrasLoader::m_bEnabledFeatures.set(static_cast(m_featureId)); + ModelExtras::m_bEnabledFeatures.set(static_cast(m_featureId)); } LOG(INFO) << std::format("Feature '{}' enabled.", m_name); } diff --git a/src/features/core/dummy.cpp b/src/features/core/dummy.cpp index 72dd602..69e9e04 100755 --- a/src/features/core/dummy.cpp +++ b/src/features/core/dummy.cpp @@ -17,7 +17,7 @@ int ReadHex(char a, char b) return (a << 4) + b; } -VehicleDummy::VehicleDummy(const VehicleDummyConfig& config) +VehicleDummy::VehicleDummy(const DummyConfig& config) { data = config; float angleVal = 0.0f; diff --git a/src/features/core/dummy.h b/src/features/core/dummy.h index 5a6bd11..61966cd 100755 --- a/src/features/core/dummy.h +++ b/src/features/core/dummy.h @@ -10,16 +10,16 @@ class VehicleDummy { private: - VehicleDummyConfig data; + DummyConfig data; public: - VehicleDummy(const VehicleDummyConfig& config); + VehicleDummy(const DummyConfig& config); - const VehicleDummyConfig& GetRef() { + const DummyConfig& GetRef() { return data; } - VehicleDummyConfig& Get() { + DummyConfig& Get() { return data; } diff --git a/src/features/core/dummyconfig.h b/src/features/core/dummyconfig.h index 0fdc86e..a7e8c07 100755 --- a/src/features/core/dummyconfig.h +++ b/src/features/core/dummyconfig.h @@ -11,7 +11,7 @@ class CVehicle; class RwFrame; -struct VehicleDummyConfig { +struct DummyConfig { CVehicle *pVeh = nullptr; RwFrame* frame = nullptr; CVector position; @@ -52,7 +52,7 @@ struct VehicleDummyConfig { static inline int gId = 0; int id = 0; - VehicleDummyConfig () : id(gId++) { + DummyConfig () : id(gId++) { } }; \ No newline at end of file diff --git a/src/features/core/fileconverter.cpp b/src/features/core/fileconverter.cpp deleted file mode 100755 index b284022..0000000 --- a/src/features/core/fileconverter.cpp +++ /dev/null @@ -1,325 +0,0 @@ -#include "pch.h" -#include "defines.h" -#include - -#define DEFAULT_SIREN_SHADOW "round" - -int Helper_ImVehFtReadColor(std::string input) -{ - if (input.length() == 3) - { - return std::stoi(input); - } - - std::istringstream stream(input); - int color; - stream >> std::hex >> color; - return color; -}; - -bool Helper_MoveToBackup(const std::string &src) -{ - std::string backupDir = MOD_DATA_PATH("data\\backup\\"); - std::filesystem::create_directories(backupDir); - - std::filesystem::path source(src); - std::filesystem::path destination = backupDir + source.filename().string(); - try - { - std::filesystem::rename(source, destination); - } - catch (const std::filesystem::filesystem_error &e) - { - LOG(ERROR) << std::format("Failed to move {} to backup: {}", src, e.what()); - return false; - } - - return true; -} - -bool Helper_OpenFile(const std::string &path, std::ifstream &infile, const std::string &logPrefix) -{ - infile.open(path); - if (!infile) - { - LOG(WARNING) << std::format("{}: Failed to open {}", logPrefix, path); - return false; - } - return true; -} - -bool Helper_CreateFile(const std::string &path, std::ofstream &outfile, const std::string &logPrefix) -{ - outfile.open(path); - if (!outfile) - { - LOG(ERROR) << std::format("{}: Failed to create {}", logPrefix, path); - return false; - } - return true; -} - -void Helper_LoadPrepJson(const std::string &path, nlohmann::json &jsonData, const std::string &logPrefix, const std::string &clearKey) -{ - if (std::filesystem::exists(path)) - { - std::ifstream temp(path); - jsonData = nlohmann::json::parse(temp, NULL, true, true); - temp.close(); - - LOG(WARNING) << std::format("{}: Merging with {}", logPrefix, path); - if (jsonData.contains(clearKey)) - { - LOG(WARNING) << std::format("{}: {} already contains {}, replacing...", logPrefix, path, clearKey); - jsonData[clearKey] = {}; - } - } -} - -int Convert_EmlToJsonc(const std::string &emlPath) -{ - std::ifstream infile; - if (!Helper_OpenFile(emlPath, infile, "EML2JSONC")) - return -1; - - std::string line; - int model = -1; - - while (std::getline(infile, line)) - { - if (line.empty() || line[0] == '#') - continue; - std::istringstream iss(line); - if (!(iss >> model)) - { - LOG(WARNING) << std::format("EML2JSONC: Failed to parse model ID from {}", emlPath); - return -1; - } - break; - } - - std::string jsonPath = MOD_DATA_PATH("data\\") + std::to_string(model) + ".jsonc"; - nlohmann::json jsonData; - Helper_LoadPrepJson(jsonPath, jsonData, "EML2JSONC", "Sirens"); - - jsonData["metadata"]["author"] = "Unknown"; - jsonData["metadata"]["desc"] = "Converted from ImVehFt"; - jsonData["metadata"]["minver"] = 20000; // First ME Version with support - jsonData["sirens"]["imvehft"] = true; - auto &extras = jsonData["sirens"]["states"]["1. modelextras"]; - - std::ofstream outfile; - if (!Helper_CreateFile(jsonPath, outfile, "EML2JSONC")) - return -1; - - while (std::getline(infile, line)) - { - if (line.empty() || line[0] == '#') - continue; - - std::istringstream iss(line); - int id, parent, type, switches, starting; - int red, green, blue, alpha; - float size, flash, shadow; - std::string tempColor; - - if (!(iss >> id >> parent)) - continue; - if (!(iss >> tempColor)) - continue; - red = Helper_ImVehFtReadColor(tempColor); - if (!(iss >> tempColor)) - continue; - green = Helper_ImVehFtReadColor(tempColor); - if (!(iss >> tempColor)) - continue; - blue = Helper_ImVehFtReadColor(tempColor); - if (!(iss >> tempColor)) - continue; - alpha = Helper_ImVehFtReadColor(tempColor); - if (!(iss >> type >> size >> shadow >> flash)) - continue; - if (!(iss >> switches >> starting)) - continue; - - std::vector pattern; - uint64_t count = 0; - for (int i = 0; i < switches; i++) - { - std::string t; - if (!(iss >> t)) - continue; - uint64_t ms = std::stoi(t) - count; - count += ms; - if (ms == 0) - continue; - pattern.push_back(ms); - } - - if (count == 0 || count > 64553) - { - starting = 1; - pattern.clear(); - } - - auto &state = extras[std::to_string(id)]; - state["size"] = size; - state["color"] = {{"red", red}, {"green", green}, {"blue", blue}, {"alpha", alpha}}; - state["state"] = starting; - state["pattern"] = pattern; - state["shadow"]["angleoffset"] = type == 1 ? 180.0f : 0.0f; - state["shadow"]["size"] = shadow / 1.5f; - state["inertia"] = flash / 100.0f; - state["shadow"]["type"] = type == 2 ? "pointlight" : "round"; - state["type"] = type == 0 ? "directional" : (type == 1 ? "inversed-directional" : "non-directional"); - } - - infile.close(); - outfile << jsonData.dump(4); - outfile.close(); - - if (!Helper_MoveToBackup(emlPath)) - return -1; - LOG(INFO) << std::format("Successfully converted {} to {}", emlPath, jsonPath); - return model; -} - -const char* GetShadowTypeName(int index) { - static const char* shadowTypeNames[] = { - "round", "pointlight", "arealight", "bollard", "comet", - "cylindernarrow", "defined", "defineddiffuse", "defineddiffusespot", "definedspot", - "narrow", "jellyfish", "mediumscatter", "overhead", "parallelbeam", - "pear", "round", "scatterlight", "softarrow", "softdisplay", - "star", "starfocused", "threelobeumbrella", "threelobevee", "tightfocused", - "toppost", "trapezoid", "umbrella", "vee", "veeup", - "xarrow", "xarrowdiffuse", "xarrowsoft" - }; - - constexpr int count = sizeof(shadowTypeNames) / sizeof(shadowTypeNames[0]); - - if (index < 0 || index >= count) { - return (char*)DEFAULT_SIREN_SHADOW; - } - - return shadowTypeNames[index]; -} - -void Helper_UpdateAVSRecursive(nlohmann::json& j) { - if (j.is_object()) { - for (auto& [key, value] : j.items()) { - if (key == "shadow" && value.is_object()) { - if (value.contains("type") && value["type"].is_number()) { - std::string name = GetShadowTypeName(value["type"].get()); - value["type"] = name; - if (strcmp(name.c_str(), DEFAULT_SIREN_SHADOW) != 0) - { - value["size"] = value["size"].get() * 2.0f / 3.0f; - } - } - } - Helper_UpdateAVSRecursive(value); - } - } else if (j.is_array()) { - for (auto& item : j) { - Helper_UpdateAVSRecursive(item); - } - } -} - -void Convert_JsonToJsonc(const std::string &inPath) -{ - std::string outPath = inPath + "c"; - std::ifstream infile; - if (!Helper_OpenFile(inPath, infile, "JSON2JSONC")) - return; - - nlohmann::json jsonData; - Helper_LoadPrepJson(outPath, jsonData, "JSON2JSONC", "Sirens"); - - std::ofstream outfile; - if (!Helper_CreateFile(outPath, outfile, "JSON2JSONC")) - return; - - jsonData["metadata"]["author"] = "Unknown"; - jsonData["metadata"]["desc"] = "Converted from AVS"; - jsonData["metadata"]["minver"] = 20000; // First ME Version with support - jsonData["sirens"] = nlohmann::json::parse(infile); - Helper_UpdateAVSRecursive(jsonData); - infile.close(); - outfile << jsonData.dump(4); - outfile.close(); - - if (!Helper_MoveToBackup(inPath)) - return; - LOG(INFO) << std::format("Successfully converted {} to {}", inPath, outPath); -} - -int Convert_IvfcToJsonc(const std::string &inPath) -{ - std::ifstream infile; - if (!Helper_OpenFile(inPath, infile, "IVFC2JSONC")) - return -1; - - std::string line; - int model = -1; - while (std::getline(infile, line)) - { - if (line.empty() || line[0] == '#') - continue; - if (line.rfind("vehicle_id", 0) == 0) - { - std::istringstream iss(line); - std::string key; - iss >> key >> model; - break; - } - } - - std::string outPath = MOD_DATA_PATH("data\\") + std::to_string(model) + ".jsonc"; - nlohmann::json jsonData; - Helper_LoadPrepJson(outPath, jsonData, "IVFC2JSONC", "Carcols"); - - std::ofstream outfile; - if (!Helper_CreateFile(outPath, outfile, "IVFC2JSONC")) - return -1; - - bool parsingColors = false, parsingVariations = false; - while (std::getline(infile, line)) - { - if (line.empty() || line[0] == '#') - continue; - - if (line.starts_with("num_colors")) - parsingColors = true, parsingVariations = false; - else if (line.starts_with("num_variations")) - parsingColors = false, parsingVariations = true; - else if (model != -1) - { - std::istringstream iss(line); - if (parsingColors) - { - int r, g, b; - if (iss >> r >> g >> b) - jsonData["carcols"]["colors"].push_back({{"red", r}, {"green", g}, {"blue", b}}); - } - else if (parsingVariations) - { - int a, b, c, d; - if (iss >> a >> b >> c >> d) - jsonData["carcols"]["variations"].push_back({{"primary", a}, {"secondary", b}, {"tertiary", c}, {"quaternary", d}}); - } - } - } - - jsonData["metadata"]["author"] = "Unknown"; - jsonData["metadata"]["desc"] = "Converted from IVF"; - jsonData["metadata"]["minver"] = 20000; // First ME Version with support - infile.close(); - outfile << jsonData.dump(4); - outfile.close(); - - if (!Helper_MoveToBackup(inPath)) - return -1; - LOG(INFO) << std::format("Successfully converted {} to {}", inPath, outPath); - return model; -} diff --git a/src/features/lights.cpp b/src/features/lights.cpp index 406d0e2..866ada0 100755 --- a/src/features/lights.cpp +++ b/src/features/lights.cpp @@ -189,7 +189,7 @@ void Lights::Init() ModelInfoMgr::RegisterDummy([](CVehicle *pVeh, RwFrame *frame, const std::string_view name2) { std::string name = GetFrameNodeName(frame); - VehicleDummyConfig c; + DummyConfig c; c.pVeh = pVeh; c.frame = frame; c.corona.color = {255, 255, 255, static_cast(gGlobalCoronaIntensity)}; @@ -664,7 +664,7 @@ void Lights::RenderLight(CVehicle *pVeh, eMaterialType state, bool shadows, std: { for (auto e : m_Dummies[pVeh][state]) { - const VehicleDummyConfig &c = e->GetRef(); + const DummyConfig &c = e->GetRef(); e->Update(); RwFrame *parent = RwFrameGetParent(e->Get().frame); eMaterialType type = e->GetRef().lightType; @@ -774,7 +774,7 @@ void Lights::EnableDummy(int id, VehicleDummy *dummy, CVehicle *pVeh, float szMu { if (gConfig.ReadBoolean("FEATURES", "LightCoronas", false)) { - const VehicleDummyConfig &c = dummy->GetRef(); + const DummyConfig &c = dummy->GetRef(); if (c.corona.lightingType == eLightingMode::NonDirectional) { RenderUtil::RegisterCorona(pVeh, (reinterpret_cast(pVeh) * 255) + 255 + id, c.position, c.corona.color, c.corona.size * szMul); @@ -848,16 +848,16 @@ void Lights::SetLightState(CVehicle *pVeh, eMaterialType lightId, bool state) m_VehData.Get(pVeh).m_bLightStates[lightId] = state; } -extern enum ME_MaterialID; +extern enum ME_LightID; extern "C" { - bool ME_GetVehicleLightState(CVehicle *pVeh, ME_MaterialID lightId) + bool ME_GetVehicleLightState(CVehicle *pVeh, ME_LightID lightId) { return Lights::GetLightState(pVeh, static_cast(lightId)); } - void ME_SetVehicleLightState(CVehicle *pVeh, ME_MaterialID lightId, bool state) + void ME_SetVehicleLightState(CVehicle *pVeh, ME_LightID lightId, bool state) { Lights::SetLightState(pVeh, static_cast(lightId), state); } diff --git a/src/features/lights/base.cpp b/src/features/lights/base.cpp deleted file mode 100644 index ae69eac..0000000 --- a/src/features/lights/base.cpp +++ /dev/null @@ -1,128 +0,0 @@ -#include "pch.h" -#include "base.h" -#include "utils/modelinfomgr.h" - -bool ILightBehaviorBase::IsDummyAvail(CVehicle* pVeh) { - auto types = GetTypes(); - for (const auto e : types) { - auto& data = commonData.Get(pVeh); - if (!data.dummies[e].empty()) { - return true; - } - } - return false; -} - -bool ILightBehaviorBase::IsValidDummy(RwFrame *frame) { - std::string name = GetFrameNodeName(frame); - return IsValidDummy(name); -} - -bool ILightBehaviorBase::RegisterDummy(RwFrame *frame) { - std::string name = GetFrameNodeName(frame); - return RegisterDummy(name); -} - -bool ILightBehaviorBase::IsValidMaterial(RpMaterial *pMat) { - return IsValidMaterial(Util::GetMaterialColor(pMat)); -} - -eMaterialType ILightBehaviorBase::GetMatType(RpMaterial *pMat) { - return GetMatType(Util::GetMaterialColor(pMat)); -} - -bool ILightBehaviorBase::IsDummyAvail(CVehicle* pVeh, eMaterialType state) { - auto& data = commonData.Get(pVeh); - return !data.dummies[state].empty(); -} - -bool ILightBehaviorBase::IsMatAvail(CVehicle* pVeh) { - auto types = GetTypes(); - for (const auto e : types) { - if (ModelInfoMgr::IsMaterialAvailable(pVeh, e)) { - return true; - } - } - return false; -} - -void ILightBehaviorBase::EnableDummy(CVehicle *pVeh, VehicleDummy *pDummy) -{ - if (gConfig.ReadBoolean("FEATURES", "LightCoronas", false)) - { - const VehicleDummyConfig &c = pDummy->GetRef(); - if (c.corona.lightingType == eLightingMode::NonDirectional) - { - RenderUtil::RegisterCorona(pVeh, c.id, c.position, c.corona.color, c.corona.size); - } - else - { - RenderUtil::RegisterCoronaDirectional(&pDummy->Get(), c.rotation.angle, 180.0f, 1.0f, c.corona.lightingType == eLightingMode::Inversed, false); - } - } -} - -void ILightBehaviorBase::RenderLights(CVehicle *pControlVeh, CVehicle *pTowedVeh) -{ - int model = pControlVeh->m_nModelIndex; - - auto types = GetTypes(); - for (const auto e : types) { - if (!LightsGlobal::Get().m_bLightStates[e]) - { - continue; - } - - auto &controlData = commonData.Get(pControlVeh); - - RenderLight(pControlVeh, e); - - if (pControlVeh != pTowedVeh) - { - auto &towedData = commonData.Get(pTowedVeh); - RenderLight(pTowedVeh, e); - } - } -} - -void ILightBehaviorBase::RenderLight(CVehicle *pVeh, eMaterialType state) -{ - bool litMats = true; - - if (IsDummyAvail(pVeh, state)) - { - for (auto e : commonData.Get(pVeh).dummies[state]) - { - const VehicleDummyConfig &dummy = e->GetRef(); - e->Update(); - RwFrame *parent = RwFrameGetParent(e->Get().frame); - eMaterialType type = e->GetRef().lightType; - bool atomicCheck = type != eMaterialType::HeadLightLeft && type != eMaterialType::HeadLightRight && !FrameUtil::IsOkAtomicVisible(parent); - - auto& data = commonData.Get(pVeh); - if (atomicCheck || (dummy.dummyPos == eDummyPos::Rear && pVeh->m_pTrailer) || (!dummy.isParentDummy && !data.shouldRender(pVeh))) - { - litMats = false; - break; - } - - EnableDummy(pVeh, e); - - // Skip front shadows on bike wheelie - if (dummy.dummyPos == eDummyPos::Front && Util::IsVehicleDoingWheelie(pVeh)) - { - continue; - } - - if (dummy.shadow.render) - { - RenderUtil::RegisterShadowDirectional(&e->Get(), dummy.shadow.texture, dummy.shadow.size); - } - } - } - - if (litMats) - { - ModelInfoMgr::EnableMaterial(pVeh, state); - } -} \ No newline at end of file diff --git a/src/features/lights/base.h b/src/features/lights/base.h deleted file mode 100644 index 0f0dba4..0000000 --- a/src/features/lights/base.h +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once -#include -#include -#include - -#include "CVehicle.h" -#include "config.h" -#include "core/dummyconfig.h" -#include "enums/materialtype.h" -#include - -class ILightBehaviorBase { -protected: - VehicleExtendedData commonData; - - virtual bool IsDummyAvail(CVehicle *pVeh) final; - virtual bool IsDummyAvail(CVehicle *pVeh, eMaterialType state) final; - virtual bool IsMatAvail(CVehicle *pVeh) final; - virtual void EnableDummy(CVehicle *pVeh, VehicleDummy *pDummy) final; - - void RenderLight(CVehicle *pVeh, eMaterialType state); - - virtual void RenderLights(CVehicle *pControlVeh, CVehicle *pTowedVeh); - -public: - static inline std::vector ptrs; - - ILightBehaviorBase() { ptrs.push_back(this); } - - virtual ~ILightBehaviorBase() { - ptrs.erase(std::remove(ptrs.begin(), ptrs.end(), this), ptrs.end()); - } - - virtual std::vector GetTypes() const { - return {}; - } - - virtual bool IsValidDummy(RwFrame *frame) = 0; - virtual bool IsValidDummy(const std::string& dummyName) = 0; - virtual bool IsValidMaterial(RpMaterial *pMat) = 0; - virtual bool IsValidMaterial(const CRGBA &color) = 0; - virtual bool RegisterDummy(RwFrame *frame) = 0; - virtual bool RegisterDummy(const std::string& dummyName) = 0; - - virtual VehicleDummyConfig GetDummyConfig(RwFrame *frame) = 0; - virtual eMaterialType GetMatType(RpMaterial *pMat) = 0; - virtual eMaterialType GetMatType(const CRGBA &color) = 0; - - virtual void Process(CVehicle *pVeh) = 0; - virtual void Render(CVehicle *pControlVeh, CVehicle *pTowedVeh) = 0; - - VehicleExtendedData &GetCommonData() { - return commonData; - } -}; - -template class ILightBehavior : public ILightBehaviorBase { -protected: - VehicleExtendedData typeData; - -public: - ILightBehavior() = default; - virtual ~ILightBehavior() = default; - - VehicleExtendedData &GetTypeData() { return typeData; } -}; diff --git a/src/features/lights/components/allday_light.cpp b/src/features/lights/components/allday_light.cpp new file mode 100644 index 0000000..9788f0b --- /dev/null +++ b/src/features/lights/components/allday_light.cpp @@ -0,0 +1,23 @@ +#include "pch.h" +#include "allday_light.h" +#include "utils/util.h" + +eMaterialType AllDayLightComponent::GetMatType(CRGBA matCol) { + if (matCol == VEHCOL_ALLDAYLIGHT_1 || matCol == VEHCOL_ALLDAYLIGHT_2) return eMaterialType::AllDayLight; + return eMaterialType::UnknownMaterial; +} + +bool AllDayLightComponent::TryRegisterDummy(CVehicle* pVeh, RwFrame* pFrame, const std::string& name, VehLightData& data) { + if (name.starts_with("light_a")) { + DummyConfig c = LightManager::CreateBaseConfig(pVeh, pFrame); + c.lightType = eMaterialType::AllDayLight; + c.dummyPos = eDummyPos::Front; + data.dummies[c.lightType].push_back(new VehicleDummy(c)); + return true; + } + return false; +} + +void AllDayLightComponent::Render(CVehicle* pControlVeh, CVehicle* pTowedVeh, VehLightData& data) { + LightManager::RenderLight(pTowedVeh, data, eMaterialType::AllDayLight, true); +} diff --git a/src/features/lights/components/allday_light.h b/src/features/lights/components/allday_light.h new file mode 100644 index 0000000..592917f --- /dev/null +++ b/src/features/lights/components/allday_light.h @@ -0,0 +1,10 @@ +#pragma once +#include "base.h" +#include "../manager.h" + +class AllDayLightComponent : public BaseLightComponent { +public: + eMaterialType GetMatType(CRGBA matCol) override; + bool TryRegisterDummy(CVehicle* pVeh, RwFrame* pFrame, const std::string& name, VehLightData& data) override; + void Render(CVehicle* pControlVeh, CVehicle* pTowedVeh, VehLightData& data) override; +}; diff --git a/src/features/lights/components/base.h b/src/features/lights/components/base.h new file mode 100644 index 0000000..79488a8 --- /dev/null +++ b/src/features/lights/components/base.h @@ -0,0 +1,13 @@ +#pragma once +#include "../data.h" +#include "core/base.h" + +class BaseLightComponent { +public: + virtual ~BaseLightComponent() = default; + + virtual eMaterialType GetMatType(CRGBA matCol) { return eMaterialType::UnknownMaterial; } + virtual bool TryRegisterDummy(CVehicle* pVeh, RwFrame* pFrame, const std::string& name, VehLightData& data) { return false; } + virtual void Process(CVehicle* pVeh, VehLightData& data) {} + virtual void Render(CVehicle* pControlVeh, CVehicle* pTowedVeh, VehLightData& data) {} +}; diff --git a/src/features/lights/components/day_light.cpp b/src/features/lights/components/day_light.cpp new file mode 100644 index 0000000..685e9dc --- /dev/null +++ b/src/features/lights/components/day_light.cpp @@ -0,0 +1,23 @@ +#include "pch.h" +#include "day_light.h" +#include "utils/util.h" + +eMaterialType DayLightComponent::GetMatType(CRGBA matCol) { + if (matCol == VEHCOL_DAYLIGHT_1 || matCol == VEHCOL_DAYLIGHT_2) return eMaterialType::DayLight; + return eMaterialType::UnknownMaterial; +} + +bool DayLightComponent::TryRegisterDummy(CVehicle* pVeh, RwFrame* pFrame, const std::string& name, VehLightData& data) { + if (name.starts_with("light_d")) { + DummyConfig c = LightManager::CreateBaseConfig(pVeh, pFrame); + c.lightType = eMaterialType::DayLight; + c.dummyPos = eDummyPos::Front; + data.dummies[c.lightType].push_back(new VehicleDummy(c)); + return true; + } + return false; +} + +void DayLightComponent::Render(CVehicle* pControlVeh, CVehicle* pTowedVeh, VehLightData& data) { + LightManager::RenderLight(pTowedVeh, data, eMaterialType::DayLight, !Util::IsNightTime()); +} diff --git a/src/features/lights/components/day_light.h b/src/features/lights/components/day_light.h new file mode 100644 index 0000000..0e333b5 --- /dev/null +++ b/src/features/lights/components/day_light.h @@ -0,0 +1,10 @@ +#pragma once +#include "base.h" +#include "../manager.h" + +class DayLightComponent : public BaseLightComponent { +public: + eMaterialType GetMatType(CRGBA matCol) override; + bool TryRegisterDummy(CVehicle* pVeh, RwFrame* pFrame, const std::string& name, VehLightData& data) override; + void Render(CVehicle* pControlVeh, CVehicle* pTowedVeh, VehLightData& data) override; +}; diff --git a/src/features/lights/components/fog_light.cpp b/src/features/lights/components/fog_light.cpp new file mode 100644 index 0000000..e99ae42 --- /dev/null +++ b/src/features/lights/components/fog_light.cpp @@ -0,0 +1,45 @@ +#include "pch.h" +#include "fog_light.h" +#include "utils/audiomgr.h" +#include "defines.h" + +eMaterialType FogLightComponent::GetMatType(CRGBA matCol) { + if (matCol == VEHCOL_FOGLIGHT_LEFT) return eMaterialType::FogLightLeft; + if (matCol == VEHCOL_FOGLIGHT_RIGHT) return eMaterialType::FogLightRight; + return eMaterialType::UnknownMaterial; +} + +bool FogLightComponent::TryRegisterDummy(CVehicle* pVeh, RwFrame* pFrame, const std::string& name, VehLightData& data) { + if (name.starts_with("fogl") && (STR_FOUND(name, "_l") || STR_FOUND(name, "_r"))) { + DummyConfig c = LightManager::CreateBaseConfig(pVeh, pFrame); + c.dummyPos = eDummyPos::Front; + c.lightType = STR_FOUND(name, "_l") ? eMaterialType::FogLightLeft : eMaterialType::FogLightRight; + c.shadow.render = false; + c.corona.lightingType = eLightingMode::Directional; + data.dummies[c.lightType].push_back(new VehicleDummy(c)); + return true; + } + return false; +} + +void FogLightComponent::Process(CVehicle* pVeh, VehLightData& data) { + if (pVeh->m_pDriver == FindPlayerPed()) { + static size_t prev = 0; + static uint32_t fogLightKey = gConfig.ReadInteger("KEYS", "FogLightKey", VK_J); + + if (KeyPressed(fogLightKey)) { + size_t now = CTimer::m_snTimeInMilliseconds; + if (now - prev > 500) { + data.bFogLightsOn = !data.bFogLightsOn; + prev = now; + AudioMgr::PlaySwitchSound(pVeh); + } + } + } +} + +void FogLightComponent::Render(CVehicle* pControlVeh, CVehicle* pTowedVeh, VehLightData& data) { + if (!data.bFogLightsOn) return; + LightManager::RenderLight(pTowedVeh, data, eMaterialType::FogLightLeft, true, "foglight"); + LightManager::RenderLight(pTowedVeh, data, eMaterialType::FogLightRight, true, "foglight"); +} diff --git a/src/features/lights/components/fog_light.h b/src/features/lights/components/fog_light.h new file mode 100644 index 0000000..091a694 --- /dev/null +++ b/src/features/lights/components/fog_light.h @@ -0,0 +1,12 @@ +#pragma once +#include "base.h" +#include "../manager.h" + +class FogLightComponent : public BaseLightComponent { +public: + eMaterialType GetMatType(CRGBA matCol) override; + bool TryRegisterDummy(CVehicle* pVeh, RwFrame* pFrame, const std::string& name, VehLightData& data) override; + + void Process(CVehicle* pVeh, VehLightData& data) override; + void Render(CVehicle* pControlVeh, CVehicle* pTowedVeh, VehLightData& data) override; +}; diff --git a/src/features/lights/components/headlight.cpp b/src/features/lights/components/headlight.cpp new file mode 100644 index 0000000..89fc9ac --- /dev/null +++ b/src/features/lights/components/headlight.cpp @@ -0,0 +1,79 @@ +#include "pch.h" +#include "headlight.h" +#include "utils/util.h" +#include "utils/car.h" +#include "utils/audiomgr.h" +#include + +eMaterialType HeadlightComponent::GetMatType(CRGBA matCol) { + if (matCol == VEHCOL_HEADLIGHT_LEFT) return eMaterialType::HeadLightLeft; + if (matCol == VEHCOL_HEADLIGHT_RIGHT) return eMaterialType::HeadLightRight; + return eMaterialType::UnknownMaterial; +} + +bool HeadlightComponent::TryRegisterDummy(CVehicle* pVeh, RwFrame* pFrame, const std::string& name, VehLightData& data) { + if (name == "headlights" || name == "headlights2") { + DummyConfig c = LightManager::CreateBaseConfig(pVeh, pFrame); + c.dummyPos = eDummyPos::Front; + c.lightType = eMaterialType::HeadLightLeft; + c.corona.lightingType = eLightingMode::Directional; + c.shadow.render = name != "headlights2"; + + c.mirroredX = true; + data.dummies[eMaterialType::HeadLightLeft].push_back(new VehicleDummy(c)); + + c.mirroredX = false; + c.lightType = eMaterialType::HeadLightRight; + data.dummies[eMaterialType::HeadLightRight].push_back(new VehicleDummy(c)); + return true; + } + return false; +} + +void HeadlightComponent::Process(CVehicle* pVeh, VehLightData& data) { + if (pVeh->m_pDriver == FindPlayerPed()) { + static size_t prev = 0; + static uint32_t longLightKey = gConfig.ReadInteger("KEYS", "LongLightKey", VK_G); + + if (KeyPressed(longLightKey) && (pVeh->bLightsOn || CarUtil::IsLightsForcedOn(pVeh))) { + size_t now = CTimer::m_snTimeInMilliseconds; + if (now - prev > 500) { + data.bLongLightsOn = !data.bLongLightsOn; + prev = now; + AudioMgr::PlaySwitchSound(pVeh); + } + } + } else if (pVeh->m_nVehicleSubClass != VEHICLE_BMX && pVeh->m_nVehicleSubClass != VEHICLE_BOAT && pVeh->m_nVehicleSubClass != VEHICLE_TRAILER && !Util::IsEngineOff(pVeh)) { + if (DistanceBetweenPoints(pVeh->GetPosition(), TheCamera.GetPosition()) < 150.0f || pVeh->GetIsOnScreen()) { + bool isLeftFrontOk = !Util::IsLightDamaged(pVeh, eLights::LIGHT_FRONT_LEFT); + bool isRightFrontOk = !Util::IsLightDamaged(pVeh, eLights::LIGHT_FRONT_RIGHT); + // Render Headlights directly from Process logic for AI/Parked if visible to camera. + // This replicates the old ProcessScriptsEvent headlight render for non-player vehicles. + if (pVeh->bLightsOn || CarUtil::IsLightsForcedOn(pVeh) || Util::IsNightTime()) { + std::string texName = data.bLongLightsOn ? "headlight_long" : "headlight_short"; + LightManager::RenderLight(pVeh, data, eMaterialType::HeadLightLeft, isLeftFrontOk, texName); + LightManager::RenderLight(pVeh, data, eMaterialType::HeadLightRight, isRightFrontOk, texName); + } + } + } +} + +void HeadlightComponent::Render(CVehicle* pControlVeh, CVehicle* pTowedVeh, VehLightData& data) { + if (CarUtil::IsLightsForcedOff(pControlVeh)) return; + + if (pControlVeh->m_pDriver == FindPlayerPed() && (pControlVeh->bLightsOn || CarUtil::IsLightsForcedOn(pControlVeh) || Util::IsNightTime())) { + bool leftOn = pControlVeh->m_renderLights.m_bLeftFront && !Util::IsLightDamaged(pControlVeh, eLights::LIGHT_FRONT_LEFT); + bool rightOn = pControlVeh->m_renderLights.m_bRightFront && !Util::IsLightDamaged(pControlVeh, eLights::LIGHT_FRONT_RIGHT); + + std::string texName = data.bLongLightsOn ? "headlight_long" : "headlight_short"; + + LightManager::RenderLight(pControlVeh, data, eMaterialType::HeadLightLeft, leftOn, texName); + LightManager::RenderLight(pControlVeh, data, eMaterialType::HeadLightRight, rightOn, texName); + + if (pControlVeh != pTowedVeh) { + LightManager::RenderLight(pTowedVeh, data, eMaterialType::HeadLightLeft, leftOn, texName); + LightManager::RenderLight(pTowedVeh, data, eMaterialType::HeadLightRight, rightOn, texName); + } + } +} + diff --git a/src/features/lights/components/headlight.h b/src/features/lights/components/headlight.h new file mode 100644 index 0000000..b0a32be --- /dev/null +++ b/src/features/lights/components/headlight.h @@ -0,0 +1,12 @@ +#pragma once +#include "base.h" +#include "../manager.h" + +class HeadlightComponent : public BaseLightComponent { +public: + eMaterialType GetMatType(CRGBA matCol) override; + bool TryRegisterDummy(CVehicle* pVeh, RwFrame* pFrame, const std::string& name, VehLightData& data) override; + + void Process(CVehicle* pVeh, VehLightData& data) override; + void Render(CVehicle* pControlVeh, CVehicle* pTowedVeh, VehLightData& data) override; +}; diff --git a/src/features/lights/components/indicator.cpp b/src/features/lights/components/indicator.cpp new file mode 100644 index 0000000..f9bbf5d --- /dev/null +++ b/src/features/lights/components/indicator.cpp @@ -0,0 +1,112 @@ +#include "pch.h" +#include "indicator.h" +#include "utils/util.h" +#include "utils/car.h" +#include + +eMaterialType IndicatorComponent::GetMatType(CRGBA matCol) { + if (matCol == VEHCOL_INDICATOR_LEFT_REAR) return eMaterialType::IndicatorLightLeftRear; + if (matCol == VEHCOL_INDICATOR_LEFT_SIDE) return eMaterialType::IndicatorLightLeftMiddle; + if (matCol == VEHCOL_INDICATOR_LEFT_FRONT) return eMaterialType::IndicatorLightLeftFront; + if (matCol == VEHCOL_INDICATOR_RIGHT_REAR) return eMaterialType::IndicatorLightRightRear; + if (matCol == VEHCOL_INDICATOR_RIGHT_SIDE) return eMaterialType::IndicatorLightRightMiddle; + if (matCol == VEHCOL_INDICATOR_RIGHT_FRONT) return eMaterialType::IndicatorLightRightFront; + return eMaterialType::UnknownMaterial; +} + +bool IndicatorComponent::TryRegisterDummy(CVehicle* pVeh, RwFrame* pFrame, const std::string& name, VehLightData& data) { + if (name.starts_with("turnl_") || name.starts_with("indicator_")) { + auto d = Util::GetCharsAfterPrefix(name, "turnl_", 2); + if (!d) d = Util::GetCharsAfterPrefix(name, "indicator_", 2); + if (d) { + DummyConfig c = LightManager::CreateBaseConfig(pVeh, pFrame); + bool isLeft = (d.value()[0] == 'L'); + c.corona.color = {255, 128, 0, 255}; + c.corona.lightingType = eLightingMode::Directional; + switch (d.value()[1]) { + case 'F': c.lightType = isLeft ? eMaterialType::IndicatorLightLeftFront : eMaterialType::IndicatorLightRightFront; c.dummyPos = eDummyPos::Front; break; + case 'R': c.lightType = isLeft ? eMaterialType::IndicatorLightLeftRear : eMaterialType::IndicatorLightRightRear; c.dummyPos = eDummyPos::Rear; break; + case 'M': c.lightType = isLeft ? eMaterialType::IndicatorLightLeftMiddle : eMaterialType::IndicatorLightRightMiddle; c.dummyPos = isLeft ? eDummyPos::Left : eDummyPos::Right; break; + } + data.dummies[c.lightType].push_back(new VehicleDummy(c)); + return true; + } + } + return false; +} + +static CVector2D GetCarPathLinkPosition(CCarPathLinkAddress &address) { + if (address.m_nAreaId >= 0 && address.m_nCarPathLinkId >= 0 && ThePaths.m_pNaviNodes && ThePaths.m_pNaviNodes[address.m_nAreaId]) { + return CVector2D(static_cast(ThePaths.m_pNaviNodes[address.m_nAreaId][address.m_nCarPathLinkId].m_vecPosn.x) / 8.0f, + static_cast(ThePaths.m_pNaviNodes[address.m_nAreaId][address.m_nCarPathLinkId].m_vecPosn.y) / 8.0f); + } + return CVector2D(0.0f, 0.0f); +} + +void IndicatorComponent::Process(CVehicle* pVeh, VehLightData& data) { + static bool bSAMP = GetModuleHandle("SAMP.asi") || GetModuleHandle("SAMP.dll"); + + if (pVeh->m_pDriver == FindPlayerPed()) { + static uint32_t indicatorNoneKey = gConfig.ReadInteger("KEYS", "IndicatorLightNoneKey", VK_SHIFT); + static uint32_t indicatorLeftKey = gConfig.ReadInteger("KEYS", "IndicatorLightLeftKey", VK_Z); + static uint32_t indicatorRightKey = gConfig.ReadInteger("KEYS", "IndicatorLightRightKey", VK_C); + static uint32_t indicatorBothKey = gConfig.ReadInteger("KEYS", "IndicatorLightBothKey", VK_X); + + if (KeyPressed(indicatorNoneKey)) { + data.nIndicatorState = eIndicatorState::Off; + } else if (KeyPressed(indicatorLeftKey)) { + data.nIndicatorState = eIndicatorState::LeftOn; + } else if (KeyPressed(indicatorRightKey)) { + data.nIndicatorState = eIndicatorState::RightOn; + } else if (KeyPressed(indicatorBothKey)) { + data.nIndicatorState = eIndicatorState::BothOn; + } + } else if (pVeh->m_pDriver && !bSAMP) { + data.nIndicatorState = eIndicatorState::Off; + CVector2D prevPoint = GetCarPathLinkPosition(pVeh->m_autoPilot.m_nPreviousPathNodeInfo); + CVector2D currPoint = GetCarPathLinkPosition(pVeh->m_autoPilot.m_nCurrentPathNodeInfo); + CVector2D nextPoint = GetCarPathLinkPosition(pVeh->m_autoPilot.m_nNextPathNodeInfo); + + float angle = Util::NormalizeAngle(CGeneral::GetATanOfXY(nextPoint.x - currPoint.x, nextPoint.y - currPoint.y) * 57.295776f - + CGeneral::GetATanOfXY(currPoint.x - prevPoint.x, currPoint.y - prevPoint.y) * 57.295776f); + + if (angle >= 30.0f && angle < 180.0f) { + data.nIndicatorState = eIndicatorState::LeftOn; + } else if (angle <= 330.0f && angle > 180.0f) { + data.nIndicatorState = eIndicatorState::RightOn; + } + + if (data.nIndicatorState == eIndicatorState::Off) { + if (pVeh->m_autoPilot.m_nCurrentLane == 0 && pVeh->m_autoPilot.m_nNextLane == 1) { + data.nIndicatorState = eIndicatorState::RightOn; + } else if (pVeh->m_autoPilot.m_nCurrentLane == 1 && pVeh->m_autoPilot.m_nNextLane == 0) { + data.nIndicatorState = eIndicatorState::LeftOn; + } + } + } +} + +void IndicatorComponent::Render(CVehicle* pControlVeh, CVehicle* pTowedVeh, VehLightData& data) { + if (data.nIndicatorState == eIndicatorState::Off || !LightsGlobal::Get().bIndicatorsDelay) return; + + bool leftOn = (data.nIndicatorState == eIndicatorState::LeftOn || data.nIndicatorState == eIndicatorState::BothOn); + bool rightOn = (data.nIndicatorState == eIndicatorState::RightOn || data.nIndicatorState == eIndicatorState::BothOn); + + bool isLeftFrontOk = !Util::IsLightDamaged(pControlVeh, eLights::LIGHT_FRONT_LEFT); + bool isRightFrontOk = !Util::IsLightDamaged(pControlVeh, eLights::LIGHT_FRONT_RIGHT); + bool isLeftRearOk = !Util::IsLightDamaged(pTowedVeh, eLights::LIGHT_REAR_LEFT); + bool isRightRearOk = !Util::IsLightDamaged(pTowedVeh, eLights::LIGHT_REAR_RIGHT); + + if (leftOn) { + LightManager::RenderLight(pControlVeh, data, eMaterialType::IndicatorLightLeftFront, isLeftFrontOk, "indicator"); + LightManager::RenderLight(pControlVeh, data, eMaterialType::IndicatorLightLeftMiddle, true, "indicator"); + LightManager::RenderLight(pTowedVeh, data, eMaterialType::IndicatorLightLeftRear, isLeftRearOk, "indicator"); + } + + if (rightOn) { + LightManager::RenderLight(pControlVeh, data, eMaterialType::IndicatorLightRightFront, isRightFrontOk, "indicator"); + LightManager::RenderLight(pControlVeh, data, eMaterialType::IndicatorLightRightMiddle, true, "indicator"); + LightManager::RenderLight(pTowedVeh, data, eMaterialType::IndicatorLightRightRear, isRightRearOk, "indicator"); + } +} + diff --git a/src/features/lights/components/indicator.h b/src/features/lights/components/indicator.h new file mode 100644 index 0000000..9fbf467 --- /dev/null +++ b/src/features/lights/components/indicator.h @@ -0,0 +1,12 @@ +#pragma once +#include "base.h" +#include "../manager.h" + +class IndicatorComponent : public BaseLightComponent { +public: + eMaterialType GetMatType(CRGBA matCol) override; + bool TryRegisterDummy(CVehicle* pVeh, RwFrame* pFrame, const std::string& name, VehLightData& data) override; + + void Process(CVehicle* pVeh, VehLightData& data) override; + void Render(CVehicle* pControlVeh, CVehicle* pTowedVeh, VehLightData& data) override; +}; diff --git a/src/features/lights/components/night_light.cpp b/src/features/lights/components/night_light.cpp new file mode 100644 index 0000000..366dbfd --- /dev/null +++ b/src/features/lights/components/night_light.cpp @@ -0,0 +1,23 @@ +#include "pch.h" +#include "night_light.h" +#include "utils/util.h" + +eMaterialType NightLightComponent::GetMatType(CRGBA matCol) { + if (matCol == VEHCOL_NIGHTLIGHT_1 || matCol == VEHCOL_NIGHTLIGHT_2) return eMaterialType::NightLight; + return eMaterialType::UnknownMaterial; +} + +bool NightLightComponent::TryRegisterDummy(CVehicle* pVeh, RwFrame* pFrame, const std::string& name, VehLightData& data) { + if (name.starts_with("light_n")) { + DummyConfig c = LightManager::CreateBaseConfig(pVeh, pFrame); + c.lightType = eMaterialType::NightLight; + c.dummyPos = eDummyPos::Front; + data.dummies[c.lightType].push_back(new VehicleDummy(c)); + return true; + } + return false; +} + +void NightLightComponent::Render(CVehicle* pControlVeh, CVehicle* pTowedVeh, VehLightData& data) { + LightManager::RenderLight(pTowedVeh, data, eMaterialType::NightLight, Util::IsNightTime()); +} diff --git a/src/features/lights/components/night_light.h b/src/features/lights/components/night_light.h new file mode 100644 index 0000000..bcf3068 --- /dev/null +++ b/src/features/lights/components/night_light.h @@ -0,0 +1,10 @@ +#pragma once +#include "base.h" +#include "../manager.h" + +class NightLightComponent : public BaseLightComponent { +public: + eMaterialType GetMatType(CRGBA matCol) override; + bool TryRegisterDummy(CVehicle* pVeh, RwFrame* pFrame, const std::string& name, VehLightData& data) override; + void Render(CVehicle* pControlVeh, CVehicle* pTowedVeh, VehLightData& data) override; +}; diff --git a/src/features/lights/components/rear_lights.cpp b/src/features/lights/components/rear_lights.cpp new file mode 100644 index 0000000..aecbb99 --- /dev/null +++ b/src/features/lights/components/rear_lights.cpp @@ -0,0 +1,116 @@ +#include "pch.h" +#include "rear_lights.h" +#include "utils/util.h" +#include "utils/car.h" +#include "defines.h" + +eMaterialType RearLightsComponent::GetMatType(CRGBA matCol) { + if (matCol == VEHCOL_TAILLIGHT_LEFT) return eMaterialType::TailLightLeft; + if (matCol == VEHCOL_TAILLIGHT_RIGHT) return eMaterialType::TailLightRight; + if (matCol == VEHCOL_REVERSELIGHT_LEFT) return eMaterialType::ReverseLightLeft; + if (matCol == VEHCOL_REVERSELIGHT_RIGHT) return eMaterialType::ReverseLightRight; + if (matCol == VEHCOL_BRAKELIGHT_LEFT) return eMaterialType::BrakeLightLeft; + if (matCol == VEHCOL_BRAKELIGHT_RIGHT) return eMaterialType::BrakeLightRight; + if (matCol == VEHCOL_STTLIGHT_LEFT) return eMaterialType::STTLightLeft; + if (matCol == VEHCOL_STTLIGHT_RIGHT) return eMaterialType::STTLightRight; + if (matCol == VEHCOL_NABRAKE_LEFT) return eMaterialType::NABrakeLightLeft; + if (matCol == VEHCOL_NABRAKE_RIGHT) return eMaterialType::NABrakeLightRight; + return eMaterialType::UnknownMaterial; +} + +bool RearLightsComponent::TryRegisterDummy(CVehicle* pVeh, RwFrame* pFrame, const std::string& name, VehLightData& data) { + if (name.starts_with("rev") && (STR_FOUND(name, "_l") || STR_FOUND(name, "_r"))) { + DummyConfig c = LightManager::CreateBaseConfig(pVeh, pFrame); + c.dummyPos = eDummyPos::Rear; + c.lightType = STR_FOUND(name, "_l") ? eMaterialType::ReverseLightLeft : eMaterialType::ReverseLightRight; + c.corona.lightingType = eLightingMode::Directional; + data.dummies[c.lightType].push_back(new VehicleDummy(c)); + return true; + } else if (name.starts_with("breakl") && (STR_FOUND(name, "_l") || STR_FOUND(name, "_r"))) { + DummyConfig c = LightManager::CreateBaseConfig(pVeh, pFrame); + c.dummyPos = eDummyPos::Rear; + c.lightType = STR_FOUND(name, "_l") ? eMaterialType::BrakeLightLeft : eMaterialType::BrakeLightRight; + c.corona.color = {240, 0, 0, 255}; + c.corona.lightingType = eLightingMode::Directional; + data.dummies[c.lightType].push_back(new VehicleDummy(c)); + return true; + } else if (auto d = Util::GetCharsAfterPrefix(name, "sttlight_", 1)) { + DummyConfig c = LightManager::CreateBaseConfig(pVeh, pFrame); + c.lightType = (d == "L") ? eMaterialType::STTLightLeft : eMaterialType::STTLightRight; + c.dummyPos = eDummyPos::Rear; + c.corona.color = {240, 0, 0, 255}; + c.corona.lightingType = eLightingMode::Directional; + data.dummies[c.lightType].push_back(new VehicleDummy(c)); + return true; + } else if (auto d = Util::GetCharsAfterPrefix(name, "nabrakelight_", 1)) { + DummyConfig c = LightManager::CreateBaseConfig(pVeh, pFrame); + c.lightType = (d == "L") ? eMaterialType::NABrakeLightLeft : eMaterialType::NABrakeLightRight; + c.dummyPos = eDummyPos::Rear; + c.corona.color = {240, 0, 0, 255}; + c.corona.lightingType = eLightingMode::Directional; + data.dummies[c.lightType].push_back(new VehicleDummy(c)); + return true; + } else if (name == "taillights" || name == "taillights2") { + DummyConfig c = LightManager::CreateBaseConfig(pVeh, pFrame); + c.dummyPos = eDummyPos::Rear; + c.corona.color = {250, 0, 0, 255}; + c.corona.lightingType = eLightingMode::Directional; + c.shadow.render = name != "taillights2"; + + c.mirroredX = true; + c.lightType = eMaterialType::TailLightLeft; + data.dummies[eMaterialType::TailLightLeft].push_back(new VehicleDummy(c)); + + c.mirroredX = false; + c.lightType = eMaterialType::TailLightRight; + data.dummies[eMaterialType::TailLightRight].push_back(new VehicleDummy(c)); + return true; + } + return false; +} + +void RearLightsComponent::Process(CVehicle* pVeh, VehLightData& data) {} + +void RearLightsComponent::Render(CVehicle* pControlVeh, CVehicle* pTowedVeh, VehLightData& data) { + bool isBike = CModelInfo::IsBikeModel(pControlVeh->m_nModelIndex); + std::string shdwName = (isBike ? "taillight_bike" : "taillight"); + + if (pControlVeh->m_nVehicleSubClass == VEHICLE_AUTOMOBILE || pControlVeh->m_nVehicleSubClass == VEHICLE_MTRUCK + || pControlVeh->m_nVehicleSubClass == VEHICLE_QUAD || pControlVeh->m_nVehicleSubClass == VEHICLE_BIKE + || pControlVeh->m_nVehicleSubClass == VEHICLE_TRAILER) + { + bool isLeftRearOk = !(Util::IsLightDamaged(pTowedVeh, eLights::LIGHT_REAR_LEFT) || Util::IsPanelDamaged(pTowedVeh, ePanels::WING_REAR_LEFT)); + bool isRightRearOk = !(Util::IsLightDamaged(pTowedVeh, eLights::LIGHT_REAR_RIGHT) || Util::IsPanelDamaged(pTowedVeh, ePanels::WING_REAR_RIGHT)); + + // 1. Reverse Lights + bool reverseOn = !isBike && pControlVeh->m_nCurrentGear == 0 && (Util::GetVehicleSpeed(pControlVeh) >= 0.001f) && pControlVeh->m_pDriver; + if (reverseOn) { + LightManager::RenderLight(pTowedVeh, data, eMaterialType::ReverseLightLeft, isLeftRearOk, shdwName); + LightManager::RenderLight(pTowedVeh, data, eMaterialType::ReverseLightRight, isRightRearOk, shdwName); + } + + // 2. Brake Lights (Standard, STT, and NA Brake) + bool brakeOn = pControlVeh->m_fBreakPedal && pControlVeh->m_pDriver; + if (brakeOn) { + LightManager::RenderLight(pTowedVeh, data, eMaterialType::BrakeLightLeft, isLeftRearOk, shdwName); + LightManager::RenderLight(pTowedVeh, data, eMaterialType::BrakeLightRight, isRightRearOk, shdwName); + + LightManager::RenderLight(pTowedVeh, data, eMaterialType::NABrakeLightLeft, isLeftRearOk, shdwName); + LightManager::RenderLight(pTowedVeh, data, eMaterialType::NABrakeLightRight, isRightRearOk, shdwName); + + LightManager::RenderLight(pTowedVeh, data, eMaterialType::STTLightLeft, isLeftRearOk, shdwName); + LightManager::RenderLight(pTowedVeh, data, eMaterialType::STTLightRight, isRightRearOk, shdwName); + } + + // 3. Tail Lights (Standard and STT) + bool tailOn = (Util::IsNightTime() || CarUtil::IsLightsForcedOn(pControlVeh)) && !CarUtil::IsLightsForcedOff(pControlVeh); + if (tailOn) { + LightManager::RenderLight(pTowedVeh, data, eMaterialType::TailLightLeft, isLeftRearOk, shdwName); + LightManager::RenderLight(pTowedVeh, data, eMaterialType::TailLightRight, isRightRearOk, shdwName); + + LightManager::RenderLight(pTowedVeh, data, eMaterialType::STTLightLeft, isLeftRearOk, shdwName); + LightManager::RenderLight(pTowedVeh, data, eMaterialType::STTLightRight, isRightRearOk, shdwName); + } + } +} + diff --git a/src/features/lights/components/rear_lights.h b/src/features/lights/components/rear_lights.h new file mode 100644 index 0000000..6adb4af --- /dev/null +++ b/src/features/lights/components/rear_lights.h @@ -0,0 +1,12 @@ +#pragma once +#include "base.h" +#include "../manager.h" + +class RearLightsComponent : public BaseLightComponent { +public: + eMaterialType GetMatType(CRGBA matCol) override; + bool TryRegisterDummy(CVehicle* pVeh, RwFrame* pFrame, const std::string& name, VehLightData& data) override; + + void Process(CVehicle* pVeh, VehLightData& data) override; + void Render(CVehicle* pControlVeh, CVehicle* pTowedVeh, VehLightData& data) override; +}; diff --git a/src/features/lights/components/side_light.cpp b/src/features/lights/components/side_light.cpp new file mode 100644 index 0000000..f8476b0 --- /dev/null +++ b/src/features/lights/components/side_light.cpp @@ -0,0 +1,25 @@ +#include "pch.h" +#include "side_light.h" +#include "utils/util.h" + +eMaterialType SideLightComponent::GetMatType(CRGBA matCol) { + if (matCol == VEHCOL_SIDELIGHT_LEFT) return eMaterialType::SideLightLeft; + if (matCol == VEHCOL_SIDELIGHT_RIGHT) return eMaterialType::SideLightRight; + return eMaterialType::UnknownMaterial; +} + +bool SideLightComponent::TryRegisterDummy(CVehicle* pVeh, RwFrame* pFrame, const std::string& name, VehLightData& data) { + if (auto d = Util::GetCharsAfterPrefix(name, "sidelight_", 1)) { + DummyConfig c = LightManager::CreateBaseConfig(pVeh, pFrame); + c.lightType = (d == "L") ? eMaterialType::SideLightLeft : eMaterialType::SideLightRight; + c.dummyPos = (d == "L") ? eDummyPos::Left : eDummyPos::Right; + data.dummies[c.lightType].push_back(new VehicleDummy(c)); + return true; + } + return false; +} + +void SideLightComponent::Render(CVehicle* pControlVeh, CVehicle* pTowedVeh, VehLightData& data) { + LightManager::RenderLight(pTowedVeh, data, eMaterialType::SideLightLeft, true); + LightManager::RenderLight(pTowedVeh, data, eMaterialType::SideLightRight, true); +} diff --git a/src/features/lights/components/side_light.h b/src/features/lights/components/side_light.h new file mode 100644 index 0000000..41d366c --- /dev/null +++ b/src/features/lights/components/side_light.h @@ -0,0 +1,10 @@ +#pragma once +#include "base.h" +#include "../manager.h" + +class SideLightComponent : public BaseLightComponent { +public: + eMaterialType GetMatType(CRGBA matCol) override; + bool TryRegisterDummy(CVehicle* pVeh, RwFrame* pFrame, const std::string& name, VehLightData& data) override; + void Render(CVehicle* pControlVeh, CVehicle* pTowedVeh, VehLightData& data) override; +}; diff --git a/src/features/lights/components/spot_light.cpp b/src/features/lights/components/spot_light.cpp new file mode 100644 index 0000000..5dc604e --- /dev/null +++ b/src/features/lights/components/spot_light.cpp @@ -0,0 +1,29 @@ +#include "pch.h" +#include "spot_light.h" +#include "features/spotlights.h" + +eMaterialType SpotLightComponent::GetMatType(CRGBA matCol) { + if (matCol == VEHCOL_SPOTLIGHT) return eMaterialType::SpotLight; + return eMaterialType::UnknownMaterial; +} + +bool SpotLightComponent::TryRegisterDummy(CVehicle* pVeh, RwFrame* pFrame, const std::string& name, VehLightData& data) { + if (name.starts_with("spotlight_light")) { + DummyConfig c = LightManager::CreateBaseConfig(pVeh, pFrame); + c.lightType = eMaterialType::SpotLight; + data.dummies[c.lightType].push_back(new VehicleDummy(c)); + return true; + } + return false; +} + +void SpotLightComponent::Process(CVehicle* pVeh, VehLightData& data) {} + +void SpotLightComponent::Render(CVehicle* pControlVeh, CVehicle* pTowedVeh, VehLightData& data) { + if (SpotLights::IsEnabled(pControlVeh)) { + LightManager::RenderLight(pControlVeh, data, eMaterialType::SpotLight, true); + if (pControlVeh != pTowedVeh) { + LightManager::RenderLight(pTowedVeh, data, eMaterialType::SpotLight, true); + } + } +} diff --git a/src/features/lights/components/spot_light.h b/src/features/lights/components/spot_light.h new file mode 100644 index 0000000..6f5da4a --- /dev/null +++ b/src/features/lights/components/spot_light.h @@ -0,0 +1,12 @@ +#pragma once +#include "base.h" +#include "../manager.h" + +class SpotLightComponent : public BaseLightComponent { +public: + eMaterialType GetMatType(CRGBA matCol) override; + bool TryRegisterDummy(CVehicle* pVeh, RwFrame* pFrame, const std::string& name, VehLightData& data) override; + + void Process(CVehicle* pVeh, VehLightData& data) override; + void Render(CVehicle* pControlVeh, CVehicle* pTowedVeh, VehLightData& data) override; +}; diff --git a/src/features/lights/components/strobe_light.cpp b/src/features/lights/components/strobe_light.cpp new file mode 100644 index 0000000..75145c9 --- /dev/null +++ b/src/features/lights/components/strobe_light.cpp @@ -0,0 +1,47 @@ +#include "pch.h" +#include "strobe_light.h" +#include "utils/modelinfomgr.h" +#include "utils/util.h" + +eMaterialType StrobeLightComponent::GetMatType(CRGBA matCol) { + if (matCol == VEHCOL_STROBELIGHT) return eMaterialType::StrobeLight; + return eMaterialType::UnknownMaterial; +} + +bool StrobeLightComponent::TryRegisterDummy(CVehicle* pVeh, RwFrame* pFrame, const std::string& name, VehLightData& data) { + if (auto d = Util::GetDigitsAfter(name, "strobe_light")) { + DummyConfig c = LightManager::CreateBaseConfig(pVeh, pFrame); + c.lightType = eMaterialType::StrobeLight; + c.dummyPos = eDummyPos::Front; + c.dummyIdx = d.value(); + data.dummies[c.lightType].push_back(new VehicleDummy(c)); + return true; + } + return false; +} + +void StrobeLightComponent::Process(CVehicle* pVeh, VehLightData& data) { + if (data.dummies.count(eMaterialType::StrobeLight) == 0) return; + + size_t timer = CTimer::m_snTimeInMilliseconds; + for (auto* dummy : data.dummies[eMaterialType::StrobeLight]) { + auto& c = const_cast(dummy->GetRef()); + if (timer - c.strobe.timer > c.strobe.delay) { + c.strobe.enabled = !c.strobe.enabled; + c.strobe.timer = timer; + } + } +} + +void StrobeLightComponent::Render(CVehicle* pControlVeh, CVehicle* pTowedVeh, VehLightData& data) { + if (data.dummies.count(eMaterialType::StrobeLight) == 0) return; + + for (auto* dummy : data.dummies[eMaterialType::StrobeLight]) { + const auto& c = dummy->GetRef(); + if (c.strobe.enabled) { + ModelInfoMgr::EnableStrobeMaterial(pTowedVeh, c.dummyIdx); + // Strobes usually don't have shadows/coronas in the same way, but we can call RenderLight if needed + LightManager::RenderLight(pTowedVeh, data, eMaterialType::StrobeLight, true); + } + } +} diff --git a/src/features/lights/components/strobe_light.h b/src/features/lights/components/strobe_light.h new file mode 100644 index 0000000..36223fd --- /dev/null +++ b/src/features/lights/components/strobe_light.h @@ -0,0 +1,12 @@ +#pragma once +#include "base.h" +#include "../manager.h" + +class StrobeLightComponent : public BaseLightComponent { +public: + eMaterialType GetMatType(CRGBA matCol) override; + bool TryRegisterDummy(CVehicle* pVeh, RwFrame* pFrame, const std::string& name, VehLightData& data) override; + + void Process(CVehicle* pVeh, VehLightData& data) override; + void Render(CVehicle* pControlVeh, CVehicle* pTowedVeh, VehLightData& data) override; +}; diff --git a/src/features/lights/config.h b/src/features/lights/config.h deleted file mode 100644 index c6bbbba..0000000 --- a/src/features/lights/config.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once -#include "enums/materialtype.h" -#include "core/dummy.h" -#include - -class LightsGlobal { -public: - static LightsGlobal& Get() { - static LightsGlobal instance; - return instance; - } - - bool gbGlobalIndicatorLights = false; - float gfGlobalCoronaSize = 0.3f; - int gGlobalCoronaIntensity = 80; - int gGlobalShadowIntensity = 80; - float headlightSz = 5.0f; - bool m_bLightStates[eMaterialType::TotalMaterial]; - -private: - LightsGlobal() { - std::fill(std::begin(m_bLightStates), std::end(m_bLightStates), true); - } - LightsGlobal(const LightsGlobal&) = delete; - - bool IsLightEnabled(eMaterialType type) { - return m_bLightStates[type]; - } -}; - -struct LightsCommonData { - std::map> dummies; - std::function shouldRender; - - LightsCommonData(CVehicle* pVeh) { - } -}; \ No newline at end of file diff --git a/src/features/lights/data.h b/src/features/lights/data.h new file mode 100644 index 0000000..314b6cd --- /dev/null +++ b/src/features/lights/data.h @@ -0,0 +1,50 @@ +#pragma once +#include "enums/materialtype.h" +#include "enums/indicatorstate.h" +#include "core/dummy.h" +#include "core/colors.h" +#include +#include +#include +#include + +struct LightsGlobal { + static LightsGlobal& Get() { + static LightsGlobal instance; + return instance; + } + + bool gbGlobalIndicatorLights = false; + float gfGlobalCoronaSize = 0.3f; + int gGlobalCoronaIntensity = 80; + int gGlobalShadowIntensity = 80; + float headlightSz = 5.0f; + bool bIndicatorsDelay = false; + uint64_t nDelayTimer = 0; + +private: + LightsGlobal() = default; +}; + +struct VehLightData { + bool bFogLightsOn = false; + bool bLongLightsOn = false; + eIndicatorState nIndicatorState = eIndicatorState::Off; + bool bUsingGlobalIndicators = false; + + std::map> dummies; + + bool bLightStates[eMaterialType::TotalMaterial]; + + VehLightData(CVehicle* pVeh) { + std::fill(std::begin(bLightStates), std::end(bLightStates), true); + } + + ~VehLightData() { + for (auto& pair : dummies) { + for (auto* dummy : pair.second) { + delete dummy; + } + } + } +}; diff --git a/src/features/lights/loader.cpp b/src/features/lights/lights.cpp similarity index 62% rename from src/features/lights/loader.cpp rename to src/features/lights/lights.cpp index c63d8e4..776a170 100644 --- a/src/features/lights/loader.cpp +++ b/src/features/lights/lights.cpp @@ -1,8 +1,7 @@ #include "enums/materialtype.h" #include "pch.h" -#include "loader.h" -#include "config.h" -#include "base.h" +#include "lights.h" +#include "manager.h" void LightsFeature::Init() { if (!gConfig.ReadBoolean("FEATURES", "StandardLightsv2", false)) { @@ -16,14 +15,6 @@ void LightsFeature::Init() { patch::SetUChar(0x6E0CF8, 0); patch::SetUChar(0x6E0DEE, 0); - // NOP CVehicle::DoHeadLightBeam - if (!gConfig.ReadBoolean("TWEAKS", "HeadLightBeams", true)) - { - // cmp ax, ax - patch::SetRaw(0x6A2EA5, (void *)"\x66\x39\xC0\x90", 4); - patch::SetRaw(0x6BDE63, (void *)"\x66\x39\xC0\x90\x90\x90\x90", 7); - } - Events::initGameEvent += []() { LightsGlobal::Get().gbGlobalIndicatorLights = gConfig.ReadBoolean("FEATURES", "StandardLights_GlobalIndicatorLights", false); @@ -33,47 +24,33 @@ void LightsFeature::Init() { }; ModelInfoMgr::RegisterMaterial([](CVehicle *pVeh, RpMaterial *pMat) { - for (auto &e : ILightBehaviorBase::ptrs) { - if (e->IsValidMaterial(pMat)) { - return e->GetMatType(pMat); - } - } - return eMaterialType::UnknownMaterial; + return LightManager::GetMatType(pMat); }); ModelInfoMgr::RegisterDummy([](CVehicle *pVeh, RwFrame *pFrame, const std::string_view& nodeName) { - for (auto &e : ILightBehaviorBase::ptrs) { - if (e->IsValidDummy(pFrame) && e->RegisterDummy(pFrame)) { - return; - } - } + LightManager::RegisterDummy(pVeh, pFrame, std::string(nodeName)); }); Events::processScriptsEvent += []() { CVehicle *pVeh = FindPlayerVehicle(-1, false); - for (auto &e : ILightBehaviorBase::ptrs) { - e->Process(pVeh); - } + if (pVeh) { + LightManager::Process(pVeh); + } }; ModelInfoMgr::RegisterRender([](CVehicle *pControlVeh) { int model = pControlVeh->m_nModelIndex; - // skip directly processing trailers if (CModelInfo::IsTrailerModel(model)) { return; } CVehicle *pTowedVeh = pControlVeh; - - if (pControlVeh->m_pTrailer) - { + if (pControlVeh->m_pTrailer) { pTowedVeh = pControlVeh->m_pTrailer; } - for (auto &e : ILightBehaviorBase::ptrs) { - e->Render(pControlVeh, pTowedVeh); - } + LightManager::Render(pControlVeh, pTowedVeh); }); } \ No newline at end of file diff --git a/src/features/lights/loader.h b/src/features/lights/lights.h similarity index 100% rename from src/features/lights/loader.h rename to src/features/lights/lights.h diff --git a/src/features/lights/manager.cpp b/src/features/lights/manager.cpp new file mode 100644 index 0000000..fb6458e --- /dev/null +++ b/src/features/lights/manager.cpp @@ -0,0 +1,132 @@ +#include "pch.h" +#include "manager.h" +#include "utils/modelinfomgr.h" +#include "utils/render.h" +#include "utils/util.h" +#include "defines.h" +#include "components/headlight.h" +#include "components/indicator.h" +#include "components/rear_lights.h" +#include "components/fog_light.h" +#include "components/strobe_light.h" +#include "components/day_light.h" +#include "components/night_light.h" +#include "components/allday_light.h" +#include "components/side_light.h" +#include "components/spot_light.h" + +void LightManager::Init() { + m_Components.push_back(std::make_unique()); + m_Components.push_back(std::make_unique()); + m_Components.push_back(std::make_unique()); + m_Components.push_back(std::make_unique()); + m_Components.push_back(std::make_unique()); + m_Components.push_back(std::make_unique()); + m_Components.push_back(std::make_unique()); + m_Components.push_back(std::make_unique()); + m_Components.push_back(std::make_unique()); + m_Components.push_back(std::make_unique()); +} + +DummyConfig LightManager::CreateBaseConfig(CVehicle* pVeh, RwFrame* pFrame) { + DummyConfig c; + c.pVeh = pVeh; + c.frame = pFrame; + c.corona.color = {255, 255, 255, static_cast(LightsGlobal::Get().gGlobalCoronaIntensity)}; + return c; +} + +eMaterialType LightManager::GetMatType(RpMaterial* pMat) { + CRGBA matCol = *reinterpret_cast(RpMaterialGetColor(pMat)); + matCol.a = 255; + + for (const auto& comp : m_Components) { + eMaterialType type = comp->GetMatType(matCol); + if (type != eMaterialType::UnknownMaterial) return type; + } + + return eMaterialType::UnknownMaterial; +} + +void LightManager::RegisterDummy(CVehicle* pVeh, RwFrame* pFrame, const std::string& name) { + VehLightData& data = m_VehData.Get(pVeh); + + for (const auto& comp : m_Components) { + if (comp->TryRegisterDummy(pVeh, pFrame, name, data)) return; + } +} + +void LightManager::Process(CVehicle* pVeh) { + if (!pVeh) return; + + static uint64_t lastFlashUpdate = 0; + uint64_t now = CTimer::m_snTimeInMilliseconds; + if (now - lastFlashUpdate > 500) { + LightsGlobal::Get().bIndicatorsDelay = !LightsGlobal::Get().bIndicatorsDelay; + lastFlashUpdate = now; + } + + if (Util::IsEngineOff(pVeh)) return; + + VehLightData& data = m_VehData.Get(pVeh); + for (const auto& comp : m_Components) { + comp->Process(pVeh, data); + } +} + +void LightManager::Render(CVehicle* pControlVeh, CVehicle* pTowedVeh) { + if (Util::IsEngineOff(pControlVeh)) return; + + VehLightData& data = m_VehData.Get(pControlVeh); + for (const auto& comp : m_Components) { + comp->Render(pControlVeh, pTowedVeh, data); + } +} + +void LightManager::RenderLight(CVehicle* pVeh, VehLightData& data, eMaterialType type, bool isOn, const std::string& texture) { + if (!isOn) return; + + if (IsDummyAvailable(data, type)) { + for (auto* dummy : data.dummies[type]) { + dummy->Update(); + const DummyConfig& c = dummy->GetRef(); + + if (gConfig.ReadBoolean("FEATURES", "LightCoronas", false)) { + if (c.corona.lightingType == eLightingMode::NonDirectional) { + RenderUtil::RegisterCorona(pVeh, (reinterpret_cast(pVeh) * 255) + 255 + (int)type, c.position, c.corona.color, c.corona.size); + } else { + RenderUtil::RegisterCoronaDirectional(&dummy->Get(), c.rotation.angle, 180.0f, 1.0f, c.corona.lightingType == eLightingMode::Inversed, false); + } + } + + if (c.shadow.render && !texture.empty()) { + RenderUtil::RegisterShadowDirectional(&dummy->Get(), texture, c.shadow.size); + } + } + } + ModelInfoMgr::EnableMaterial(pVeh, type); +} + +bool LightManager::IsDummyAvailable(VehLightData& data, eMaterialType type) { + return data.dummies.count(type) > 0 && !data.dummies[type].empty(); +} + +#include "ModelExtrasAPI.h" + +extern "C" +{ + bool ME_GetVehicleLightState(CVehicle *pVeh, ME_LightID lightId) + { + return LightManager::m_VehData.Get(pVeh).bLightStates[static_cast(lightId)]; + } + + void ME_SetVehicleLightState(CVehicle *pVeh, ME_LightID lightId, bool state) + { + LightManager::m_VehData.Get(pVeh).bLightStates[static_cast(lightId)] = state; + } + + int __declspec(dllexport) ignore4(int i) + { + return 1; + } +} diff --git a/src/features/lights/manager.h b/src/features/lights/manager.h new file mode 100644 index 0000000..84372cb --- /dev/null +++ b/src/features/lights/manager.h @@ -0,0 +1,24 @@ +#pragma once +#include "data.h" +#include "core/base.h" +#include +#include +#include +#include "components/base.h" + +class LightManager { +public: + static inline VehicleExtendedData m_VehData; + static inline std::vector> m_Components; + + static void Init(); + static eMaterialType GetMatType(RpMaterial* pMat); + static void RegisterDummy(CVehicle* pVeh, RwFrame* pFrame, const std::string& name); + + static void Process(CVehicle* pVeh); + static void Render(CVehicle* pControlVeh, CVehicle* pTowedVeh); + + static DummyConfig CreateBaseConfig(CVehicle* pVeh, RwFrame* pFrame); + static void RenderLight(CVehicle* pVeh, VehLightData& data, eMaterialType type, bool isOn, const std::string& texture = ""); + static bool IsDummyAvailable(VehLightData& data, eMaterialType type); +}; diff --git a/src/features/sirens.cpp b/src/features/sirens.cpp index 77e4d03..8662ddd 100755 --- a/src/features/sirens.cpp +++ b/src/features/sirens.cpp @@ -641,7 +641,7 @@ void Sirens::Init() id = Util::GetDigitsAfter(name, "light_em").value_or(id); if (id != -1) { - VehicleDummyConfig config; + DummyConfig config; config.pVeh = vehicle; config.frame = frame; vehicleData[vehicle]->Dummies[id].push_back(new VehicleDummy(config)); @@ -969,7 +969,7 @@ void Sirens::EnableDummy(int id, VehicleDummy *dummy, CVehicle *vehicle, Vehicle alpha = static_cast(alpha * material->InertiaMultiplier); } - VehicleDummyConfig *pDummyConfig = &dummy->Get(); + DummyConfig *pDummyConfig = &dummy->Get(); pDummyConfig->shadow.color = pDummyConfig->corona.color = material->Color; pDummyConfig->corona.size = material->Size; float dummyAngle = Util::NormalizeAngle(pDummyConfig->rotation.angle + material->Shadow.AngleOffset); diff --git a/src/loader.cpp b/src/loader.cpp index fff33bd..45a86ae 100755 --- a/src/loader.cpp +++ b/src/loader.cpp @@ -1,4 +1,4 @@ -#include "lights/loader.h" +#include "lights/lights.h" #include "pch.h" #include #include @@ -37,11 +37,9 @@ #include "utils/frameextention.h" #include "utils/meevents.h" -void InitLogFile(); - constexpr uint32_t TEST_CHEAT = 0x0ADC; -void ModelExtrasLoader::Init() +void ModelExtras::Init() { AudioMgr::Init(); ModelInfoMgr::Init(); @@ -134,14 +132,14 @@ void ModelExtrasLoader::Init() new SpotLights(); for (auto *pFeature : m_Features) { - // if (pFeature->IsActive()) - // { + if (pFeature->IsActive()) + { pFeature->Init(); - // }StandardLights + } } } -void ModelExtrasLoader::Reload(CVehicle *pVeh) +void ModelExtras::Reload(CVehicle *pVeh) { for (auto* pFeature : m_Features) { if (pFeature) { diff --git a/src/loader.h b/src/loader.h index 4288810..2e99a08 100755 --- a/src/loader.h +++ b/src/loader.h @@ -5,7 +5,7 @@ #include #include "features/core/base.h" -class ModelExtrasLoader { +class ModelExtras { public: static inline std::vector m_Features; static inline std::bitset(eFeatureMatrix::FeatureCount)> m_bEnabledFeatures; diff --git a/src/utils/datamgr.cpp b/src/utils/datamgr.cpp index 7a3812d..4d6dc80 100755 --- a/src/utils/datamgr.cpp +++ b/src/utils/datamgr.cpp @@ -11,40 +11,12 @@ bool is_number(const std::string &s) return !s.empty() && std::all_of(s.begin(), s.end(), ::isdigit); } -extern int Convert_EmlToJsonc(const std::string &inPath); -extern void Convert_JsonToJsonc(const std::string &inPath); -extern int Convert_IvfcToJsonc(const std::string &inPath); - void DataMgr::Init() { - Convert(); - Parse(); -} - -void DataMgr::Convert() -{ - std::string path = std::string(MOD_DATA_PATH("data/")); - - if (std::filesystem::exists(path)) { - for (auto &p : std::filesystem::directory_iterator(path)) - { - std::string filePath = p.path().string(); - std::string fileExt = p.path().extension().string(); - if (fileExt == ".eml") - { - Convert_EmlToJsonc(filePath); - } - else if (fileExt == ".json") - { - Convert_JsonToJsonc(filePath); - } - else if (fileExt == ".ivfc") - { - Convert_IvfcToJsonc(filePath); - } - } - } else { - LOG(WARNING) << "ModelExtras/data directory doesn't exist"; + LOG(INFO) << "Loading data files from ModelExtras/data..."; + for (const auto &e : std::filesystem::directory_iterator(MOD_DATA_PATH("data/"))) + { + LoadFile(e); } } @@ -69,13 +41,6 @@ void DataMgr::LoadFile(const std::filesystem::directory_entry &e) return; } - // Ignore folders with '.' int their names .data / .profile etc - std::string parentPath = e.path().parent_path().string(); - if (STR_FOUND(parentPath, '.')) - { - return; - } - std::string filename = e.path().filename().string(); std::string key = e.path().stem().string(); int model = 0; @@ -146,15 +111,6 @@ void DataMgr::LoadFile(const std::filesystem::directory_entry &e) } } -void DataMgr::Parse() -{ - LOG(INFO) << "Loading data files from ModelExtras/data..."; - for (const auto &e : std::filesystem::directory_iterator(MOD_DATA_PATH("data/"))) - { - LoadFile(e); - } -} - nlohmann::json& DataMgr::Get(int model) { return data[model]; diff --git a/src/utils/datamgr.h b/src/utils/datamgr.h index 6cdeeda..3dff322 100755 --- a/src/utils/datamgr.h +++ b/src/utils/datamgr.h @@ -9,11 +9,9 @@ class DataMgr static inline std::map modelPath; public: - static void Convert(); static void Init(); static void LoadFile(const std::filesystem::directory_entry &entry); static void Reload(int model); - static void Parse(); static nlohmann::json &Get(int model); static const std::string &GetPath(int model); }; \ No newline at end of file diff --git a/src/utils/render.cpp b/src/utils/render.cpp index 84a61a2..143beda 100755 --- a/src/utils/render.cpp +++ b/src/utils/render.cpp @@ -84,7 +84,7 @@ void RenderUtil::RegisterCorona(CEntity *pEntity, int coronaID, CVector pos, CRG coronaSz, 260.0f, CORONATYPE_SHINYSTAR, FLARETYPE_NONE, true, false, 0, 0.0f, false, 0.3f, 0, 30.0f, false, false); }; -void RenderUtil::RegisterCoronaDirectional(const VehicleDummyConfig *pConfig, float angle, float radius, float szMul, bool inversed, bool skipCheck) +void RenderUtil::RegisterCoronaDirectional(const DummyConfig *pConfig, float angle, float radius, float szMul, bool inversed, bool skipCheck) { const float FADE_RANGE = 20.0f; float sz = pConfig->corona.size * szMul; @@ -137,7 +137,7 @@ void RenderUtil::RegisterCoronaDirectional(const VehicleDummyConfig *pConfig, fl extern int gGlobalShadowIntensity; -void RenderUtil::RegisterShadowDirectional(const VehicleDummyConfig *pConfig, const std::string &shadwTexName, float shdwSz) +void RenderUtil::RegisterShadowDirectional(const DummyConfig *pConfig, const std::string &shadwTexName, float shdwSz) { const float SHDW_SZ_MUL = 2.0f; if (!pConfig->pVeh || !pConfig || shdwSz == 0.0f || !gConfig.ReadBoolean("FEATURES", "LightShadows", false)) diff --git a/src/utils/render.h b/src/utils/render.h index 516b6c9..7413159 100755 --- a/src/utils/render.h +++ b/src/utils/render.h @@ -7,13 +7,13 @@ class CEntity; class CRGBA; enum class eDummyPos; -class VehicleDummyConfig; +class DummyConfig; class RenderUtil { public: static void RegisterCorona(CEntity *pEntity, int coronaID, CVector pos, CRGBA col, float size); - static void RegisterCoronaDirectional(const VehicleDummyConfig *pConfig, float angle, float radius, float szMul = 1.0f, bool inversed = false, bool skipCheck = true); + static void RegisterCoronaDirectional(const DummyConfig *pConfig, float angle, float radius, float szMul = 1.0f, bool inversed = false, bool skipCheck = true); static void RegisterShadow(CEntity *pEntity, CVector position, CRGBA col, float angle, eDummyPos dummyPos, const std::string &shadwTexName, CVector2D shdwSz = {1.0f, 1.0f}, CVector2D shdwOffset = {0.0f, 0.0f}, RwTexture *pTexture = nullptr); - static void RegisterShadowDirectional(const VehicleDummyConfig *pConfig, const std::string &shadwTexName, float shdwSz); + static void RegisterShadowDirectional(const DummyConfig *pConfig, const std::string &shadwTexName, float shdwSz); }; \ No newline at end of file diff --git a/tools/convert_avs_json_to_jsonc.py b/tools/convert_avs_json_to_jsonc.py new file mode 100644 index 0000000..5f48e15 --- /dev/null +++ b/tools/convert_avs_json_to_jsonc.py @@ -0,0 +1,54 @@ +""" +=============================================================================== +INSTRUCTIONS FOR NON-PROGRAMMERS: +1. Place this script ('convert_avs.py') in a folder. +2. Put your old AVS '.json' files in that same folder. +3. Double-click this script to run it. +4. It will create new '.jsonc' files and move the old ones to 'backup'. +=============================================================================== +""" + +import json +import shutil +from pathlib import Path + +DATA_DIR = Path("data") +BACKUP_DIR = DATA_DIR / "backup" +SHADOW_TYPES = ["round", "pointlight", "arealight", "bollard", "comet", "cylindernarrow", "defined", "defineddiffuse", "defineddiffusespot", "definedspot", "narrow", "jellyfish", "mediumscatter", "overhead", "parallelbeam", "pear", "round", "scatterlight", "softarrow", "softdisplay", "star", "starfocused", "threelobeumbrella", "threelobevee", "tightfocused", "toppost", "trapezoid", "umbrella", "vee", "veeup", "xarrow", "xarrowdiffuse", "xarrowsoft"] + +def setup_directories(): + DATA_DIR.mkdir(exist_ok=True) + BACKUP_DIR.mkdir(exist_ok=True) + +def update_recursive(data): + if isinstance(data, dict): + for k, v in data.items(): + if k == "shadow" and isinstance(v, dict) and "type" in v and isinstance(v["type"], int): + idx = v["type"] + name = SHADOW_TYPES[idx] if 0 <= idx < len(SHADOW_TYPES) else "round" + v["type"] = name + if name != "round" and "size" in v: + v["size"] = float(v["size"]) * 0.666 + update_recursive(v) + elif isinstance(data, list): + for i in data: update_recursive(i) + +def convert(p: Path): + out = Path(str(p) + "c") + with open(p, 'r', encoding='utf-8') as f: + old_data = json.load(f) + + new_data = {"metadata": {"author": "Unknown", "desc": "AVS Upgrade", "minver": 20000}, "sirens": old_data} + update_recursive(new_data["sirens"]) + + with open(out, 'w', encoding='utf-8') as f: + json.dump(new_data, f, indent=4) + + shutil.move(str(p), str(BACKUP_DIR / p.name)) + print(f"Done: {p.name} -> {out.name}") + +if __name__ == "__main__": + setup_directories() + for f in Path(".").glob("*.json"): + convert(f) + input("\nPress Enter to close...") \ No newline at end of file diff --git a/tools/convert_ivf_carcols_to_jsonc.py b/tools/convert_ivf_carcols_to_jsonc.py new file mode 100644 index 0000000..4c0bbc0 --- /dev/null +++ b/tools/convert_ivf_carcols_to_jsonc.py @@ -0,0 +1,59 @@ +""" +=============================================================================== +INSTRUCTIONS FOR NON-PROGRAMMERS: +1. Place this script ('convert_carcols.py') in a folder. +2. Put your '.ivfc' files (ImVehFt carcols) in that same folder. +3. Double-click this script to run it. +4. It will extract colors and variations into a new '.jsonc' file. +=============================================================================== +""" + +import json +import shutil +from pathlib import Path + +DATA_DIR = Path("data") +BACKUP_DIR = DATA_DIR / "backup" + +def setup_directories(): + DATA_DIR.mkdir(exist_ok=True) + BACKUP_DIR.mkdir(exist_ok=True) + +def convert(p: Path): + with open(p, 'r', encoding='utf-8') as f: + lines = [l.strip() for l in f if l.strip() and not l.startswith('#')] + + model = -1 + for l in lines: + if l.lower().startswith("vehicle_id"): + model = int(l.split()[1]) + break + + if model == -1: return + + out = DATA_DIR / f"{model}.jsonc" + carcols = {"colors": [], "variations": []} + mode = None + + for l in lines: + if "num_colors" in l.lower(): mode = "c" + elif "num_variations" in l.lower(): mode = "v" + else: + parts = l.split() + if mode == "c" and len(parts) >= 3: + carcols["colors"].append({"red": int(parts[0]), "green": int(parts[1]), "blue": int(parts[2])}) + elif mode == "v" and len(parts) >= 4: + carcols["variations"].append({"primary": int(parts[0]), "secondary": int(parts[1]), "tertiary": int(parts[2]), "quaternary": int(parts[3])}) + + data = {"metadata": {"author": "Unknown", "desc": "IVF Carcols", "minver": 20000}, "carcols": carcols} + with open(out, 'w', encoding='utf-8') as f: + json.dump(data, f, indent=4) + + shutil.move(str(p), str(BACKUP_DIR / p.name)) + print(f"Done: {p.name} -> {out.name}") + +if __name__ == "__main__": + setup_directories() + for f in Path(".").glob("*.ivfc"): + convert(f) + input("\nPress Enter to close...") \ No newline at end of file diff --git a/tools/convert_ivf_eml_to_jsonc.py b/tools/convert_ivf_eml_to_jsonc.py new file mode 100644 index 0000000..b2851f2 --- /dev/null +++ b/tools/convert_ivf_eml_to_jsonc.py @@ -0,0 +1,96 @@ +""" +=============================================================================== +INSTRUCTIONS FOR NON-PROGRAMMERS: +1. Install Python from python.org (if you haven't already). +2. Place this script ('convert_eml.py') in a folder. +3. Put all your '.eml' files in that same folder. +4. Double-click this script to run it. +5. It will create a 'data' folder with your new '.jsonc' files and move + the originals to a 'backup' folder. +=============================================================================== +""" + +import json +import shutil +from pathlib import Path + +# Configuration +DATA_DIR = Path("data") +BACKUP_DIR = DATA_DIR / "backup" + +def setup_directories(): + DATA_DIR.mkdir(exist_ok=True) + BACKUP_DIR.mkdir(exist_ok=True) + +def read_color(val: str) -> int: + if len(val) == 3: return int(val) + return int(val, 16) + +def convert_eml_to_jsonc(eml_path: Path): + with open(eml_path, 'r', encoding='utf-8') as f: + lines = [line.strip() for line in f if line.strip() and not line.startswith('#')] + + if not lines: return + + try: + model = int(lines[0].split()[0]) + except: return + + json_path = DATA_DIR / f"{model}.jsonc" + + # Load existing or start new + json_data = {} + if json_path.exists(): + with open(json_path, 'r') as f: json_data = json.load(f) + + json_data["metadata"] = {"author": "Unknown", "desc": "Converted EML", "minver": 20000} + + sirens = {"imvehft": True, "states": {"1. modelextras": {}}} + extras = sirens["states"]["1. modelextras"] + + for line in lines[1:]: + p = line.split() + if len(p) < 12: continue + + # Mapping the columns from the EML text file + id_val = p[0] + red, green, blue, alpha = read_color(p[2]), read_color(p[3]), read_color(p[4]), read_color(p[5]) + l_type, size, shadow, flash, sw, start = int(p[6]), float(p[7]), float(p[8]), float(p[9]), int(p[10]), int(p[11]) + + pattern = [] + count = 0 + if len(p) >= 12 + sw: + for i in range(sw): + ms = int(p[12+i]) - count + count += ms + if ms != 0: pattern.append(ms) + + extras[id_val] = { + "type": "directional" if l_type == 0 else ("inversed-directional" if l_type == 1 else "non-directional"), + "size": size, + "color": {"red": red, "green": green, "blue": blue, "alpha": alpha}, + "state": 1 if (count == 0 or count > 64553) else start, + "pattern": [] if (count == 0 or count > 64553) else pattern, + "inertia": flash / 100.0, + "shadow": { + "type": "pointlight" if l_type == 2 else "round", + "size": shadow / 1.5, + "angleoffset": 180.0 if l_type == 1 else 0.0 + } + } + + json_data["sirens"] = sirens + with open(json_path, 'w', encoding='utf-8') as f: + json.dump(json_data, f, indent=4) + + shutil.move(str(eml_path), str(BACKUP_DIR / eml_path.name)) + print(f"Done: {eml_path.name} -> {json_path.name}") + +if __name__ == "__main__": + setup_directories() + files = list(Path(".").glob("*.eml")) + if not files: + print("No .eml files found in this folder!") + for f in files: + convert_eml_to_jsonc(f) + input("\nPress Enter to close...") \ No newline at end of file