@@ -7,52 +7,28 @@ namespace ScavShrapnelMod
77 /// <summary>
88 /// Осколки от пуль при попадании в металлический блок.
99 ///
10+ /// Все числовые параметры читаются из <see cref="ShrapnelConfig"/> (секция Bullets).
11+ ///
1012 /// Механика:
1113 /// 1. Пуля попадает в блок (TurretScript.Shoot → Postfix)
12- /// 2. Делаем raycast по направлению выстрела
14+ /// 2. Raycast по направлению выстрела
1315 /// 3. Если попали в металлический блок → 1-3 мелких осколка
1416 /// 4. Осколки летят от точки попадания + рандомный разброс
1517 ///
1618 /// Ограничения производительности:
17- /// - Макс 1 спавн за MinFramesBetweenSpawns кадров
18- /// - Макс 3 осколка за спавн
19+ /// - Throttle по кадрам (конфигурируемый)
20+ /// - Макс осколков за спавн (конфигурируемый)
1921 /// - Только metallic блоки
20- /// - Raycast макс RaycastDistance единиц
22+ /// - Raycast макс 200 единиц
2123 /// </summary>
2224 public static class BulletShrapnelLogic
2325 {
24- // Константы
25-
2626 /// <summary>Дистанция raycast. Совпадает с TurretScript.Shoot (200f).</summary>
2727 private const float RaycastDistance = 200f ;
2828
2929 /// <summary>Имя слоя Ground в Unity.</summary>
3030 private const string GroundLayerName = "Ground" ;
3131
32- /// <summary>Минимальный интервал между спавнами (кадры).</summary>
33- private const int MinFramesBetweenSpawns = 3 ;
34-
35- /// <summary>Базовая скорость осколков от пуль (м/с).</summary>
36- private const float BaseSpeed = 25 ;
37-
38- /// <summary>Количество осколков: min inclusive.</summary>
39- private const int MinFragments = 1 ;
40-
41- /// <summary>Количество осколков: max exclusive.</summary>
42- private const int MaxFragmentsExclusive = 4 ;
43-
44- /// <summary>Искры: min inclusive.</summary>
45- private const int MinSparks = 4 ;
46-
47- /// <summary>Искры: max exclusive.</summary>
48- private const int MaxSparksExclusive = 8 ;
49-
50- /// <summary>Множитель масштаба (мельче чем от взрыва).</summary>
51- private const float ScaleMultiplier = 0.72f ;
52-
53- /// <summary>Множитель нагрева (менее горячие).</summary>
54- private const float HeatMultiplier = 0.5f ;
55-
5632 /// <summary>Шанс что осколок Hot vs Medium.</summary>
5733 private const float HotWeightChance = 0.6f ;
5834
@@ -72,23 +48,22 @@ private static int GroundMask
7248
7349 /// <summary>
7450 /// Точка входа. Вызывается из Postfix патча TurretScript.Shoot.
51+ /// Параметры читаются из конфига.
7552 /// </summary>
7653 public static void TrySpawnFromBullet ( FireInfo info )
7754 {
7855 try
7956 {
80- // Throttle
8157 int frame = Time . frameCount ;
82- if ( frame - _lastSpawnFrame < MinFramesBetweenSpawns ) return ;
58+ if ( frame - _lastSpawnFrame < ShrapnelConfig . BulletMinFramesBetweenSpawns . Value )
59+ return ;
8360
8461 Vector2 origin = info . pos ;
8562 Vector2 direction = info . dir ;
8663
87- // Raycast по Ground
8864 RaycastHit2D hit = Physics2D . Raycast ( origin , direction , RaycastDistance , GroundMask ) ;
8965 if ( ! hit . collider ) return ;
9066
91- // Проверка металлического блока
9267 Vector2 blockSamplePos = hit . point + direction * 0.1f ;
9368 Vector2Int blockPos ;
9469 try
@@ -105,18 +80,22 @@ public static void TrySpawnFromBullet(FireInfo info)
10580
10681 _lastSpawnFrame = frame ;
10782
108- // Детерминированный RNG
10983 int seed = unchecked (
11084 ( int ) ( hit . point . x * 10000f ) * 397 ^
11185 ( int ) ( hit . point . y * 10000f ) ^
11286 frame ) ;
11387 System . Random rng = new System . Random ( seed ) ;
11488
115- int fragmentCount = rng . Range ( MinFragments , MaxFragmentsExclusive ) ;
89+ int fragmentCount = rng . Range (
90+ ShrapnelConfig . BulletFragmentsMin . Value ,
91+ ShrapnelConfig . BulletFragmentsMax . Value ) ;
92+
93+ // Применяем глобальный множитель количества
94+ fragmentCount = Mathf . Max ( 1 ,
95+ Mathf . RoundToInt ( fragmentCount * ShrapnelConfig . SpawnCountMultiplier . Value ) ) ;
96+
11697 for ( int i = 0 ; i < fragmentCount ; i ++ )
117- {
11898 SpawnBulletFragment ( hit . point , hit . normal , rng , i ) ;
119- }
12099
121100 SpawnBulletSparks ( hit . point , hit . normal , rng ) ;
122101 }
@@ -128,13 +107,19 @@ public static void TrySpawnFromBullet(FireInfo info)
128107
129108 /// <summary>
130109 /// Спавнит один мелкий осколок от попадания пули.
110+ /// Регистрирует в <see cref="DebrisTracker"/>.
131111 /// </summary>
132112 private static void SpawnBulletFragment ( Vector2 hitPoint , Vector2 hitNormal ,
133113 System . Random rng , int index )
134114 {
135115 Material litMat = ShrapnelVisuals . LitMaterial ;
136116 if ( litMat == null ) return ;
137117
118+ float scaleMultiplier = ShrapnelConfig . BulletScaleMultiplier . Value ;
119+ float heatMultiplier = ShrapnelConfig . BulletHeatMultiplier . Value ;
120+ float baseSpeed = ShrapnelConfig . BulletBaseSpeed . Value ;
121+ float globalMaxSpeed = ShrapnelConfig . GlobalMaxSpeed . Value ;
122+
138123 ShrapnelWeight weight = rng . NextFloat ( ) < HotWeightChance
139124 ? ShrapnelWeight . Hot
140125 : ShrapnelWeight . Medium ;
@@ -149,15 +134,15 @@ private static void SpawnBulletFragment(Vector2 hitPoint, Vector2 hitNormal,
149134 obj . transform . position = hitPoint + rng . InsideUnitCircle ( ) * 0.1f ;
150135 obj . layer = 0 ;
151136
152- float scale = ShrapnelFactory . ScaleForWeight ( weight , rng ) * ScaleMultiplier ;
137+ float scale = ShrapnelFactory . ScaleForWeight ( weight , rng ) * scaleMultiplier ;
153138 obj . transform . localScale = Vector3 . one * scale ;
154139
155140 SpriteRenderer sr = obj . AddComponent < SpriteRenderer > ( ) ;
156141 sr . sprite = sprite ;
157142 sr . sortingOrder = 10 ;
158143 sr . sharedMaterial = litMat ;
159144
160- float heat = ShrapnelFactory . HeatForWeight ( weight ) * HeatMultiplier ;
145+ float heat = ShrapnelFactory . HeatForWeight ( weight ) * heatMultiplier ;
161146 sr . color = Color . Lerp (
162147 ShrapnelVisuals . GetColdColor ( ShrapnelProjectile . ShrapnelType . Metal ) ,
163148 ShrapnelVisuals . GetHotColor ( ) , heat ) ;
@@ -185,19 +170,24 @@ private static void SpawnBulletFragment(Vector2 hitPoint, Vector2 hitNormal,
185170 dir . Normalize ( ) ;
186171
187172 float speed = Mathf . Min (
188- BaseSpeed * rng . Range ( 0.5f , 1.5f ) ,
189- ShrapnelSpawnLogic . GlobalMaxSpeed ) ;
173+ baseSpeed * rng . Range ( 0.5f , 1.5f ) ,
174+ globalMaxSpeed ) ;
190175
191176 rb . AddForce ( dir * speed * rb . mass , ForceMode2D . Impulse ) ;
192177 rb . AddTorque ( rng . Range ( - 200f , 200f ) ) ;
178+
179+ DebrisTracker . Register ( obj ) ;
193180 }
194181
195182 /// <summary>
196183 /// Спавнит визуальные искры при попадании пули в металл.
184+ /// Количество берётся из конфига.
197185 /// </summary>
198186 private static void SpawnBulletSparks ( Vector2 hitPoint , Vector2 hitNormal , System . Random rng )
199187 {
200- int sparkCount = rng . Range ( MinSparks , MaxSparksExclusive ) ;
188+ int sparkCount = rng . Range (
189+ ShrapnelConfig . BulletSparksMin . Value ,
190+ ShrapnelConfig . BulletSparksMax . Value ) ;
201191
202192 for ( int i = 0 ; i < sparkCount ; i ++ )
203193 {
0 commit comments