From 3bd78d848da961a5ef3de67c067a139435c85947 Mon Sep 17 00:00:00 2001 From: dexy Date: Fri, 11 Jan 2019 14:24:50 +1100 Subject: [PATCH] Vehicle files progress --- CodeWalker.Core/CodeWalker.Core.csproj | 4 + .../GameFiles/FileTypes/CarColsFile.cs | 616 ++++++++++++++++++ .../GameFiles/FileTypes/CarModColsFile.cs | 33 + .../GameFiles/FileTypes/CarVariationsFile.cs | 33 + .../GameFiles/FileTypes/VehicleLayoutsFile.cs | 33 + .../GameFiles/FileTypes/VehiclesFile.cs | 329 +++++++++- CodeWalker.Core/GameFiles/GameFile.cs | 4 + CodeWalker.Core/GameFiles/GameFileCache.cs | 123 +++- .../GameFiles/MetaTypes/MetaNames.cs | 46 +- .../GameFiles/MetaTypes/MetaXml.cs | 4 +- .../GameFiles/MetaTypes/PsoTypes.cs | 232 +++---- CodeWalker.Core/GameFiles/MetaTypes/XmlPso.cs | 12 +- CodeWalker.Core/GameFiles/RpfManager.cs | 156 ++--- CodeWalker.csproj | 9 + Program.cs | 9 + Vehicles/VehicleForm.Designer.cs | 115 ++++ Vehicles/VehicleForm.cs | 609 +++++++++++++++++ Vehicles/VehicleForm.resx | 415 ++++++++++++ 18 files changed, 2571 insertions(+), 211 deletions(-) create mode 100644 CodeWalker.Core/GameFiles/FileTypes/CarColsFile.cs create mode 100644 CodeWalker.Core/GameFiles/FileTypes/CarModColsFile.cs create mode 100644 CodeWalker.Core/GameFiles/FileTypes/CarVariationsFile.cs create mode 100644 CodeWalker.Core/GameFiles/FileTypes/VehicleLayoutsFile.cs create mode 100644 Vehicles/VehicleForm.Designer.cs create mode 100644 Vehicles/VehicleForm.cs create mode 100644 Vehicles/VehicleForm.resx diff --git a/CodeWalker.Core/CodeWalker.Core.csproj b/CodeWalker.Core/CodeWalker.Core.csproj index c0142de..85c1a62 100644 --- a/CodeWalker.Core/CodeWalker.Core.csproj +++ b/CodeWalker.Core/CodeWalker.Core.csproj @@ -51,6 +51,9 @@ + + + @@ -60,6 +63,7 @@ + diff --git a/CodeWalker.Core/GameFiles/FileTypes/CarColsFile.cs b/CodeWalker.Core/GameFiles/FileTypes/CarColsFile.cs new file mode 100644 index 0000000..6679055 --- /dev/null +++ b/CodeWalker.Core/GameFiles/FileTypes/CarColsFile.cs @@ -0,0 +1,616 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using TC = System.ComponentModel.TypeConverterAttribute; +using EXP = System.ComponentModel.ExpandableObjectConverter; +using SharpDX; + +namespace CodeWalker.GameFiles +{ + [TC(typeof(EXP))] public class CarColsFile : GameFile, PackedFile + { + public CarColsFile() : base(null, GameFileType.CarCols) + { } + public CarColsFile(RpfFileEntry entry) : base(entry, GameFileType.CarCols) + { + } + + public void Load(byte[] data, RpfFileEntry entry) + { + RpfFileEntry = entry; + Name = entry.Name; + FilePath = Name; + + + + //TODO + + //can be PSO .ymt or XML .meta + + + + + //for carcols wheels: + //< Item /> < !--VWT_SPORT-- > + //< Item /> < !--VWT_MUSCLE-- > + //< Item /> < !--VWT_LOWRIDER-- > + //< Item /> < !--VWT_SUV-- > + //< Item /> < !--VWT_OFFROAD-- > + //< Item /> < !--VWT_TUNER-- > + //< Item /> < !--VWT_BIKE-- > + //< Item /> < !--VWT_HIEND-- > + //< Item /> < !--VWT_SUPERMOD1-- > + //< Item > < !--VWT_SUPERMOD2-- > + + + + + Loaded = true; + } + } + + + [TC(typeof(EXP))] public class CVehicleModelInfoVarGlobal + { + public CVehicleModelInfoVarGlobal_465922034 VehiclePlates { get; set; } + public CVehicleModelColor[] Colors { get; set; } + public CVehicleMetallicSetting[] MetallicSettings { get; set; } + public CVehicleWindowColor[] WindowColors { get; set; } + public vehicleLightSettings[] Lights { get; set; } + public sirenSettings[] Sirens { get; set; } + public CVehicleKit[] Kits { get; set; } + public CVehicleWheel[][] Wheels { get; set; } + public CVehicleModelInfoVarGlobal_3062246906 GlobalVariationData { get; set; } + public CVehicleModelInfoVarGlobal_2807227399[] XenonLightColors { get; set; } + } + [TC(typeof(EXP))] public class CVehicleModelInfoVarGlobal_465922034 //VehiclePlates + { + public CVehicleModelInfoVarGlobal_3027500557[] Textures { get; set; } + public int DefaultTexureIndex { get; set; } + public byte NumericOffset { get; set; } + public byte AlphabeticOffset { get; set; } + public byte SpaceOffset { get; set; } + public byte RandomCharOffset { get; set; } + public byte NumRandomChar { get; set; } + } + [TC(typeof(EXP))] public class CVehicleModelInfoVarGlobal_3027500557 //VehiclePlates Texture + { + public MetaHash TextureSetName { get; set; } + public MetaHash DiffuseMapName { get; set; } + public MetaHash NormalMapName { get; set; } + public Vector4 FontExtents { get; set; } + public Vector2 MaxLettersOnPlate { get; set; } + public uint FontColor { get; set; } + public uint FontOutlineColor { get; set; } + public bool IsFontOutlineEnabled { get; set; } + public Vector2 FontOutlineMinMaxDepth { get; set; } + } + [TC(typeof(EXP))] public class CVehicleModelColor + { + public uint Color { get; set; } + public CVehicleModelColor_360458334 metallicID { get; set; } + public CVehicleModelColor_544262540 audioColor { get; set; } + public CVehicleModelColor_2065815796 audioPrefix { get; set; } + public MetaHash audioColorHash { get; set; } + public MetaHash audioPrefixHash { get; set; } + public string colorName { get; set; } + } + [TC(typeof(EXP))] public class CVehicleMetallicSetting + { + public float specInt { get; set; } + public float specFalloff { get; set; } + public float specFresnel { get; set; } + } + [TC(typeof(EXP))] public class CVehicleWindowColor + { + public uint color { get; set; } + public MetaHash name { get; set; } + } + [TC(typeof(EXP))] public class vehicleLightSettings + { + public byte id { get; set; } + public vehicleLight indicator { get; set; } + public vehicleCorona rearIndicatorCorona { get; set; } + public vehicleCorona frontIndicatorCorona { get; set; } + public vehicleLight tailLight { get; set; } + public vehicleCorona tailLightCorona { get; set; } + public vehicleCorona tailLightMiddleCorona { get; set; } + public vehicleLight headLight { get; set; } + public vehicleCorona headLightCorona { get; set; } + public vehicleLight reversingLight { get; set; } + public vehicleCorona reversingLightCorona { get; set; } + public string name { get; set; } + } + [TC(typeof(EXP))] public class vehicleLight + { + public float intensity { get; set; } + public float falloffMax { get; set; } + public float falloffExponent { get; set; } + public float innerConeAngle { get; set; } + public float outerConeAngle { get; set; } + public bool emmissiveBoost { get; set; } + public uint color { get; set; } + public MetaHash textureName { get; set; } + public bool mirrorTexture { get; set; } + } + [TC(typeof(EXP))] public class vehicleCorona + { + public float size { get; set; } + public float size_far { get; set; } + public float intensity { get; set; } + public float intensity_far { get; set; } + public uint color { get; set; } + public byte numCoronas { get; set; } + public byte distBetweenCoronas { get; set; } + public byte distBetweenCoronas_far { get; set; } + public float xRotation { get; set; } + public float yRotation { get; set; } + public float zRotation { get; set; } + public float zBias { get; set; } + public bool pullCoronaIn { get; set; } + } + [TC(typeof(EXP))] public class sirenSettings + { + public byte id { get; set; } + public string name { get; set; } + public float timeMultiplier { get; set; } + public float lightFalloffMax { get; set; } + public float lightFalloffExponent { get; set; } + public float lightInnerConeAngle { get; set; } + public float lightOuterConeAngle { get; set; } + public float lightOffset { get; set; } + public MetaHash textureName { get; set; } + public uint sequencerBpm { get; set; } + public sirenSettings_188820339 leftHeadLight { get; set; } + public sirenSettings_188820339 rightHeadLight { get; set; } + public sirenSettings_188820339 leftTailLight { get; set; } + public sirenSettings_188820339 rightTailLight { get; set; } + public byte leftHeadLightMultiples { get; set; } + public byte rightHeadLightMultiples { get; set; } + public byte leftTailLightMultiples { get; set; } + public byte rightTailLightMultiples { get; set; } + public bool useRealLights { get; set; } + public sirenLight[] sirens { get; set; } + } + [TC(typeof(EXP))] public class sirenSettings_188820339 + { + public uint sequencer { get; set; } + } + [TC(typeof(EXP))] public class sirenLight + { + public sirenLight_1356743507 rotation { get; set; } + public sirenLight_1356743507 flashiness { get; set; } + public sirenCorona corona { get; set; } + public uint color { get; set; } + public float intensity { get; set; } + public byte lightGroup { get; set; } + public bool rotate { get; set; } + public bool scale { get; set; } + public byte scaleFactor { get; set; } + public bool flash { get; set; } + public bool light { get; set; } + public bool spotLight { get; set; } + public bool castShadows { get; set; } + } + [TC(typeof(EXP))] public class sirenLight_1356743507 + { + public float delta { get; set; } + public float start { get; set; } + public float speed { get; set; } + public uint sequencer { get; set; } + public byte multiples { get; set; } + public bool direction { get; set; } + public bool syncToBpm { get; set; } + } + [TC(typeof(EXP))] public class sirenCorona + { + public float intensity { get; set; } + public float size { get; set; } + public float pull { get; set; } + public bool faceCamera { get; set; } + } + [TC(typeof(EXP))] public class CVehicleKit + { + public MetaHash kitName { get; set; } + public ushort id { get; set; } + public CVehicleKit_3865430600 kitType { get; set; } + public CVehicleModVisible[] visibleMods { get; set; } + public CVehicleModLink[] linkMods { get; set; } + public CVehicleModStat[] statMods { get; set; } + public CVehicleKit_427606548[] slotNames { get; set; } + public MetaHash[] liveryNames { get; set; } + public MetaHash[] livery2Names { get; set; } + } + [TC(typeof(EXP))] public class CVehicleModVisible + { + public MetaHash modelName { get; set; } + public string modShopLabel { get; set; } + public MetaHash[] linkedModels { get; set; } + public CVehicleMod_3635907608[] turnOffBones { get; set; } + public CVehicleMod_2363989491 type { get; set; } + public CVehicleMod_3635907608 bone { get; set; } + public CVehicleMod_3635907608 collisionBone { get; set; } + public CVehicleMod_3413962745 cameraPos { get; set; } + public float audioApply { get; set; } + public byte weight { get; set; } + public bool turnOffExtra { get; set; } + public bool disableBonnetCamera { get; set; } + public bool allowBonnetSlide { get; set; } + public byte weaponSlot { get; set; } //SByte? + public byte Unk_2656206330 { get; set; } //SByte? + public bool disableProjectileDriveby { get; set; } + public bool disableDriveby { get; set; } + public int Unk_161724223 { get; set; } + public int Unk_484538291 { get; set; } + } + [TC(typeof(EXP))] public class CVehicleModLink + { + public MetaHash modelName { get; set; } + public CVehicleMod_3635907608 bone { get; set; } + public bool turnOffExtra { get; set; } + } + [TC(typeof(EXP))] public class CVehicleModStat + { + public MetaHash identifier { get; set; } + public uint modifier { get; set; } + public float audioApply { get; set; } + public byte weight { get; set; } + public CVehicleMod_2363989491 type { get; set; } + } + [TC(typeof(EXP))] public class CVehicleKit_427606548 + { + public CVehicleMod_2363989491 slot { get; set; } + public string name { get; set; } + } + [TC(typeof(EXP))] public class CVehicleWheel + { + public MetaHash wheelName { get; set; } + public MetaHash wheelVariation { get; set; } + public string modShopLabel { get; set; } + public float rimRadius { get; set; } + public bool rear { get; set; } + } + [TC(typeof(EXP))] public class CVehicleModelInfoVarGlobal_3062246906 //GlobalVariationData + { + public uint xenonLightColor { get; set; } + public uint xenonCoronaColor { get; set; } + public float xenonLightIntensityModifier { get; set; } + public float xenonCoronaIntensityModifier { get; set; } + } + [TC(typeof(EXP))] public class CVehicleModelInfoVarGlobal_2807227399 //XenonLightColors + { + public uint lightColor { get; set; } + public uint coronaColor { get; set; } + public float lightIntensityModifier { get; set; } + public float coronaIntensityModifier { get; set; } + } + + + public enum CVehicleModelColor_360458334 //vehicle mod color metallic id + { + none = -1, + Unk_815563434 = 0, + Unk_969376721 = 1, + Unk_731244402 = 2, + Unk_3537679873 = 3, + Unk_3183119293 = 4, + Unk_4039766491 = 5, + Unk_3777516184 = 6, + Unk_229878718 = 7, + Unk_4285337393 = 8, + Unk_847803751 = 9 + } + public enum CVehicleModelColor_544262540 //vehicle mod color audio color + { + Unk_52583446 = 0, + Unk_2253400966 = 1, + Unk_4012089111 = 2, + Unk_2477037232 = 3, + Unk_437487559 = 4, + Unk_730308174 = 5, + Unk_3129410619 = 6, + Unk_1762671403 = 7, + Unk_2615326998 = 8, + Unk_4157715503 = 9, + Unk_2969646890 = 10, + Unk_1645071976 = 11, + Unk_1358390657 = 12 + } + public enum CVehicleModelColor_2065815796 //vehicle mod color audio prefix + { + none = 0, + Unk_2318284788 = 1, + Unk_840729009 = 2, + Unk_3921902053 = 3 + } + + public enum CVehicleKit_3865430600 //vehicle mod kit type + { + MKT_STANDARD = 0, + MKT_SPORT = 1, + MKT_SUV = 2, + MKT_SPECIAL = 3 + } + public enum CVehicleMod_3635907608 //vehicle mod bone + { + none = -1, + chassis = 0, + Unk_1970334199 = 48, + bumper_f = 49, + bumper_r = 50, + wing_rf = 51, + wing_lf = 52, + bonnet = 53, + boot = 54, + exhaust = 56, + exhaust_2 = 57, + exhaust_3 = 58, + exhaust_4 = 59, + Unk_1666652977 = 60, + Unk_1972682668 = 61, + Unk_3204862618 = 62, + Unk_3503093287 = 63, + Unk_442599751 = 64, + Unk_2600343066 = 65, + Unk_3598945568 = 66, + Unk_3896619164 = 67, + Unk_2989016171 = 68, + Unk_3320572913 = 69, + Unk_529211190 = 70, + Unk_823345734 = 71, + extra_1 = 401, + extra_2 = 402, + extra_3 = 403, + extra_4 = 404, + extra_5 = 405, + Unk_3145755371 = 406, + Unk_2360446286 = 407, + Unk_2661527858 = 408, + Unk_1913477126 = 409, + Unk_2125833567 = 410, + Unk_2431830489 = 411, + Unk_2720558148 = 412, + Unk_903844796 = 413, + Unk_1202337617 = 414, + Unk_2190258525 = 417, + Unk_1950749904 = 418, + Unk_1709504522 = 419, + Unk_1480285367 = 420, + Unk_1213709552 = 421, + Unk_848662892 = 422, + Unk_3990325233 = 423, + Unk_367056899 = 424, + Unk_3413787451 = 425, + Unk_2734584581 = 426, + mod_col_1 = 427, + mod_col_2 = 428, + mod_col_3 = 429, + mod_col_4 = 430, + mod_col_5 = 431, + Unk_1547719720 = 432, + Unk_580018373 = 433, + Unk_4191162177 = 434, + Unk_3257212908 = 435, + Unk_3033709986 = 436, + Unk_2249285664 = 437, + Unk_1498318491 = 438, + Unk_1787603223 = 439, + Unk_1573326728 = 440, + Unk_1862676998 = 441, + Unk_1044598917 = 442, + misc_a = 369, + misc_b = 370, + misc_c = 371, + misc_d = 372, + misc_e = 373, + misc_f = 374, + misc_g = 375, + misc_h = 376, + misc_i = 377, + misc_j = 378, + misc_k = 379, + misc_l = 380, + misc_m = 381, + misc_n = 382, + misc_o = 383, + misc_p = 384, + misc_q = 385, + misc_r = 386, + misc_s = 387, + misc_t = 388, + misc_u = 389, + misc_v = 390, + misc_w = 391, + misc_x = 392, + misc_y = 393, + misc_z = 394, + Unk_2690009945 = 395, + Unk_1385115596 = 396, + Unk_2921986035 = 79, + steeringwheel = 80, + Unk_3929033220 = 29, + Unk_837923007 = 21, + Unk_991413023 = 22, + headlight_l = 91, + headlight_r = 92, + Unk_3979005071 = 97, + indicator_lf = 95, + Unk_112742354 = 98, + indicator_rf = 96, + Unk_3008822349 = 93, + Unk_914195096 = 94, + window_lf = 42, + window_rf = 43, + Unk_2355575415 = 45, + Unk_2639884295 = 44, + Unk_2675373130 = 46, + Unk_3523659197 = 47, + hub_lf = 30, + hub_rf = 31, + windscreen_r = 41, + Unk_4084563217 = 104, + Unk_556062831 = 105, + Unk_3850133799 = 106, + Unk_728001778 = 107, + door_dside_f = 3, + door_dside_r = 4, + door_pside_f = 5, + door_pside_r = 6, + bobble_head = 361, + bobble_base = 362, + Unk_785162942 = 363, + engineblock = 364, + Unk_3654959273 = 474, + Unk_808381781 = 475, + Unk_4268165574 = 476, + Unk_3579951032 = 477, + Unk_2733953759 = 478, + Unk_4123490435 = 479, + Unk_3342441320 = 480, + Unk_1726175929 = 481, + Unk_1947366679 = 482, + Unk_2065498928 = 483, + Unk_2572238744 = 484, + Unk_730555402 = 485, + Unk_4194074861 = 486, + Unk_1343696161 = 487, + Unk_506677594 = 488, + Unk_4167728581 = 489, + Unk_3326122354 = 490, + Unk_217851628 = 491, + Unk_3666821647 = 492, + Unk_2168885119 = 493, + Unk_2399611648 = 494, + Unk_3519328378 = 495, + Unk_2958716326 = 496, + Unk_3292501248 = 497, + Unk_2651277456 = 498, + Unk_3888995355 = 499, + Unk_3843353624 = 500, + Unk_3135215534 = 501, + Unk_3364434689 = 502, + Unk_2723112578 = 503, + Unk_2970026993 = 504, + Unk_2245832093 = 505, + Unk_2492156666 = 506, + Unk_1765012564 = 507, + Unk_2014155263 = 508, + Unk_1286290243 = 509, + Unk_1535367412 = 510, + Unk_3992710274 = 511, + Unk_1077448950 = 512, + Unk_1382757723 = 513, + Unk_614062521 = 514, + Unk_3783807571 = 524, + Unk_2839830988 = 525, + Unk_3138651499 = 526, + Unk_2400824695 = 527, + Unk_4141162370 = 560, + Unk_451472348 = 561, + Unk_1768767594 = 562, + Unk_3599310922 = 563, + Unk_1496111458 = 564, + Unk_3929521030 = 565, + Unk_1157497495 = 566, + Unk_1032498025 = 567, + Unk_2573434709 = 568, + Unk_930609265 = 569, + Unk_879315983 = 570, + Unk_411536741 = 571, + Unk_1086719913 = 572, + Unk_3237490897 = 573, + Unk_3375838140 = 574, + Unk_2381840182 = 575, + Unk_3607058940 = 576, + Unk_3607058940_again = 577, + Unk_1208798824 = 578, + Unk_303656220 = 579, + Unk_660207018 = 580, + Unk_2796607005 = 581, + Unk_3045655218 = 582, + Unk_2017296145 = 583, + Unk_3978311755 = 584, + Unk_1122332083 = 585, + Unk_1123212214 = 586, + Unk_4063416457 = 587, + Unk_4011591561 = 588, + Unk_2320654166 = 589, + Unk_2292220415 = 590, + Unk_2166816405 = 591, + Unk_2486991428 = 592 + } + public enum CVehicleMod_2363989491 //vehicle mod type + { + VMT_SPOILER = 0, + VMT_BUMPER_F = 1, + VMT_BUMPER_R = 2, + VMT_SKIRT = 3, + VMT_EXHAUST = 4, + VMT_CHASSIS = 5, + VMT_GRILL = 6, + VMT_BONNET = 7, + VMT_WING_L = 8, + VMT_WING_R = 9, + VMT_ROOF = 10, + VMT_PLTHOLDER = 11, + VMT_PLTVANITY = 12, + VMT_INTERIOR1 = 13, + VMT_INTERIOR2 = 14, + VMT_INTERIOR3 = 15, + VMT_INTERIOR4 = 16, + VMT_INTERIOR5 = 17, + VMT_SEATS = 18, + VMT_STEERING = 19, + VMT_KNOB = 20, + VMT_PLAQUE = 21, + VMT_ICE = 22, + VMT_TRUNK = 23, + VMT_HYDRO = 24, + VMT_ENGINEBAY1 = 25, + VMT_ENGINEBAY2 = 26, + VMT_ENGINEBAY3 = 27, + VMT_CHASSIS2 = 28, + VMT_CHASSIS3 = 29, + VMT_CHASSIS4 = 30, + VMT_CHASSIS5 = 31, + VMT_DOOR_L = 32, + Unk_514696742 = 33, + VMT_LIVERY_MOD = 34, + Unk_3409280882 = 35, + VMT_ENGINE = 36, + VMT_BRAKES = 37, + VMT_GEARBOX = 38, + VMT_HORN = 39, + VMT_SUSPENSION = 40, + VMT_ARMOUR = 41, + Unk_3278520444 = 42, + Unk_2334449168 = 43, + Unk_1675686396 = 44, + Unk_3968559424 = 45, + Unk_3919652883 = 46, + Unk_2656522436 = 47, + VMT_WHEELS = 48, + VMT_WHEELS_REAR_OR_HYDRAULICS = 49 + } + public enum CVehicleMod_3413962745 //vehicle mod camera position + { + VMCP_DEFAULT = 0, + Unk_3001706694 = 1, + Unk_1148399176 = 2, + Unk_2057559994 = 3, + Unk_1556139353 = 4, + Unk_1830737308 = 5, + Unk_457854237 = 6, + Unk_1629770278 = 7, + Unk_2879151926 = 8, + Unk_3193071790 = 9, + Unk_2770495034 = 10 + } + + +} + diff --git a/CodeWalker.Core/GameFiles/FileTypes/CarModColsFile.cs b/CodeWalker.Core/GameFiles/FileTypes/CarModColsFile.cs new file mode 100644 index 0000000..f67df29 --- /dev/null +++ b/CodeWalker.Core/GameFiles/FileTypes/CarModColsFile.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + [TypeConverter(typeof(ExpandableObjectConverter))] + public class CarModColsFile : GameFile, PackedFile + { + public CarModColsFile() : base(null, GameFileType.CarModCols) + { } + public CarModColsFile(RpfFileEntry entry) : base(entry, GameFileType.CarModCols) + { + } + + public void Load(byte[] data, RpfFileEntry entry) + { + RpfFileEntry = entry; + Name = entry.Name; + FilePath = Name; + + //TODO + + //always PSO .ymt + + + Loaded = true; + } + } +} diff --git a/CodeWalker.Core/GameFiles/FileTypes/CarVariationsFile.cs b/CodeWalker.Core/GameFiles/FileTypes/CarVariationsFile.cs new file mode 100644 index 0000000..c7e3294 --- /dev/null +++ b/CodeWalker.Core/GameFiles/FileTypes/CarVariationsFile.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + [TypeConverter(typeof(ExpandableObjectConverter))] + public class CarVariationsFile : GameFile, PackedFile + { + public CarVariationsFile() : base(null, GameFileType.CarVariations) + { } + public CarVariationsFile(RpfFileEntry entry) : base(entry, GameFileType.CarVariations) + { + } + + public void Load(byte[] data, RpfFileEntry entry) + { + RpfFileEntry = entry; + Name = entry.Name; + FilePath = Name; + + //TODO + + //can be PSO .ymt or XML .meta + + + Loaded = true; + } + } +} diff --git a/CodeWalker.Core/GameFiles/FileTypes/VehicleLayoutsFile.cs b/CodeWalker.Core/GameFiles/FileTypes/VehicleLayoutsFile.cs new file mode 100644 index 0000000..825cc17 --- /dev/null +++ b/CodeWalker.Core/GameFiles/FileTypes/VehicleLayoutsFile.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + [TypeConverter(typeof(ExpandableObjectConverter))] + public class VehicleLayoutsFile : GameFile, PackedFile + { + public VehicleLayoutsFile() : base(null, GameFileType.VehicleLayouts) + { } + public VehicleLayoutsFile(RpfFileEntry entry) : base(entry, GameFileType.VehicleLayouts) + { + } + + public void Load(byte[] data, RpfFileEntry entry) + { + RpfFileEntry = entry; + Name = entry.Name; + FilePath = Name; + + //TODO + + //always XML .meta + + + Loaded = true; + } + } +} diff --git a/CodeWalker.Core/GameFiles/FileTypes/VehiclesFile.cs b/CodeWalker.Core/GameFiles/FileTypes/VehiclesFile.cs index 8b3ad01..bcd18db 100644 --- a/CodeWalker.Core/GameFiles/FileTypes/VehiclesFile.cs +++ b/CodeWalker.Core/GameFiles/FileTypes/VehiclesFile.cs @@ -1,4 +1,5 @@ -using System; +using SharpDX; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -10,9 +11,9 @@ namespace CodeWalker.GameFiles public class VehiclesFile : GameFile, PackedFile { - public RbfFile Rbf { get; set; } - + public string ResidentTxd { get; set; } + public List InitDatas { get; set; } public Dictionary TxdRelationships { get; set; } @@ -48,7 +49,10 @@ namespace CodeWalker.GameFiles XmlDocument xmldoc = new XmlDocument(); xmldoc.LoadXml(xml); - LoadVehicles(xmldoc); + + ResidentTxd = Xml.GetChildInnerText(xmldoc.SelectSingleNode("CVehicleModelInfo__InitDataList"), "residentTxd"); + + LoadInitDatas(xmldoc); LoadTxdRelationships(xmldoc); @@ -57,12 +61,17 @@ namespace CodeWalker.GameFiles } - private void LoadVehicles(XmlDocument xmldoc) + private void LoadInitDatas(XmlDocument xmldoc) { XmlNodeList items = xmldoc.SelectNodes("CVehicleModelInfo__InitDataList/InitDatas/Item | CVehicleModelInfo__InitDataList/InitDatas/item"); + + InitDatas = new List(); for (int i = 0; i < items.Count; i++) { - //TODO... + var node = items[i]; + VehicleInitData d = new VehicleInitData(); + d.Load(node); + InitDatas.Add(d); } } @@ -82,10 +91,318 @@ namespace CodeWalker.GameFiles { TxdRelationships.Add(childstr, parentstr); } + else + { } } } } } + + + public class VehicleInitData + { + + public string modelName { get; set; } //impaler3 + public string txdName { get; set; } //impaler3 + public string handlingId { get; set; } //IMPALER3 + public string gameName { get; set; } //IMPALER3 + public string vehicleMakeName { get; set; } //DECLASSE + public string expressionDictName { get; set; } //null + public string expressionName { get; set; } //null + public string animConvRoofDictName { get; set; } //null + public string animConvRoofName { get; set; } //null + public string animConvRoofWindowsAffected { get; set; } // + public string ptfxAssetName { get; set; } //weap_xs_vehicle_weapons + public string audioNameHash { get; set; } // + public string layout { get; set; } //LAYOUT_STD_ARENA_1HONLY + public string coverBoundOffsets { get; set; } //IMPALER_COVER_OFFSET_INFO + public string explosionInfo { get; set; } //EXPLOSION_INFO_DEFAULT + public string scenarioLayout { get; set; } // + public string cameraName { get; set; } //FOLLOW_CHEETAH_CAMERA + public string aimCameraName { get; set; } //DEFAULT_THIRD_PERSON_VEHICLE_AIM_CAMERA + public string bonnetCameraName { get; set; } //VEHICLE_BONNET_CAMERA_STANDARD_LONG_DEVIANT + public string povCameraName { get; set; } //REDUCED_NEAR_CLIP_POV_CAMERA + public Vector3 FirstPersonDriveByIKOffset { get; set; } // + public Vector3 FirstPersonDriveByUnarmedIKOffset { get; set; } // + public Vector3 FirstPersonProjectileDriveByIKOffset { get; set; } // + public Vector3 FirstPersonProjectileDriveByPassengerIKOffset { get; set; } // + public Vector3 FirstPersonDriveByRightPassengerIKOffset { get; set; } // + public Vector3 FirstPersonDriveByRightPassengerUnarmedIKOffset { get; set; }// + public Vector3 FirstPersonMobilePhoneOffset { get; set; } // + public Vector3 FirstPersonPassengerMobilePhoneOffset { get; set; } // + public Vector3 PovCameraOffset { get; set; } // + public Vector3 PovCameraVerticalAdjustmentForRollCage { get; set; } // + public Vector3 PovPassengerCameraOffset { get; set; } // + public Vector3 PovRearPassengerCameraOffset { get; set; } // + public string vfxInfoName { get; set; } //VFXVEHICLEINFO_CAR_GENERIC + public bool shouldUseCinematicViewMode { get; set; } // + public bool shouldCameraTransitionOnClimbUpDown { get; set; } // + public bool shouldCameraIgnoreExiting { get; set; } // + public bool AllowPretendOccupants { get; set; } // + public bool AllowJoyriding { get; set; } // + public bool AllowSundayDriving { get; set; } // + public bool AllowBodyColorMapping { get; set; } // + public float wheelScale { get; set; } // + public float wheelScaleRear { get; set; } // + public float dirtLevelMin { get; set; } // + public float dirtLevelMax { get; set; } // + public float envEffScaleMin { get; set; } // + public float envEffScaleMax { get; set; } // + public float envEffScaleMin2 { get; set; } // + public float envEffScaleMax2 { get; set; } // + public float damageMapScale { get; set; } // + public float damageOffsetScale { get; set; } // + public Color4 diffuseTint { get; set; } // + public float steerWheelMult { get; set; } // + public float HDTextureDist { get; set; } // + public float[] lodDistances { get; set; } //// 10.000000// 25.000000// 60.000000// 120.000000// 500.000000// 500.000000// + public float minSeatHeight { get; set; } // + public float identicalModelSpawnDistance { get; set; } // + public int maxNumOfSameColor { get; set; } // + public float defaultBodyHealth { get; set; } // + public float pretendOccupantsScale { get; set; } // + public float visibleSpawnDistScale { get; set; } // + public float trackerPathWidth { get; set; } // + public float weaponForceMult { get; set; } // + public float frequency { get; set; } // + public string swankness { get; set; } //SWANKNESS_4 + public int maxNum { get; set; } // + public string[] flags { get; set; } //FLAG_RECESSED_HEADLIGHT_CORONAS FLAG_EXTRAS_STRONG FLAG_AVERAGE_CAR FLAG_HAS_INTERIOR_EXTRAS FLAG_CAN_HAVE_NEONS FLAG_HAS_JUMP_MOD FLAG_HAS_NITROUS_MOD FLAG_HAS_RAMMING_SCOOP_MOD FLAG_USE_AIRCRAFT_STYLE_WEAPON_TARGETING FLAG_HAS_SIDE_SHUNT FLAG_HAS_WEAPON_SPIKE_MODS FLAG_HAS_SUPERCHARGER FLAG_INCREASE_CAMBER_WITH_SUSPENSION_MOD FLAG_DISABLE_DEFORMATION + public string type { get; set; } //VEHICLE_TYPE_CAR + public string plateType { get; set; } //VPT_FRONT_AND_BACK_PLATES + public string dashboardType { get; set; } //VDT_DUKES + public string vehicleClass { get; set; } //VC_MUSCLE + public string wheelType { get; set; } //VWT_MUSCLE + public string[] trailers { get; set; } // + public string[] additionalTrailers { get; set; } // + public VehicleDriver[] drivers { get; set; } // + public string[] extraIncludes { get; set; } // + public string[] doorsWithCollisionWhenClosed { get; set; } // + public string[] driveableDoors { get; set; } // + public bool bumpersNeedToCollideWithMap { get; set; } // + public bool needsRopeTexture { get; set; } // + public string[] requiredExtras { get; set; } //EXTRA_1 EXTRA_2 EXTRA_3 + public string[] rewards { get; set; } // + public string[] cinematicPartCamera { get; set; } //// WHEEL_FRONT_RIGHT_CAMERA// WHEEL_FRONT_LEFT_CAMERA// WHEEL_REAR_RIGHT_CAMERA// WHEEL_REAR_LEFT_CAMERA// + public string NmBraceOverrideSet { get; set; } // + public Vector3 buoyancySphereOffset { get; set; } // + public float buoyancySphereSizeScale { get; set; } // + public VehicleOverrideRagdollThreshold pOverrideRagdollThreshold { get; set; } // + public string[] firstPersonDrivebyData { get; set; } //// STD_IMPALER2_FRONT_LEFT// STD_IMPALER2_FRONT_RIGHT// + + + public void Load(XmlNode node) + { + modelName = Xml.GetChildInnerText(node, "modelName"); + txdName = Xml.GetChildInnerText(node, "txdName"); + handlingId = Xml.GetChildInnerText(node, "handlingId"); + gameName = Xml.GetChildInnerText(node, "gameName"); + vehicleMakeName = Xml.GetChildInnerText(node, "vehicleMakeName"); + expressionDictName = Xml.GetChildInnerText(node, "expressionDictName"); + expressionName = Xml.GetChildInnerText(node, "expressionName"); + animConvRoofDictName = Xml.GetChildInnerText(node, "animConvRoofDictName"); + animConvRoofName = Xml.GetChildInnerText(node, "animConvRoofName"); + animConvRoofWindowsAffected = Xml.GetChildInnerText(node, "animConvRoofWindowsAffected");//? + ptfxAssetName = Xml.GetChildInnerText(node, "ptfxAssetName"); + audioNameHash = Xml.GetChildInnerText(node, "audioNameHash"); + layout = Xml.GetChildInnerText(node, "layout"); + coverBoundOffsets = Xml.GetChildInnerText(node, "coverBoundOffsets"); + explosionInfo = Xml.GetChildInnerText(node, "explosionInfo"); + scenarioLayout = Xml.GetChildInnerText(node, "scenarioLayout"); + cameraName = Xml.GetChildInnerText(node, "cameraName"); + aimCameraName = Xml.GetChildInnerText(node, "aimCameraName"); + bonnetCameraName = Xml.GetChildInnerText(node, "bonnetCameraName"); + povCameraName = Xml.GetChildInnerText(node, "povCameraName"); + FirstPersonDriveByIKOffset = Xml.GetChildVector3Attributes(node, "FirstPersonDriveByIKOffset", "x", "y", "z"); + FirstPersonDriveByUnarmedIKOffset = Xml.GetChildVector3Attributes(node, "FirstPersonDriveByUnarmedIKOffset", "x", "y", "z"); + FirstPersonProjectileDriveByIKOffset = Xml.GetChildVector3Attributes(node, "FirstPersonProjectileDriveByIKOffset", "x", "y", "z"); + FirstPersonProjectileDriveByPassengerIKOffset = Xml.GetChildVector3Attributes(node, "FirstPersonProjectileDriveByPassengerIKOffset", "x", "y", "z"); + FirstPersonDriveByRightPassengerIKOffset = Xml.GetChildVector3Attributes(node, "FirstPersonDriveByRightPassengerIKOffset", "x", "y", "z"); + FirstPersonDriveByRightPassengerUnarmedIKOffset = Xml.GetChildVector3Attributes(node, "FirstPersonDriveByRightPassengerUnarmedIKOffset", "x", "y", "z"); + FirstPersonMobilePhoneOffset = Xml.GetChildVector3Attributes(node, "FirstPersonMobilePhoneOffset", "x", "y", "z"); + FirstPersonPassengerMobilePhoneOffset = Xml.GetChildVector3Attributes(node, "FirstPersonPassengerMobilePhoneOffset", "x", "y", "z"); + PovCameraOffset = Xml.GetChildVector3Attributes(node, "PovCameraOffset", "x", "y", "z"); + PovCameraVerticalAdjustmentForRollCage = Xml.GetChildVector3Attributes(node, "PovCameraVerticalAdjustmentForRollCage", "x", "y", "z"); + PovPassengerCameraOffset = Xml.GetChildVector3Attributes(node, "PovPassengerCameraOffset", "x", "y", "z"); + PovRearPassengerCameraOffset = Xml.GetChildVector3Attributes(node, "PovRearPassengerCameraOffset", "x", "y", "z"); + vfxInfoName = Xml.GetChildInnerText(node, "vfxInfoName"); + shouldUseCinematicViewMode = Xml.GetChildBoolAttribute(node, "shouldUseCinematicViewMode", "value"); + shouldCameraTransitionOnClimbUpDown = Xml.GetChildBoolAttribute(node, "shouldCameraTransitionOnClimbUpDown", "value"); + shouldCameraIgnoreExiting = Xml.GetChildBoolAttribute(node, "shouldCameraIgnoreExiting", "value"); + AllowPretendOccupants = Xml.GetChildBoolAttribute(node, "AllowPretendOccupants", "value"); + AllowJoyriding = Xml.GetChildBoolAttribute(node, "AllowJoyriding", "value"); + AllowSundayDriving = Xml.GetChildBoolAttribute(node, "AllowSundayDriving", "value"); + AllowBodyColorMapping = Xml.GetChildBoolAttribute(node, "AllowBodyColorMapping", "value"); + wheelScale = Xml.GetChildFloatAttribute(node, "wheelScale", "value"); + wheelScaleRear = Xml.GetChildFloatAttribute(node, "wheelScaleRear", "value"); + dirtLevelMin = Xml.GetChildFloatAttribute(node, "dirtLevelMin", "value"); + dirtLevelMax = Xml.GetChildFloatAttribute(node, "dirtLevelMax", "value"); + envEffScaleMin = Xml.GetChildFloatAttribute(node, "envEffScaleMin", "value"); + envEffScaleMax = Xml.GetChildFloatAttribute(node, "envEffScaleMax", "value"); + envEffScaleMin2 = Xml.GetChildFloatAttribute(node, "envEffScaleMin2", "value"); + envEffScaleMax2 = Xml.GetChildFloatAttribute(node, "envEffScaleMax2", "value"); + damageMapScale = Xml.GetChildFloatAttribute(node, "damageMapScale", "value"); + damageOffsetScale = Xml.GetChildFloatAttribute(node, "damageOffsetScale", "value"); + diffuseTint = new Color4(Convert.ToUInt32(Xml.GetChildStringAttribute(node, "diffuseTint", "value").Replace("0x", ""), 16)); + steerWheelMult = Xml.GetChildFloatAttribute(node, "steerWheelMult", "value"); + HDTextureDist = Xml.GetChildFloatAttribute(node, "HDTextureDist", "value"); + lodDistances = GetFloatArray(node, "lodDistances", '\n'); + minSeatHeight = Xml.GetChildFloatAttribute(node, "minSeatHeight", "value"); + identicalModelSpawnDistance = Xml.GetChildFloatAttribute(node, "identicalModelSpawnDistance", "value"); + maxNumOfSameColor = Xml.GetChildIntAttribute(node, "maxNumOfSameColor", "value"); + defaultBodyHealth = Xml.GetChildFloatAttribute(node, "defaultBodyHealth", "value"); + pretendOccupantsScale = Xml.GetChildFloatAttribute(node, "pretendOccupantsScale", "value"); + visibleSpawnDistScale = Xml.GetChildFloatAttribute(node, "visibleSpawnDistScale", "value"); + trackerPathWidth = Xml.GetChildFloatAttribute(node, "trackerPathWidth", "value"); + weaponForceMult = Xml.GetChildFloatAttribute(node, "weaponForceMult", "value"); + frequency = Xml.GetChildFloatAttribute(node, "frequency", "value"); + swankness = Xml.GetChildInnerText(node, "swankness"); + maxNum = Xml.GetChildIntAttribute(node, "maxNum", "value"); + flags = GetStringArray(node, "flags", ' '); + type = Xml.GetChildInnerText(node, "type"); + plateType = Xml.GetChildInnerText(node, "plateType"); + dashboardType = Xml.GetChildInnerText(node, "dashboardType"); + vehicleClass = Xml.GetChildInnerText(node, "vehicleClass"); + wheelType = Xml.GetChildInnerText(node, "wheelType"); + trailers = GetStringItemArray(node, "trailers"); + additionalTrailers = GetStringItemArray(node, "additionalTrailers"); + var dnode = node.SelectSingleNode("drivers"); + if (dnode != null) + { + var items = dnode.SelectNodes("Item"); + if (items.Count > 0) + { + drivers = new VehicleDriver[items.Count]; + for (int i = 0; i < items.Count; i++) + { + var item = items[i]; + var driver = new VehicleDriver(); + driver.driverName = Xml.GetChildInnerText(item, "driverName"); + driver.npcName = Xml.GetChildInnerText(item, "npcName"); + drivers[i] = driver; + } + } + } + extraIncludes = GetStringItemArray(node, "extraIncludes"); + doorsWithCollisionWhenClosed = GetStringItemArray(node, "doorsWithCollisionWhenClosed"); + driveableDoors = GetStringItemArray(node, "driveableDoors"); + bumpersNeedToCollideWithMap = Xml.GetChildBoolAttribute(node, "bumpersNeedToCollideWithMap", "value"); + needsRopeTexture = Xml.GetChildBoolAttribute(node, "needsRopeTexture", "value"); + requiredExtras = GetStringArray(node, "requiredExtras", ' '); + rewards = GetStringItemArray(node, "rewards"); + cinematicPartCamera = GetStringItemArray(node, "cinematicPartCamera"); + NmBraceOverrideSet = Xml.GetChildInnerText(node, "NmBraceOverrideSet"); + buoyancySphereOffset = Xml.GetChildVector3Attributes(node, "buoyancySphereOffset", "x", "y", "z"); + buoyancySphereSizeScale = Xml.GetChildFloatAttribute(node, "buoyancySphereSizeScale", "value"); + var tnode = node.SelectSingleNode("pOverrideRagdollThreshold"); + if (tnode != null) + { + var ttype = tnode.Attributes["type"]?.Value; + switch (ttype) + { + case "NULL": break; + case "CVehicleModelInfo__CVehicleOverrideRagdollThreshold": + pOverrideRagdollThreshold = new VehicleOverrideRagdollThreshold(); + pOverrideRagdollThreshold.MinComponent = Xml.GetChildIntAttribute(tnode, "MinComponent", "value"); + pOverrideRagdollThreshold.MaxComponent = Xml.GetChildIntAttribute(tnode, "MaxComponent", "value"); + pOverrideRagdollThreshold.ThresholdMult = Xml.GetChildFloatAttribute(tnode, "ThresholdMult", "value"); + break; + default: + break; + } + } + firstPersonDrivebyData = GetStringItemArray(node, "firstPersonDrivebyData"); + } + + private string[] GetStringItemArray(XmlNode node, string childName) + { + var cnode = node.SelectSingleNode(childName); + if (cnode == null) return null; + var items = cnode.SelectNodes("Item"); + if (items == null) return null; + getStringArrayList.Clear(); + foreach (XmlNode inode in items) + { + var istr = inode.InnerText; + if (!string.IsNullOrEmpty(istr)) + { + getStringArrayList.Add(istr); + } + } + if (getStringArrayList.Count == 0) return null; + return getStringArrayList.ToArray(); + } + private string[] GetStringArray(XmlNode node, string childName, char delimiter) + { + var ldastr = Xml.GetChildInnerText(node, childName); + var ldarr = ldastr?.Split(delimiter); + if (ldarr == null) return null; + getStringArrayList.Clear(); + foreach (var ldstr in ldarr) + { + var ldt = ldstr?.Trim(); + if (!string.IsNullOrEmpty(ldt)) + { + getStringArrayList.Add(ldt); + } + } + if (getStringArrayList.Count == 0) return null; + return getStringArrayList.ToArray(); + } + private float[] GetFloatArray(XmlNode node, string childName, char delimiter) + { + var ldastr = Xml.GetChildInnerText(node, childName); + var ldarr = ldastr?.Split(delimiter); + if (ldarr == null) return null; + getFloatArrayList.Clear(); + foreach (var ldstr in ldarr) + { + var ldt = ldstr?.Trim(); + if (!string.IsNullOrEmpty(ldt)) + { + float f; + if (FloatUtil.TryParse(ldt, out f)) + { + getFloatArrayList.Add(f); + } + } + } + if (getFloatArrayList.Count == 0) return null; + return getFloatArrayList.ToArray(); + } + + private static List getStringArrayList = new List(); //kinda hacky.. + private static List getFloatArrayList = new List(); //kinda hacky.. + + + public override string ToString() + { + return modelName; + } + } + + public class VehicleOverrideRagdollThreshold + { + public int MinComponent { get; set; } + public int MaxComponent { get; set; } + public float ThresholdMult { get; set; } + + public override string ToString() + { + return MinComponent.ToString() + ", " + MaxComponent.ToString() + ", " + ThresholdMult.ToString(); + } + } + public class VehicleDriver + { + public string driverName { get; set; } + public string npcName { get; set; } + + public override string ToString() + { + return driverName + ", " + npcName; + } + } + } diff --git a/CodeWalker.Core/GameFiles/GameFile.cs b/CodeWalker.Core/GameFiles/GameFile.cs index 44806f1..e941522 100644 --- a/CodeWalker.Core/GameFiles/GameFile.cs +++ b/CodeWalker.Core/GameFiles/GameFile.cs @@ -71,6 +71,10 @@ namespace CodeWalker.GameFiles Yvr = 15, Gtxd = 16, Vehicles = 17, + CarCols = 18, + CarModCols = 19, + CarVariations = 20, + VehicleLayouts = 21, } diff --git a/CodeWalker.Core/GameFiles/GameFileCache.cs b/CodeWalker.Core/GameFiles/GameFileCache.cs index a222877..fdab745 100644 --- a/CodeWalker.Core/GameFiles/GameFileCache.cs +++ b/CodeWalker.Core/GameFiles/GameFileCache.cs @@ -78,12 +78,17 @@ namespace CodeWalker.GameFiles public Dictionary TimeCycleModsDict = new Dictionary(); + public Dictionary VehiclesInitDict { get; set; } + + public List BaseRpfs { get; private set; } public List AllRpfs { get; private set; } public List DlcRpfs { get; private set; } public bool DoFullStringIndex = false; - + public bool BuildExtendedJenkIndex = true; + public bool LoadArchetypes = true; + public bool LoadVehicles = false; private bool PreloadedMode = false; private string GTAFolder; @@ -149,13 +154,14 @@ namespace CodeWalker.GameFiles if (RpfMan == null) { - EnableDlc = !string.IsNullOrEmpty(SelectedDlc); + //EnableDlc = !string.IsNullOrEmpty(SelectedDlc); RpfMan = new RpfManager(); RpfMan.ExcludePaths = GetExcludePaths(); RpfMan.EnableMods = EnableMods; + RpfMan.BuildExtendedJenkIndex = BuildExtendedJenkIndex; RpfMan.Init(GTAFolder, UpdateStatus, ErrorLog);//, true); //RE test area! @@ -255,6 +261,9 @@ namespace CodeWalker.GameFiles UpdateStatus("Loading strings..."); InitStringDicts(); + + UpdateStatus("Loading vehicles..."); + InitVehicles(); } private void InitDlcList() @@ -410,6 +419,14 @@ namespace CodeWalker.GameFiles if ((sfile == null) || (sfile.DlcFile == null)) continue; DlcNameList.Add(GetDlcNameFromPath(sfile.DlcFile.Path)); } + + if (DlcNameList.Count > 0) + { + if (string.IsNullOrEmpty(SelectedDlc)) + { + SelectedDlc = DlcNameList[DlcNameList.Count - 1]; + } + } } private void InitImagesMetas() @@ -1058,7 +1075,7 @@ namespace CodeWalker.GameFiles } else if (entry.NameLower == "vehicles.meta") { - VehiclesFile vf = RpfMan.GetFile(entry); + VehiclesFile vf = RpfMan.GetFile(entry);//could also get loaded in InitVehicles... if (vf.TxdRelationships != null) { addTxdRelationships(vf.TxdRelationships); @@ -1243,6 +1260,8 @@ namespace CodeWalker.GameFiles archetypesLoaded = false; archetypeDict.Clear(); + if (!LoadArchetypes) return; + var rpfs = EnableDlc ? AllRpfs : BaseRpfs; @@ -1424,6 +1443,104 @@ namespace CodeWalker.GameFiles StatsNames.FullIndexBuilt = true; } + public void InitVehicles() + { + if (!LoadVehicles) return; + + + //Neos7 + //Involved files(at least for rendering purpose ) + //Vehicles.meta + //Carcols.meta + //Carvariations.meta + //Vehiclelayouts.meta + //The other metas shouldn't be important for rendering + //Then the global carcols.ymt is required too + //As it contains the general shared tuning options + //Carcols for modkits and lights kits definitions + //Carvariations links such modkits and lights kits to each vehicle plus defines colours combinations of spawned vehicles + //Vehiclelayouts mostly to handle ped interactions with the vehicle + + + + + + IEnumerable rpfs = PreloadedMode ? AllRpfs : (IEnumerable)ActiveMapRpfFiles.Values; + + + var allVehicles = new Dictionary(); + + var addVehicleFiles = new Action>((from) => + { + foreach (RpfFile file in from) + { + if (file.AllEntries == null) continue; + foreach (RpfEntry entry in file.AllEntries) + { +#if !DEBUG + try +#endif + { + if (entry.NameLower == "vehicles.meta") + { + VehiclesFile vf = RpfMan.GetFile(entry); + if (vf.InitDatas != null) + { + foreach (var initData in vf.InitDatas) + { + var name = initData.modelName.ToLowerInvariant(); + var hash = JenkHash.GenHash(name); + if (allVehicles.ContainsKey(hash)) + { } + allVehicles[hash] = initData; + } + } + } + if ((entry.NameLower == "carcols.ymt") || (entry.NameLower == "carcols.meta")) + { + var cf = RpfMan.GetFile(entry); + + } + if (entry.NameLower == "carmodcols.ymt") + { + var cf = RpfMan.GetFile(entry); + + } + if ((entry.NameLower == "carvariations.ymt") || (entry.NameLower == "carvariations.meta")) + { + var cf = RpfMan.GetFile(entry); + + } + if (entry.NameLower.StartsWith("vehiclelayouts") && entry.NameLower.EndsWith(".meta")) + { + var lf = RpfMan.GetFile(entry); + + } + } +#if !DEBUG + catch (Exception ex) + { + string errstr = entry.Path + "\n" + ex.ToString(); + ErrorLog(errstr); + } +#endif + } + } + + }); + + + addVehicleFiles(rpfs); + + if (EnableDlc) + { + addVehicleFiles(DlcActiveRpfs); + } + + + VehiclesInitDict = allVehicles; + + } public bool SetDlcLevel(string dlc, bool enable) diff --git a/CodeWalker.Core/GameFiles/MetaTypes/MetaNames.cs b/CodeWalker.Core/GameFiles/MetaTypes/MetaNames.cs index f9c25a3..90ed2b1 100644 --- a/CodeWalker.Core/GameFiles/MetaTypes/MetaNames.cs +++ b/CodeWalker.Core/GameFiles/MetaTypes/MetaNames.cs @@ -3469,12 +3469,30 @@ namespace CodeWalker.GameFiles TB_COLD = 3827341951, TB_HOT = 2709699671, - - - - - - + vehicleLight = 1339481019, + vehicleLightSettings = 2581049192, + vehicleCorona = 1860240263, + CVehicleKit = 679130282, + CVehicleModVisible = 4238291236, + CVehicleModLink = 2730707380, + CVehicleModStat = 243590259, + CVehicleModelColor = 4213335822, + CVehicleWindowColor = 2561269966, + CVehicleMetallicSetting = 2073371064, + PlateProbabilities = 2135495316, + CVehicleModColors = 2858318490, + CVehicleModColor = 1443412025, + metallic = 2204727143, + classic = 2458459502, + matte = 1951049216, + metals = 2740125593, + chrome = 1114790148, + pearlescent = 3095366650, + spec = 1912906641, + sirens = 2047330294, + CCreditItem = 113388969, + JOB_MED = 568575574, + JOB_SMALL = 4127034762, @@ -3638,6 +3656,9 @@ namespace CodeWalker.GameFiles //rage__spdAABB = 4084721864, scaleBySunIntensity = 59101696, + CVehicleModPearlescentColors = 1380492417, + baseCols = 2645876692, + specCols = 666439252, @@ -3816,6 +3837,13 @@ namespace CodeWalker.GameFiles ASSET_TYPE_DRAWABLEDICTIONARY = 1580165652, ASSET_TYPE_ASSETLESS = 4161085041, + aLevelsData = 1643066032, + cFriendlyName = 2077026003, + cTitle = 834048882, + cFilename = 3760135447, + cBugstarName = 3970741067, + + //openIV carcols.ymt VehiclePlates = 593302648, @@ -3881,7 +3909,11 @@ namespace CodeWalker.GameFiles xenonCoronaColor = 4113209874, xenonLightIntensityModifier = 849227792, xenonCoronaIntensityModifier = 3145775573, - + XenonLightColors = 2580788834, + lightColor = 78766281, + coronaColor = 3615736814, + lightIntensityModifier = 1981979787, + coronaIntensityModifier = 3155797354, diff --git a/CodeWalker.Core/GameFiles/MetaTypes/MetaXml.cs b/CodeWalker.Core/GameFiles/MetaTypes/MetaXml.cs index 453aaf8..fd9499e 100644 --- a/CodeWalker.Core/GameFiles/MetaTypes/MetaXml.cs +++ b/CodeWalker.Core/GameFiles/MetaTypes/MetaXml.cs @@ -821,8 +821,8 @@ namespace CodeWalker.GameFiles break; case 1: //unsigned int var int6bVal = MetaTypes.SwapBytes(BitConverter.ToUInt32(data, eoffset)); - ValueTag(sb, cind, ename, int6bVal.ToString()); - //ValueTag(sb, cind, ename, "0x" + int6bVal.ToString("X").PadLeft(8, '0')); + //ValueTag(sb, cind, ename, int6bVal.ToString()); + ValueTag(sb, cind, ename, "0x" + int6bVal.ToString("X").PadLeft(8, '0')); break; } break; diff --git a/CodeWalker.Core/GameFiles/MetaTypes/PsoTypes.cs b/CodeWalker.Core/GameFiles/MetaTypes/PsoTypes.cs index c31cf4b..c20c573 100644 --- a/CodeWalker.Core/GameFiles/MetaTypes/PsoTypes.cs +++ b/CodeWalker.Core/GameFiles/MetaTypes/PsoTypes.cs @@ -350,29 +350,29 @@ namespace CodeWalker.GameFiles new PsoStructureEntryInfo(MetaName.fCycleOffset, PsoDataType.Float, 16, 0, 0), new PsoStructureEntryInfo(MetaName.fCycleDuration, PsoDataType.Float, 20, 0, 0) ); - case MetaName.CVehicleModelInfoVarGlobal: + case MetaName.CVehicleModelInfoVarGlobal: //carcols.ymt root return new PsoStructureInfo(MetaName.CVehicleModelInfoVarGlobal, 0, 0, 392, new PsoStructureEntryInfo(MetaName.VehiclePlates, PsoDataType.Structure, 8, 0, (MetaName)465922034), - new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)4213335822), + new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, MetaName.CVehicleModelColor), new PsoStructureEntryInfo(MetaName.Colors, PsoDataType.Array, 48, 0, (MetaName)1), - new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)2073371064), + new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, MetaName.CVehicleMetallicSetting), new PsoStructureEntryInfo(MetaName.MetallicSettings, PsoDataType.Array, 64, 0, (MetaName)3), - new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)2561269966), + new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, MetaName.CVehicleWindowColor), new PsoStructureEntryInfo(MetaName.WindowColors, PsoDataType.Array, 80, 0, (MetaName)5), - new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)2581049192), + new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, MetaName.vehicleLightSettings), new PsoStructureEntryInfo(MetaName.Lights, PsoDataType.Array, 96, 0, MetaName.POINTER), new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, MetaName.sirenSettings), new PsoStructureEntryInfo(MetaName.Sirens, PsoDataType.Array, 112, 0, (MetaName)9), - new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)679130282), + new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, MetaName.CVehicleKit), new PsoStructureEntryInfo(MetaName.Kits, PsoDataType.Array, 128, 0, (MetaName)11), new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, MetaName.CVehicleWheel), new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Array, 0, 0, (MetaName)13), new PsoStructureEntryInfo(MetaName.Wheels, PsoDataType.Array, 144, 4, (MetaName)851982), new PsoStructureEntryInfo(MetaName.GlobalVariationData, PsoDataType.Structure, 352, 0, (MetaName)3062246906), new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)2807227399), - new PsoStructureEntryInfo((MetaName)2580788834, PsoDataType.Array, 376, 0, MetaName.BYTE) + new PsoStructureEntryInfo(MetaName.XenonLightColors, PsoDataType.Array, 376, 0, MetaName.BYTE) ); - case (MetaName)465922034: + case (MetaName)465922034: //CVehicleModelInfoVarGlobal VehiclePlates return new PsoStructureInfo((MetaName)465922034, 0, 0, 40, new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)3027500557), new PsoStructureEntryInfo(MetaName.Textures, PsoDataType.Array, 8, 0, 0), @@ -383,14 +383,7 @@ namespace CodeWalker.GameFiles new PsoStructureEntryInfo(MetaName.RandomCharOffset, PsoDataType.UByte, 31, 0, 0), new PsoStructureEntryInfo(MetaName.NumRandomChar, PsoDataType.UByte, 32, 0, 0) ); - case (MetaName)3062246906: - return new PsoStructureInfo((MetaName)3062246906, 0, 0, 24, - new PsoStructureEntryInfo(MetaName.xenonLightColor, PsoDataType.UInt, 8, 1, 0), - new PsoStructureEntryInfo(MetaName.xenonCoronaColor, PsoDataType.UInt, 12, 1, 0), - new PsoStructureEntryInfo(MetaName.xenonLightIntensityModifier, PsoDataType.Float, 16, 0, 0), - new PsoStructureEntryInfo(MetaName.xenonCoronaIntensityModifier, PsoDataType.Float, 20, 0, 0) - ); - case (MetaName)3027500557: + case (MetaName)3027500557: //CVehicleModelInfoVarGlobal VehiclePlates Texture return new PsoStructureInfo((MetaName)3027500557, 0, 0, 80, new PsoStructureEntryInfo(MetaName.TextureSetName, PsoDataType.String, 8, 7, 0), new PsoStructureEntryInfo(MetaName.DiffuseMapName, PsoDataType.String, 12, 7, 0), @@ -402,8 +395,22 @@ namespace CodeWalker.GameFiles new PsoStructureEntryInfo(MetaName.IsFontOutlineEnabled, PsoDataType.Bool, 64, 0, 0), new PsoStructureEntryInfo(MetaName.FontOutlineMinMaxDepth, PsoDataType.Float2, 68, 0, 0) ); - case (MetaName)4213335822: - return new PsoStructureInfo((MetaName)4213335822, 0, 0, 32, + case (MetaName)3062246906: //CVehicleModelInfoVarGlobal GlobalVariationData + return new PsoStructureInfo((MetaName)3062246906, 0, 0, 24, + new PsoStructureEntryInfo(MetaName.xenonLightColor, PsoDataType.UInt, 8, 1, 0), + new PsoStructureEntryInfo(MetaName.xenonCoronaColor, PsoDataType.UInt, 12, 1, 0), + new PsoStructureEntryInfo(MetaName.xenonLightIntensityModifier, PsoDataType.Float, 16, 0, 0), + new PsoStructureEntryInfo(MetaName.xenonCoronaIntensityModifier, PsoDataType.Float, 20, 0, 0) + ); + case (MetaName)2807227399: //CVehicleModelInfoVarGlobal XenonLightColors //vehicle xenon light color + return new PsoStructureInfo((MetaName)2807227399, 0, 0, 24, + new PsoStructureEntryInfo(MetaName.lightColor, PsoDataType.UInt, 8, 1, 0), + new PsoStructureEntryInfo(MetaName.coronaColor, PsoDataType.UInt, 12, 1, 0), + new PsoStructureEntryInfo(MetaName.lightIntensityModifier, PsoDataType.Float, 16, 0, 0), + new PsoStructureEntryInfo(MetaName.coronaIntensityModifier, PsoDataType.Float, 20, 0, 0) + ); + case MetaName.CVehicleModelColor: //CVehicleModelInfoVarGlobal Colors + return new PsoStructureInfo(MetaName.CVehicleModelColor, 0, 0, 32, new PsoStructureEntryInfo(MetaName.color, PsoDataType.UInt, 8, 1, 0), new PsoStructureEntryInfo(MetaName.metallicID, PsoDataType.Enum, 12, 2, (MetaName)360458334), new PsoStructureEntryInfo(MetaName.audioColor, PsoDataType.Enum, 13, 2, (MetaName)544262540), @@ -412,34 +419,34 @@ namespace CodeWalker.GameFiles new PsoStructureEntryInfo(MetaName.audioPrefixHash, PsoDataType.UInt, 20, 0, 0), new PsoStructureEntryInfo(MetaName.colorName, PsoDataType.String, 24, 1, 0) ); - case (MetaName)2073371064: - return new PsoStructureInfo((MetaName)2073371064, 0, 0, 24, + case MetaName.CVehicleMetallicSetting: //CVehicleModelInfoVarGlobal MetallicSettings + return new PsoStructureInfo(MetaName.CVehicleMetallicSetting, 0, 0, 24, new PsoStructureEntryInfo(MetaName.specInt, PsoDataType.Float, 8, 0, 0), new PsoStructureEntryInfo(MetaName.specFalloff, PsoDataType.Float, 12, 0, 0), new PsoStructureEntryInfo(MetaName.specFresnel, PsoDataType.Float, 16, 0, 0) ); - case (MetaName)2561269966: - return new PsoStructureInfo((MetaName)2561269966, 0, 0, 16, + case MetaName.CVehicleWindowColor: //CVehicleModelInfoVarGlobal WindowColors + return new PsoStructureInfo(MetaName.CVehicleWindowColor, 0, 0, 16, new PsoStructureEntryInfo(MetaName.color, PsoDataType.UInt, 8, 1, 0), new PsoStructureEntryInfo(MetaName.name, PsoDataType.String, 12, 7, 0) ); - case (MetaName)2581049192: - return new PsoStructureInfo((MetaName)2581049192, 0, 0, 552, + case MetaName.vehicleLightSettings: //CVehicleModelInfoVarGlobal Lights + return new PsoStructureInfo(MetaName.vehicleLightSettings, 0, 0, 552, new PsoStructureEntryInfo(MetaName.id, PsoDataType.UByte, 8, 0, 0), - new PsoStructureEntryInfo(MetaName.indicator, PsoDataType.Structure, 16, 0, (MetaName)1339481019), - new PsoStructureEntryInfo(MetaName.rearIndicatorCorona, PsoDataType.Structure, 64, 0, (MetaName)1860240263), - new PsoStructureEntryInfo(MetaName.frontIndicatorCorona, PsoDataType.Structure, 120, 0, (MetaName)1860240263), - new PsoStructureEntryInfo(MetaName.tailLight, PsoDataType.Structure, 176, 0, (MetaName)1339481019), - new PsoStructureEntryInfo(MetaName.tailLightCorona, PsoDataType.Structure, 224, 0, (MetaName)1860240263), - new PsoStructureEntryInfo(MetaName.tailLightMiddleCorona, PsoDataType.Structure, 280, 0, (MetaName)1860240263), - new PsoStructureEntryInfo(MetaName.headLight, PsoDataType.Structure, 336, 0, (MetaName)1339481019), - new PsoStructureEntryInfo(MetaName.headLightCorona, PsoDataType.Structure, 384, 0, (MetaName)1860240263), - new PsoStructureEntryInfo(MetaName.reversingLight, PsoDataType.Structure, 440, 0, (MetaName)1339481019), - new PsoStructureEntryInfo(MetaName.reversingLightCorona, PsoDataType.Structure, 488, 0, (MetaName)1860240263), + new PsoStructureEntryInfo(MetaName.indicator, PsoDataType.Structure, 16, 0, MetaName.vehicleLight), + new PsoStructureEntryInfo(MetaName.rearIndicatorCorona, PsoDataType.Structure, 64, 0, MetaName.vehicleCorona), + new PsoStructureEntryInfo(MetaName.frontIndicatorCorona, PsoDataType.Structure, 120, 0, MetaName.vehicleCorona), + new PsoStructureEntryInfo(MetaName.tailLight, PsoDataType.Structure, 176, 0, MetaName.vehicleLight), + new PsoStructureEntryInfo(MetaName.tailLightCorona, PsoDataType.Structure, 224, 0, MetaName.vehicleCorona), + new PsoStructureEntryInfo(MetaName.tailLightMiddleCorona, PsoDataType.Structure, 280, 0, MetaName.vehicleCorona), + new PsoStructureEntryInfo(MetaName.headLight, PsoDataType.Structure, 336, 0, MetaName.vehicleLight), + new PsoStructureEntryInfo(MetaName.headLightCorona, PsoDataType.Structure, 384, 0, MetaName.vehicleCorona), + new PsoStructureEntryInfo(MetaName.reversingLight, PsoDataType.Structure, 440, 0, MetaName.vehicleLight), + new PsoStructureEntryInfo(MetaName.reversingLightCorona, PsoDataType.Structure, 488, 0, MetaName.vehicleCorona), new PsoStructureEntryInfo(MetaName.name, PsoDataType.String, 544, 1, 0) ); - case (MetaName)1339481019: - return new PsoStructureInfo((MetaName)1339481019, 0, 0, 48, + case MetaName.vehicleLight: //CVehicleModelInfoVarGlobal Lights Light info + return new PsoStructureInfo(MetaName.vehicleLight, 0, 0, 48, new PsoStructureEntryInfo(MetaName.intensity, PsoDataType.Float, 8, 0, 0), new PsoStructureEntryInfo(MetaName.falloffMax, PsoDataType.Float, 12, 0, 0), new PsoStructureEntryInfo(MetaName.falloffExponent, PsoDataType.Float, 16, 0, 0), @@ -450,8 +457,8 @@ namespace CodeWalker.GameFiles new PsoStructureEntryInfo(MetaName.textureName, PsoDataType.String, 36, 7, 0), new PsoStructureEntryInfo(MetaName.mirrorTexture, PsoDataType.Bool, 40, 0, 0) ); - case (MetaName)1860240263: - return new PsoStructureInfo((MetaName)1860240263, 0, 0, 56, + case MetaName.vehicleCorona: //CVehicleModelInfoVarGlobal Lights Corona info + return new PsoStructureInfo(MetaName.vehicleCorona, 0, 0, 56, new PsoStructureEntryInfo(MetaName.size, PsoDataType.Float, 8, 0, 0), new PsoStructureEntryInfo(MetaName.size_far, PsoDataType.Float, 12, 0, 0), new PsoStructureEntryInfo(MetaName.intensity, PsoDataType.Float, 16, 0, 0), @@ -488,7 +495,7 @@ namespace CodeWalker.GameFiles new PsoStructureEntryInfo(MetaName.rightTailLightMultiples, PsoDataType.UByte, 123, 0, 0), new PsoStructureEntryInfo(MetaName.useRealLights, PsoDataType.Bool, 124, 0, 0), new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, MetaName.sirenLight), - new PsoStructureEntryInfo((MetaName)2047330294, PsoDataType.Array, 128, 1, (MetaName)1310739) + new PsoStructureEntryInfo(MetaName.sirens, PsoDataType.Array, 128, 1, (MetaName)1310739) ); case (MetaName)188820339: return new PsoStructureInfo((MetaName)188820339, 0, 0, 16, @@ -527,17 +534,17 @@ namespace CodeWalker.GameFiles new PsoStructureEntryInfo(MetaName.pull, PsoDataType.Float, 16, 0, 0), new PsoStructureEntryInfo(MetaName.faceCamera, PsoDataType.Bool, 20, 0, 0) ); - case (MetaName)679130282: - return new PsoStructureInfo((MetaName)679130282, 0, 0, 120, + case MetaName.CVehicleKit: + return new PsoStructureInfo(MetaName.CVehicleKit, 0, 0, 120, new PsoStructureEntryInfo(MetaName.kitName, PsoDataType.String, 8, 7, 0), new PsoStructureEntryInfo(MetaName.id, PsoDataType.UShort, 12, 0, 0), new PsoStructureEntryInfo(MetaName.kitType, PsoDataType.Enum, 16, 0, (MetaName)3865430600), - new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)4238291236), + new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, MetaName.CVehicleModVisible), new PsoStructureEntryInfo(MetaName.visibleMods, PsoDataType.Array, 24, 0, (MetaName)3), - new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)2730707380), + new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, MetaName.CVehicleModLink), new PsoStructureEntryInfo(MetaName.linkMods, PsoDataType.Array, 40, 0, (MetaName)5), - new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)243590259), - new PsoStructureEntryInfo(MetaName.statMods, PsoDataType.Array, 56, 0, MetaName.POINTER), + new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, MetaName.CVehicleModStat), + new PsoStructureEntryInfo(MetaName.statMods, PsoDataType.Array, 56, 0, (MetaName)7), new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)427606548), new PsoStructureEntryInfo(MetaName.slotNames, PsoDataType.Array, 72, 0, (MetaName)9), new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.String, 0, 2, 0), @@ -545,16 +552,16 @@ namespace CodeWalker.GameFiles new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.String, 0, 2, 0), new PsoStructureEntryInfo(MetaName.livery2Names, PsoDataType.Array, 104, 0, (MetaName)13) ); - case (MetaName)243590259: - return new PsoStructureInfo((MetaName)243590259, 0, 0, 32, + case MetaName.CVehicleModStat: + return new PsoStructureInfo(MetaName.CVehicleModStat, 0, 0, 32, new PsoStructureEntryInfo(MetaName.identifier, PsoDataType.String, 8, 7, 0), new PsoStructureEntryInfo(MetaName.modifier, PsoDataType.UInt, 12, 0, 0), new PsoStructureEntryInfo(MetaName.audioApply, PsoDataType.Float, 16, 0, 0), new PsoStructureEntryInfo(MetaName.weight, PsoDataType.UByte, 20, 0, 0), new PsoStructureEntryInfo(MetaName.type, PsoDataType.Enum, 24, 0, (MetaName)2363989491) ); - case (MetaName)4238291236: - return new PsoStructureInfo((MetaName)4238291236, 0, 0, 96, + case MetaName.CVehicleModVisible: + return new PsoStructureInfo(MetaName.CVehicleModVisible, 0, 0, 96, new PsoStructureEntryInfo(MetaName.modelName, PsoDataType.String, 8, 7, 0), new PsoStructureEntryInfo(MetaName.modShopLabel, PsoDataType.String, 16, 2, 0), new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.String, 0, 7, 0), @@ -582,8 +589,8 @@ namespace CodeWalker.GameFiles new PsoStructureEntryInfo(MetaName.slot, PsoDataType.Enum, 8, 0, (MetaName)2363989491), new PsoStructureEntryInfo(MetaName.name, PsoDataType.String, 16, 2, 0) ); - case (MetaName)2730707380: - return new PsoStructureInfo((MetaName)2730707380, 0, 0, 24, + case MetaName.CVehicleModLink: + return new PsoStructureInfo(MetaName.CVehicleModLink, 0, 0, 24, new PsoStructureEntryInfo(MetaName.modelName, PsoDataType.String, 8, 7, 0), new PsoStructureEntryInfo(MetaName.bone, PsoDataType.Enum, 12, 0, (MetaName)3635907608), new PsoStructureEntryInfo(MetaName.turnOffExtra, PsoDataType.Bool, 16, 0, 0) @@ -596,39 +603,39 @@ namespace CodeWalker.GameFiles new PsoStructureEntryInfo(MetaName.rimRadius, PsoDataType.Float, 24, 0, 0), new PsoStructureEntryInfo(MetaName.rear, PsoDataType.Bool, 28, 0, 0) ); - case (MetaName)2858318490: - return new PsoStructureInfo((MetaName)2858318490, 0, 0, 128, - new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)1443412025), - new PsoStructureEntryInfo((MetaName)2204727143, PsoDataType.Array, 8, 0, 0), - new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)1443412025), - new PsoStructureEntryInfo((MetaName)2458459502, PsoDataType.Array, 24, 0, (MetaName)2), - new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)1443412025), - new PsoStructureEntryInfo((MetaName)1951049216, PsoDataType.Array, 40, 0, (MetaName)4), - new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)1443412025), - new PsoStructureEntryInfo((MetaName)2740125593, PsoDataType.Array, 56, 0, (MetaName)6), - new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)1443412025), - new PsoStructureEntryInfo((MetaName)1114790148, PsoDataType.Array, 72, 0, (MetaName)8), - new PsoStructureEntryInfo((MetaName)3095366650, PsoDataType.Structure, 88, 0, (MetaName)1380492417) + case MetaName.CVehicleModColors: //carmodcols.ymt root + return new PsoStructureInfo(MetaName.CVehicleModColors, 0, 0, 128, + new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, MetaName.CVehicleModColor), + new PsoStructureEntryInfo(MetaName.metallic, PsoDataType.Array, 8, 0, 0), + new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, MetaName.CVehicleModColor), + new PsoStructureEntryInfo(MetaName.classic, PsoDataType.Array, 24, 0, (MetaName)2), + new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, MetaName.CVehicleModColor), + new PsoStructureEntryInfo(MetaName.matte, PsoDataType.Array, 40, 0, (MetaName)4), + new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, MetaName.CVehicleModColor), + new PsoStructureEntryInfo(MetaName.metals, PsoDataType.Array, 56, 0, (MetaName)6), + new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, MetaName.CVehicleModColor), + new PsoStructureEntryInfo(MetaName.chrome, PsoDataType.Array, 72, 0, (MetaName)8), + new PsoStructureEntryInfo(MetaName.pearlescent, PsoDataType.Structure, 88, 0, MetaName.CVehicleModPearlescentColors) ); - case (MetaName)1380492417: - return new PsoStructureInfo((MetaName)1380492417, 0, 0, 40, - new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)1443412025), - new PsoStructureEntryInfo((MetaName)2645876692, PsoDataType.Array, 8, 0, 0), - new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)1443412025), - new PsoStructureEntryInfo((MetaName)666439252, PsoDataType.Array, 24, 0, (MetaName)2) + case MetaName.CVehicleModPearlescentColors: + return new PsoStructureInfo(MetaName.CVehicleModPearlescentColors, 0, 0, 40, + new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, MetaName.CVehicleModColor), + new PsoStructureEntryInfo(MetaName.baseCols, PsoDataType.Array, 8, 0, 0), + new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, MetaName.CVehicleModColor), + new PsoStructureEntryInfo(MetaName.specCols, PsoDataType.Array, 24, 0, (MetaName)2) ); - case (MetaName)1443412025: - return new PsoStructureInfo((MetaName)1443412025, 0, 0, 24, + case MetaName.CVehicleModColor: + return new PsoStructureInfo(MetaName.CVehicleModColor, 0, 0, 24, new PsoStructureEntryInfo(MetaName.name, PsoDataType.String, 8, 2, 0), new PsoStructureEntryInfo(MetaName.col, PsoDataType.UByte, 16, 0, 0), - new PsoStructureEntryInfo((MetaName)1912906641, PsoDataType.UByte, 17, 0, 0) + new PsoStructureEntryInfo(MetaName.spec, PsoDataType.UByte, 17, 0, 0) ); - case MetaName.CVehicleModelInfoVariation: + case MetaName.CVehicleModelInfoVariation: //carvariations.ymt root return new PsoStructureInfo(MetaName.CVehicleModelInfoVariation, 0, 0, 24, new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)418053801), new PsoStructureEntryInfo(MetaName.variationData, PsoDataType.Array, 8, 0, 0) ); - case (MetaName)418053801: + case (MetaName)418053801: //CVehicleModelInfoVariation variationData return new PsoStructureInfo((MetaName)418053801, 0, 0, 96, new PsoStructureEntryInfo(MetaName.modelName, PsoDataType.String, 8, 1, 0), new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)2575850962), @@ -637,34 +644,34 @@ namespace CodeWalker.GameFiles new PsoStructureEntryInfo(MetaName.kits, PsoDataType.Array, 32, 0, (MetaName)3), new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.String, 0, 7, 0), new PsoStructureEntryInfo(MetaName.windowsWithExposedEdges, PsoDataType.Array, 48, 0, (MetaName)5), - new PsoStructureEntryInfo(MetaName.plateProbabilities, PsoDataType.Structure, 64, 0, (MetaName)2135495316), + new PsoStructureEntryInfo(MetaName.plateProbabilities, PsoDataType.Structure, 64, 0, MetaName.PlateProbabilities), new PsoStructureEntryInfo(MetaName.lightSettings, PsoDataType.UByte, 88, 0, 0), new PsoStructureEntryInfo(MetaName.sirenSettings, PsoDataType.UByte, 89, 0, 0) ); - case (MetaName)2135495316: - return new PsoStructureInfo((MetaName)2135495316, 0, 0, 24, - new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)938618322), - new PsoStructureEntryInfo(MetaName.Probabilities, PsoDataType.Array, 8, 0, 0) - ); - case (MetaName)2575850962: + case (MetaName)2575850962: //CVehicleModelInfoVariation variationData colors return new PsoStructureInfo((MetaName)2575850962, 0, 0, 44 /*40*/, new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.UByte, 0, 0, 0), new PsoStructureEntryInfo(MetaName.indices, PsoDataType.Array, 8, 4, (MetaName)393216 /*262144*/), new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Bool, 0, 0, 0), new PsoStructureEntryInfo(MetaName.liveries, PsoDataType.Array, 14 /*12*/, 4, (MetaName)1966082 /*1638402*/) ); + case MetaName.PlateProbabilities: + return new PsoStructureInfo(MetaName.PlateProbabilities, 0, 0, 24, + new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)938618322), + new PsoStructureEntryInfo(MetaName.Probabilities, PsoDataType.Array, 8, 0, 0) + ); case (MetaName)938618322: return new PsoStructureInfo((MetaName)938618322, 0, 0, 16, new PsoStructureEntryInfo(MetaName.Name, PsoDataType.String, 8, 7, 0), new PsoStructureEntryInfo(MetaName.Value, PsoDataType.UInt, 12, 0, 0) ); - case (MetaName)1998252412: + case (MetaName)1998252412: //credits.ymt root return new PsoStructureInfo((MetaName)1998252412, 0, 0, 24, - new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)113388969), + new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, MetaName.CCreditItem), new PsoStructureEntryInfo(MetaName.CreditItems, PsoDataType.Array, 8, 0, 0) ); - case (MetaName)113388969: - return new PsoStructureInfo((MetaName)113388969, 0, 0, 48, + case MetaName.CCreditItem: + return new PsoStructureInfo(MetaName.CCreditItem, 0, 0, 48, new PsoStructureEntryInfo(MetaName.LineType, PsoDataType.Enum, 8, 0, (MetaName)1795685103), new PsoStructureEntryInfo(MetaName.cTextId1, PsoDataType.String, 16, 3, 0), new PsoStructureEntryInfo(MetaName.cTextId2, PsoDataType.String, 32, 3, 0) @@ -701,19 +708,19 @@ namespace CodeWalker.GameFiles new PsoStructureEntryInfo(MetaName.contents, PsoDataType.Enum, 168, 0, MetaName.DataFileContents), new PsoStructureEntryInfo(MetaName.installPartition, PsoDataType.Enum, 172, 0, MetaName.InstallPartition) ); - case MetaName.CLevelData: + case MetaName.CLevelData: //levels.ymt root return new PsoStructureInfo(MetaName.CLevelData, 0, 0, 24, new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, MetaName.sLevelData), - new PsoStructureEntryInfo((MetaName)1643066032, PsoDataType.Array, 8, 0, 0) + new PsoStructureEntryInfo(MetaName.aLevelsData, PsoDataType.Array, 8, 0, 0) ); case MetaName.sLevelData: return new PsoStructureInfo(MetaName.sLevelData, 0, 0, 72, - new PsoStructureEntryInfo((MetaName)2077026003, PsoDataType.String, 8, 3, 0), - new PsoStructureEntryInfo((MetaName)834048882, PsoDataType.String, 24, 3, 0), - new PsoStructureEntryInfo((MetaName)3760135447, PsoDataType.String, 40, 3, 0), - new PsoStructureEntryInfo((MetaName)3970741067, PsoDataType.String, 56, 3, 0) + new PsoStructureEntryInfo(MetaName.cFriendlyName, PsoDataType.String, 8, 3, 0), + new PsoStructureEntryInfo(MetaName.cTitle, PsoDataType.String, 24, 3, 0), + new PsoStructureEntryInfo(MetaName.cFilename, PsoDataType.String, 40, 3, 0), + new PsoStructureEntryInfo(MetaName.cBugstarName, PsoDataType.String, 56, 3, 0) ); - case (MetaName)1056751197: + case (MetaName)1056751197: //mapdatacullboxes.ymt root return new PsoStructureInfo((MetaName)1056751197, 0, 0, 24, new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)322201475), new PsoStructureEntryInfo((MetaName)934859523, PsoDataType.Array, 8, 0, 0) @@ -741,7 +748,7 @@ namespace CodeWalker.GameFiles new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, MetaName.CTxdRelationship), new PsoStructureEntryInfo(MetaName.txdRelationships, PsoDataType.Array, 56, 0, (MetaName)5), new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, MetaName.CMultiTxdRelationship), - new PsoStructureEntryInfo(MetaName.multiTxdRelationships, PsoDataType.Array, 72, 0, MetaName.POINTER) + new PsoStructureEntryInfo(MetaName.multiTxdRelationships, PsoDataType.Array, 72, 0, (MetaName)7) ); case MetaName.CPedModelInfo__InitData: return new PsoStructureInfo(MetaName.CPedModelInfo__InitData, 0, 0, 296, @@ -14185,13 +14192,6 @@ namespace CodeWalker.GameFiles new PsoStructureEntryInfo((MetaName)2721898107, PsoDataType.UInt, 0, 0, 0), new PsoStructureEntryInfo((MetaName)1084559223, PsoDataType.SInt, 4, 0, 0) ); - case (MetaName)2807227399: - return new PsoStructureInfo((MetaName)2807227399, 0, 0, 24, - new PsoStructureEntryInfo((MetaName)78766281, PsoDataType.UInt, 8, 1, 0), - new PsoStructureEntryInfo((MetaName)3615736814, PsoDataType.UInt, 12, 1, 0), - new PsoStructureEntryInfo((MetaName)1981979787, PsoDataType.Float, 16, 0, 0), - new PsoStructureEntryInfo((MetaName)3155797354, PsoDataType.Float, 20, 0, 0) - ); case MetaName.camMotionBlurSettingsMetadata: return new PsoStructureInfo(MetaName.camMotionBlurSettingsMetadata, 0, 0, 64, new PsoStructureEntryInfo(MetaName.Name, PsoDataType.String, 8, 7, 0), @@ -14285,7 +14285,7 @@ namespace CodeWalker.GameFiles //to generate enuminfos switch (name) { - case (MetaName)360458334: + case (MetaName)360458334: //vehicle mod color metallic id return new PsoEnumInfo((MetaName)360458334, 1, new PsoEnumEntryInfo(MetaName.none, -1), new PsoEnumEntryInfo((MetaName)815563434, 0), @@ -14299,7 +14299,7 @@ namespace CodeWalker.GameFiles new PsoEnumEntryInfo((MetaName)4285337393, 8), new PsoEnumEntryInfo((MetaName)847803751, 9) ); - case (MetaName)544262540: + case (MetaName)544262540: //vehicle mod color audio color return new PsoEnumInfo((MetaName)544262540, 1, new PsoEnumEntryInfo((MetaName)52583446, 0), new PsoEnumEntryInfo((MetaName)2253400966, 1), @@ -14315,21 +14315,21 @@ namespace CodeWalker.GameFiles new PsoEnumEntryInfo((MetaName)1645071976, 11), new PsoEnumEntryInfo((MetaName)1358390657, 12) ); - case (MetaName)2065815796: + case (MetaName)2065815796: //vehicle mod color audio prefix return new PsoEnumInfo((MetaName)2065815796, 1, new PsoEnumEntryInfo(MetaName.none, 0), new PsoEnumEntryInfo((MetaName)2318284788, 1), new PsoEnumEntryInfo((MetaName)840729009, 2), new PsoEnumEntryInfo((MetaName)3921902053, 3) ); - case (MetaName)3865430600: + case (MetaName)3865430600: //vehicle mod kit type return new PsoEnumInfo((MetaName)3865430600, 1, new PsoEnumEntryInfo(MetaName.MKT_STANDARD, 0), new PsoEnumEntryInfo(MetaName.MKT_SPORT, 1), new PsoEnumEntryInfo(MetaName.MKT_SUV, 2), new PsoEnumEntryInfo(MetaName.MKT_SPECIAL, 3) ); - case (MetaName)2363989491: + case (MetaName)2363989491: //vehicle mod type return new PsoEnumInfo((MetaName)2363989491, 1, new PsoEnumEntryInfo(MetaName.VMT_SPOILER, 0), new PsoEnumEntryInfo(MetaName.VMT_BUMPER_F, 1), @@ -14382,7 +14382,7 @@ namespace CodeWalker.GameFiles new PsoEnumEntryInfo(MetaName.VMT_WHEELS, 48), new PsoEnumEntryInfo(MetaName.VMT_WHEELS_REAR_OR_HYDRAULICS, 49) ); - case (MetaName)3635907608: + case (MetaName)3635907608: //vehicle mod bone return new PsoEnumInfo((MetaName)3635907608, 1, new PsoEnumEntryInfo(MetaName.none, -1), new PsoEnumEntryInfo(MetaName.chassis, 0), @@ -14590,7 +14590,7 @@ namespace CodeWalker.GameFiles new PsoEnumEntryInfo((MetaName)2166816405, 591), new PsoEnumEntryInfo((MetaName)2486991428, 592) ); - case (MetaName)3413962745: + case (MetaName)3413962745: //vehicle mod camera position return new PsoEnumInfo((MetaName)3413962745, 1, new PsoEnumEntryInfo(MetaName.VMCP_DEFAULT, 0), new PsoEnumEntryInfo((MetaName)3001706694, 1), @@ -14604,11 +14604,11 @@ namespace CodeWalker.GameFiles new PsoEnumEntryInfo((MetaName)3193071790, 9), new PsoEnumEntryInfo((MetaName)2770495034, 10) ); - case (MetaName)1795685103: + case (MetaName)1795685103: //credit item job line type return new PsoEnumInfo((MetaName)1795685103, 1, new PsoEnumEntryInfo(MetaName.JOB_BIG, 0), - new PsoEnumEntryInfo((MetaName)568575574, 1), - new PsoEnumEntryInfo((MetaName)4127034762, 2), + new PsoEnumEntryInfo(MetaName.JOB_MED, 1), + new PsoEnumEntryInfo(MetaName.JOB_SMALL, 2), new PsoEnumEntryInfo((MetaName)1877679104, 3), new PsoEnumEntryInfo((MetaName)2980984179, 4), new PsoEnumEntryInfo((MetaName)298596333, 5), @@ -14904,7 +14904,7 @@ namespace CodeWalker.GameFiles new PsoEnumEntryInfo((MetaName)551739454, 3), new PsoEnumEntryInfo((MetaName)462532381, 4) ); - case (MetaName)3029795674: + case (MetaName)3029795674: //CPedModelInfo__InitData ScenarioPopStreamingSlot return new PsoEnumInfo((MetaName)3029795674, 1, new PsoEnumEntryInfo(MetaName.SCENARIO_POP_STREAMING_NORMAL, 0), new PsoEnumEntryInfo((MetaName)1152280719, 1) @@ -14923,7 +14923,7 @@ namespace CodeWalker.GameFiles new PsoEnumEntryInfo((MetaName)3916722287, 2), new PsoEnumEntryInfo((MetaName)157616235, 3) ); - case (MetaName)224899699: + case (MetaName)224899699: //animation clip flags return new PsoEnumInfo((MetaName)224899699, 1, new PsoEnumEntryInfo((MetaName)2933717348, 0), new PsoEnumEntryInfo((MetaName)892548521, 1), @@ -14958,7 +14958,7 @@ namespace CodeWalker.GameFiles new PsoEnumEntryInfo((MetaName)1321103795, 30), new PsoEnumEntryInfo((MetaName)3765996064, 31) ); - case (MetaName)1498349301: + case (MetaName)1498349301: //animation clip priority return new PsoEnumInfo((MetaName)1498349301, 1, new PsoEnumEntryInfo(MetaName.AP_LOW, 0), new PsoEnumEntryInfo(MetaName.AP_MEDIUM, 1), @@ -14967,13 +14967,13 @@ namespace CodeWalker.GameFiles new PsoEnumEntryInfo((MetaName)3509068476, 4), new PsoEnumEntryInfo((MetaName)611607097, 5) ); - case (MetaName)1631789397: + case (MetaName)1631789397: //anim clip dictionary streaming policy return new PsoEnumInfo((MetaName)1631789397, 1, new PsoEnumEntryInfo(MetaName.SP_STREAMING, 0), new PsoEnumEntryInfo(MetaName.SP_SINGLEPLAYER_RESIDENT, 1), new PsoEnumEntryInfo(MetaName.SP_MULTIPLAYER_RESIDENT, 2) ); - case (MetaName)733577798: + case (MetaName)733577798: //anim clip dictionary streaming priority return new PsoEnumInfo((MetaName)733577798, 1, new PsoEnumEntryInfo((MetaName)3866220764, 0), new PsoEnumEntryInfo(MetaName.SP_Low, 1), diff --git a/CodeWalker.Core/GameFiles/MetaTypes/XmlPso.cs b/CodeWalker.Core/GameFiles/MetaTypes/XmlPso.cs index 6584027..40f4cdb 100644 --- a/CodeWalker.Core/GameFiles/MetaTypes/XmlPso.cs +++ b/CodeWalker.Core/GameFiles/MetaTypes/XmlPso.cs @@ -166,7 +166,17 @@ namespace CodeWalker.GameFiles Write(sval, data, entry.DataOffset); break; case 1: //unsigned int - var uval = Convert.ToUInt32(cnode.Attributes["value"].Value); + var ustr = cnode.Attributes["value"].Value; + uint uval = 0; + if (ustr.StartsWith("0x")) + { + ustr = ustr.Substring(2); + uval = Convert.ToUInt32(ustr, 16); + } + else + { + uval = Convert.ToUInt32(ustr); + } Write(uval, data, entry.DataOffset); break; } diff --git a/CodeWalker.Core/GameFiles/RpfManager.cs b/CodeWalker.Core/GameFiles/RpfManager.cs index 49a1b43..be8686f 100644 --- a/CodeWalker.Core/GameFiles/RpfManager.cs +++ b/CodeWalker.Core/GameFiles/RpfManager.cs @@ -15,6 +15,7 @@ namespace CodeWalker.GameFiles public string Folder { get; private set; } public string[] ExcludePaths { get; set; } public bool EnableMods { get; set; } + public bool BuildExtendedJenkIndex { get; set; } = true; public Action UpdateStatus { get; private set; } public Action ErrorLog { get; private set; } @@ -381,102 +382,105 @@ namespace CodeWalker.GameFiles JenkIndex.Ensure(entry.Name); JenkIndex.Ensure(nlow); } - if (nlow.EndsWith(".ydr") || nlow.EndsWith(".yft")) + if (BuildExtendedJenkIndex) { - var sname = nlow.Substring(0, nlow.Length - 4); - JenkIndex.Ensure(sname + "_lod"); - JenkIndex.Ensure(sname + "_loda"); - JenkIndex.Ensure(sname + "_lodb"); - } - if (nlow.EndsWith(".ydd")) - { - if (nlow.EndsWith("_children.ydd")) + if (nlow.EndsWith(".ydr") || nlow.EndsWith(".yft")) { - var strn = nlow.Substring(0, nlow.Length - 13); - JenkIndex.Ensure(strn); - JenkIndex.Ensure(strn + "_lod"); - JenkIndex.Ensure(strn + "_loda"); - JenkIndex.Ensure(strn + "_lodb"); + var sname = nlow.Substring(0, nlow.Length - 4); + JenkIndex.Ensure(sname + "_lod"); + JenkIndex.Ensure(sname + "_loda"); + JenkIndex.Ensure(sname + "_lodb"); } - var idx = nlow.LastIndexOf('_'); - if (idx > 0) + if (nlow.EndsWith(".ydd")) { - var str1 = nlow.Substring(0, idx); - var idx2 = str1.LastIndexOf('_'); - if (idx2 > 0) + if (nlow.EndsWith("_children.ydd")) { - var str2 = str1.Substring(0, idx2); - JenkIndex.Ensure(str2 + "_lod"); - var maxi = 100; - for (int i = 1; i <= maxi; i++) + var strn = nlow.Substring(0, nlow.Length - 13); + JenkIndex.Ensure(strn); + JenkIndex.Ensure(strn + "_lod"); + JenkIndex.Ensure(strn + "_loda"); + JenkIndex.Ensure(strn + "_lodb"); + } + var idx = nlow.LastIndexOf('_'); + if (idx > 0) + { + var str1 = nlow.Substring(0, idx); + var idx2 = str1.LastIndexOf('_'); + if (idx2 > 0) { - var str3 = str2 + "_" + i.ToString().PadLeft(2, '0'); - //JenkIndex.Ensure(str3); - JenkIndex.Ensure(str3 + "_lod"); + var str2 = str1.Substring(0, idx2); + JenkIndex.Ensure(str2 + "_lod"); + var maxi = 100; + for (int i = 1; i <= maxi; i++) + { + var str3 = str2 + "_" + i.ToString().PadLeft(2, '0'); + //JenkIndex.Ensure(str3); + JenkIndex.Ensure(str3 + "_lod"); + } } } } - } - if (nlow.EndsWith(".awc")) //create audio container path hashes... - { - string[] parts = entry.Path.Split('\\'); - int pl = parts.Length; - if (pl > 2) + if (nlow.EndsWith(".awc")) //create audio container path hashes... { - string fn = parts[pl - 1]; - string fd = parts[pl - 2]; - string hpath = fn.Substring(0, fn.Length - 4); - if (fd.EndsWith(".rpf")) + string[] parts = entry.Path.Split('\\'); + int pl = parts.Length; + if (pl > 2) { - fd = fd.Substring(0, fd.Length - 4); - } - hpath = fd + "/" + hpath; - if (parts[pl - 3] != "sfx") - { }//no hit - - JenkIndex.Ensure(hpath); - } - } - if (nlow.EndsWith(".nametable")) - { - RpfBinaryFileEntry binfe = entry as RpfBinaryFileEntry; - if (binfe != null) - { - byte[] data = file.ExtractFile(binfe); - if (data != null) - { - sb.Clear(); - for (int i = 0; i < data.Length; i++) + string fn = parts[pl - 1]; + string fd = parts[pl - 2]; + string hpath = fn.Substring(0, fn.Length - 4); + if (fd.EndsWith(".rpf")) { - byte c = data[i]; - if (c == 0) + fd = fd.Substring(0, fd.Length - 4); + } + hpath = fd + "/" + hpath; + if (parts[pl - 3] != "sfx") + { }//no hit + + JenkIndex.Ensure(hpath); + } + } + if (nlow.EndsWith(".nametable")) + { + RpfBinaryFileEntry binfe = entry as RpfBinaryFileEntry; + if (binfe != null) + { + byte[] data = file.ExtractFile(binfe); + if (data != null) + { + sb.Clear(); + for (int i = 0; i < data.Length; i++) { - string str = sb.ToString(); - if (!string.IsNullOrEmpty(str)) + byte c = data[i]; + if (c == 0) { - string strl = str.ToLowerInvariant(); - //JenkIndex.Ensure(str); - JenkIndex.Ensure(strl); + string str = sb.ToString(); + if (!string.IsNullOrEmpty(str)) + { + string strl = str.ToLowerInvariant(); + //JenkIndex.Ensure(str); + JenkIndex.Ensure(strl); - ////DirMod_Sounds_ entries apparently can be used to infer SP audio strings - ////no luck here yet though - //if (strl.StartsWith("dirmod_sounds_") && (strl.Length > 14)) - //{ - // strl = strl.Substring(14); - // JenkIndex.Ensure(strl); - //} + ////DirMod_Sounds_ entries apparently can be used to infer SP audio strings + ////no luck here yet though + //if (strl.StartsWith("dirmod_sounds_") && (strl.Length > 14)) + //{ + // strl = strl.Substring(14); + // JenkIndex.Ensure(strl); + //} + } + sb.Clear(); + } + else + { + sb.Append((char)c); } - sb.Clear(); - } - else - { - sb.Append((char)c); } } } + else + { } } - else - { } } } diff --git a/CodeWalker.csproj b/CodeWalker.csproj index b6dc6a5..b9da053 100644 --- a/CodeWalker.csproj +++ b/CodeWalker.csproj @@ -534,6 +534,12 @@ + + Form + + + VehicleForm.cs + Form @@ -752,6 +758,9 @@ TextInputForm.cs + + VehicleForm.cs + WorldForm.cs diff --git a/Program.cs b/Program.cs index 50b889f..6bb6187 100644 --- a/Program.cs +++ b/Program.cs @@ -18,6 +18,7 @@ namespace CodeWalker bool menumode = false; bool explorermode = false; bool projectmode = false; + bool vehiclesmode = false; if ((args != null) && (args.Length > 0)) { foreach (string arg in args) @@ -35,6 +36,10 @@ namespace CodeWalker { projectmode = true; } + if (argl == "vehicles") + { + vehiclesmode = true; + } } } @@ -64,6 +69,10 @@ namespace CodeWalker { Application.Run(new Project.ProjectForm()); } + else if (vehiclesmode) + { + Application.Run(new Vehicles.VehicleForm()); + } else { Application.Run(new WorldForm()); diff --git a/Vehicles/VehicleForm.Designer.cs b/Vehicles/VehicleForm.Designer.cs new file mode 100644 index 0000000..35ebed0 --- /dev/null +++ b/Vehicles/VehicleForm.Designer.cs @@ -0,0 +1,115 @@ +namespace CodeWalker.Vehicles +{ + partial class VehicleForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(VehicleForm)); + this.StatusStrip = new System.Windows.Forms.StatusStrip(); + this.StatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.MousedLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.StatsLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.StatsUpdateTimer = new System.Windows.Forms.Timer(this.components); + this.StatusStrip.SuspendLayout(); + this.SuspendLayout(); + // + // StatusStrip + // + this.StatusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.StatusLabel, + this.MousedLabel, + this.StatsLabel}); + this.StatusStrip.Location = new System.Drawing.Point(0, 689); + this.StatusStrip.Name = "StatusStrip"; + this.StatusStrip.Size = new System.Drawing.Size(984, 22); + this.StatusStrip.TabIndex = 2; + this.StatusStrip.Text = "statusStrip1"; + // + // StatusLabel + // + this.StatusLabel.BackColor = System.Drawing.SystemColors.Control; + this.StatusLabel.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.StatusLabel.Name = "StatusLabel"; + this.StatusLabel.Size = new System.Drawing.Size(878, 17); + this.StatusLabel.Spring = true; + this.StatusLabel.Text = "Initialising"; + this.StatusLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // MousedLabel + // + this.MousedLabel.BackColor = System.Drawing.SystemColors.Control; + this.MousedLabel.Name = "MousedLabel"; + this.MousedLabel.Size = new System.Drawing.Size(16, 17); + this.MousedLabel.Text = " "; + // + // StatsLabel + // + this.StatsLabel.BackColor = System.Drawing.SystemColors.Control; + this.StatsLabel.Name = "StatsLabel"; + this.StatsLabel.Size = new System.Drawing.Size(75, 17); + this.StatsLabel.Text = "0 geometries"; + // + // StatsUpdateTimer + // + this.StatsUpdateTimer.Enabled = true; + this.StatsUpdateTimer.Interval = 500; + this.StatsUpdateTimer.Tick += new System.EventHandler(this.StatsUpdateTimer_Tick); + // + // VehicleForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.Color.MidnightBlue; + this.ClientSize = new System.Drawing.Size(984, 711); + this.Controls.Add(this.StatusStrip); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "VehicleForm"; + this.Text = "Vehicle Viewer - CodeWalker by dexyfex"; + this.Deactivate += new System.EventHandler(this.VehicleForm_Deactivate); + this.Load += new System.EventHandler(this.VehicleForm_Load); + this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.VehicleForm_KeyDown); + this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.VehicleForm_KeyUp); + this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.VehicleForm_MouseDown); + this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.VehicleForm_MouseMove); + this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.VehicleForm_MouseUp); + this.StatusStrip.ResumeLayout(false); + this.StatusStrip.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.StatusStrip StatusStrip; + private System.Windows.Forms.ToolStripStatusLabel StatusLabel; + private System.Windows.Forms.ToolStripStatusLabel MousedLabel; + private System.Windows.Forms.ToolStripStatusLabel StatsLabel; + private System.Windows.Forms.Timer StatsUpdateTimer; + } +} \ No newline at end of file diff --git a/Vehicles/VehicleForm.cs b/Vehicles/VehicleForm.cs new file mode 100644 index 0000000..bd49827 --- /dev/null +++ b/Vehicles/VehicleForm.cs @@ -0,0 +1,609 @@ +using CodeWalker.GameFiles; +using CodeWalker.Properties; +using CodeWalker.Rendering; +using CodeWalker.World; +using SharpDX; +using SharpDX.Direct3D11; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Diagnostics; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker.Vehicles +{ + public partial class VehicleForm : Form, DXForm + { + public Form Form { get { return this; } } //for DXForm/DXManager use + + public Renderer Renderer = null; + public object RenderSyncRoot { get { return Renderer.RenderSyncRoot; } } + + volatile bool formopen = false; + volatile bool running = false; + volatile bool pauserendering = false; + //volatile bool initialised = false; + + Stopwatch frametimer = new Stopwatch(); + Camera camera; + Timecycle timecycle; + Weather weather; + Clouds clouds; + + Entity camEntity = new Entity(); + + + bool MouseLButtonDown = false; + bool MouseRButtonDown = false; + int MouseX; + int MouseY; + System.Drawing.Point MouseDownPoint; + System.Drawing.Point MouseLastPoint; + + + public GameFileCache GameFileCache { get; } = GameFileCacheFactory.Create(); + + + InputManager Input = new InputManager(); + + + bool initedOk = false; + + + + + public VehicleForm() + { + InitializeComponent(); + + Renderer = new Renderer(this, GameFileCache); + camera = Renderer.camera; + timecycle = Renderer.timecycle; + weather = Renderer.weather; + clouds = Renderer.clouds; + + initedOk = Renderer.Init(); + + Renderer.controllightdir = !Settings.Default.Skydome; + Renderer.rendercollisionmeshes = false; + Renderer.renderclouds = false; + //Renderer.renderclouds = true; + //Renderer.individualcloudfrag = "Contrails"; + Renderer.rendermoon = false; + Renderer.renderskeletons = false; + Renderer.SelectionFlagsTestAll = true; + + } + + + public void InitScene(Device device) + { + int width = ClientSize.Width; + int height = ClientSize.Height; + + try + { + Renderer.DeviceCreated(device, width, height); + } + catch (Exception ex) + { + MessageBox.Show("Error loading shaders!\n" + ex.ToString()); + return; + } + + + camera.FollowEntity = camEntity; + camera.FollowEntity.Position = Vector3.Zero;// prevworldpos; + camera.FollowEntity.Orientation = Quaternion.LookAtLH(Vector3.Zero, Vector3.Up, Vector3.ForwardLH); + camera.TargetDistance = 2.0f; + camera.CurrentDistance = 2.0f; + camera.TargetRotation.Y = 0.2f; + camera.CurrentRotation.Y = 0.2f; + camera.TargetRotation.X = 0.5f * (float)Math.PI; + camera.CurrentRotation.X = 0.5f * (float)Math.PI; + + + //LoadSettings(); + + + formopen = true; + new Thread(new ThreadStart(ContentThread)).Start(); + + frametimer.Start(); + + } + public void CleanupScene() + { + formopen = false; + + Renderer.DeviceDestroyed(); + + int count = 0; + while (running && (count < 5000)) //wait for the content thread to exit gracefully + { + Thread.Sleep(1); + count++; + } + } + public void RenderScene(DeviceContext context) + { + float elapsed = (float)frametimer.Elapsed.TotalSeconds; + frametimer.Restart(); + + if (pauserendering) return; + + if (!Monitor.TryEnter(Renderer.RenderSyncRoot, 50)) + { return; } //couldn't get a lock, try again next time + + //UpdateControlInputs(elapsed); + //space.Update(elapsed); + + + Renderer.Update(elapsed, MouseLastPoint.X, MouseLastPoint.Y); + + + + //UpdateWidgets(); + //BeginMouseHitTest(); + + + + + Renderer.BeginRender(context); + + Renderer.RenderSkyAndClouds(); + + Renderer.SelectedDrawable = null;// SelectedItem.Drawable; + + + //if (renderworld) + //{ + // RenderWorld(); + //} + //else if (rendermaps) + //{ + // RenderYmaps(); + //} + //else + //{ + // RenderSingleItem(); + //} + //UpdateMouseHitsFromRenderer(); + //RenderSelection(); + + + //RenderGrid(context); + + + Renderer.RenderQueued(); + + //Renderer.RenderBounds(MapSelectionMode.Entity); + + //Renderer.RenderSelectionGeometry(MapSelectionMode.Entity); + + //RenderMoused(); + + Renderer.RenderFinalPass(); + + //RenderMarkers(); + //RenderWidgets(); + + Renderer.EndRender(); + + Monitor.Exit(Renderer.RenderSyncRoot); + + //UpdateMarkerSelectionPanelInvoke(); + } + public void BuffersResized(int w, int h) + { + Renderer.BuffersResized(w, h); + } + + + + + + private void Init() + { + //called from VehicleForm_Load + + if (!initedOk) + { + Close(); + return; + } + + + MouseWheel += VehicleForm_MouseWheel; + + if (!GTAFolder.UpdateGTAFolder(true)) + { + Close(); + return; + } + + + Input.Init(); + + + Renderer.Start(); + } + + + private void ContentThread() + { + //main content loading thread. + running = true; + + UpdateStatus("Scanning..."); + + try + { + GTA5Keys.LoadFromPath(GTAFolder.CurrentGTAFolder, Settings.Default.Key); + } + catch + { + MessageBox.Show("Keys not found! This shouldn't happen."); + Close(); + return; + } + + GameFileCache.EnableDlc = true; + GameFileCache.LoadVehicles = true; + GameFileCache.LoadArchetypes = false;//to speed things up a little + GameFileCache.BuildExtendedJenkIndex = false;//to speed things up a little + GameFileCache.Init(UpdateStatus, LogError); + + //UpdateDlcListComboBox(gameFileCache.DlcNameList); + + //EnableCacheDependentUI(); + + LoadWorld(); + + + + //initialised = true; + + //EnableDLCModsUI(); + + //UpdateStatus("Ready"); + + + Task.Run(() => { + while (formopen && !IsDisposed) //renderer content loop + { + bool rcItemsPending = Renderer.ContentThreadProc(); + + if (!rcItemsPending) + { + Thread.Sleep(1); //sleep if there's nothing to do + } + } + }); + + while (formopen && !IsDisposed) //main asset loop + { + bool fcItemsPending = GameFileCache.ContentThreadProc(); + + if (!fcItemsPending) + { + Thread.Sleep(1); //sleep if there's nothing to do + } + } + + GameFileCache.Clear(); + + running = false; + } + + + + + private void LoadWorld() + { + UpdateStatus("Loading timecycles..."); + timecycle.Init(GameFileCache, UpdateStatus); + timecycle.SetTime(Renderer.timeofday); + + UpdateStatus("Loading materials..."); + BoundsMaterialTypes.Init(GameFileCache); + + UpdateStatus("Loading weather..."); + weather.Init(GameFileCache, UpdateStatus, timecycle); + //UpdateWeatherTypesComboBox(weather); + + UpdateStatus("Loading clouds..."); + clouds.Init(GameFileCache, UpdateStatus, weather); + //UpdateCloudTypesComboBox(clouds); + + } + + + + + + + private void UpdateStatus(string text) + { + try + { + if (InvokeRequired) + { + BeginInvoke(new Action(() => { UpdateStatus(text); })); + } + else + { + StatusLabel.Text = text; + } + } + catch { } + } + private void LogError(string text) + { + try + { + if (InvokeRequired) + { + Invoke(new Action(() => { LogError(text); })); + } + else + { + //TODO: error logging.. + //ConsoleTextBox.AppendText(text + "\r\n"); + //StatusLabel.Text = text; + //MessageBox.Show(text); + } + } + catch { } + } + + + + + private void UpdateMousePosition(MouseEventArgs e) + { + MouseX = e.X; + MouseY = e.Y; + MouseLastPoint = e.Location; + } + + private void RotateCam(int dx, int dy) + { + camera.MouseRotate(dx, dy); + } + + + + + private void VehicleForm_Load(object sender, EventArgs e) + { + Init(); + } + + private void VehicleForm_MouseDown(object sender, MouseEventArgs e) + { + switch (e.Button) + { + case MouseButtons.Left: MouseLButtonDown = true; break; + case MouseButtons.Right: MouseRButtonDown = true; break; + } + + //if (!ToolsPanelShowButton.Focused) + //{ + // ToolsPanelShowButton.Focus(); //make sure no textboxes etc are focused! + //} + + MouseDownPoint = e.Location; + MouseLastPoint = MouseDownPoint; + + if (MouseLButtonDown) + { + } + + if (MouseRButtonDown) + { + //SelectMousedItem(); + } + + MouseX = e.X; //to stop jumps happening on mousedown, sometimes the last MouseMove event was somewhere else... (eg after clicked a menu) + MouseY = e.Y; + } + + private void VehicleForm_MouseUp(object sender, MouseEventArgs e) + { + switch (e.Button) + { + case MouseButtons.Left: MouseLButtonDown = false; break; + case MouseButtons.Right: MouseRButtonDown = false; break; + } + + + + if (e.Button == MouseButtons.Left) + { + } + } + + private void VehicleForm_MouseMove(object sender, MouseEventArgs e) + { + int dx = e.X - MouseX; + int dy = e.Y - MouseY; + + //if (MouseInvert) + //{ + // dy = -dy; + //} + + //if (ControlMode == WorldControlMode.Free && !ControlBrushEnabled) + { + if (MouseLButtonDown) + { + RotateCam(dx, dy); + } + if (MouseRButtonDown) + { + if (Renderer.controllightdir) + { + Renderer.lightdirx += (dx * camera.Sensitivity); + Renderer.lightdiry += (dy * camera.Sensitivity); + } + else if (Renderer.controltimeofday) + { + float tod = Renderer.timeofday; + tod += (dx - dy) / 30.0f; + while (tod >= 24.0f) tod -= 24.0f; + while (tod < 0.0f) tod += 24.0f; + timecycle.SetTime(tod); + Renderer.timeofday = tod; + + //float fv = tod * 60.0f; + //TimeOfDayTrackBar.Value = (int)fv; + //UpdateTimeOfDayLabel(); + } + } + + UpdateMousePosition(e); + + } + + + + } + + private void VehicleForm_MouseWheel(object sender, MouseEventArgs e) + { + if (e.Delta != 0) + { + camera.MouseZoom(e.Delta); + } + } + + private void VehicleForm_KeyDown(object sender, KeyEventArgs e) + { + if (ActiveControl is TextBox) + { + var tb = ActiveControl as TextBox; + if (!tb.ReadOnly) return; //don't move the camera when typing! + } + if (ActiveControl is ComboBox) + { + var cb = ActiveControl as ComboBox; + if (cb.DropDownStyle != ComboBoxStyle.DropDownList) return; //nontypable combobox + } + + bool enablemove = true;// (!iseditmode) || (MouseLButtonDown && (GrabbedMarker == null) && (GrabbedWidget == null)); + + Input.KeyDown(e, enablemove); + + var k = e.KeyCode; + var kb = Input.keyBindings; + bool ctrl = Input.CtrlPressed; + bool shift = Input.ShiftPressed; + + + if (!ctrl) + { + if (k == kb.MoveSlowerZoomIn) + { + camera.MouseZoom(1); + } + if (k == kb.MoveFasterZoomOut) + { + camera.MouseZoom(-1); + } + } + + + if (!Input.kbmoving) //don't trigger further actions if moving. + { + if (!ctrl) + { + + } + else + { + //switch (k) + //{ + // //case Keys.N: + // // New(); + // // break; + // //case Keys.O: + // // Open(); + // // break; + // //case Keys.S: + // // if (shift) SaveAll(); + // // else Save(); + // // break; + // //case Keys.Z: + // // Undo(); + // // break; + // //case Keys.Y: + // // Redo(); + // // break; + // //case Keys.C: + // // CopyItem(); + // // break; + // //case Keys.V: + // // PasteItem(); + // // break; + // //case Keys.U: + // // ToolsPanelShowButton.Visible = !ToolsPanelShowButton.Visible; + // // break; + //} + } + } + + //if (ControlMode != WorldControlMode.Free || ControlBrushEnabled) + //{ + // e.Handled = true; + //} + } + + private void VehicleForm_KeyUp(object sender, KeyEventArgs e) + { + Input.KeyUp(e); + + if (ActiveControl is TextBox) + { + var tb = ActiveControl as TextBox; + if (!tb.ReadOnly) return; //don't move the camera when typing! + } + if (ActiveControl is ComboBox) + { + var cb = ActiveControl as ComboBox; + if (cb.DropDownStyle != ComboBoxStyle.DropDownList) return; //non-typable combobox + } + + //if (ControlMode != WorldControlMode.Free) + //{ + // e.Handled = true; + //} + } + + private void VehicleForm_Deactivate(object sender, EventArgs e) + { + //try not to lock keyboard movement if the form loses focus. + Input.KeyboardStop(); + } + + private void StatsUpdateTimer_Tick(object sender, EventArgs e) + { + StatsLabel.Text = Renderer.GetStatusText(); + + if (Renderer.timerunning) + { + //float fv = Renderer.timeofday * 60.0f; + ////TimeOfDayTrackBar.Value = (int)fv; + //UpdateTimeOfDayLabel(); + } + + //CameraPositionTextBox.Text = FloatUtil.GetVector3String(camera.Position, "0.##"); + } + } +} diff --git a/Vehicles/VehicleForm.resx b/Vehicles/VehicleForm.resx new file mode 100644 index 0000000..36d72f5 --- /dev/null +++ b/Vehicles/VehicleForm.resx @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 127, 17 + + + + + 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 + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file