引入 UISerializationRoot 和 Item
- 完成 MenuForm 和 SelectRoleForm 的迁移
This commit is contained in:
@@ -79,5 +79,25 @@ namespace SepCore.UI
|
||||
{
|
||||
_onPointerExitAction.Invoke();
|
||||
}
|
||||
|
||||
public void RegisterPointerEnterAction(UnityAction action)
|
||||
{
|
||||
_onPointerEnterAction.AddListener(action);
|
||||
}
|
||||
|
||||
public void RegisterPointerExitAction(UnityAction action)
|
||||
{
|
||||
_onPointerExitAction.AddListener(action);
|
||||
}
|
||||
|
||||
public void UnregisterPointerEnterAction(UnityAction action)
|
||||
{
|
||||
_onPointerEnterAction.RemoveListener(action);
|
||||
}
|
||||
|
||||
public void UnregisterPointerExitAction(UnityAction action)
|
||||
{
|
||||
_onPointerExitAction.RemoveListener(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ namespace SepCore.UI
|
||||
{
|
||||
public class LevelUpUseCase : IUIUseCase
|
||||
{
|
||||
private const int BaseRefreshPrice = 2;
|
||||
private readonly Action _onCompleted;
|
||||
private readonly LevelUpRewardConfig[] _allRewards;
|
||||
private readonly Dictionary<Rarity, List<LevelUpRewardConfig>> _rewardsByRarity = new();
|
||||
@@ -32,28 +31,28 @@ namespace SepCore.UI
|
||||
BuildRewardRarityPools();
|
||||
}
|
||||
|
||||
public LevelUpRawData CreateInitialModel(int count = 4)
|
||||
public LevelUpRawData CreateInitialModel()
|
||||
{
|
||||
_refreshCount = 0;
|
||||
|
||||
if (_player == null || _player.PendingLevelPoints <= 0)
|
||||
if (_player.PendingLevelPoints <= 0)
|
||||
{
|
||||
_currentModel = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
_currentModel = BuildModel(BaseRefreshPrice, count);
|
||||
_currentModel = BuildModel(GameEntry.Luban.Global.LevelUpRefreshPriceBase);
|
||||
return _currentModel;
|
||||
}
|
||||
|
||||
public LevelUpRawData TryRefresh(int refreshCost, int count = 4)
|
||||
public LevelUpRawData TryRefresh(int refreshCost)
|
||||
{
|
||||
if (_currentModel == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (_player == null || _player.Coin < refreshCost)
|
||||
if (_player.Coin < refreshCost)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -61,11 +60,11 @@ namespace SepCore.UI
|
||||
_player.Coin -= refreshCost;
|
||||
|
||||
_refreshCount++;
|
||||
_currentModel = BuildModel((_refreshCount + 1) * BaseRefreshPrice, count);
|
||||
_currentModel = BuildModel((_refreshCount + 1) * GameEntry.Luban.Global.LevelUpRefreshPriceBase);
|
||||
return _currentModel;
|
||||
}
|
||||
|
||||
public LevelUpRawData SelectReward(int selectedIndex, int count = 4)
|
||||
public LevelUpRawData SelectReward(int selectedIndex)
|
||||
{
|
||||
if (_currentModel?.Rewards == null)
|
||||
{
|
||||
@@ -74,7 +73,7 @@ namespace SepCore.UI
|
||||
|
||||
if (selectedIndex < 0 || selectedIndex >= _currentModel.Rewards.Count)
|
||||
{
|
||||
Log.Warning("LevelUpFormUseCase::SelectReward: Invalid index");
|
||||
Log.Error("LevelUpFormUseCase::SelectReward: Invalid index");
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -83,7 +82,7 @@ namespace SepCore.UI
|
||||
if (--_player.PendingLevelPoints > 0)
|
||||
{
|
||||
_refreshCount = 0;
|
||||
_currentModel = BuildModel(BaseRefreshPrice, count);
|
||||
_currentModel = BuildModel(GameEntry.Luban.Global.LevelUpRefreshPriceBase);
|
||||
return _currentModel;
|
||||
}
|
||||
|
||||
@@ -92,25 +91,25 @@ namespace SepCore.UI
|
||||
return null;
|
||||
}
|
||||
|
||||
private LevelUpRawData BuildModel(int refreshPrice, int count)
|
||||
private LevelUpRawData BuildModel(int refreshPrice)
|
||||
{
|
||||
if (_allRewards == null || _allRewards.Length == 0)
|
||||
if (_allRewards.Length == 0)
|
||||
{
|
||||
Log.Error("LevelUpFormUseCase::BuildModel(): _allRewards is empty");
|
||||
return null;
|
||||
}
|
||||
|
||||
int finalCount = count > 0 ? Mathf.Min(count, _allRewards.Length) : _allRewards.Length;
|
||||
int finalCount = Mathf.Min(GameEntry.Luban.Global.LevelUpRewardCount, _allRewards.Length);
|
||||
List<LevelUpRewardConfig> selections = new List<LevelUpRewardConfig>(finalCount);
|
||||
|
||||
int currentLevel = _player != null ? _player.CurrentLevel : 1;
|
||||
int currentLevel = _player.CurrentLevel;
|
||||
for (int i = 0; i < finalCount; i++)
|
||||
{
|
||||
Rarity rarity = RarityUtility.SelectRarityForLevel(currentLevel);
|
||||
LevelUpRewardConfig reward = PickRewardByRarity(rarity);
|
||||
if (reward == null)
|
||||
{
|
||||
Log.Warning("LevelUpFormUseCase::BuildModel(): No available reward for selection.");
|
||||
Log.Error("LevelUpFormUseCase::BuildModel(): No available reward for selection.");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -126,23 +125,6 @@ namespace SepCore.UI
|
||||
|
||||
private void ApplyReward(LevelUpRewardConfig reward)
|
||||
{
|
||||
if (reward == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_player == null)
|
||||
{
|
||||
Log.Warning("LevelUpFormUseCase::ApplyReward: Player is null");
|
||||
return;
|
||||
}
|
||||
|
||||
if (reward.Modifiers == null || reward.Modifiers.Count == 0)
|
||||
{
|
||||
Log.Warning("LevelUpFormUseCase::ApplyReward: Reward modifiers are empty");
|
||||
return;
|
||||
}
|
||||
|
||||
_player.AddProp(new PropItem(reward.Modifiers, reward.Rarity, reward.Title, reward.Sprite));
|
||||
}
|
||||
|
||||
@@ -151,15 +133,8 @@ namespace SepCore.UI
|
||||
_rewardsByRarity.Clear();
|
||||
_validRewards.Clear();
|
||||
|
||||
if (_allRewards == null) return;
|
||||
|
||||
foreach (LevelUpRewardConfig reward in _allRewards)
|
||||
{
|
||||
if (reward == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Rarity rarity = reward.Rarity;
|
||||
_validRewards.Add(reward);
|
||||
|
||||
|
||||
@@ -25,8 +25,6 @@ namespace SepCore.UI
|
||||
|
||||
public class ShopUseCase : IUIUseCase
|
||||
{
|
||||
private const float WeaponRecycleRate = 0.3f;
|
||||
|
||||
private readonly Player _player;
|
||||
private readonly int _currentLevel;
|
||||
private readonly Action _onShopFinish;
|
||||
@@ -39,8 +37,6 @@ namespace SepCore.UI
|
||||
private readonly List<ShopGoodsSelection> _selections = new();
|
||||
private int _refreshTime;
|
||||
|
||||
private Player Player => _player;
|
||||
|
||||
private sealed class ShopGoodsSelection
|
||||
{
|
||||
public GoodsType GoodsType;
|
||||
@@ -63,42 +59,34 @@ namespace SepCore.UI
|
||||
{
|
||||
_refreshTime = 0;
|
||||
|
||||
Player player = Player;
|
||||
if (_player == null || player == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int currentLevel = _currentLevel;
|
||||
return new ShopRawData
|
||||
{
|
||||
CurrentLevel = currentLevel,
|
||||
RefreshPrice = currentLevel,
|
||||
PlayerCoin = player.Coin,
|
||||
GoodsItems = BuildRandomGoodsItems(4),
|
||||
PropItems = player.Props,
|
||||
PropMaxCount = -1,
|
||||
WeaponItems = player.Weapons,
|
||||
WeaponMaxCount = player.WeaponCapacity
|
||||
CurrentLevel = _currentLevel,
|
||||
RefreshPrice = _currentLevel,
|
||||
PlayerCoin = _player.Coin,
|
||||
GoodsItems = BuildRandomGoodsItems(GameEntry.Luban.Global.ShopGoodsCount),
|
||||
PropItems = _player.Props,
|
||||
PropMaxCount = GameEntry.Luban.Global.PropMaxCount,
|
||||
WeaponItems = _player.Weapons,
|
||||
WeaponMaxCount = _player.WeaponCapacity
|
||||
};
|
||||
}
|
||||
|
||||
public ShopRefreshResult TryRefresh(int cost)
|
||||
{
|
||||
Player player = Player;
|
||||
if (player == null || _player == null || player.Coin < cost)
|
||||
if (_player.Coin < cost)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
player.Coin -= cost;
|
||||
_player.Coin -= cost;
|
||||
|
||||
int refreshPrice = (_refreshTime + 1) * _currentLevel;
|
||||
_refreshTime++;
|
||||
|
||||
return new ShopRefreshResult
|
||||
{
|
||||
GoodsItems = BuildRandomGoodsItems(4),
|
||||
GoodsItems = BuildRandomGoodsItems(GameEntry.Luban.Global.ShopGoodsCount),
|
||||
RefreshPrice = refreshPrice
|
||||
};
|
||||
}
|
||||
@@ -107,7 +95,7 @@ namespace SepCore.UI
|
||||
{
|
||||
if (goodsIndex < 0 || goodsIndex >= _selections.Count)
|
||||
{
|
||||
Log.Warning("ShopFormUseCase::TryPurchase: Invalid index");
|
||||
Log.Error("ShopFormUseCase::TryPurchase: Invalid index");
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -118,8 +106,7 @@ namespace SepCore.UI
|
||||
return null;
|
||||
}
|
||||
|
||||
Player player = Player;
|
||||
if (player == null || player.Coin < selection.Price)
|
||||
if (_player.Coin < selection.Price)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -130,7 +117,7 @@ namespace SepCore.UI
|
||||
return null;
|
||||
}
|
||||
|
||||
player.Coin -= selection.Price;
|
||||
_player.Coin -= selection.Price;
|
||||
_selections[goodsIndex] = null;
|
||||
|
||||
return new ShopPurchaseResult
|
||||
@@ -147,7 +134,7 @@ namespace SepCore.UI
|
||||
|
||||
private List<GoodsItemRawData> BuildRandomGoodsItems(int count)
|
||||
{
|
||||
if (_allGoods == null || _allGoods.Count == 0)
|
||||
if (_allGoods.Count == 0)
|
||||
{
|
||||
Log.Error("ShopFormUseCase::BuildRandomGoodsItems(): _allGoods is empty");
|
||||
return null;
|
||||
@@ -157,7 +144,8 @@ namespace SepCore.UI
|
||||
List<GoodsItemRawData> goodsItems = new List<GoodsItemRawData>(finalCount);
|
||||
_selections.Clear();
|
||||
|
||||
int currentLevel = _currentLevel > 0 ? _currentLevel : 1;
|
||||
int currentLevel = _currentLevel;
|
||||
float priceRandomPercent = GameEntry.Luban.Global.ShopPriceRandomPercent / 1000f;
|
||||
|
||||
for (int i = 0; i < finalCount; i++)
|
||||
{
|
||||
@@ -165,7 +153,7 @@ namespace SepCore.UI
|
||||
GoodsConfig goodsConfig = PickGoodsByRarity(rarity);
|
||||
if (goodsConfig == null)
|
||||
{
|
||||
Log.Warning("ShopFormUseCase::BuildRandomGoodsItems: No available goods for selection.");
|
||||
Log.Error("ShopFormUseCase::BuildRandomGoodsItems: No available goods for selection.");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -176,9 +164,8 @@ namespace SepCore.UI
|
||||
{
|
||||
PropConfig propConfig = GameEntry.Luban.Get<PropConfig>(goodsConfig.PropId);
|
||||
int basePrice = propConfig.Price;
|
||||
float randomPercent = 0.05f;
|
||||
|
||||
price = CalculateRandomizedPrice(basePrice, randomPercent);
|
||||
price = CalculateRandomizedPrice(basePrice, priceRandomPercent);
|
||||
goodsItem.ItemType = ItemType.Prop;
|
||||
goodsItem.Rarity = propConfig.Rarity;
|
||||
goodsItem.DataRow = propConfig;
|
||||
@@ -187,9 +174,8 @@ namespace SepCore.UI
|
||||
{
|
||||
WeaponConfig weaponConfig = GameEntry.Luban.Get<WeaponConfig>((int)goodsConfig.WeaponType);
|
||||
int basePrice = weaponConfig.Price;
|
||||
float randomPercent = 0.05f;
|
||||
|
||||
price = CalculateRandomizedPrice(basePrice, randomPercent);
|
||||
price = CalculateRandomizedPrice(basePrice, priceRandomPercent);
|
||||
goodsItem.ItemType = ItemType.Weapon;
|
||||
goodsItem.Rarity = weaponConfig.Rarity;
|
||||
goodsItem.DataRow = weaponConfig;
|
||||
@@ -222,12 +208,8 @@ namespace SepCore.UI
|
||||
_goodsByRarity.Clear();
|
||||
_validGoods.Clear();
|
||||
|
||||
if (_allGoods == null) return;
|
||||
|
||||
foreach (GoodsConfig goods in _allGoods)
|
||||
{
|
||||
if (goods == null) continue;
|
||||
|
||||
if (!TryGetGoodsRarity(goods, out Rarity rarity))
|
||||
{
|
||||
continue;
|
||||
@@ -263,10 +245,6 @@ namespace SepCore.UI
|
||||
private bool TryGetGoodsRarity(GoodsConfig goods, out Rarity rarity)
|
||||
{
|
||||
rarity = Rarity.None;
|
||||
if (goods == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (goods.GoodsType == GoodsType.Prop)
|
||||
{
|
||||
@@ -293,30 +271,17 @@ namespace SepCore.UI
|
||||
|
||||
private static int CalculateRandomizedPrice(int basePrice, float priceRandomPercent)
|
||||
{
|
||||
float normalizedPercent = priceRandomPercent > 1f ? priceRandomPercent / 100f : priceRandomPercent;
|
||||
normalizedPercent = Mathf.Max(0f, normalizedPercent);
|
||||
float offsetPercent = Random.Range(-normalizedPercent, normalizedPercent);
|
||||
float offsetPercent = Random.Range(-priceRandomPercent, priceRandomPercent);
|
||||
int finalPrice = Mathf.RoundToInt(basePrice * (1f + offsetPercent));
|
||||
return Mathf.Max(1, finalPrice);
|
||||
return Mathf.Max(GameEntry.Luban.Global.ShopMinPrice, finalPrice);
|
||||
}
|
||||
|
||||
private async UniTask<DisplayItemRawData> ApplyGoodsPurchaseAsync(ShopGoodsSelection goods)
|
||||
{
|
||||
if (goods == null || Player == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (goods.GoodsType == GoodsType.Prop)
|
||||
{
|
||||
PropConfig propConfig = GameEntry.Luban.Get<PropConfig>(goods.PropId);
|
||||
if (propConfig.Modifiers == null || propConfig.Modifiers.Count == 0)
|
||||
{
|
||||
Log.Warning("ShopFormUseCase::ApplyGoodsPurchase: Prop modifiers are empty");
|
||||
return null;
|
||||
}
|
||||
|
||||
Player.AddProp(new PropItem(propConfig));
|
||||
_player.AddProp(new PropItem(propConfig));
|
||||
return new DisplayItemRawData
|
||||
{
|
||||
IconAssetName = propConfig.Sprite,
|
||||
@@ -327,7 +292,7 @@ namespace SepCore.UI
|
||||
|
||||
if (goods.GoodsType == GoodsType.Weapon)
|
||||
{
|
||||
if (Player.Weapons != null && Player.Weapons.Count >= Player.WeaponCapacity)
|
||||
if (_player.Weapons.Count >= _player.WeaponCapacity)
|
||||
{
|
||||
Log.Warning("ShopFormUseCase::ApplyGoodsPurchase: Weapon capacity is full.");
|
||||
return null;
|
||||
@@ -335,9 +300,9 @@ namespace SepCore.UI
|
||||
|
||||
WeaponConfig weaponConfig = GameEntry.Luban.Get<WeaponConfig>((int)goods.WeaponType);
|
||||
int id = GameEntry.Entity.NextId();
|
||||
var weaponData = EntityDataFactory.Create(id, weaponConfig, Player.Id, CampType.Player);
|
||||
var weaponData = EntityDataFactory.Create(id, weaponConfig, _player.Id, CampType.Player);
|
||||
|
||||
WeaponBase weapon = await Player.AddWeaponAsync(weaponData);
|
||||
WeaponBase weapon = await _player.AddWeaponAsync(weaponData);
|
||||
if (weapon == null)
|
||||
{
|
||||
Log.Warning(
|
||||
@@ -358,7 +323,7 @@ namespace SepCore.UI
|
||||
|
||||
public bool TryRecycleWeapon(int argsIndex, int argsPrice)
|
||||
{
|
||||
var weapons = Player.Weapons;
|
||||
var weapons = _player.Weapons;
|
||||
if (weapons.Count <= 1)
|
||||
{
|
||||
Log.Warning("ShopFormUseCase::TryRecycleWeapon: Can not recycle the last weapon.");
|
||||
@@ -368,19 +333,19 @@ namespace SepCore.UI
|
||||
var weapon = weapons[argsIndex];
|
||||
|
||||
int recyclePrice = Mathf.Max(0, argsPrice);
|
||||
if (!Player.RemoveWeapon(weapon))
|
||||
if (!_player.RemoveWeapon(weapon))
|
||||
{
|
||||
Log.Warning("ShopFormUseCase::TryRecycleWeapon: Remove weapon failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
Player.Coin += recyclePrice;
|
||||
_player.Coin += recyclePrice;
|
||||
return true;
|
||||
}
|
||||
|
||||
public int CalculateRecyclePrice(int basePrice)
|
||||
{
|
||||
return Mathf.FloorToInt(basePrice * WeaponRecycleRate);
|
||||
return Mathf.FloorToInt(basePrice * (GameEntry.Luban.Global.WeaponRecycleRate / 1000f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f228612923ff51343a4dab06ce4c1f92
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8e4010de30b33144fa20400058edfeba
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 35c8961f073eae8479506bdec8b745f8
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+1
-1
@@ -3,6 +3,6 @@ namespace SepCore.UI
|
||||
public class SelectRoleRawData
|
||||
{
|
||||
public RoleItemRawData[] RoleItems;
|
||||
public RolePropertyAreaRawData SelectedRole;
|
||||
public ShowAreaRawData SelectedRole;
|
||||
}
|
||||
}
|
||||
+17
-9
@@ -2,6 +2,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SepCore.Definition;
|
||||
using SepCore.Procedure;
|
||||
using UnityGameFramework.Runtime;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
namespace SepCore.UI
|
||||
@@ -62,16 +63,23 @@ namespace SepCore.UI
|
||||
};
|
||||
}
|
||||
|
||||
RoleConfig selectedRole = string.IsNullOrEmpty(selectedRoleName)
|
||||
? null
|
||||
: roles.FirstOrDefault(r => r.Name == selectedRoleName);
|
||||
RolePropertyAreaRawData selectedRoleData = selectedRole == null
|
||||
? null
|
||||
: new RolePropertyAreaRawData
|
||||
ShowAreaRawData selectedRoleData = null;
|
||||
if (!string.IsNullOrEmpty(selectedRoleName))
|
||||
{
|
||||
RoleConfig selectedRole = roles.FirstOrDefault(r => r.Name == selectedRoleName);
|
||||
if (selectedRole == null)
|
||||
{
|
||||
Name = selectedRole.Name,
|
||||
InitialProperties = selectedRole.Modifiers
|
||||
};
|
||||
Log.Error("SelectRoleUseCase.BuildModel() role '{0}' is not found.", selectedRoleName);
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedRoleData = new ShowAreaRawData
|
||||
{
|
||||
Name = selectedRole.Name,
|
||||
InitialProperties = selectedRole.Modifiers
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return new SelectRoleRawData
|
||||
{
|
||||
+1
-1
@@ -3,7 +3,7 @@ using SepCore.Definition;
|
||||
|
||||
namespace SepCore.UI
|
||||
{
|
||||
public class RolePropertyAreaRawData
|
||||
public class ShowAreaRawData
|
||||
{
|
||||
public string Name;
|
||||
public List<modifier> InitialProperties;
|
||||
Reference in New Issue
Block a user