2.5 update
This commit is contained in:
@@ -567,7 +567,7 @@ namespace BumpCombat.Progression
|
||||
ShowOptions();
|
||||
}
|
||||
|
||||
private static string GetPassiveRelicName(PassiveRelicId id)
|
||||
internal static string GetPassiveRelicName(PassiveRelicId id)
|
||||
{
|
||||
return id switch
|
||||
{
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using BumpCombat.Constants;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BumpCombat.Progression
|
||||
{
|
||||
public sealed class ExperienceProgress
|
||||
{
|
||||
private float fractionalExperience;
|
||||
|
||||
public event Action<int, int, int> ExperienceChanged;
|
||||
public event Action<int> LevelGained;
|
||||
|
||||
public int Level { get; private set; } = 1;
|
||||
public int CurrentExperience { get; private set; }
|
||||
public int RequiredExperience => RequiredExperienceForLevel(Level);
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
Level = 1;
|
||||
CurrentExperience = 0;
|
||||
fractionalExperience = 0f;
|
||||
}
|
||||
|
||||
public void AddEvaluated(float evaluatedAmount)
|
||||
{
|
||||
fractionalExperience += Mathf.Max(0f, evaluatedAmount);
|
||||
int wholeExperience = Mathf.FloorToInt(
|
||||
fractionalExperience + 0.0001f);
|
||||
fractionalExperience = Mathf.Max(
|
||||
0f,
|
||||
fractionalExperience - wholeExperience);
|
||||
CurrentExperience += wholeExperience;
|
||||
|
||||
while (CurrentExperience >= RequiredExperience)
|
||||
{
|
||||
CurrentExperience -= RequiredExperience;
|
||||
Level++;
|
||||
LevelGained?.Invoke(Level);
|
||||
}
|
||||
|
||||
ExperienceChanged?.Invoke(
|
||||
CurrentExperience,
|
||||
RequiredExperience,
|
||||
Level);
|
||||
}
|
||||
|
||||
internal static int RequiredExperienceForLevel(int level)
|
||||
{
|
||||
LevelUpConstants tuning = GameplayConstants.Current.LevelUp;
|
||||
return tuning.BaseExperienceToNextLevel
|
||||
+ (Mathf.Max(1, level) - 1)
|
||||
* tuning.AdditionalExperiencePerLevel;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 030f13063dd14111976e7d7cc4e95223
|
||||
@@ -1,6 +1,5 @@
|
||||
using BumpCombat.Core;
|
||||
using System;
|
||||
using BumpCombat.Constants;
|
||||
using BumpCombat.Player;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -10,19 +9,26 @@ namespace BumpCombat.Progression
|
||||
public sealed class ExperienceSystem : MonoBehaviour
|
||||
{
|
||||
private PlayerStats playerStats;
|
||||
private float fractionalExperience;
|
||||
private ExperienceProgress progress;
|
||||
|
||||
public event Action<int, int, int> OnExperienceChanged;
|
||||
public event Action<int> OnLevelGained;
|
||||
public event Action OnExperienceOrbPickedUp;
|
||||
|
||||
public int Level { get; private set; } = 1;
|
||||
public int CurrentExperience { get; private set; }
|
||||
public int RequiredExperience => RequiredExperienceForLevel(Level);
|
||||
public int Level => progress != null ? progress.Level : 1;
|
||||
public int CurrentExperience => progress != null
|
||||
? progress.CurrentExperience
|
||||
: 0;
|
||||
public int RequiredExperience => progress != null
|
||||
? progress.RequiredExperience
|
||||
: RequiredExperienceForLevel(1);
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
playerStats = GetComponent<PlayerStats>();
|
||||
progress = new ExperienceProgress();
|
||||
progress.ExperienceChanged += HandleProgressExperienceChanged;
|
||||
progress.LevelGained += HandleProgressLevelGained;
|
||||
}
|
||||
|
||||
private void Start()
|
||||
@@ -48,31 +54,31 @@ namespace BumpCombat.Progression
|
||||
|
||||
private void AddExperienceInternal(int amount)
|
||||
{
|
||||
fractionalExperience += Mathf.Max(0f, playerStats.Evaluate(
|
||||
float evaluatedAmount = playerStats.Evaluate(
|
||||
CharacterStat.ExperienceGain,
|
||||
Mathf.Max(0, amount)));
|
||||
int wholeExperience = Mathf.FloorToInt(
|
||||
fractionalExperience + 0.0001f);
|
||||
fractionalExperience = Mathf.Max(
|
||||
0f,
|
||||
fractionalExperience - wholeExperience);
|
||||
CurrentExperience += wholeExperience;
|
||||
while (CurrentExperience >= RequiredExperience)
|
||||
{
|
||||
CurrentExperience -= RequiredExperience;
|
||||
Level++;
|
||||
OnLevelGained?.Invoke(Level);
|
||||
}
|
||||
Mathf.Max(0, amount));
|
||||
progress.AddEvaluated(evaluatedAmount);
|
||||
}
|
||||
|
||||
OnExperienceChanged?.Invoke(CurrentExperience, RequiredExperience, Level);
|
||||
private void HandleProgressExperienceChanged(
|
||||
int currentExperience,
|
||||
int requiredExperience,
|
||||
int level)
|
||||
{
|
||||
OnExperienceChanged?.Invoke(
|
||||
currentExperience,
|
||||
requiredExperience,
|
||||
level);
|
||||
}
|
||||
|
||||
private void HandleProgressLevelGained(int level)
|
||||
{
|
||||
OnLevelGained?.Invoke(level);
|
||||
}
|
||||
|
||||
public static int RequiredExperienceForLevel(int level)
|
||||
{
|
||||
LevelUpConstants tuning = GameplayConstants.Current.LevelUp;
|
||||
return tuning.BaseExperienceToNextLevel
|
||||
+ (Mathf.Max(1, level) - 1)
|
||||
* tuning.AdditionalExperiencePerLevel;
|
||||
return ExperienceProgress.RequiredExperienceForLevel(level);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using BumpCombat.Player;
|
||||
using BumpCombat.Core;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BumpCombat.Progression
|
||||
@@ -25,30 +27,109 @@ namespace BumpCombat.Progression
|
||||
public int MaximumStacks => maximumStacks;
|
||||
public float HealOnApply => healOnApply;
|
||||
|
||||
public string GetKoreanDisplayName()
|
||||
{
|
||||
return $"{GetKoreanStatName(stat)} 강화";
|
||||
}
|
||||
|
||||
public string GetKoreanEffectDescription(float effectMultiplier)
|
||||
{
|
||||
string statName = GetKoreanStatName(stat);
|
||||
string effectValue = operation == ModifierOperation.Flat
|
||||
? FormatSignedValue(value * effectMultiplier)
|
||||
: $"{FormatSignedValue(value * effectMultiplier * 100f)}%";
|
||||
string description = $"{statName} {effectValue}";
|
||||
if (healOnApply > 0f)
|
||||
{
|
||||
description += $"\n즉시 체력 회복 {FormatSignedValue(healOnApply * effectMultiplier)}";
|
||||
}
|
||||
|
||||
return description + "\n선택하면 즉시 적용됩니다.";
|
||||
}
|
||||
|
||||
private static string GetKoreanStatName(CharacterStat targetStat)
|
||||
{
|
||||
switch (targetStat)
|
||||
{
|
||||
case CharacterStat.CollisionDamage: return "몸통박치기 피해";
|
||||
case CharacterStat.MoveSpeed: return "이동 속도";
|
||||
case CharacterStat.MaxHealth: return "최대 체력";
|
||||
case CharacterStat.Armor: return "방어력";
|
||||
case CharacterStat.LifeSteal: return "생명력 흡수";
|
||||
case CharacterStat.ExperienceGain: return "경험치 획득량";
|
||||
case CharacterStat.ExperiencePickupRange: return "경험치 획득 범위";
|
||||
case CharacterStat.ArtifactGaugeGain: return "유물 게이지 획득량";
|
||||
case CharacterStat.IncomingDamage: return "받는 피해";
|
||||
case CharacterStat.AttackDamage: return "공격 피해";
|
||||
default: return "능력치";
|
||||
}
|
||||
}
|
||||
|
||||
private static string FormatSignedValue(float amount)
|
||||
{
|
||||
if (Mathf.Approximately(amount, 0f))
|
||||
{
|
||||
return "0";
|
||||
}
|
||||
|
||||
string formatted = amount.ToString("0.##", CultureInfo.InvariantCulture);
|
||||
return amount > 0f ? $"+{formatted}" : formatted;
|
||||
}
|
||||
|
||||
public bool CanApply(PlayerStats playerStats)
|
||||
{
|
||||
return playerStats != null
|
||||
&& playerStats.GetStackCount(modifierId, stat) < maximumStacks;
|
||||
return CanApplyToModel(playerStats);
|
||||
}
|
||||
|
||||
public bool CanApplyToModel(CharacterModel model)
|
||||
{
|
||||
return model != null
|
||||
&& model.GetStackCount(modifierId, stat) < maximumStacks;
|
||||
}
|
||||
|
||||
public bool TryApply(
|
||||
PlayerStats playerStats,
|
||||
PlayerHealth playerHealth)
|
||||
{
|
||||
if (!CanApply(playerStats)
|
||||
|| !playerStats.AddModifier(new StatModifier(
|
||||
Action<float> heal = playerHealth == null
|
||||
? null
|
||||
: amount => playerHealth.Heal(amount);
|
||||
return TryApplyToModel(playerStats, heal);
|
||||
}
|
||||
|
||||
public bool TryApplyToModel(
|
||||
CharacterModel model,
|
||||
Action<float> heal)
|
||||
{
|
||||
return TryApplyToModel(model, heal, 1f);
|
||||
}
|
||||
|
||||
public bool TryApplyToModel(
|
||||
CharacterModel model,
|
||||
Action<float> heal,
|
||||
float effectMultiplier)
|
||||
{
|
||||
if (float.IsNaN(effectMultiplier)
|
||||
|| float.IsInfinity(effectMultiplier)
|
||||
|| effectMultiplier < 0f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CanApplyToModel(model)
|
||||
|| !model.AddModifier(new StatModifier(
|
||||
modifierId,
|
||||
stat,
|
||||
operation,
|
||||
value,
|
||||
value * effectMultiplier,
|
||||
maximumStacks)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (healOnApply > 0f && playerHealth != null)
|
||||
if (healOnApply > 0f && heal != null)
|
||||
{
|
||||
playerHealth.Heal(healOnApply);
|
||||
heal(healOnApply * effectMultiplier);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user