142 lines
5.8 KiB
C#
142 lines
5.8 KiB
C#
using System.Collections.Generic;
|
|
using GeometryTD.DataTable;
|
|
using GeometryTD.Definition;
|
|
using UnityEngine;
|
|
using UnityGameFramework.Runtime;
|
|
|
|
namespace GeometryTD.CustomComponent
|
|
{
|
|
public sealed class CombatSettlementCalculator
|
|
{
|
|
private const float FullBaseHpGoldBonusRate = 0.3f;
|
|
private const float HighBaseHpGoldBonusRate = 0.1f;
|
|
private const float HighBaseHpThreshold = 0.8f;
|
|
private const float SettlementTowerEnduranceLoss = 1f;
|
|
|
|
public CombatSettlementContext BuildSettlementContext(
|
|
bool didCombatWin,
|
|
DRLevel currentLevel,
|
|
int defeatedEnemyCount,
|
|
CombatRunResourceStore resourceStore)
|
|
{
|
|
bool shouldOpenFullBaseHpRewardSelect = false;
|
|
ResolveSettlementByBaseHp(
|
|
didCombatWin,
|
|
currentLevel,
|
|
resourceStore,
|
|
out int currentBaseHp,
|
|
out int maxBaseHp,
|
|
out int levelRewardGold,
|
|
out float bonusRate,
|
|
out int bonusGold,
|
|
out shouldOpenFullBaseHpRewardSelect);
|
|
|
|
CombatSettlementContext settlementContext = new CombatSettlementContext();
|
|
settlementContext.Result.DidCombatWin = didCombatWin;
|
|
settlementContext.Result.FinalCoin = Mathf.Max(0, resourceStore != null ? resourceStore.CurrentCoin : 0);
|
|
settlementContext.Result.FinalBaseHp = currentBaseHp;
|
|
settlementContext.Result.MaxBaseHp = maxBaseHp;
|
|
settlementContext.Result.DefeatedEnemyCount = Mathf.Max(0, defeatedEnemyCount);
|
|
settlementContext.Result.GainedGold = Mathf.Max(0, resourceStore != null ? resourceStore.GainedGold : 0);
|
|
settlementContext.Result.RewardInventory = resourceStore != null
|
|
? resourceStore.GetRewardInventorySnapshot()
|
|
: new BackpackInventoryData();
|
|
PopulateEnduranceSettlement(settlementContext, resourceStore);
|
|
settlementContext.Flags.ShouldOpenRewardSelection = shouldOpenFullBaseHpRewardSelect;
|
|
settlementContext.Flags.DidEnterRewardSelection = false;
|
|
settlementContext.Summary.DefeatedEnemyCount = settlementContext.Result.DefeatedEnemyCount;
|
|
settlementContext.Summary.GainedGold = settlementContext.Result.GainedGold;
|
|
settlementContext.Summary.RewardInventory = settlementContext.Result.RewardInventory;
|
|
|
|
Log.Info(
|
|
"Combat settlement resolved. Level={0}, BaseHp={1}/{2}, LevelReward={3}, BonusRate={4:P0}, BonusGold={5}, FullHpRewardSelect={6}, EnduranceTargets={7}.",
|
|
currentLevel != null ? currentLevel.Id : 0,
|
|
currentBaseHp,
|
|
maxBaseHp,
|
|
levelRewardGold,
|
|
bonusRate,
|
|
bonusGold,
|
|
shouldOpenFullBaseHpRewardSelect,
|
|
settlementContext.Result.Endurance.TargetTowerInstanceIds.Count);
|
|
return settlementContext;
|
|
}
|
|
|
|
private static void ResolveSettlementByBaseHp(
|
|
bool didCombatWin,
|
|
DRLevel currentLevel,
|
|
CombatRunResourceStore resourceStore,
|
|
out int currentBaseHp,
|
|
out int maxBaseHp,
|
|
out int levelRewardGold,
|
|
out float bonusRate,
|
|
out int bonusGold,
|
|
out bool shouldOpenFullBaseHpRewardSelect)
|
|
{
|
|
currentBaseHp = Mathf.Max(0, resourceStore != null ? resourceStore.CurrentBaseHp : 0);
|
|
maxBaseHp = resourceStore != null ? Mathf.Max(0, resourceStore.MaxBaseHp) : 0;
|
|
if (maxBaseHp > 0)
|
|
{
|
|
currentBaseHp = Mathf.Clamp(currentBaseHp, 0, maxBaseHp);
|
|
}
|
|
|
|
levelRewardGold = currentLevel != null ? Mathf.Max(0, currentLevel.RewardGold) : 0;
|
|
bonusRate = 0f;
|
|
bonusGold = 0;
|
|
shouldOpenFullBaseHpRewardSelect = false;
|
|
|
|
if (!didCombatWin || resourceStore == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (maxBaseHp > 0 && currentBaseHp >= maxBaseHp)
|
|
{
|
|
bonusRate = FullBaseHpGoldBonusRate;
|
|
shouldOpenFullBaseHpRewardSelect = true;
|
|
}
|
|
else if (maxBaseHp > 0)
|
|
{
|
|
float hpRate = (float)currentBaseHp / maxBaseHp;
|
|
if (hpRate >= HighBaseHpThreshold)
|
|
{
|
|
bonusRate = HighBaseHpGoldBonusRate;
|
|
}
|
|
}
|
|
|
|
int goldForBonusCalculation = Mathf.Max(0, resourceStore.GainedGold) + levelRewardGold;
|
|
bonusGold = bonusRate > 0f ? Mathf.FloorToInt(goldForBonusCalculation * bonusRate) : 0;
|
|
int settlementGold = levelRewardGold + bonusGold;
|
|
resourceStore.AddSettlementGold(settlementGold);
|
|
}
|
|
|
|
private static void PopulateEnduranceSettlement(
|
|
CombatSettlementContext settlementContext,
|
|
CombatRunResourceStore resourceStore)
|
|
{
|
|
if (settlementContext == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
CombatSettlementEnduranceResult enduranceResult = settlementContext.Result.Endurance;
|
|
enduranceResult.TargetTowerInstanceIds.Clear();
|
|
enduranceResult.EnduranceLossPerComponent = SettlementTowerEnduranceLoss;
|
|
|
|
IReadOnlyList<long> participantTowerIds = resourceStore?.GetParticipantTowerInstanceIdSnapshot();
|
|
if (participantTowerIds == null || participantTowerIds.Count <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < participantTowerIds.Count; i++)
|
|
{
|
|
long towerId = participantTowerIds[i];
|
|
if (towerId > 0)
|
|
{
|
|
enduranceResult.TargetTowerInstanceIds.Add(towerId);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|