From 3cb6514f78c743815adb57439df8805e01d35cdf Mon Sep 17 00:00:00 2001 From: Oscar Date: Sat, 28 Jun 2025 19:17:59 +0300 Subject: [PATCH] upd --- Assets/Items/pistol_test.weapon | 4 +- Assets/Items/rifle.weapon | 12 +-- Assets/prefabs/Player.prefab | 168 +++++++++++++++---------------- Code/Inventory/Inventar.cs | 11 +- Code/Inventory/InventoryItem.cs | 5 +- Code/Player/Dedugan.Inventory.cs | 12 +++ Code/Player/Dedugan.cs | 56 +++++++---- Code/Weapons/BaseWeapon.cs | 67 +++++++++++- Code/Weapons/README.md | 132 +----------------------- 9 files changed, 216 insertions(+), 251 deletions(-) diff --git a/Assets/Items/pistol_test.weapon b/Assets/Items/pistol_test.weapon index 9a91164..0c4ed9e 100644 --- a/Assets/Items/pistol_test.weapon +++ b/Assets/Items/pistol_test.weapon @@ -11,8 +11,8 @@ "Range": 1000, "MagazineSize": 30, "AmmoType": "Pistol", - "ReloadTime": 2, - "Spread": 0.02, + "ReloadTime": 1.5, + "Spread": 0.01, "IsAutomatic": false, "Category": "Weapon", "Name": "Pistol Test", diff --git a/Assets/Items/rifle.weapon b/Assets/Items/rifle.weapon index 530e067..3488541 100644 --- a/Assets/Items/rifle.weapon +++ b/Assets/Items/rifle.weapon @@ -1,18 +1,18 @@ { - "Slot": "RightHand", + "Slot": "LeftHand, RightHand", "HoldType": "Rifle", "WeaponDefinition": { - "Position": "0,0,0", - "Rotation": "0,0,0,0", - "Scale": "0,0,0" + "Position": "2.6,-0.4078665,-4.897", + "Rotation": "-0.01896472,-0.05759383,0.002379653,0.9981571", + "Scale": "1,1,1" }, "Damage": 20, "FireRate": 14, "Range": 1000, "MagazineSize": 40, "AmmoType": "Rifle", - "ReloadTime": 2, - "Spread": 0.02, + "ReloadTime": 1.8, + "Spread": 0.01, "IsAutomatic": true, "Category": "Weapon", "Name": "Rifle", diff --git a/Assets/prefabs/Player.prefab b/Assets/prefabs/Player.prefab index 578d4ad..0a00287 100644 --- a/Assets/prefabs/Player.prefab +++ b/Assets/prefabs/Player.prefab @@ -1999,8 +1999,8 @@ "__version": 1, "Flags": 8, "Name": "aim_matrix_01", - "Position": "5.864844,0.005568608,11.81102", - "Rotation": "-0.0001240181,-0.01503032,-0.008244861,0.999853", + "Position": "5.870217,0.005632026,11.81102", + "Rotation": "-0.0001436457,-0.01695743,-0.008462192,0.9998204", "Scale": "1,1,1", "Tags": "", "Enabled": true, @@ -2016,7 +2016,7 @@ "__version": 1, "Flags": 8, "Name": "aim_matrix_02a", - "Position": "5.864844,0.005568608,9.842515", + "Position": "5.870218,0.005633741,9.842515", "Rotation": "-0.00000000000000000000001185265,0.0000000000000001455021,-0.0000003871369,1", "Scale": "1,1,1", "Tags": "", @@ -2033,7 +2033,7 @@ "__version": 1, "Flags": 8, "Name": "aim_matrix_02b", - "Position": "9.801846,0.005565077,9.842513", + "Position": "9.80722,0.005630211,9.842513", "Rotation": "-0.00000000000000000000001185278,0.0000000000000001455018,-0.0000003871369,1", "Scale": "1,1,1", "Tags": "", @@ -2050,9 +2050,9 @@ "__version": 1, "Flags": 8, "Name": "ankle_R", - "Position": "0.4100087,-4.377703,3.807678", - "Rotation": "0.6728455,0.2185408,-0.3316475,0.6241224", - "Scale": "1.000001,1.000001,1.000001", + "Position": "0.410028,-4.377077,3.807501", + "Rotation": "0.672856,0.2185198,-0.3316688,0.6241072", + "Scale": "1.000002,1.000002,1.000002", "Tags": "", "Enabled": true, "NetworkMode": 2, @@ -2067,9 +2067,9 @@ "__version": 1, "Flags": 8, "Name": "ankle_L", - "Position": "0.4083801,4.427946,3.805992", - "Rotation": "0.6245957,0.3320946,-0.2183304,0.6722538", - "Scale": "1,1,1", + "Position": "0.4083693,4.427526,3.805846", + "Rotation": "0.6245864,0.3321082,-0.2183172,0.6722601", + "Scale": "1.000002,1.000002,1.000002", "Tags": "", "Enabled": true, "NetworkMode": 2, @@ -2084,9 +2084,9 @@ "__version": 1, "Flags": 8, "Name": "arm_lower_R", - "Position": "-1.944306,-9.198144,41.10852", - "Rotation": "0.4837707,0.4009385,-0.5580629,0.542015", - "Scale": "1.000004,1.000004,1.000004", + "Position": "-2.194259,-8.597884,41.03161", + "Rotation": "0.4999644,0.3842734,-0.5448902,0.5526884", + "Scale": "1.000002,1.000002,1.000002", "Tags": "", "Enabled": true, "NetworkMode": 2, @@ -2101,8 +2101,8 @@ "__version": 1, "Flags": 8, "Name": "arm_lower_L", - "Position": "-1.786701,8.974261,41.26266", - "Rotation": "0.5538174,0.5558982,-0.3962672,0.4766927", + "Position": "-1.81736,9.811557,41.48081", + "Rotation": "0.5791489,0.5418196,-0.3768404,0.4785494", "Scale": "1.000003,1.000003,1.000003", "Tags": "", "Enabled": true, @@ -2118,9 +2118,9 @@ "__version": 1, "Flags": 8, "Name": "hand_R", - "Position": "-1.515604,-10.87078,33.59772", - "Rotation": "0.4529333,0.3786638,-0.6138031,0.5241288", - "Scale": "1.000005,1.000005,1.000005", + "Position": "-1.339935,-10.27848,33.559", + "Rotation": "0.4707156,0.3625441,-0.6014581,0.5340759", + "Scale": "1.000003,1.000003,1.000003", "Tags": "", "Enabled": true, "NetworkMode": 2, @@ -2135,8 +2135,8 @@ "__version": 1, "Flags": 8, "Name": "hand_L", - "Position": "-1.263442,10.80791,33.7956", - "Rotation": "0.5359527,0.6116646,-0.3731866,0.4464895", + "Position": "-0.8243989,11.86851,34.12033", + "Rotation": "0.5608078,0.5982507,-0.3530176,0.4505211", "Scale": "1.000004,1.000004,1.000004", "Tags": "", "Enabled": true, @@ -2152,9 +2152,9 @@ "__version": 1, "Flags": 8, "Name": "hold_R", - "Position": "-0.5782236,-9.393594,27.46674", - "Rotation": "0.3187549,0.7460795,0.05836753,0.581682", - "Scale": "1.000006,1.000006,1.000006", + "Position": "-0.04774434,-8.809499,27.49088", + "Rotation": "0.3177992,0.7286226,0.06634814,0.6030844", + "Scale": "1.000003,1.000003,1.000003", "Tags": "", "Enabled": true, "NetworkMode": 2, @@ -2169,8 +2169,8 @@ "__version": 1, "Flags": 8, "Name": "hold_L", - "Position": "-0.2961033,9.453352,27.64081", - "Rotation": "-0.305681,0.7467785,-0.05618108,0.5879837", + "Position": "0.4636755,10.68709,27.98863", + "Rotation": "-0.2854522,0.7340876,-0.05970929,0.6132432", "Scale": "1.000004,1.000004,1.000004", "Tags": "", "Enabled": true, @@ -2186,8 +2186,8 @@ "__version": 1, "Flags": 8, "Name": "IK_right_hand", - "Position": "-1.684358,-11.3081,33.23968", - "Rotation": "0.4603033,0.3490922,-0.6097354,0.5426587", + "Position": "-1.69492,-11.30738,33.23634", + "Rotation": "0.4603694,0.3490216,-0.6097843,0.5425929", "Scale": "1,1,1", "Tags": "", "Enabled": true, @@ -2203,8 +2203,8 @@ "__version": 1, "Flags": 8, "Name": "IK_left_hand", - "Position": "-1.501041,11.36666,33.23686", - "Rotation": "0.5482481,0.6048241,-0.3533375,0.4569075", + "Position": "-1.506716,11.36749,33.23344", + "Rotation": "0.5483295,0.6047426,-0.3533798,0.4568848", "Scale": "1,1,1", "Tags": "", "Enabled": true, @@ -2220,8 +2220,8 @@ "__version": 1, "Flags": 8, "Name": "leg_lower_R", - "Position": "3.235427,-4.608579,15.99795", - "Rotation": "0.4655335,0.530396,-0.5758093,0.4127981", + "Position": "2.184814,-4.448565,16.19641", + "Rotation": "0.4909281,0.5035037,-0.5633716,0.4336888", "Scale": "1.000001,1.000001,1.000001", "Tags": "", "Enabled": true, @@ -2237,9 +2237,9 @@ "__version": 1, "Flags": 8, "Name": "leg_lower_L", - "Position": "2.338159,4.713587,16.16856", - "Rotation": "0.4252933,0.5630658,-0.5099532,0.4919657", - "Scale": "1.000001,1.000001,1.000001", + "Position": "3.076369,4.83484,16.02696", + "Rotation": "0.4118131,0.5700959,-0.5306391,0.4730991", + "Scale": "1.000002,1.000002,1.000002", "Tags": "", "Enabled": true, "NetworkMode": 2, @@ -2254,9 +2254,9 @@ "__version": 1, "Flags": 8, "Name": "middle_of_both_hands", - "Position": "-1.561194,0.02484846,28.83653", - "Rotation": "0.007330432,0.7686383,0.001971816,0.6396385", - "Scale": "1.000004,1.000004,1.000004", + "Position": "-0.9578716,0.9275346,29.00694", + "Rotation": "0.0188594,0.7564194,0.003402324,0.6538061", + "Scale": "1.000003,1.000003,1.000003", "Tags": "", "Enabled": true, "NetworkMode": 2, @@ -2271,9 +2271,9 @@ "__version": 1, "Flags": 8, "Name": "driver_arm_upper_R_twist1", - "Position": "-0.9131499,-8.264956,45.93478", + "Position": "-1.254098,-7.691903,45.88158", "Rotation": "0,0,0,1", - "Scale": "1.000004,1.000004,1.000004", + "Scale": "1.000002,1.000002,1.000002", "Tags": "", "Enabled": true, "NetworkMode": 2, @@ -2288,9 +2288,9 @@ "__version": 1, "Flags": 8, "Name": "driver_arm_lower_R_twist1", - "Position": "-1.729955,-10.03446,37.35312", + "Position": "-1.767097,-9.438183,37.29531", "Rotation": "0,0,0,1", - "Scale": "1.000004,1.000004,1.000004", + "Scale": "1.000003,1.000003,1.000003", "Tags": "", "Enabled": true, "NetworkMode": 2, @@ -2305,9 +2305,9 @@ "__version": 1, "Flags": 8, "Name": "driver_elbow_R_position", - "Position": "-1.904696,-9.206528,41.10199", - "Rotation": "-0.007202899,-0.6295701,0.7761958,0.03331204", - "Scale": "1.000005,1.000005,1.000005", + "Position": "-2.190993,-8.60187,41.02747", + "Rotation": "-0.02503278,-0.6311682,0.7749069,0.02278909", + "Scale": "1.000003,1.000003,1.000003", "Tags": "", "Enabled": true, "NetworkMode": 2, @@ -2322,9 +2322,9 @@ "__version": 1, "Flags": 8, "Name": "driver_elbow_L_position", - "Position": "-1.746899,8.982116,41.25662", - "Rotation": "-0.06745388,0.780771,-0.6183518,0.05905678", - "Scale": "1.000004,1.000004,1.000004", + "Position": "-1.813897,9.815627,41.47688", + "Rotation": "-0.04689195,0.7901233,-0.6070659,0.07055109", + "Scale": "1.000003,1.000003,1.000003", "Tags": "", "Enabled": true, "NetworkMode": 2, @@ -2339,9 +2339,9 @@ "__version": 1, "Flags": 8, "Name": "driver_arm_upper_L_twist1", - "Position": "-0.8141831,7.915582,46.07516", + "Position": "-0.9609264,8.598832,46.279", "Rotation": "0,0,0,1", - "Scale": "1.000003,1.000003,1.000003", + "Scale": "1.000002,1.000002,1.000002", "Tags": "", "Enabled": true, "NetworkMode": 2, @@ -2356,9 +2356,9 @@ "__version": 1, "Flags": 8, "Name": "driver_arm_lower_L_twist1", - "Position": "-1.525071,9.891087,37.52913", + "Position": "-1.320879,10.84003,37.80057", "Rotation": "0,0,0,1", - "Scale": "1.000004,1.000004,1.000004", + "Scale": "1.000003,1.000003,1.000003", "Tags": "", "Enabled": true, "NetworkMode": 2, @@ -2373,7 +2373,7 @@ "__version": 1, "Flags": 8, "Name": "driver_leg_upper_R_twist1", - "Position": "1.935349,-4.430572,23.11317", + "Position": "1.417546,-4.285876,23.38899", "Rotation": "0,0,0,1", "Scale": "1.000001,1.000001,1.000001", "Tags": "", @@ -2390,7 +2390,7 @@ "__version": 1, "Flags": 8, "Name": "driver_leg_upper_L_twist1", - "Position": "1.490429,4.655171,23.35368", + "Position": "1.893557,4.78091,23.1646", "Rotation": "0,0,0,1", "Scale": "1.000001,1.000001,1.000001", "Tags": "", @@ -2407,8 +2407,8 @@ "__version": 1, "Flags": 8, "Name": "driver_kneecap_R_position", - "Position": "3.838389,-4.672735,15.96004", - "Rotation": "0.5150546,0.4793396,-0.5310991,0.4721081", + "Position": "2.55332,-4.490733,16.16589", + "Rotation": "0.5185107,0.4741844,-0.5331934,0.4711695", "Scale": "1.000001,1.000001,1.000001", "Tags": "", "Enabled": true, @@ -2424,8 +2424,8 @@ "__version": 1, "Flags": 8, "Name": "driver_kneecap_L_position", - "Position": "2.741635,4.759412,16.13647", - "Rotation": "0.7031127,0.0449258,0.03150867,0.7089581", + "Position": "3.636433,4.894081,15.98802", + "Rotation": "0.7003412,0.04433943,0.02620117,0.7119479", "Scale": "1.000001,1.000001,1.000001", "Tags": "", "Enabled": true, @@ -2441,7 +2441,7 @@ "__version": 1, "Flags": 8, "Name": "driver_leg_lower_R_twist1", - "Position": "1.822711,-4.493139,9.902801", + "Position": "1.297414,-4.412823,10.00197", "Rotation": "0,0,0,1", "Scale": "1.000002,1.000002,1.000002", "Tags": "", @@ -2458,9 +2458,9 @@ "__version": 1, "Flags": 8, "Name": "driver_leg_lower_L_twist1", - "Position": "1.373267,4.570763,9.987267", + "Position": "1.742369,4.631183,9.916401", "Rotation": "0,0,0,1", - "Scale": "1.000001,1.000001,1.000001", + "Scale": "1.000002,1.000002,1.000002", "Tags": "", "Enabled": true, "NetworkMode": 2, @@ -2475,7 +2475,7 @@ "__version": 1, "Flags": 8, "Name": "forward_reference_modelspace", - "Position": "0.07471489,-0.05039266,43.35883", + "Position": "-0.1452158,0.252435,43.40723", "Rotation": "0,0,0,1", "Scale": "1.000001,1.000001,1.000001", "Tags": "", @@ -2492,9 +2492,9 @@ "__version": 1, "Flags": 8, "Name": "eyes", - "Position": "6.744137,-0.4365017,63.04519", - "Rotation": "0.003984303,-0.002858207,-0.008915529,0.9999482", - "Scale": "1.000003,1.000003,1.000003", + "Position": "6.100418,-0.1673432,63.23436", + "Rotation": "0.01170801,-0.0143232,-0.01524511,0.9997126", + "Scale": "1.000002,1.000002,1.000002", "Tags": "", "Enabled": true, "NetworkMode": 2, @@ -2509,9 +2509,9 @@ "__version": 1, "Flags": 8, "Name": "eye_R_forward", - "Position": "6.684545,-3.782319,63.01836", - "Rotation": "0.003984303,-0.002858207,-0.008915529,0.9999482", - "Scale": "1.000003,1.000003,1.000003", + "Position": "5.999535,-3.511322,63.15456", + "Rotation": "0.01170801,-0.0143232,-0.01524511,0.9997126", + "Scale": "1.000002,1.000002,1.000002", "Tags": "", "Enabled": true, "NetworkMode": 2, @@ -2526,9 +2526,9 @@ "__version": 1, "Flags": 8, "Name": "eye_L_forward", - "Position": "6.803728,2.909316,63.07203", - "Rotation": "0.003984303,-0.002858207,-0.008915529,0.9999482", - "Scale": "1.000003,1.000003,1.000003", + "Position": "6.201299,3.176636,63.31416", + "Rotation": "0.01170801,-0.0143232,-0.01524511,0.9997126", + "Scale": "1.000002,1.000002,1.000002", "Tags": "", "Enabled": true, "NetworkMode": 2, @@ -2543,9 +2543,9 @@ "__version": 1, "Flags": 8, "Name": "forward_reference", - "Position": "1.469969,-0.2870641,56.12576", - "Rotation": "0.003984303,-0.002858207,-0.008915529,0.9999482", - "Scale": "1.000003,1.000003,1.000003", + "Position": "0.989872,0.1547238,56.19901", + "Rotation": "0.01170801,-0.0143232,-0.01524511,0.9997126", + "Scale": "1.000002,1.000002,1.000002", "Tags": "", "Enabled": true, "NetworkMode": 2, @@ -2560,9 +2560,9 @@ "__version": 1, "Flags": 8, "Name": "foot_R", - "Position": "1.98215,-4.910992,0.1894621", - "Rotation": "0.0004820525,-0.00001450255,-0.08708134,0.9962011", - "Scale": "1.000003,1.000003,1.000003", + "Position": "1.982141,-4.910424,0.1893171", + "Rotation": "0.0004869699,-0.00001408905,-0.08711599,0.9961981", + "Scale": "1.000002,1.000002,1.000002", "Tags": "", "Enabled": true, "NetworkMode": 2, @@ -2577,9 +2577,9 @@ "__version": 1, "Flags": 8, "Name": "foot_L", - "Position": "1.978714,4.967169,1.053503", - "Rotation": "-0.08721654,0.9961893,0.0004095733,0.00001492791", - "Scale": "1.000001,1.000001,1.000001", + "Position": "1.978678,4.966802,1.053338", + "Rotation": "-0.08723825,0.9961874,0.0004065633,0.00001362779", + "Scale": "1.000002,1.000002,1.000002", "Tags": "", "Enabled": true, "NetworkMode": 2, @@ -2594,9 +2594,9 @@ "__version": 1, "Flags": 8, "Name": "hat", - "Position": "1.677502,-0.4118944,71.28418", - "Rotation": "0.003984303,-0.002858207,-0.008915529,0.9999482", - "Scale": "1.000003,1.000003,1.000003", + "Position": "0.8454286,-0.2021334,71.35446", + "Rotation": "0.01170801,-0.0143232,-0.01524511,0.9997126", + "Scale": "1.000002,1.000002,1.000002", "Tags": "", "Enabled": true, "NetworkMode": 2, @@ -2611,8 +2611,8 @@ "__version": 1, "Flags": 0, "Name": "Pivot", - "Position": "0.8795685,-15.7399,52.21443", - "Rotation": "0,0,0,1", + "Position": "1.812938,-15.65946,51.27624", + "Rotation": "0.003578067,0.06026466,-0.01210088,0.9981027", "Scale": "1,1,1", "Tags": "", "Enabled": true, diff --git a/Code/Inventory/Inventar.cs b/Code/Inventory/Inventar.cs index f58f3e2..2fe8d68 100644 --- a/Code/Inventory/Inventar.cs +++ b/Code/Inventory/Inventar.cs @@ -91,7 +91,7 @@ public class Inventar : Component while ( toAdd > 0 && (UnlimitedSlots || Items.Count < MaxInventorySlots) ) { int stackCount = Math.Min( toAdd, item.Definition.MaxCount ); - var newStack = new InventoryItem { Definition = item.Definition, Count = stackCount }; + var newStack = new InventoryItem { Definition = item.Definition, Count = stackCount, MagazineAmmo = item.MagazineAmmo }; Items.Add( newStack ); toAdd -= stackCount; OnChanged?.Invoke(); @@ -161,19 +161,14 @@ public class Inventar : Component if ( item == null || !Items.Contains( item ) ) return; - // // Создаем копию предмета для выбрасывания - // var droppedItem = new InventoryItem - // { - // Definition = item.Definition, - // Count = item.Count // Выбрасываем всю стопку - // }; - GameObject gO = item.Definition.Prefab.Clone( position ); if ( gO.Components.TryGet( out var inventoryItem ) ) { inventoryItem.Count = item.Count; inventoryItem.Definition = item.Definition; + // Копируем патроны из оригинального предмета + inventoryItem.MagazineAmmo = item.MagazineAmmo; } gO.NetworkSpawn(); diff --git a/Code/Inventory/InventoryItem.cs b/Code/Inventory/InventoryItem.cs index a0813fa..5ae917a 100644 --- a/Code/Inventory/InventoryItem.cs +++ b/Code/Inventory/InventoryItem.cs @@ -8,6 +8,9 @@ public class InventoryItem : Component [Property] public BaseItemDefinition Definition { get; set; } [Sync, Property] public int Count { get; set; } = 1; [Sync] public bool Equipped { get; set; } = false; + + // Сохранение патронов в магазине для оружия + [Sync] public int MagazineAmmo { get; set; } = 0; protected override void OnStart() { @@ -64,7 +67,7 @@ public class InventoryItem : Component public InventoryItem Clone() { - var clone = new InventoryItem { Definition = Definition, Count = Count, Equipped = false }; + var clone = new InventoryItem { Definition = Definition, Count = Count, Equipped = false, MagazineAmmo = MagazineAmmo }; return clone; } diff --git a/Code/Player/Dedugan.Inventory.cs b/Code/Player/Dedugan.Inventory.cs index a5c159f..765b9ed 100644 --- a/Code/Player/Dedugan.Inventory.cs +++ b/Code/Player/Dedugan.Inventory.cs @@ -61,6 +61,8 @@ public sealed partial class Dedugan : Component // Получаем компонент оружия и вызываем экипировку if ( go.Components.TryGet( out var weapon ) ) { + // Передаем ссылку на InventoryItem в оружие + weapon.SetInventoryItem( item ); weapon.OnEquipped(); _useableCache[weaponDef.Slot] = (go, weapon); } @@ -212,6 +214,16 @@ public sealed partial class Dedugan : Component if ( weapon != null && !weapon.IsReloading ) { weapon.StartReload(); + + // Анимация перезарядки персонажа (скорость уже установлена в weapon.StartReload()) + // Дополнительно устанавливаем здесь на случай, если weapon.StartReload() не вызвался + var weaponDef = weapon.GetWeaponDefinition(); + if ( weaponDef != null ) + { + float reloadSpeed = weaponDef.ReloadTime > 0 ? 1f / weaponDef.ReloadTime : 1f; + Renderer.Set( "b_reload", true ); + Renderer.Set( "speed_reload", reloadSpeed ); + } } } diff --git a/Code/Player/Dedugan.cs b/Code/Player/Dedugan.cs index 1be7a6f..7a98468 100644 --- a/Code/Player/Dedugan.cs +++ b/Code/Player/Dedugan.cs @@ -73,15 +73,7 @@ public sealed partial class Dedugan : Component, IUseContext, Component.INetwork EyeAngles = EyeAngles.WithPitch( MathX.Clamp( EyeAngles.pitch, -89f, 89f ) ); NetworkedEyeAngles = EyeAngles; - var targetRotation = Rotation.LookAt( Rotation.FromYaw( EyeAngles.yaw ).Forward, -_directionToAxis ); - var currentForward = Renderer.LocalRotation.Forward; - float angleDiff = currentForward.Angle( targetRotation.Forward ); - - if ( angleDiff > 15f && Controller.Velocity.Length > 10f ) - { - Renderer.LocalRotation = Rotation.Slerp( Renderer.LocalRotation, Rotation.FromYaw( EyeAngles.yaw ), - Time.Delta * 3f ); - } + UpdateBodyRotation(); RotateCamera(); InteractionsUpdate(); @@ -90,15 +82,7 @@ public sealed partial class Dedugan : Component, IUseContext, Component.INetwork { EyeAngles = NetworkedEyeAngles; - var targetRotation = Rotation.LookAt( Rotation.FromYaw( EyeAngles.yaw ).Forward, -_directionToAxis ); - var currentForward = Renderer.LocalRotation.Forward; - float angleDiff = currentForward.Angle( targetRotation.Forward ); - - if ( angleDiff > 15f && Controller.Velocity.Length > 10f ) - { - Renderer.LocalRotation = Rotation.Slerp( Renderer.LocalRotation, Rotation.FromYaw( EyeAngles.yaw ), - Time.Delta * 3f ); - } + UpdateBodyRotation(); // Renderer.LocalRotation = Rotation.Slerp(Renderer.LocalRotation, Rotation.FromYaw(EyeAngles.yaw), Time.Delta * 5f); @@ -133,4 +117,40 @@ public sealed partial class Dedugan : Component, IUseContext, Component.INetwork // Возвращаем пустой список, так как теперь оружие управляется через новую систему return Enumerable.Empty(); } + + /// + /// Обновление поворота тела с учетом режима прицеливания + /// + private void UpdateBodyRotation() + { + var targetRotation = Rotation.LookAt( Rotation.FromYaw( EyeAngles.yaw ).Forward, -_directionToAxis ); + var currentForward = Renderer.LocalRotation.Forward; + float angleDiff = currentForward.Angle( targetRotation.Forward ); + + // Проверяем, нужно ли поворачивать тело + bool shouldRotateBody = false; + + if ( InAds ) + { + // В режиме прицеливания - мертвая зона 85 градусов + if ( angleDiff > 85f ) + { + shouldRotateBody = true; + } + } + else + { + // В обычном режиме - поворот при движении и угле больше 15 градусов + if ( angleDiff > 15f && Controller.Velocity.Length > 10f ) + { + shouldRotateBody = true; + } + } + + if ( shouldRotateBody ) + { + Renderer.LocalRotation = Rotation.Slerp( Renderer.LocalRotation, Rotation.FromYaw( EyeAngles.yaw ), + Time.Delta * 3f ); + } + } } diff --git a/Code/Weapons/BaseWeapon.cs b/Code/Weapons/BaseWeapon.cs index c2664ee..9d9c3ee 100644 --- a/Code/Weapons/BaseWeapon.cs +++ b/Code/Weapons/BaseWeapon.cs @@ -22,7 +22,6 @@ public class BaseWeapon : InventoryItem, IUseable [Property] public GameObject EjectTransform { get; set; } // Состояние оружия - [Sync] public int CurrentAmmo { get; set; } [Sync] public bool IsReloading { get; set; } [Sync] public TimeSince TimeSinceLastShot { get; set; } [Sync] public TimeSince TimeSinceReloadStart { get; set; } @@ -35,6 +34,7 @@ public class BaseWeapon : InventoryItem, IUseable // Кэш для производительности private WeaponItemDefinition _weaponDefinition; private bool _isInitialized; + private InventoryItem _inventoryItem; // IUseable реализация - Cooldown вычисляется на основе FireRate public float Cooldown @@ -46,6 +46,32 @@ public class BaseWeapon : InventoryItem, IUseable } } + /// + /// Установить ссылку на InventoryItem + /// + public void SetInventoryItem( InventoryItem item ) + { + _inventoryItem = item; + + // Инициализируем оружие после установки InventoryItem + InitializeWeapon(); + } + + /// + /// Получить количество патронов в магазине из InventoryItem + /// + public int CurrentAmmo + { + get => _inventoryItem?.MagazineAmmo ?? 0; + set + { + if ( _inventoryItem != null ) + { + _inventoryItem.MagazineAmmo = value; + } + } + } + protected override void OnStart() { base.OnStart(); @@ -54,8 +80,7 @@ public class BaseWeapon : InventoryItem, IUseable _sound = GameObject.GetComponent( true ); _pickupItem = GameObject.Components.Get(); - // Инициализируем оружие - InitializeWeapon(); + // Инициализация оружия будет вызвана после установки InventoryItem } protected override void OnUpdate() @@ -88,8 +113,7 @@ public class BaseWeapon : InventoryItem, IUseable return; } - // Оружие начинается с пустым магазином - патроны нужно зарядить - CurrentAmmo = 0; + // Инициализация завершена _isInitialized = true; } @@ -308,6 +332,24 @@ public class BaseWeapon : InventoryItem, IUseable IsReloading = true; TimeSinceReloadStart = 0; + var weaponDef = GetWeaponDefinition(); + float reloadSpeed = weaponDef?.ReloadTime > 0 ? 1f / weaponDef.ReloadTime : 1f; + + // Анимация перезарядки оружия + if ( GunRenderer != null ) + { + GunRenderer.Set( "b_reload", true ); + GunRenderer.Set( "speed_reload", reloadSpeed ); + } + + // Анимация перезарядки персонажа + var player = Dedugan.Local; + if ( player?.Renderer != null ) + { + player.Renderer.Set( "b_reload", true ); + player.Renderer.Set( "speed_reload", reloadSpeed ); + } + // Эффекты перезарядки PlayReloadEffects(); } @@ -319,6 +361,21 @@ public class BaseWeapon : InventoryItem, IUseable { IsReloading = false; + // Сбрасываем анимацию перезарядки оружия + if ( GunRenderer != null ) + { + GunRenderer.Set( "b_reload", false ); + GunRenderer.Set( "speed_reload", 1f ); + } + + // Сбрасываем анимацию перезарядки персонажа + var player = Dedugan.Local; + if ( player?.Renderer != null ) + { + player.Renderer.Set( "b_reload", false ); + player.Renderer.Set( "speed_reload", 1f ); + } + var weaponDef = GetWeaponDefinition(); if ( weaponDef == null ) return; diff --git a/Code/Weapons/README.md b/Code/Weapons/README.md index 7297c38..56c5337 100644 --- a/Code/Weapons/README.md +++ b/Code/Weapons/README.md @@ -45,12 +45,16 @@ ### 3. Система патронов - **Оружие начинается с пустым магазином** - патроны нужно зарядить - **Сохранение патронов в магазине** - при выбрасывании оружия патроны остаются +- **Патроны сохраняются при снятии/экипировке** - патроны в магазине не теряются при переключении оружия - Патроны хранятся в инвентаре как отдельные предметы - **Стрельба зависит ТОЛЬКО от патронов в магазине** - CurrentAmmo - **HUD показывает патроны в магазине** - не зависит от инвентаря - **Патроны тратятся только из магазина при выстреле** - CurrentAmmo уменьшается - **Патроны тратятся из инвентаря только при перезарядке** - загружаются в магазин - **Перезарядка только вручную** - кнопка R или автоматически при пустом магазине +- **Анимация перезарядки оружия** - `b_reload` параметр анимации оружия +- **Анимация перезарядки персонажа** - `b_reload` параметр анимации персонажа +- **Скорость анимации перезарядки** - `speed_reload` параметр для контроля скорости анимации (рассчитывается как 1/ReloadTime) - **Безопасная обработка неполных магазинов** - загружается столько патронов, сколько есть в инвентаре ### 4. HUD и UI @@ -136,130 +140,4 @@ player.Inventory.AddItem(flashlightItem); ### 3. Создание собственного предмета -```csharp -// Создайте новый класс -public sealed class Medkit : Component, IUseable -{ - [Property] public float Cooldown { get; set; } = 5f; - [Property] public int HealAmount { get; set; } = 50; - - private TimeSince _lastUseTime; - - public bool CanUse() - { - return IsValid && _lastUseTime >= Cooldown; - } - - public void Use() - { - if (!CanUse()) return; - - _lastUseTime = 0; - - // Логика лечения - var player = Dedugan.Local; - if (player != null) - { - player.Health = Math.Min(player.Health + HealAmount, 100); - Log.Info($"Игрок вылечен на {HealAmount} HP"); - } - } -} -``` - -## WeaponFactory - подробное руководство - -### Основные методы: - -#### 1. `CreateUseableItem(BaseItemDefinition, InventoryItem)` -Создает любой используемый предмет: -```csharp -var itemDef = ResourceLibrary.Get("path/to/item"); -var item = WeaponFactory.CreateUseableItem(itemDef, inventoryItem); -``` - -#### 2. `CreateWeapon(WeaponItemDefinition, InventoryItem)` -Создает оружие (для обратной совместимости): -```csharp -var weaponDef = ResourceLibrary.Get("path/to/weapon"); -var weapon = WeaponFactory.CreateWeapon(weaponDef, inventoryItem); -``` - -#### 3. `CreateItem(BaseItemDefinition)` -Создает предмет для инвентаря: -```csharp -var itemDef = ResourceLibrary.Get("path/to/item"); -var inventoryItem = WeaponFactory.CreateItem(itemDef); -``` - -### Автоматическое определение типа - -WeaponFactory автоматически определяет тип предмета по имени: - -- **Оружие**: содержит "pistol", "rifle", "gun" → создается `BaseWeapon` -- **Фонарик**: содержит "flashlight", "light" → создается `Flashlight` -- **По умолчанию**: создается `BaseWeapon` - -### Примеры использования - -#### Создание пистолета: -```csharp -// 1. Создаем предмет для инвентаря -var pistolDef = ResourceLibrary.Get("Items/pistol.weapon"); -var pistolItem = WeaponFactory.CreateWeaponItem(pistolDef); - -// 2. Добавляем в инвентарь -player.Inventory.AddItem(pistolItem); - -// 3. Экипируем -player.Inventory.EquipItem(pistolItem); -``` - -#### Создание фонарика: -```csharp -// 1. Создаем предмет -var flashlightDef = ResourceLibrary.Get("Items/flashlight.item"); -var flashlightItem = WeaponFactory.CreateItem(flashlightDef); - -// 2. Добавляем в инвентарь -player.Inventory.AddItem(flashlightItem); -``` - -#### Создание аптечки: -```csharp -// 1. Создаем предмет -var medkitDef = ResourceLibrary.Get("Items/medkit.item"); -var medkitItem = WeaponFactory.CreateItem(medkitDef); - -// 2. Добавляем в инвентарь -player.Inventory.AddItem(medkitItem); -``` - -## Настройка в префабах - -### Для оружия: -1. Добавьте компонент `BaseWeapon` -2. Настройте все необходимые ссылки (рендерер, звуки, эффекты) -3. Установите параметры стрельбы (Cooldown, FireRate и т.д.) - -### Для других предметов: -1. Добавьте компонент, реализующий `IUseable` -2. Настройте специфичные параметры -3. Реализуйте логику в методах `CanUse()` и `Use()` - -## Преимущества системы - -1. **Универсальность** - один интерфейс для всех предметов -2. **Гибкость** - каждый предмет может иметь свою логику -3. **Простота** - настройка в префабах, без создания отдельных файлов -4. **Расширяемость** - легко добавлять новые типы предметов -5. **Производительность** - кэширование и оптимизация -6. **Читаемость** - понятная структура и документация - -## Примеры предметов - -- **Оружие** - стрельба, перезарядка, патроны -- **Фонарик** - включение/выключение света -- **Аптечка** - лечение игрока -- **Инструменты** - ремонт, строительство -- **Еда** - восстановление здоровья/голода \ No newline at end of file +``` \ No newline at end of file