Phase 1: 复合属性修饰器管线与伤害结算系统

This commit is contained in:
2026-09-24 22:37:22 +08:00
parent ba25ec1926
commit 02f4c67464
35 changed files with 334 additions and 141 deletions
Binary file not shown.
@@ -3,19 +3,19 @@
"weaponCapacity": 6,
"propMaxCount": -1,
"playerEntity": "Player",
"absorbSpeed": 15000,
"collectDistance": 350,
"defaultAbsorbRange": 3000,
"weaponRecycleRate": 300,
"absorbSpeed": 12,
"collectDistance": 0.5,
"defaultAbsorbRange": 4,
"weaponRecycleRate": 0.3,
"shopGoodsCount": 4,
"shopPriceRandomPercent": 50,
"shopPriceRandomPercent": 0.05,
"shopMinPrice": 1,
"levelUpRefreshPriceBase": 2,
"levelUpRewardCount": 4,
"spawnEnemyMaxCount": 5000,
"enemySpawnDistanceMin": 14000,
"enemySpawnDistanceMax": 18000,
"weaponRotateSpeed": 5000,
"enemySpawnDistanceMin": 14,
"enemySpawnDistanceMax": 18,
"weaponRotateSpeed": 5,
"weaponBaseCrit": 0.05,
"playerGroupName": "Player",
"enemyGroupName": "Enemy",
Binary file not shown.
+21 -21
View File
@@ -6,7 +6,7 @@
"price": 120,
"statModifierConfigs": [
{
"statType": 4,
"statType": 5,
"value": 10,
"modifierType": 100
},
@@ -35,7 +35,7 @@
"modifierType": 200
},
{
"statType": 4,
"statType": 5,
"value": 11,
"modifierType": 100
}
@@ -88,11 +88,11 @@
"statModifierConfigs": [
{
"statType": 14,
"value": 800,
"value": 0.8,
"modifierType": 100
},
{
"statType": 4,
"statType": 5,
"value": 10,
"modifierType": 100
}
@@ -107,11 +107,11 @@
"statModifierConfigs": [
{
"statType": 13,
"value": 10,
"value": 0.1,
"modifierType": 100
},
{
"statType": 4,
"statType": 5,
"value": 12,
"modifierType": 100
},
@@ -144,13 +144,13 @@
"price": 433,
"statModifierConfigs": [
{
"statType": 4,
"statType": 6,
"value": 44,
"modifierType": 100
},
{
"statType": 13,
"value": 27,
"value": 0.27,
"modifierType": 100
}
],
@@ -168,7 +168,7 @@
"modifierType": 100
},
{
"statType": 4,
"statType": 6,
"value": 7,
"modifierType": 100
},
@@ -201,7 +201,7 @@
"price": 341,
"statModifierConfigs": [
{
"statType": 4,
"statType": 6,
"value": 57,
"modifierType": 100
}
@@ -221,7 +221,7 @@
},
{
"statType": 9,
"value": 27,
"value": 0.27,
"modifierType": 100
}
],
@@ -235,12 +235,12 @@
"statModifierConfigs": [
{
"statType": 9,
"value": 5,
"value": 0.05,
"modifierType": 100
},
{
"statType": 13,
"value": 7,
"value": 0.07,
"modifierType": 100
}
],
@@ -254,7 +254,7 @@
"statModifierConfigs": [
{
"statType": 14,
"value": 600,
"value": 0.6,
"modifierType": 100
},
{
@@ -273,7 +273,7 @@
"statModifierConfigs": [
{
"statType": 14,
"value": 1600,
"value": 1.6,
"modifierType": 100
},
{
@@ -292,7 +292,7 @@
"statModifierConfigs": [
{
"statType": 13,
"value": 28,
"value": 0.28,
"modifierType": 100
},
{
@@ -301,7 +301,7 @@
"modifierType": 100
},
{
"statType": 4,
"statType": 5,
"value": 24,
"modifierType": 100
}
@@ -329,7 +329,7 @@
"price": 204,
"statModifierConfigs": [
{
"statType": 4,
"statType": 7,
"value": 17,
"modifierType": 100
},
@@ -353,13 +353,13 @@
"modifierType": 100
},
{
"statType": 4,
"statType": 7,
"value": 19,
"modifierType": 100
},
{
"statType": 13,
"value": 20,
"value": 0.2,
"modifierType": 100
}
],
@@ -377,7 +377,7 @@
"modifierType": 200
},
{
"statType": 4,
"statType": 7,
"value": 29,
"modifierType": 100
},
Binary file not shown.
+2 -2
View File
@@ -32,7 +32,7 @@
{
"statType": 4,
"name": "伤害",
"defaultBaseValue": 0,
"defaultBaseValue": 1,
"hasMin": true,
"minValue": -1,
"hasMax": false,
@@ -72,7 +72,7 @@
{
"statType": 8,
"name": "攻击速度",
"defaultBaseValue": 0,
"defaultBaseValue": 1,
"hasMin": true,
"minValue": -0.8,
"hasMax": false,
Binary file not shown.
+15 -15
View File
@@ -5,14 +5,14 @@
"rarity": 1,
"price": 120,
"attack": 100,
"cooldown": 1500,
"cooldown": 1.5,
"damageType": 1,
"attackRange": 5000,
"attackRange": 5,
"attackSoundId": 10000,
"parameters": [
[
1,
2000
2
]
],
"statModifierConfigs": [],
@@ -25,9 +25,9 @@
"rarity": 1,
"price": 130,
"attack": 120,
"cooldown": 1000,
"cooldown": 1,
"damageType": 2,
"attackRange": 15000,
"attackRange": 15,
"attackSoundId": 10000,
"parameters": [],
"statModifierConfigs": [],
@@ -40,9 +40,9 @@
"rarity": 1,
"price": 100,
"attack": 150,
"cooldown": 2000,
"cooldown": 2,
"damageType": 1,
"attackRange": 5000,
"attackRange": 5,
"attackSoundId": 10000,
"parameters": [
[
@@ -60,14 +60,14 @@
"rarity": 1,
"price": 150,
"attack": 80,
"cooldown": 3000,
"cooldown": 3,
"damageType": 4,
"attackRange": 12000,
"attackRange": 12,
"attackSoundId": 10000,
"parameters": [
[
1,
3000
3
]
],
"statModifierConfigs": [],
@@ -80,22 +80,22 @@
"rarity": 1,
"price": 100,
"attack": 100,
"cooldown": 1500,
"cooldown": 1.5,
"damageType": 1,
"attackRange": 5000,
"attackRange": 5,
"attackSoundId": 10000,
"parameters": [
[
3,
700
0.7
],
[
4,
4500
4.5
],
[
5,
500
0.5
]
],
"statModifierConfigs": [],
@@ -32,32 +32,21 @@ namespace SepCore.Entity
public int Price => Config.Price;
public float Cooldown => Config.Cooldown / 1000f;
public float Cooldown => Config.Cooldown;
public float AttackRange => Config.AttackRange / 1000f;
public float AttackRange => Config.AttackRange;
public int AttackSoundId => Config.AttackSoundId;
public IReadOnlyDictionary<ParamType, int> Parameters => Config.Parameters;
public IReadOnlyDictionary<ParamType, float> Parameters => Config.Parameters;
public IReadOnlyList<StatModifierConfig> Modifiers => Config.StatModifierConfigs;
public int GetParam(ParamType paramType)
{
if (Config.Parameters.TryGetValue(paramType, out int value))
{
return value;
}
Log.Error("Weapon parameter '{0}' not found for weapon '{1}'.", paramType, Config.WeaponType);
return 0;
}
public float GetParamFloat(ParamType paramType)
{
if (Config.Parameters.TryGetValue(paramType, out int val))
if (Config.Parameters.TryGetValue(paramType, out float val))
{
return paramType == ParamType.SectorAngle ? val : val / 1000f;
return val;
}
Log.Error("Weapon parameter '{0}' not found for weapon '{1}'.", paramType, Config.WeaponType);
@@ -65,4 +54,3 @@ namespace SepCore.Entity
}
}
}
@@ -20,19 +20,19 @@ public sealed partial class GlobalConfig : Luban.BeanBase
PropMaxCount = _buf.ReadInt();
PlayerEntity = _buf.ReadString();
PlayerEntity_Ref = null;
AbsorbSpeed = _buf.ReadInt();
CollectDistance = _buf.ReadInt();
DefaultAbsorbRange = _buf.ReadInt();
WeaponRecycleRate = _buf.ReadInt();
AbsorbSpeed = _buf.ReadFloat();
CollectDistance = _buf.ReadFloat();
DefaultAbsorbRange = _buf.ReadFloat();
WeaponRecycleRate = _buf.ReadFloat();
ShopGoodsCount = _buf.ReadInt();
ShopPriceRandomPercent = _buf.ReadInt();
ShopPriceRandomPercent = _buf.ReadFloat();
ShopMinPrice = _buf.ReadInt();
LevelUpRefreshPriceBase = _buf.ReadInt();
LevelUpRewardCount = _buf.ReadInt();
SpawnEnemyMaxCount = _buf.ReadInt();
EnemySpawnDistanceMin = _buf.ReadInt();
EnemySpawnDistanceMax = _buf.ReadInt();
WeaponRotateSpeed = _buf.ReadInt();
EnemySpawnDistanceMin = _buf.ReadFloat();
EnemySpawnDistanceMax = _buf.ReadFloat();
WeaponRotateSpeed = _buf.ReadFloat();
WeaponBaseCrit = _buf.ReadFloat();
PlayerGroupName = _buf.ReadString();
EnemyGroupName = _buf.ReadString();
@@ -75,19 +75,19 @@ public sealed partial class GlobalConfig : Luban.BeanBase
/// <summary>
/// 自动收集速度
/// </summary>
public readonly int AbsorbSpeed;
public readonly float AbsorbSpeed;
/// <summary>
/// 自动收集距离
/// </summary>
public readonly int CollectDistance;
public readonly float CollectDistance;
/// <summary>
/// 默认吸收距离
/// </summary>
public readonly int DefaultAbsorbRange;
public readonly float DefaultAbsorbRange;
/// <summary>
/// 武器回收价比例
/// </summary>
public readonly int WeaponRecycleRate;
public readonly float WeaponRecycleRate;
/// <summary>
/// 商店商品数量
/// </summary>
@@ -95,7 +95,7 @@ public sealed partial class GlobalConfig : Luban.BeanBase
/// <summary>
/// 商品价格浮动
/// </summary>
public readonly int ShopPriceRandomPercent;
public readonly float ShopPriceRandomPercent;
/// <summary>
/// 商品最低价
/// </summary>
@@ -115,15 +115,15 @@ public sealed partial class GlobalConfig : Luban.BeanBase
/// <summary>
/// 敌人生成最小距离
/// </summary>
public readonly int EnemySpawnDistanceMin;
public readonly float EnemySpawnDistanceMin;
/// <summary>
/// 敌人生成最大距离
/// </summary>
public readonly int EnemySpawnDistanceMax;
public readonly float EnemySpawnDistanceMax;
/// <summary>
/// 武器旋转速度
/// </summary>
public readonly int WeaponRotateSpeed;
public readonly float WeaponRotateSpeed;
/// <summary>
/// 武器基本暴击率
/// </summary>
@@ -45,19 +45,19 @@ public partial class TbGlobalConfig
/// <summary>
/// 自动收集速度
/// </summary>
public int AbsorbSpeed => _data.AbsorbSpeed;
public float AbsorbSpeed => _data.AbsorbSpeed;
/// <summary>
/// 自动收集距离
/// </summary>
public int CollectDistance => _data.CollectDistance;
public float CollectDistance => _data.CollectDistance;
/// <summary>
/// 默认吸收距离
/// </summary>
public int DefaultAbsorbRange => _data.DefaultAbsorbRange;
public float DefaultAbsorbRange => _data.DefaultAbsorbRange;
/// <summary>
/// 武器回收价比例
/// </summary>
public int WeaponRecycleRate => _data.WeaponRecycleRate;
public float WeaponRecycleRate => _data.WeaponRecycleRate;
/// <summary>
/// 商店商品数量
/// </summary>
@@ -65,7 +65,7 @@ public partial class TbGlobalConfig
/// <summary>
/// 商品价格浮动
/// </summary>
public int ShopPriceRandomPercent => _data.ShopPriceRandomPercent;
public float ShopPriceRandomPercent => _data.ShopPriceRandomPercent;
/// <summary>
/// 商品最低价
/// </summary>
@@ -85,15 +85,15 @@ public partial class TbGlobalConfig
/// <summary>
/// 敌人生成最小距离
/// </summary>
public int EnemySpawnDistanceMin => _data.EnemySpawnDistanceMin;
public float EnemySpawnDistanceMin => _data.EnemySpawnDistanceMin;
/// <summary>
/// 敌人生成最大距离
/// </summary>
public int EnemySpawnDistanceMax => _data.EnemySpawnDistanceMax;
public float EnemySpawnDistanceMax => _data.EnemySpawnDistanceMax;
/// <summary>
/// 武器旋转速度
/// </summary>
public int WeaponRotateSpeed => _data.WeaponRotateSpeed;
public float WeaponRotateSpeed => _data.WeaponRotateSpeed;
/// <summary>
/// 武器基本暴击率
/// </summary>
@@ -21,11 +21,11 @@ public sealed partial class WeaponConfig : Luban.BeanBase
Rarity = (Rarity)_buf.ReadInt();
Price = _buf.ReadInt();
Attack = _buf.ReadInt();
Cooldown = _buf.ReadInt();
Cooldown = _buf.ReadFloat();
DamageType = (DamageType)_buf.ReadInt();
AttackRange = _buf.ReadInt();
AttackRange = _buf.ReadFloat();
AttackSoundId = _buf.ReadInt();
{int n0 = System.Math.Min(_buf.ReadSize(), _buf.Size);Parameters = new System.Collections.Generic.Dictionary<ParamType, int>(n0 * 3 / 2);for(var i0 = 0 ; i0 < n0 ; i0++) { ParamType _k0; _k0 = (ParamType)_buf.ReadInt(); int _v0; _v0 = _buf.ReadInt(); Parameters.Add(_k0, _v0);}}
{int n0 = System.Math.Min(_buf.ReadSize(), _buf.Size);Parameters = new System.Collections.Generic.Dictionary<ParamType, float>(n0 * 3 / 2);for(var i0 = 0 ; i0 < n0 ; i0++) { ParamType _k0; _k0 = (ParamType)_buf.ReadInt(); float _v0; _v0 = _buf.ReadFloat(); Parameters.Add(_k0, _v0);}}
{int n0 = System.Math.Min(_buf.ReadSize(), _buf.Size);StatModifierConfigs = new System.Collections.Generic.List<StatModifierConfig>(n0);for(var i0 = 0 ; i0 < n0 ; i0++) { StatModifierConfig _e0; _e0 = StatModifierConfig.DeserializeStatModifierConfig(_buf); StatModifierConfigs.Add(_e0);}}
Prefab = _buf.ReadString();
Prefab_Ref = null;
@@ -61,7 +61,7 @@ public sealed partial class WeaponConfig : Luban.BeanBase
/// <summary>
/// 冷却
/// </summary>
public readonly int Cooldown;
public readonly float Cooldown;
/// <summary>
/// 伤害类型
/// </summary>
@@ -69,7 +69,7 @@ public sealed partial class WeaponConfig : Luban.BeanBase
/// <summary>
/// 攻击范围
/// </summary>
public readonly int AttackRange;
public readonly float AttackRange;
/// <summary>
/// 攻击音效编号
/// </summary>
@@ -77,7 +77,7 @@ public sealed partial class WeaponConfig : Luban.BeanBase
/// <summary>
/// 参数类型
/// </summary>
public readonly System.Collections.Generic.Dictionary<ParamType, int> Parameters;
public readonly System.Collections.Generic.Dictionary<ParamType, float> Parameters;
public readonly System.Collections.Generic.List<StatModifierConfig> StatModifierConfigs;
/// <summary>
/// 预制体
@@ -51,13 +51,39 @@ namespace SepCore.CustomUtility
string colorTag = statModifierConfig.Value >= 0 ? "green" : "red";
string sign = statModifierConfig.Value >= 0 ? "+" : "";
if (statModifierConfig.ModifierType == ModifierType.PercentAdd)
StatConfig statConfig = null;
if (GameEntry.Luban != null && GameEntry.Luban.IsReady)
{
statConfig = GameEntry.Luban.Get<StatConfig>(index);
}
if (statConfig != null && !string.IsNullOrEmpty(statConfig.Name))
{
name = statConfig.Name;
}
// 是否以百分比展示:由 StatConfig.IsPercentDisplay 真正驱动(Luban 未就绪时 fallback 到已知百分比属性)
bool isPercentDisplay = statConfig != null
? statConfig.IsPercentDisplay
: (statModifierConfig.StatType is StatType.DamagePercent or StatType.AttackSpeed or StatType.CritChance or StatType.Dodge);
// 1. 修饰类型判断
bool isPercentAdd = statModifierConfig.ModifierType == ModifierType.PercentAdd;
bool isPercentMult = statModifierConfig.ModifierType == ModifierType.PercentMult;
bool isFlat = statModifierConfig.ModifierType == ModifierType.Flat;
// 2. UI 百分比展示裁决:
// - 任意属性的 PercentAdd 词条属于比例加成(如 攻速 +19%、伤害 +5%、移速 +15%)
// - 或属性自身在配置表中标记为百分比显示(IsPercentDisplay 为 true,如暴击率、闪避率等),其 Flat 加成应以百分比呈现(如 0.1 -> +10%)
bool shouldDisplayAsPercent = isPercentAdd || (isFlat && isPercentDisplay);
if (shouldDisplayAsPercent)
{
float displayPercent = statModifierConfig.Value * 100f;
return $"{name}: <color={colorTag}>{sign}{displayPercent:0.##}%</color>";
}
if (statModifierConfig.ModifierType == ModifierType.PercentMult)
if (isPercentMult)
{
return $"{name}: <color={colorTag}>x{statModifierConfig.Value:0.##}</color>";
}
@@ -89,8 +115,8 @@ namespace SepCore.CustomUtility
return null;
}
return CreateWeaponDescription(weaponConfig.Attack, weaponConfig.Cooldown / 1000f,
weaponConfig.AttackRange / 1000f, weaponConfig.StatModifierConfigs, weaponConfig.Parameters);
return CreateWeaponDescription(weaponConfig.Attack, weaponConfig.Cooldown,
weaponConfig.AttackRange, weaponConfig.StatModifierConfigs, weaponConfig.Parameters);
}
public static string CreateWeaponDescription(WeaponBase weapon)
@@ -125,7 +151,7 @@ namespace SepCore.CustomUtility
}
private static string CreateWeaponDescription(int attack, float cooldown, float attackRange,
IEnumerable<StatModifierConfig> modifiers, IReadOnlyDictionary<ParamType, int> parameters)
IEnumerable<StatModifierConfig> modifiers, IReadOnlyDictionary<ParamType, float> parameters)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine($"攻击: {attack}");
@@ -152,7 +178,7 @@ namespace SepCore.CustomUtility
string valStr = kvp.Key == ParamType.SectorAngle
? kvp.Value.ToString()
: (kvp.Value / 1000f).ToString("0.##");
: kvp.Value.ToString("0.##");
sb.AppendLine($"{paramName}: {valStr}");
}
@@ -13,6 +13,7 @@ namespace SepCore.Battle
{
private readonly List<StatModifier> _modifiers = new();
private float _baseValue;
private bool _isBaseValueExplicitlySet;
private bool _isDirty = true;
private float _cachedValue;
private StatConfig _config;
@@ -26,6 +27,11 @@ namespace SepCore.Battle
if (_config == null && GameEntry.Luban != null && GameEntry.Luban.IsReady)
{
_config = GameEntry.Luban.Get<StatConfig>((int)Type);
if (!_isBaseValueExplicitlySet && _config != null)
{
_baseValue = _config.DefaultBaseValue;
_isDirty = true;
}
}
return _config;
@@ -33,15 +39,35 @@ namespace SepCore.Battle
set
{
_config = value;
if (!_isBaseValueExplicitlySet && _config != null)
{
_baseValue = _config.DefaultBaseValue;
}
_isDirty = true;
}
}
public float BaseValue
{
get => _baseValue;
get
{
if (!_isBaseValueExplicitlySet)
{
if (Config != null)
{
_baseValue = Config.DefaultBaseValue;
}
else if (Type is StatType.DamagePercent or StatType.AttackSpeed)
{
_baseValue = 1.0f;
}
}
return _baseValue;
}
set
{
_isBaseValueExplicitlySet = true;
if (Math.Abs(_baseValue - value) > 1e-6f)
{
_baseValue = value;
@@ -69,8 +95,21 @@ namespace SepCore.Battle
public CharacterStat(StatType type, float baseValue = 0f, StatConfig config = null)
{
Type = type;
_baseValue = baseValue;
_config = config;
if (Math.Abs(baseValue) > 1e-6f)
{
_baseValue = baseValue;
_isBaseValueExplicitlySet = true;
}
else if (_config != null)
{
_baseValue = _config.DefaultBaseValue;
_isBaseValueExplicitlySet = true;
}
else if (type is StatType.DamagePercent or StatType.AttackSpeed)
{
_baseValue = 1.0f;
}
_isDirty = true;
}
@@ -154,7 +193,7 @@ namespace SepCore.Battle
}
}
float finalValue = ((_baseValue + sumFlat) * (1f + sumPercentAdd)) * prodPercentMult;
float finalValue = ((BaseValue + sumFlat) * (1f + sumPercentAdd)) * prodPercentMult;
return ClampStat(finalValue);
}
@@ -26,7 +26,15 @@ namespace SepCore.Battle
float maxDodge = 0.8f;
if (GameEntry.Luban != null && GameEntry.Luban.IsReady)
{
maxDodge = GameEntry.Luban.Global.MaxDodgeRate / 1000f;
StatConfig dodgeConfig = GameEntry.Luban.Get<StatConfig>((int)StatType.Dodge);
if (dodgeConfig != null && dodgeConfig.HasMax)
{
maxDodge = dodgeConfig.MaxValue;
}
else
{
maxDodge = GameEntry.Luban.Global.MaxDodgeRate / 1000f;
}
}
dodgeChance = Mathf.Clamp(dodgeChance, 0f, maxDodge);
@@ -55,9 +63,11 @@ namespace SepCore.Battle
// 3. 全局百分比增伤放大 (DamagePercent)
float damagePercent = context.AttackerPipeline != null
? context.AttackerPipeline.GetValue(StatType.DamagePercent)
: 0f;
float amplifiedDamage = rawDamage * (1f + damagePercent);
amplifiedDamage = Mathf.Max(amplifiedDamage, 1f);
: 1f;
// 允许百分比降至 0,防止负向修饰(如 -100% 增伤/重度虚弱)被错误重置为 1 倍全额伤害
damagePercent = Mathf.Max(0f, damagePercent);
float amplifiedDamage = rawDamage * damagePercent;
amplifiedDamage = Mathf.Max(amplifiedDamage, 0f);
// 4. 暴击判定 (CritChance & CritMultiplier)
float attackerCrit = context.AttackerPipeline != null
@@ -65,12 +75,16 @@ namespace SepCore.Battle
: 0f;
float baseCrit = context.BaseCritChance;
if (baseCrit <= 0f && GameEntry.Luban != null && GameEntry.Luban.IsReady)
float maxCrit = 0.9f;
if (GameEntry.Luban != null && GameEntry.Luban.IsReady)
{
baseCrit = GameEntry.Luban.Global.WeaponBaseCrit;
StatConfig critConfig = GameEntry.Luban.Get<StatConfig>((int)StatType.CritChance);
if (critConfig != null && critConfig.HasMax)
{
maxCrit = critConfig.MaxValue;
}
}
float totalCritChance = Mathf.Clamp(baseCrit + attackerCrit, 0f, 0.9f);
float totalCritChance = Mathf.Clamp(baseCrit + attackerCrit, 0f, maxCrit);
bool isCrit = totalCritChance > 0f && Random.value < totalCritChance;
float critMultiplier = context.CritMultiplier;
@@ -8,13 +8,11 @@ namespace SepCore.Components
private Player _player;
private Transform _target;
private float AbsorbRangeBase => GameEntry.Luban.Global.DefaultAbsorbRange / 1000f;
private float AbsorbSpeed => GameEntry.Luban.Global.AbsorbSpeed / 1000f;
private float CollectDistance => GameEntry.Luban.Global.CollectDistance / 1000f;
public float AbsorbRange => GameEntry.Luban.Global.DefaultAbsorbRange;
public float AbsorbSpeed => GameEntry.Luban.Global.AbsorbSpeed;
public float CollectDistance => GameEntry.Luban.Global.CollectDistance;
private float AbsorbRange => AbsorbRangeBase;
public void OnInit(Player player, StatComponent statComponent)
public void OnInit(Player player)
{
_player = player;
_target = player.CachedTransform;
@@ -80,8 +80,8 @@ namespace SepCore.EnemyManager
_isStopped = false;
_spawnEnemyMaxCount = GameEntry.Luban.Global.SpawnEnemyMaxCount;
float minDistance = GameEntry.Luban.Global.EnemySpawnDistanceMin / 1000f;
float maxDistance = GameEntry.Luban.Global.EnemySpawnDistanceMax / 1000f;
float minDistance = GameEntry.Luban.Global.EnemySpawnDistanceMin;
float maxDistance = GameEntry.Luban.Global.EnemySpawnDistanceMax;
_player = player.CachedTransform;
_spawnPositionStrategy = new RandomCircleSpawnStrategy(minDistance, maxDistance);
@@ -23,19 +23,19 @@ namespace SepCore.Simulation
private float ResolveAbsorbRange()
{
if (_playerAbsorbRange >= 0f) return _playerAbsorbRange;
return GameEntry.Luban != null ? GameEntry.Luban.Global.DefaultAbsorbRange / 1000f : 2f;
return GameEntry.Luban != null ? GameEntry.Luban.Global.DefaultAbsorbRange : 2f;
}
private float ResolveAbsorbSpeed()
{
if (_playerAbsorbSpeed >= 0f) return _playerAbsorbSpeed;
return GameEntry.Luban != null ? GameEntry.Luban.Global.AbsorbSpeed / 1000f : 8f;
return GameEntry.Luban != null ? GameEntry.Luban.Global.AbsorbSpeed : 8f;
}
private float ResolveCollectDistance()
{
if (_playerCollectDistance >= 0f) return _playerCollectDistance;
return GameEntry.Luban != null ? GameEntry.Luban.Global.CollectDistance / 1000f : 0.5f;
return GameEntry.Luban != null ? GameEntry.Luban.Global.CollectDistance : 0.5f;
}
[Header("敌人互斥参数")]
@@ -216,7 +216,7 @@ namespace SepCore.Entity
_inputComponent.OnInit();
_inputComponent.SetListening(true);
_absorbComponent.OnInit(this, _statComponent);
_absorbComponent.OnInit(this);
_weaponEnabled = true;
_currentLevel = 0;
@@ -34,8 +34,8 @@ namespace SepCore.Entity
get
{
if (WeaponData == null) return 0f;
float attackSpeed = _ownerAttributeProvider?.GetValue(StatType.AttackSpeed) ?? 0f;
float speedFactor = Mathf.Max(0.2f, 1f + attackSpeed);
float attackSpeed = _ownerAttributeProvider?.GetValue(StatType.AttackSpeed) ?? 1f;
float speedFactor = Mathf.Max(0.2f, attackSpeed);
return Mathf.Max(0.02f, WeaponData.Cooldown / speedFactor);
}
}
@@ -46,8 +46,7 @@ namespace SepCore.Entity
{
if (WeaponData == null) return 0f;
float rangeBonus = _ownerAttributeProvider?.GetValue(StatType.Range) ?? 0f;
float effectiveBonus = rangeBonus >= 50f ? rangeBonus / 1000f : rangeBonus;
return Mathf.Max(0.5f, WeaponData.AttackRange + effectiveBonus);
return Mathf.Max(0.5f, WeaponData.AttackRange + rangeBonus);
}
}
@@ -124,7 +124,7 @@ namespace SepCore.UI
_selections.Clear();
int currentLevel = _currentLevel;
float priceRandomPercent = GameEntry.Luban.Global.ShopPriceRandomPercent / 1000f;
float priceRandomPercent = GameEntry.Luban.Global.ShopPriceRandomPercent;
for (int i = 0; i < finalCount; i++)
{
@@ -324,7 +324,7 @@ namespace SepCore.UI
public int CalculateRecyclePrice(int basePrice)
{
return Mathf.FloorToInt(basePrice * (GameEntry.Luban.Global.WeaponRecycleRate / 1000f));
return Mathf.FloorToInt(basePrice * GameEntry.Luban.Global.WeaponRecycleRate);
}
}
}