gameplay所有基本功能都装了,加入了全局警告。加入飘字等各种东西。

This commit is contained in:
FloatGaming
2026-02-21 00:20:03 +08:00
parent 9f7c1c57b7
commit 14fb281d6f
254 changed files with 102927 additions and 9427 deletions
@@ -6,6 +6,18 @@ using TMPro;
public class BeatmapManager : MonoBehaviour
{
public static BeatmapManager Instance { get; private set; }
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
}
// static holder to accept SongData passed from previous scene before this manager exists
public static SongData pendingSongData = null;
public static int pendingDifficulty = -1;
@@ -45,6 +57,9 @@ public class BeatmapManager : MonoBehaviour
// Documentation text normalized.
public teamUIController uiController;
[Header("Enemy Ball UI")]
public load_enemyBall_light enemyBallLoader;
[Header("UI Display")]
public Text gameplay_songname;
@@ -232,6 +247,9 @@ public class BeatmapManager : MonoBehaviour
// No globalDelaySeconds available in this path. Call NoteSpawner directly.
noteSpawner.LoadBeatmap(beatmap);
ApplyTrackScoreCaps(beatmap);
// Also setup enemies if loading this way
SetupEnemiesAndHP();
}
// Documentation text normalized.
@@ -477,17 +495,29 @@ public class BeatmapManager : MonoBehaviour
List<int> enemyIds = new List<int>();
// 优先从 SO 读取
if (assignedSongData != null && assignedSongData.enemyList != null && assignedSongData.enemyList.Count > 0)
if (assignedSongData != null && assignedSongData.chartFiles != null)
{
enemyIds = new List<int>(assignedSongData.enemyList);
foreach (var entry in assignedSongData.chartFiles)
{
if (entry.difficulty == assignedDifficulty)
{
if (entry.enemyConfigList != null && entry.enemyConfigList.Count > 0)
{
foreach (var config in entry.enemyConfigList)
{
enemyIds.Add(config.enemyID);
}
}
break;
}
}
}
// 确保 5 个槽位:截断或补 0
while (enemyIds.Count < 5) enemyIds.Add(0);
if (enemyIds.Count > 5) enemyIds = enemyIds.GetRange(0, 5);
uiController.enemySlotIds = enemyIds;
uiController.PopulateEnemySOsFromIds();
Debug.Log($"[BeatmapManager] SyncEnemyListToUI: {string.Join(",", enemyIds)}");
}
@@ -500,15 +530,31 @@ public class BeatmapManager : MonoBehaviour
}
List<int> enemyIds = new List<int>();
List<float> activePercentages = new List<float>();
bool foundInDifficulty = false;
// 优先使用 SongData SO 中配置的敌人列表
if (assignedSongData != null && assignedSongData.enemyList != null && assignedSongData.enemyList.Count > 0)
if (assignedSongData != null && assignedSongData.chartFiles != null)
{
enemyIds = new List<int>(assignedSongData.enemyList);
Debug.Log($"[BeatmapManager] Using enemyList from SongData SO: {string.Join(",", enemyIds)}");
foreach (var entry in assignedSongData.chartFiles)
{
if (entry.difficulty == assignedDifficulty)
{
if (entry.enemyConfigList != null && entry.enemyConfigList.Count > 0)
{
foreach (var config in entry.enemyConfigList)
{
enemyIds.Add(config.enemyID);
if (config.enemyID != 0) activePercentages.Add(config.hpPercentage);
}
foundInDifficulty = true;
Debug.Log($"[BeatmapManager] Using enemyConfigList from ChartFileEntry (difficulty {assignedDifficulty})");
}
break;
}
}
}
// 如果 SO 中没有,则尝试从谱面 JSON 解析
else if (!parsedEnemyListIsEmpty && parsedColorSegments != null && parsedColorSegments.Length > 0)
if (!foundInDifficulty && !parsedEnemyListIsEmpty && parsedColorSegments != null && parsedColorSegments.Length > 0)
{
foreach (var segment in parsedColorSegments)
{
@@ -524,7 +570,6 @@ public class BeatmapManager : MonoBehaviour
Debug.Log($"[BeatmapManager] Using enemyList from Beatmap JSON: {string.Join(",", enemyIds)}");
}
// 确保列表始终为 5 个槽位
while (enemyIds.Count < 5) enemyIds.Add(0);
if (enemyIds.Count > 5) enemyIds = enemyIds.GetRange(0, 5);
@@ -534,16 +579,102 @@ public class BeatmapManager : MonoBehaviour
if (parsedNoteAmount > 0)
{
float currentMultiplier = GetCurrentDifficultyMultiplier();
if (assignedSongData != null && assignedSongData.chartFiles != null)
{
foreach (var entry in assignedSongData.chartFiles)
{
if (entry.difficulty == assignedDifficulty)
{
if (entry.enemyTotalHP_Multiplier > 0.01f)
{
currentMultiplier = entry.enemyTotalHP_Multiplier;
Debug.Log($"[BeatmapManager] Using override enemyTotalHP_Multiplier from SongData: {currentMultiplier}");
}
break;
}
}
}
float totalCalculatedHP = parsedNoteAmount * currentMultiplier * baseHpUnitScale;
int totalHP = Mathf.RoundToInt(totalCalculatedHP);
int activeEnemyCount = enemyIds.FindAll(id => id != 0).Count;
if (activeEnemyCount == 0) activeEnemyCount = 1;
if (activeEnemyCount <= 0) activeEnemyCount = 1;
int individualMaxHP = Mathf.RoundToInt(totalCalculatedHP / activeEnemyCount);
List<int> individualHPList = new List<int>();
Debug.Log($"[BeatmapManager] HP Calc -> Notes: {parsedNoteAmount}, Multiplier: {currentMultiplier}, Total: {totalCalculatedHP:F0}, ActiveEnemies: {activeEnemyCount}, Per Enemy: {individualMaxHP}");
float sumPercentage = 0f;
for (int i = 0; i < activePercentages.Count; i++) sumPercentage += activePercentages[i];
uiController.ApplyCalculatedEnemyHP(individualMaxHP);
if (foundInDifficulty && activePercentages.Count == activeEnemyCount && sumPercentage > 0.1f)
{
float[] exact = new float[activeEnemyCount];
int[] baseHp = new int[activeEnemyCount];
float[] frac = new float[activeEnemyCount];
int allocated = 0;
for (int i = 0; i < activeEnemyCount; i++)
{
exact[i] = totalHP * (activePercentages[i] / sumPercentage);
baseHp[i] = Mathf.FloorToInt(exact[i]);
frac[i] = exact[i] - baseHp[i];
allocated += baseHp[i];
}
int remainder = totalHP - allocated;
while (remainder > 0)
{
int bestIdx = 0;
float bestFrac = -1f;
for (int i = 0; i < activeEnemyCount; i++)
{
if (frac[i] > bestFrac)
{
bestFrac = frac[i];
bestIdx = i;
}
}
baseHp[bestIdx] += 1;
frac[bestIdx] = -1f;
remainder--;
}
for (int i = 0; i < activeEnemyCount; i++) individualHPList.Add(baseHp[i]);
Debug.Log($"[BeatmapManager] HP Calc (Custom Percentages) -> Total: {totalHP}, HPs: {string.Join(",", individualHPList)}");
}
else
{
int basePer = totalHP / activeEnemyCount;
int remainder = totalHP - (basePer * activeEnemyCount);
for (int i = 0; i < activeEnemyCount; i++)
{
int hp = basePer + (i < remainder ? 1 : 0);
individualHPList.Add(hp);
}
Debug.Log($"[BeatmapManager] HP Calc (Equal Dist) -> Total: {totalHP}, Active: {activeEnemyCount}, HPs: {string.Join(",", individualHPList)}");
}
uiController.ApplyCalculatedEnemyHP(individualHPList);
}
// Initialize enemy ball list UI
if (enemyBallLoader != null)
{
List<EnemyData_SO.EnemyType> enemyTypes = new List<EnemyData_SO.EnemyType>();
// Use uiController's populated list if available, otherwise just use IDs to look them up if possible
// uiController.PopulateEnemySOsFromIds() fills uiController.recognizedEnemySOs
if (uiController.recognizedEnemySOs != null)
{
foreach (var so in uiController.recognizedEnemySOs)
{
if (so != null)
{
enemyTypes.Add(so.enemyType);
}
}
}
enemyBallLoader.InitializeEnemyBalls(enemyTypes);
}
}