274 lines
8.4 KiB
C#
274 lines
8.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Unity.Netcode;
|
|
using UnityEngine;
|
|
using Northbound.Data;
|
|
|
|
namespace Northbound
|
|
{
|
|
/// <summary>
|
|
/// 플레이어별 업그레이드 보유 상태를 관리하는 컴포넌트
|
|
/// </summary>
|
|
public class PlayerUpgradeManager : NetworkBehaviour
|
|
{
|
|
// 보유한 업그레이드 ID 목록 (네트워크 동기화)
|
|
private NetworkList<int> _ownedUpgradeIds;
|
|
|
|
// 이벤트
|
|
public event Action<int> OnUpgradePurchased; // upgradeId
|
|
|
|
private NetworkPlayerController _networkPlayerController;
|
|
|
|
public new bool IsLocalPlayer => _networkPlayerController != null && _networkPlayerController.IsLocalPlayer;
|
|
public ulong OwnerPlayerId => _networkPlayerController != null ? _networkPlayerController.OwnerPlayerId : OwnerClientId;
|
|
|
|
private void Awake()
|
|
{
|
|
_ownedUpgradeIds = new NetworkList<int>();
|
|
_networkPlayerController = GetComponent<NetworkPlayerController>();
|
|
}
|
|
|
|
public override void OnNetworkSpawn()
|
|
{
|
|
base.OnNetworkSpawn();
|
|
|
|
if (_networkPlayerController != null)
|
|
{
|
|
_networkPlayerController.OnOwnerChanged += OnOwnerChanged;
|
|
}
|
|
}
|
|
|
|
public override void OnNetworkDespawn()
|
|
{
|
|
base.OnNetworkDespawn();
|
|
|
|
if (_networkPlayerController != null)
|
|
{
|
|
_networkPlayerController.OnOwnerChanged -= OnOwnerChanged;
|
|
}
|
|
|
|
_ownedUpgradeIds.Dispose();
|
|
}
|
|
|
|
private void OnOwnerChanged(ulong newOwnerId)
|
|
{
|
|
// 소유자 변경 시 필요한 처리
|
|
}
|
|
|
|
/// <summary>
|
|
/// 보유한 업그레이드 ID 목록 (복사본 반환)
|
|
/// </summary>
|
|
public List<int> GetOwnedUpgradeIdList()
|
|
{
|
|
var list = new List<int>();
|
|
foreach (int id in _ownedUpgradeIds)
|
|
{
|
|
list.Add(id);
|
|
}
|
|
return list;
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// 특정 업그레이드를 보유하고 있는지 확인
|
|
/// </summary>
|
|
public bool HasUpgrade(int upgradeId)
|
|
{
|
|
foreach (int id in _ownedUpgradeIds)
|
|
{
|
|
if (id == upgradeId)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 보유한 업그레이드 ID를 HashSet으로 반환
|
|
/// </summary>
|
|
public HashSet<int> GetOwnedUpgradeIdSet()
|
|
{
|
|
var set = new HashSet<int>();
|
|
foreach (int id in _ownedUpgradeIds)
|
|
{
|
|
set.Add(id);
|
|
}
|
|
return set;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 업그레이드 구매 요청 (클라이언트에서 호출)
|
|
/// </summary>
|
|
public void RequestPurchaseUpgrade(int upgradeId)
|
|
{
|
|
PurchaseUpgradeServerRpc(upgradeId);
|
|
}
|
|
|
|
[Rpc(SendTo.Server, InvokePermission = RpcInvokePermission.Everyone)]
|
|
private void PurchaseUpgradeServerRpc(int upgradeId)
|
|
{
|
|
if (!CanPurchaseUpgrade(upgradeId, out string failReason))
|
|
{
|
|
Debug.LogWarning($"[PlayerUpgradeManager] 업그레이드 구매 실패: {failReason}");
|
|
return;
|
|
}
|
|
|
|
// 업그레이드 데이터 가져오기
|
|
var upgrade = UpgradeDatabase.Instance?.GetUpgradeById(upgradeId);
|
|
if (upgrade == null)
|
|
{
|
|
Debug.LogError($"[PlayerUpgradeManager] 업그레이드 ID {upgradeId}를 찾을 수 없습니다.");
|
|
return;
|
|
}
|
|
|
|
// 비용 차감
|
|
var core = CoreResourceManager.Instance?.mainCore;
|
|
if (core == null)
|
|
{
|
|
Debug.LogError("[PlayerUpgradeManager] 코어를 찾을 수 없습니다.");
|
|
return;
|
|
}
|
|
|
|
if (!core.CanConsumeResource(upgrade.mana))
|
|
{
|
|
Debug.LogWarning($"[PlayerUpgradeManager] 자원이 부족합니다. 필요: {upgrade.mana}");
|
|
return;
|
|
}
|
|
|
|
core.ConsumeResourceServerRpc(upgrade.mana);
|
|
|
|
// 업그레이드 추가
|
|
_ownedUpgradeIds.Add(upgradeId);
|
|
|
|
Debug.Log($"<color=green>[PlayerUpgradeManager] 업그레이드 '{upgrade.memo}' 구매 완료! (ID: {upgradeId})</color>");
|
|
|
|
// 스탯 변경 확인
|
|
var playerStats = GetComponent<PlayerStats>();
|
|
playerStats?.PrintCurrentStats();
|
|
|
|
// 이벤트 발생
|
|
OnUpgradePurchased?.Invoke(upgradeId);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 업그레이드 구매 가능 여부 확인
|
|
/// </summary>
|
|
private bool CanPurchaseUpgrade(int upgradeId, out string failReason)
|
|
{
|
|
failReason = string.Empty;
|
|
|
|
var upgradeDatabase = UpgradeDatabase.Instance;
|
|
if (upgradeDatabase == null)
|
|
{
|
|
failReason = "UpgradeDatabase가 초기화되지 않았습니다.";
|
|
return false;
|
|
}
|
|
|
|
var upgrade = upgradeDatabase.GetUpgradeById(upgradeId);
|
|
if (upgrade == null)
|
|
{
|
|
failReason = $"업그레이드 ID {upgradeId}를 찾을 수 없습니다.";
|
|
return false;
|
|
}
|
|
|
|
// 이미 보유 중인지 확인
|
|
if (HasUpgrade(upgradeId))
|
|
{
|
|
failReason = "이미 보유한 업그레이드입니다.";
|
|
return false;
|
|
}
|
|
|
|
// 선행 조건 확인
|
|
if (!upgradeDatabase.ArePrerequisitesMet(upgradeId, GetOwnedUpgradeIdSet()))
|
|
{
|
|
failReason = "선행 업그레이드 조건을 충족하지 않았습니다.";
|
|
return false;
|
|
}
|
|
|
|
// 비용 확인
|
|
var core = CoreResourceManager.Instance?.mainCore;
|
|
if (core == null)
|
|
{
|
|
failReason = "코어를 찾을 수 없습니다.";
|
|
return false;
|
|
}
|
|
|
|
if (!core.CanConsumeResource(upgrade.mana))
|
|
{
|
|
failReason = $"자원이 부족합니다. 필요: {upgrade.mana}, 보유: {core.TotalResources}";
|
|
return false;
|
|
}
|
|
|
|
// 개인 업그레이드인지 확인
|
|
if (upgrade.upgradeTarget != "person")
|
|
{
|
|
failReason = "팀 업그레이드는 개인이 구매할 수 없습니다.";
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 업그레이드 구매 가능 여부 (외부용)
|
|
/// </summary>
|
|
public bool CanPurchase(int upgradeId)
|
|
{
|
|
return CanPurchaseUpgrade(upgradeId, out _);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 구매 가능한 업그레이드 목록 반환
|
|
/// </summary>
|
|
public List<UpgradeData> GetPurchasableUpgrades()
|
|
{
|
|
var result = new List<UpgradeData>();
|
|
var upgradeDatabase = UpgradeDatabase.Instance;
|
|
|
|
if (upgradeDatabase == null) return result;
|
|
|
|
var personalUpgrades = upgradeDatabase.GetPersonalUpgrades();
|
|
var ownedIds = GetOwnedUpgradeIdSet();
|
|
|
|
foreach (var upgrade in personalUpgrades)
|
|
{
|
|
if (upgrade == null) continue;
|
|
|
|
// 이미 보유하면 제외
|
|
if (ownedIds.Contains(upgrade.id)) continue;
|
|
|
|
// 선행 조건 충족 시 구매 가능
|
|
if (upgradeDatabase.ArePrerequisitesMet(upgrade.id, ownedIds))
|
|
{
|
|
result.Add(upgrade);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 보유한 업그레이드 데이터 목록 반환
|
|
/// </summary>
|
|
public List<UpgradeData> GetOwnedUpgradeData()
|
|
{
|
|
var result = new List<UpgradeData>();
|
|
var upgradeDatabase = UpgradeDatabase.Instance;
|
|
|
|
if (upgradeDatabase == null) return result;
|
|
|
|
foreach (int id in _ownedUpgradeIds)
|
|
{
|
|
var upgrade = upgradeDatabase.GetUpgradeById(id);
|
|
if (upgrade != null)
|
|
{
|
|
result.Add(upgrade);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
}
|