ワールド対応(マーケット

This commit is contained in:
kimura 2022-10-07 15:53:52 +09:00
parent 60ccfc860e
commit 10cb205ca5
4 changed files with 355 additions and 231 deletions

View File

@ -1,13 +1,13 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.ExceptionServices;
using MyGame.Scenes.marketing.Scripts;
using MyGame.Scripts;
using TMPro;
using UniRx;
using UniRx.Triggers;
using UnityEngine;
using Debug = UnityEngine.Debug;
using Random = UnityEngine.Random;
public enum ShopState
@ -22,6 +22,7 @@ public class Market : MonoBehaviour
// 購入時アニメーションタイミング
private static readonly float waitSellTime = 1.5f;
private static readonly float waitRefillTime = 1f;
private static readonly float DummyUsedCapacity = .5f;
[SerializeField] private CustomerFlow customerFlow;
[SerializeField] private GameObject orderPosisionObject;
@ -37,6 +38,13 @@ public class Market : MonoBehaviour
public List<int> ShuffledOrder => shuffledOrder;
private List<int> shuffledOrder = new List<int>();
private List<ProductStockData> ShopStock => IsPartTimer ? dummyStock : cityGameData.ShopStock;
private readonly List<ProductStockData> dummyStock = new();
private readonly List<ProductStockData> dummyStorageTank = new();
public bool IsPartTimer { get; private set; }
public bool IsLatestCity { get; private set; }
public IReadOnlyReactiveProperty<ShopState> CurrentShopState => shopState;
private readonly ReactiveProperty<ShopState> shopState = new ReactiveProperty<ShopState>();
public IReadOnlyReactiveCollection<CustomerController> CustomerControllerList => customerControllerList;
@ -60,7 +68,8 @@ public class Market : MonoBehaviour
private int orderIndex;
private int oneByOneIndex = 0;
private int salesBonus = 0;
private GameData gameData;
private GameData globalGameData;
private GameData cityGameData;
// Start is called before the first frame update
void Start()
@ -72,33 +81,36 @@ public class Market : MonoBehaviour
orderSubject.AddTo(this);
IsPause.AddTo(this);
isPromotion.AddTo(this);
}
gameData = GameDataManager.GameData;
public void Initialize(int cityId)
{
IsLatestCity = GameDataUtils.CheckLatestCity(cityId);
cityGameData = GameDataManager.GetCityGameData(cityId);
globalGameData = GameDataManager.GameData;
UpdateBonus(ShopCustomize.GetBonusList(globalGameData.ShopCustomizeLevel));
customerFlow.SetCityGameData(cityGameData);
UpdateBonus(ShopCustomize.GetBonusList(gameData.ShopCustomizeLevel));
#if UNITY_EDITOR || DEVELOPMENT_BUILD
CheckAndFixStock();
WorldMarketManager.StockFlavorLog();
#endif
// 陳列/売り順決定
ReShuffle(gameData.ShopStock);
ReShuffle(ShopStock);
Observable.Interval(TimeSpan.FromSeconds(1f))
.Where(_ => shuffledOrder.Count == 0)
.Where(_ => gameData.ShopStock.Count > 0)
.Where(_ => ShopStock.Count > 0)
.Subscribe(_ =>
{
#if UNITY_EDITOR || DEVELOPMENT_BUILD
Debug.Log("displayFlavors updated");
Debug.LogWarning("displayFlavors updated");
#endif
ReShuffle(gameData.ShopStock);
ReShuffle(ShopStock);
shopState.Value = ShopState.Open;
});
}).AddTo(this);
// お店の状態設定
CheckStock(gameData.ShopStock);
UpdateShopState();
// 購入リクエスト
var maxOrder = orderPosisionObject.transform.childCount;
@ -131,24 +143,10 @@ public class Market : MonoBehaviour
requestSubject.BatchFrame().Subscribe(customers =>
{
// 来客数カウント
gameData.AddCustomerCount(customers.Count);
var orders = new List<int>();
var dontBuyCustomerList = new List<CustomerController>();
foreach (var controller in customers)
{
// 何も買わない
if (displayFlavors.Count == 0 || controller.OrderCount == 0)
{
controller.CallWaitForSeconds(1.5f, () =>
{
controller.ChangeCustomerState(CustomerState.Leave);
});
dontBuyCustomerList.Add(controller);
continue;
}
// 売り切れ
if (shuffledOrder.Count == 0)
{
@ -166,27 +164,22 @@ public class Market : MonoBehaviour
var tmpOrderCount = Mathf.Min(controller.OrderCount, shuffledOrder.Count);
var tmpOrders = shuffledOrder.GetRange(0, tmpOrderCount);
shuffledOrder.RemoveRange(0, tmpOrderCount);
orders.AddRange(tmpOrders);
// コーンの味吹き出しを設定
try
{
// 不正なオーダーの場合お客さん制御
foreach (var t in tmpOrders)
{
if (gameData.ShopStock.Contains(displayFlavors[t]))
{
continue;
}
if (controller.OrderCount >= 1)
{
controller.OrderCount--;
}
}
// 不正なオーダーチェック
var checkedOrders = tmpOrders.Where(order => ShopStock.Contains(displayFlavors[order])).ToList();
controller.OrderCount = checkedOrders.Count;
#if UNITY_EDITOR || DEVELOPMENT_BUILD
if (tmpOrderCount != checkedOrders.Count)
throw new Exception($@"tmpOrder:{string.Join(".", tmpOrders)}
shuffledOrder:{shuffledOrder.OrderBy(x => x).Aggregate("", (s, num) => $"{s},{num}")}
shopStock:{ShopStock.Aggregate("", (s, data) => $"{s},{data.FlavorId}")}
display:{displayFlavors.Aggregate("", (s, data) => $"{s},{data.FlavorId}")}");
#endif
// 購入しないお客さん扱いで退場
if (controller.OrderCount == 0)
if (displayFlavors.Count == 0 || controller.OrderCount == 0)
{
controller.CallWaitForSeconds(1.5f, () =>
{
@ -195,17 +188,14 @@ public class Market : MonoBehaviour
dontBuyCustomerList.Add(controller);
continue;
}
controller.SetWantFlavor(displayFlavors[tmpOrders.RandomChoose()]);
// コーンの味吹き出しを設定
controller.SetWantFlavor(displayFlavors[checkedOrders.RandomChoose()]);
orders.AddRange(checkedOrders);
}
catch (Exception e)
{
/*
*
* orderを引いたのでそのまま処理せず逃がす
*/
Debug.LogError($"d:{displayFlavors.Count}, {string.Join("", tmpOrders)}" +
$"\nshuffled:{shuffledOrder.Count}, maxNum:{shuffledOrder.Max()}");
// 動作止めずに例外スロー
Observable.NextFrame().Subscribe(_ => { ExceptionDispatchInfo.Capture(e).Throw();});
controller.CallWaitForSeconds(1.5f, () =>
{
controller.ChangeCustomerState(CustomerState.Leave);
@ -217,7 +207,7 @@ public class Market : MonoBehaviour
{
customers.Remove(customerController);
}
if (gameData.ShopStock.Count == 0)
if (ShopStock.Count == 0)
{
shopState.Value = ShopState.Close;
}
@ -229,46 +219,61 @@ public class Market : MonoBehaviour
// 購入
var flavors = orders.Select(x => displayFlavors[x]).ToList();
var (coin, count) = SellPopcorn(flavors);
// 獲得処理(遅延追加用変数に加算)
gameData.WaitAddCoin += coin;
gameData.WaitAddHeart += count;
gameData.AddVipCustomerCount(customers.Count(data => data.CustomerType == CustomerType.Vip));
GameDataManager.SaveGameData();
// 商品補充
RefillShopStockData();
// 表示データ更新
var isReorder = false;
var refillList = new List<int>();
if (gameData.ShopStock.Count > shuffledOrder.Count)
if (IsPartTimer)
{
refillList = RefillDisplayFlavors(gameData.ShopStock);
// 商品補充
RefillDummyShopStockData();
refillList = RefillDisplayFlavors();
// 在庫生成
if (dummyStorageTank.Count <= 0)
{
GenerateDummyStock();
}
}
else
{
isReorder = CheckRemaining(gameData.ShopStock.Count);
if (isReorder)
// 獲得処理(遅延追加用変数に加算)
cityGameData.WaitAddCoin += coin;
cityGameData.WaitAddHeart += count;
cityGameData.AddCustomerCount(customers.Count);
cityGameData.AddVipCustomerCount(customers.Count(data => data.CustomerType == CustomerType.Vip));
GameDataManager.SaveGameData();
// 商品補充
RefillShopStockData();
// 表示データ更新
if (ShopStock.Count > shuffledOrder.Count)
{
ReShuffle(gameData.ShopStock);
refillList = RefillDisplayFlavors();
}
else
{
isReorder = CheckRemaining(ShopStock.Count);
if (isReorder)
{
ReShuffle(ShopStock);
}
}
}
this.CallWaitForSeconds(waitSellTime, () =>
{
// 獲得処理
gameData.MoveCoin(coin);
cityGameData.MoveCoin(coin);
GameDataManager.SaveGameData();
sellObservable.OnNext(coin);
sellOrderSubject.OnNext(orders);
CheckStock(gameData.ShopStock);
UpdateShopState();
this.CallWaitForSeconds(waitRefillTime, () =>
{
// 獲得処理
gameData.MoveHeart(count);
cityGameData.MoveHeart(count);
GameDataManager.SaveGameData();
refillSubject.OnNext((isReorder, refillList));
@ -300,6 +305,7 @@ public class Market : MonoBehaviour
controller.ChangeCustomerState(CustomerState.Leave);
}).AddTo(controller);
// ステートが変わるたびにオーダーチェック
controller.State
.Where(x => x != CustomerState.Order)
.Subscribe(c =>
@ -320,33 +326,24 @@ public class Market : MonoBehaviour
}
// チュートリアル中は抑制
if (!gameData.FinishedFlags.HasFlag(TutorialFlag.FirstPlay))
if (!globalGameData.FinishedFlags.HasFlag(TutorialFlag.FirstPlay))
{
return;
}
// 一般客orセレブ
CustomerState customerState;
switch (customerType)
var customerState = customerType switch
{
case CustomerType.Walker:
customerState = CustomerState.Walk;
break;
case CustomerType.Customer:
customerState = CustomerState.WalkShop;
break;
case CustomerType.Vip:
customerState = CustomerState.WalkShop;
break;
default:
throw new ArgumentOutOfRangeException(nameof(customerType), customerType, null);
}
CustomerType.Walker => CustomerState.Walk,
CustomerType.Customer => CustomerState.WalkShop,
CustomerType.Vip => CustomerState.WalkShop,
_ => throw new ArgumentOutOfRangeException(nameof(customerType), customerType, null)
};
var (isSpecial, orderCount) = customerSetting.GetCustomerData(customerType);
var customerController = SpawnCustomer();
customerController.Setup(orderPosisionObject.transform.GetComponentsInChildren<Transform>().ToList().Skip(1).ToList());
customerController.ChangeCustomerState(customerState);
// 複数パターンある場合ChooseRandom
customerController.CustomerPrefab = isSpecial ? customerData.ChooseSpecialPrefab() : customerData.ChooseNormalPrefab();
customerController.OrderCount = orderCount;
customerController.CustomerType = customerType;
@ -354,17 +351,11 @@ public class Market : MonoBehaviour
customerController.TappedObservable
.Take(1)
.Subscribe(_ =>
.Subscribe(_ => customerController.ChangeCustomerState(shopState.Value switch
{
if (shopState.Value == ShopState.Open)
{
customerController.ChangeCustomerState(CustomerState.TouchNotice);
}
else
{
customerController.ChangeCustomerState(CustomerState.TouchQuestion);
}
}).AddTo(customerController);
ShopState.Open => CustomerState.TouchNotice,
_ => CustomerState.TouchQuestion
})).AddTo(customerController);
}).AddTo(this);
// お客さんが少なくなったら弟が走る
@ -389,7 +380,7 @@ public class Market : MonoBehaviour
else
{
BrotherPinkView.Instance.StopPromotion();
if (gameData.TastingCount > 0 && shopState.Value == ShopState.Open)
if (cityGameData.TastingCount > 0 && shopState.Value == ShopState.Open)
{
BrotherPinkView.Instance.StartTasting();
}
@ -412,9 +403,7 @@ public class Market : MonoBehaviour
{
case CustomerMovingType.WalkSide:
case CustomerMovingType.WalkSideEat:
customerList.Remove(customerController);
customerControllerList.Remove(customerController);
Destroy(customerController.gameObject);
DestroyCustomer(customerController);
break;
case CustomerMovingType.TouchNotice:
customerList.Add(customerController);
@ -441,11 +430,17 @@ public class Market : MonoBehaviour
return customerController;
}
private void DestroyCustomer(CustomerController customerController)
{
customerControllerList.Remove(customerController);
customerList.Remove(customerController);
Destroy(customerController.gameObject);
}
private (int coin, int count) SellPopcorn(List<ProductStockData> stockDataList)
{
var gameData = GameDataManager.GameData;
// 品切れ
if (gameData.ShopStock.Count == 0)
if (ShopStock.Count == 0)
{
return (0, 0);
}
@ -459,18 +454,20 @@ public class Market : MonoBehaviour
{
var productData = recipeList.First(data => data.id == stockData.FlavorId);
var rarityData = rarityList.First(data => data.Rarity == stockData.Rarity);
var targetIndex = gameData.ShopStock.FindIndex(data => data.FlavorId == stockData.FlavorId && data.Rarity == stockData.Rarity);
var targetIndex = ShopStock.FindIndex(data => data.FlavorId == stockData.FlavorId && data.Rarity == stockData.Rarity);
if (targetIndex == -1)
{
Debug.LogError($@"data
-----stockData: {stockData.FlavorId}, {stockData.Rarity}
-----shopStock: {gameData.ShopStock.Aggregate("", (s, data) => $"{s},{data.FlavorId}")}
-----shopStock: {ShopStock.Aggregate("", (s, data) => $"{s},{data.FlavorId}")}
displayFlavors: {displayFlavors.Aggregate("", (s, data) => $"{s},{data.FlavorId}")}");
Observable.NextFrame().Subscribe(_ => throw new Exception("DisplayFlavors Invalid")).AddTo(this);
continue;
}
gameData.ShopStock.RemoveAt(targetIndex);
gameData.AddSalesCount(stockData.FlavorId, 1, stockData.Rarity);
ShopStock.RemoveAt(targetIndex);
// バイトは削除処理のみ
if (IsPartTimer) continue;
cityGameData.AddSalesCount(stockData.FlavorId, 1, stockData.Rarity);
coin += productData.GetRarityPrice(rarityData.Rarity);
coin += salesBonus;
count++;
@ -488,33 +485,32 @@ displayFlavors: {displayFlavors.Aggregate("", (s, data) => $"{s},{data.FlavorId}
{
// 手前のタンクから出し多分stockをへらす
// へらした分を店頭リストに追加する
var gameData = GameDataManager.GameData;
var shopSpace = WorldMarketManager.ShopStockCount - gameData.ShopStock.Count;
switch (gameData.RefillMode)
var shopSpace = WorldMarketManager.ShopStockCount - ShopStock.Count;
switch (cityGameData.RefillMode)
{
case ProductRefillMode.OneByOne:
while (shopSpace > 0 && gameData.StorageTanks.Sum(data => data.Stock) > 0)
while (shopSpace > 0 && cityGameData.StorageTanks.Sum(data => data.Stock) > 0)
{
var tanks = gameData.StorageTanks.Where(tank => !tank.IsEmpty).ToList();
var tanks = cityGameData.StorageTanks.Where(tank => !tank.IsEmpty).ToList();
if (oneByOneIndex >= tanks.Count)
{
oneByOneIndex = 0;
}
var stockList = tanks[oneByOneIndex].GetStock(1);
gameData.ShopStock.AddRange(stockList);
ShopStock.AddRange(stockList);
shopSpace -= stockList.Count;
oneByOneIndex++;
}
break;
case ProductRefillMode.TankByTank:
foreach (var tank in gameData.StorageTanks.Where(tank => !tank.IsEmpty))
foreach (var tank in cityGameData.StorageTanks.Where(tank => !tank.IsEmpty))
{
if (shopSpace == 0)
{
break;
}
var stockList = tank.GetStock(shopSpace);
gameData.ShopStock.AddRange(stockList);
ShopStock.AddRange(stockList);
shopSpace -= stockList.Count;
}
break;
@ -524,28 +520,32 @@ displayFlavors: {displayFlavors.Aggregate("", (s, data) => $"{s},{data.FlavorId}
GameDataManager.SaveGameData();
}
public List<int> RefillDisplayFlavors(List<ProductStockData> shopStock)
/// <summary>
/// shopStockを確認して追加差分をDisplayFlavorsとShuffledOrderにAddする
/// </summary>
/// <returns></returns>
public List<int> RefillDisplayFlavors()
{
// 補充された場合店頭のフレーバー入れ替え
var refillCount = shopStock.Count - shuffledOrder.Count;
var refillCount = ShopStock.Count - shuffledOrder.Count;
if (refillCount <= 0)
{
return new List<int>();
}
// 補充候補リスト
var orders = Enumerable.Range(0, shopStock.Count).Except(shuffledOrder).ToList();
var orders = Enumerable.Range(0, ShopStock.Count).Except(shuffledOrder).ToList();
var refillList = orders.GetRange(0, refillCount).OrderBy(_ => Random.value).ToList();
shuffledOrder.AddRange(refillList);
try
{
var diffDisplayCount = shopStock.Count - displayFlavors.Count;
var diffDisplayCount = ShopStock.Count - displayFlavors.Count;
if (diffDisplayCount > 0)
{
displayFlavors.AddRange(shopStock.GetRange(displayFlavors.Count, diffDisplayCount));
displayFlavors.AddRange(ShopStock.GetRange(displayFlavors.Count, diffDisplayCount));
}
for (int i = 0; i < refillList.Count; i++)
{
displayFlavors[refillList[i]] = shopStock[shopStock.Count - 1 - i];
displayFlavors[refillList[i]] = ShopStock[ShopStock.Count - 1 - i];
}
}
catch (Exception e)
@ -569,15 +569,15 @@ displayFlavors: {displayFlavors.Aggregate("", (s, data) => $"{s},{data.FlavorId}
return false;
}
public void ReShuffle(List<ProductStockData> shopStock)
private void ReShuffle(List<ProductStockData> shopStock)
{
displayFlavors = shopStock.ToList();
shuffledOrder = ShuffleOrder(displayFlavors.Count);
}
public void CheckStock(List<ProductStockData> shopStock)
public void UpdateShopState()
{
shopState.Value = shopStock.Count == 0 ? ShopState.Close : ShopState.Open;
shopState.Value = ShopStock.Count == 0 ? ShopState.Close : ShopState.Open;
}
public void AdClickAction()
@ -620,14 +620,72 @@ displayFlavors: {displayFlavors.Aggregate("", (s, data) => $"{s},{data.FlavorId}
return customerController;
}
/// <summary>
/// 兄弟モードで在庫がなくなった場合にバイト君に切り替えるためのチェック
/// </summary>
public void CheckPartTimerMode()
{
var shopStock = cityGameData.ShopStock.Count;
var tankStock = cityGameData.StorageTanks.Sum(x => x.Stock);
if (IsLatestCity || shopStock + tankStock > 0)
{
if (!IsPartTimer) return;
ReShuffle(ShopStock);
IsPartTimer = false;
return;
}
IsPartTimer = true;
// バイト用ダミー生成処理
if (dummyStorageTank.Count <= 0) GenerateDummyStock();
RefillDummyShopStockData();
ReShuffle(ShopStock);
UpdateShopState();
}
public void SetLatestCity(bool active) => IsLatestCity = active;
/// <summary>
/// ダミー在庫生成
/// ダミータンクが0の場合に入手済みレシピからランダムでフレーバー選ぶ
/// 度の生成で10個(volume), 0になる度に全部で30くらいつくっておく
/// </summary>
private void GenerateDummyStock()
{
foreach (var recipeId in globalGameData.MyRecipes.RandomChoose(3))
{
dummyStorageTank.AddRange(Enumerable.Repeat(new ProductStockData
{
FlavorId = recipeId,
Rarity = ProductRarity.Normal
}, 10));
}
}
private void RefillDummyShopStockData()
{
var shopSpace = WorldMarketManager.ShopStockCount - ShopStock.Count;
var refillCount = Mathf.Min(dummyStorageTank.Count, shopSpace);
ShopStock.AddRange(dummyStorageTank.GetRange(0, refillCount));
dummyStorageTank.RemoveRange(0, refillCount);
}
public float GetUsedStorageCapacity()
{
if (IsPartTimer) return DummyUsedCapacity;
var totalCapacity = cityGameData.StorageTanks.Sum(x => x.Capacity);
var totalStock = cityGameData.StorageTanks.Sum(x => x.Stock);
return (float)totalStock / totalCapacity;
}
[Conditional("UNITY_EDITOR"), Conditional("DEVELOPMENT_BUILD")]
private void CheckAndFixStock()
{
if (GameDataManager.GameData.ShopStock.Count > WorldMarketManager.ShopStockCount)
if (ShopStock.Count > WorldMarketManager.ShopStockCount)
{
GameDataManager.GameData.ShopStock.RemoveRange(0, GameDataManager.GameData.ShopStock.Count - WorldMarketManager.ShopStockCount);
ShopStock.RemoveRange(0, ShopStock.Count - WorldMarketManager.ShopStockCount);
}
foreach (var stockData in GameDataManager.GameData.ShopStock.Where(stockData => stockData.FlavorId < 1))
foreach (var stockData in ShopStock.Where(stockData => stockData.FlavorId < 1))
{
stockData.FlavorId = 1;
}
@ -639,8 +697,8 @@ displayFlavors: {displayFlavors.Aggregate("", (s, data) => $"{s},{data.FlavorId}
/// <param name="newGameData"></param>
public void ResetGameData(GameData newGameData)
{
gameData = newGameData;
ReShuffle(gameData.ShopStock);
CheckStock(gameData.ShopStock);
cityGameData = newGameData;
ReShuffle(ShopStock);
UpdateShopState();
}
}

View File

@ -27,6 +27,7 @@ public class MarketManager : MonoBehaviour
[SerializeField] private TutorialObjectMask walkerMask;
private Market market;
List<ProductData> productDataList;
private bool isPartTimer;
private readonly Subject<Unit> customerRewardTimerUpdateSubject = new Subject<Unit>();
private readonly Subject<Unit> vipTimerUpdateSubject = new Subject<Unit>();
@ -38,17 +39,27 @@ public class MarketManager : MonoBehaviour
customerRewardTimerUpdateSubject.AddTo(this);
vipTimerUpdateSubject.AddTo(this);
market = WorldMarketManager.Instance.GetCurrentCityMarket();
market.CheckPartTimerMode();
isPartTimer = market.IsPartTimer;
SoundManager.Instance.PlayBGM("bgm_marketing");
var gameData = GameDataManager.GameData;
var globalGameData = GameDataManager.GameData;
var cityGameData = GameDataManager.GetCurrentCityGameData();
// カスタマイズ読み込み
marketView.SetAllItem();
stockView = marketView.GetTarget(ShopCustomizeCategory.Category4).GetComponentInChildren<ShopStockView>();
stockView.SetTextActive(true);
ShopCustomizeCoinManager.Instance.ChangeCoin(gameData.ShopCustomizeCoin);
ShopCustomizeCoinManager.Instance.ChangeCoin(globalGameData.ShopCustomizeCoin);
if (!gameData.FinishedFlags.HasFlag(TutorialFlag.FirstPlay))
if (isPartTimer)
{
partTimerView.StartAnimation();
rewardButtonView.gameObject.SetActive(false);
vipCustomerButtonView.gameObject.SetActive(false);
}
if (!globalGameData.FinishedFlags.HasFlag(TutorialFlag.FirstPlay))
{
if (TutorialManager.Instance.Index == 3)
{
@ -78,7 +89,7 @@ public class MarketManager : MonoBehaviour
.Subscribe(_ => { }, () =>
{
// チュートリアル終了
gameData.FinishTutorial();
globalGameData.FinishTutorial();
GameDataManager.SaveGameData();
walkerMask.gameObject.SetActive(false);
customerRewardTimerUpdateSubject.OnNext(Unit.Default);
@ -88,8 +99,8 @@ public class MarketManager : MonoBehaviour
}
}
CoinManager.Instance.ChangeCoin(gameData.Coin);
HeartMeter.Instance.Initialize(gameData.ViewedShopLevel, gameData.Heart);
CoinManager.Instance.ChangeCoin(cityGameData.Coin);
HeartMeter.Instance.Initialize(globalGameData.ViewedShopLevel, cityGameData.Heart);
// ハートゲージがフルかつダイアログが開いていない場合レベルアップ
HeartMeter.Instance.FulledHeart
@ -100,14 +111,14 @@ public class MarketManager : MonoBehaviour
.Subscribe(_ =>
{
market.IsPause.Value = true;
ShopLevelUp.ShowDialog(gameData.ViewedShopLevel + 1, () =>
ShopLevelUp.ShowDialog(globalGameData.ViewedShopLevel + 1, () =>
{
market.IsPause.Value = false;
});
}).AddTo(this);
productDataList = SpreadsheetDataManager.Instance.GetBaseDataList<ProductData>(Const.ProductDataSheet);
stockView.SetStock(gameData.StorageTanks);
stockView.SetStock(market.GetUsedStorageCapacity());
List<(int, ProductStockData)> startStocks;
try
{
@ -134,8 +145,9 @@ public class MarketManager : MonoBehaviour
{
vipCustomerButtonView.SetActive(isPause);
// 兄弟非表示
blueView.SetActive(!isPause);
BrotherPinkView.Instance.SetActive(!isPause);
blueView.SetActive(!isPartTimer && !isPause);
BrotherPinkView.Instance.SetActive(!isPartTimer && !isPause);
partTimerView.SetActive(isPartTimer && !isPause);
}).AddTo(this);
// 宣伝ボタン
@ -144,11 +156,11 @@ public class MarketManager : MonoBehaviour
GetRewardDialog.ShowIncreaseCustomerDialog(() =>
{
market.AdClickAction();
gameData.increaseCustomerTime = DateTime.UtcNow.AddSeconds(refreshWaitTime).ToBinary();
globalGameData.increaseCustomerTime = DateTime.UtcNow.AddSeconds(refreshWaitTime).ToBinary();
#if UNITY_EDITOR
gameData.increaseCustomerTime = DateTime.UtcNow.AddSeconds(10).ToBinary();
globalGameData.increaseCustomerTime = DateTime.UtcNow.AddSeconds(10).ToBinary();
#endif
gameData.AddUseAdWalker();
cityGameData.AddUseAdWalker();
GameDataManager.SaveGameData();
customerRewardTimerUpdateSubject.OnNext(Unit.Default);
});
@ -161,39 +173,38 @@ public class MarketManager : MonoBehaviour
{
market.VipAction();
// 現在時刻に設定して期限切れにする
gameData.vipCustomerLimitTime = DateTime.UtcNow.ToBinary();
globalGameData.vipCustomerLimitTime = DateTime.UtcNow.ToBinary();
vipTimerUpdateSubject.OnNext(Unit.Default);
}, () =>
{
// 現在時刻に設定して期限切れにする
gameData.vipCustomerLimitTime = DateTime.UtcNow.ToBinary();
globalGameData.vipCustomerLimitTime = DateTime.UtcNow.ToBinary();
vipTimerUpdateSubject.OnNext(Unit.Default);
});
}).AddTo(this);
// onNextをトリガーに実行
customerRewardTimerUpdateSubject
.Select(_ => (int) DateTime.FromBinary(gameData.increaseCustomerTime).Subtract(DateTime.UtcNow).TotalSeconds)
.StartWith()
.Select(_ => (int) DateTime.FromBinary(globalGameData.increaseCustomerTime).Subtract(DateTime.UtcNow).TotalSeconds)
.Subscribe(time =>
{
rewardButtonView.ResetTimer(time);
}).AddTo(this);
if (DateTime.FromBinary(gameData.vipCustomerLimitTime) >= DateTime.UtcNow)
if (DateTime.FromBinary(globalGameData.vipCustomerLimitTime) >= DateTime.UtcNow)
{
vipCustomerButtonView.ShowButton(gameData.vipCustomerFirstOpen);
gameData.vipCustomerFirstOpen = false;
vipCustomerButtonView.ShowButton(globalGameData.vipCustomerFirstOpen);
globalGameData.vipCustomerFirstOpen = false;
vipTimerUpdateSubject
.Select(_ => (int) DateTime.FromBinary(gameData.vipCustomerLimitTime).Subtract(DateTime.UtcNow).TotalSeconds)
.StartWith()
.Select(_ => (int) DateTime.FromBinary(globalGameData.vipCustomerLimitTime).Subtract(DateTime.UtcNow).TotalSeconds)
.Subscribe(time =>
{
vipCustomerButtonView.ResetTimer(time);
}).AddTo(this);
}
customerRewardTimerUpdateSubject.OnNext(Unit.Default);
vipTimerUpdateSubject.OnNext(Unit.Default);
// アプリ復帰時に残り時間更新
Observable.EveryApplicationPause()
.Where(pause => !pause)
@ -222,11 +233,12 @@ public class MarketManager : MonoBehaviour
market.SellObservable.Subscribe(coin =>
{
// コイン獲得エフェクト
blueView.SellAction();
if (coin == 0) return;
CoinEffect(coin, pos =>
{
CoinManager.Instance.AddCoinWithEffect(coin, pos);
});
blueView.SellAction();
}).AddTo(this);
market.SellOrderSubject.Subscribe(orders =>
@ -240,37 +252,32 @@ public class MarketManager : MonoBehaviour
market.RefillSubject.Subscribe(x =>
{
stockView.SetStock(gameData.StorageTanks);
stockView.SetStock(market.GetUsedStorageCapacity());
if (x.isReorder)
{
// 陳列表示更新(陳列13=650ms,7=350ms)
var stocks = market.ShuffledOrder.Select(i => (i, market.DisplayFlavors[i])).ToList();
cartView.SetStock(stocks, true);
return;
}
else
{
var isError = false;
// 補充したフレーバーのスキンを設定
foreach (var order in x.refillList)
{
if (order >= market.DisplayFlavors.Count)
{
isError = true;
Debug.LogError($@"mismatch order:{order}, displayFlavors:{market.DisplayFlavors.Count}");
continue;
}
cartView.Refill(order, market.DisplayFlavors[order]);
}
if (isError)
// 補充したフレーバーのスキンを設定
foreach (var order in x.refillList)
{
if (order >= market.DisplayFlavors.Count)
{
Debug.LogError($@"list
shopStock: {gameData.ShopStock.Aggregate("", (s, data) => $"{s},{data.FlavorId}")}
continue;
}
cartView.Refill(order, market.DisplayFlavors[order]);
}
#if UNITY_EDITOR || DEVELOPMENT_BUILD
if (x.refillList.DefaultIfEmpty().Max() < market.DisplayFlavors.Count) return;
Debug.LogError($@"list
displayFlavors: {market.DisplayFlavors.Aggregate("", (s, data) => $"{s},{data.FlavorId}")}
refillList: {x.refillList.Aggregate("", (s, order) => $"{s},{order}")}");
throw new Exception("RefillList Invalid");
}
}
throw new Exception("RefillList Invalid");
#endif
}).AddTo(this);
// 開閉店
@ -281,58 +288,66 @@ displayFlavors: {market.DisplayFlavors.Aggregate("", (s, data) => $"{s},{data.Fl
}).AddTo(this);
// 試食看板はStart時非表示
signBoardView.SetActiveTastingBoard(false);
// signBoardView.SetActiveTastingBoard(false);
// 宣伝ボタン/試食表示切替
var tastingComplete = new Subject<Unit>().AddTo(this);
IDisposable tastingDisposable = null;
market.CurrentShopState
.SkipWhile(_ => !gameData.FinishedFlags.HasFlag(TutorialFlag.FirstPlay))
.CombineLatest(market.IsPromotion, tastingComplete, (shopState, isPromotion, _) => (shopState == ShopState.Open, isPromotion))
.SkipWhile(_ => !globalGameData.FinishedFlags.HasFlag(TutorialFlag.FirstPlay))
.CombineLatest(market.IsPromotion, tastingComplete, (shopState, isPromotion, _) => (shopState == ShopState.Close, isPromotion))
.Subscribe(x =>
{
var (isOpen, isPromotion) = x;
if (isOpen)
var (isClose, isPromotion) = x;
if (isClose || isPartTimer)
{
if (isPromotion)
{
signBoardView.SetActiveTastingBoard(false);
// 宣伝ボタン表示
rewardButtonView.gameObject.SetActive(true);
BrotherPinkView.Instance.StartPromotion();
}
else if (gameData.TastingCount > 0)
{
rewardButtonView.gameObject.SetActive(false);
// 試食表示
signBoardView.SetActiveTastingBoard(true);
BrotherPinkView.Instance.StartTasting();
BrotherPinkView.Instance.SetTastingCount(gameData.TastingCount);
signBoardView.SetTimer(gameData.TastingCount * (int)market.TastingCustomerInterval, () =>
{
BrotherPinkView.Instance.SetTastingCount(gameData.TastingCount);
}, () =>
BrotherPinkView.Instance.StopTasting();
rewardButtonView.gameObject.SetActive(false);
// signBoardView.CancelTasting();
tastingDisposable?.Dispose();
// VIP宣伝を非表示
globalGameData.vipCustomerLimitTime = DateTime.UtcNow.ToBinary();
vipTimerUpdateSubject.OnNext(Unit.Default);
return;
}
if (isPromotion)
{
// signBoardView.SetActiveTastingBoard(false);
// 宣伝ボタン表示
rewardButtonView.gameObject.SetActive(true);
BrotherPinkView.Instance.StartPromotion();
return;
}
if (cityGameData.TastingCount > 0)
{
rewardButtonView.gameObject.SetActive(false);
// 試食表示
// signBoardView.SetActiveTastingBoard(true);
BrotherPinkView.Instance.StartTasting();
BrotherPinkView.Instance.SetTastingCount(cityGameData.TastingCount);
var remaining = cityGameData.TastingCount * (int)market.TastingCustomerInterval;
tastingDisposable = Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(1f))
.TakeWhile(x => (int)(remaining - x) >= 0)
.Subscribe(_ => BrotherPinkView.Instance.SetTastingCount(cityGameData.TastingCount), () =>
{
// 試食タイマーが終わったら表示更新トリガー
tastingComplete.OnNext(Unit.Default);
BrotherPinkView.Instance.StopTasting();
});
}
else // 宣伝も試食も未発動
{
BrotherPinkView.Instance.StopTasting();
rewardButtonView.gameObject.SetActive(true);
}
}).AddTo(this);
// signBoardView.SetTimer(gameData.TastingCount * (int)market.TastingCustomerInterval,
// () => { BrotherPinkView.Instance.SetTastingCount(gameData.TastingCount); }, () =>
// {
// // 試食タイマーが終わったら表示更新トリガー
// tastingComplete.OnNext(Unit.Default);
// BrotherPinkView.Instance.StopTasting();
// });
return;
}
else // 閉店
{
BrotherPinkView.Instance.StopTasting();
rewardButtonView.gameObject.SetActive(false);
signBoardView.CancelTasting();
// 宣伝も試食も未発動
BrotherPinkView.Instance.StopTasting();
rewardButtonView.gameObject.SetActive(true);
// VIP宣伝を非表示
gameData.vipCustomerLimitTime = DateTime.UtcNow.ToBinary();
vipTimerUpdateSubject.OnNext(Unit.Default);
}
}).AddTo(this);
// CombineLatest動かすのに必要
tastingComplete.OnNext(Unit.Default);
@ -462,6 +477,7 @@ displayFlavors: {market.DisplayFlavors.Aggregate("", (s, data) => $"{s},{data.Fl
}).AddTo(customerAnimator);
var eventTrigger = customerAnimator.gameObject.AddComponent<ObservableEventTrigger>();
eventTrigger.OnPointerClickAsObservable()
.Where(_ => !isPartTimer)
.Take(1)
.Subscribe(_ =>
{

View File

@ -14,12 +14,10 @@ public class ShopStockView : MonoBehaviour
textObject.SetActive(false);
}
public void SetStock(List<StorageTank> tanks)
public void SetStock(float value)
{
var totalCapacity = tanks.Sum(x => x.Capacity);
var totalStock = tanks.Sum(x => x.Stock);
var newPos = popcornImage.transform.localPosition;
newPos.y = Mathf.Lerp(minPosision, maxPosision, (float) totalStock / totalCapacity);
newPos.y = Mathf.Lerp(minPosision, maxPosision, value);
popcornImage.transform.localPosition = newPos;
}

View File

@ -1,8 +1,11 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using MyGame.Scripts;
using UniRx;
using UnityEngine;
using Debug = UnityEngine.Debug;
namespace MyGame.Scenes.marketing.Scripts
{
@ -19,18 +22,63 @@ namespace MyGame.Scenes.marketing.Scripts
private readonly Dictionary<int, Market> cityMarketDict = new();
private void Start()
{
#if UNITY_EDITOR
var newGameData = GameDataUtils.CreateCityData(2);
newGameData.IsFundingCompleted = true;
newGameData.Heart = 0;
#endif
// 各都市マーケット生成
var latestCityId = GameDataUtils.GetLatestCityId();
CreateMarket(Const.DefaultCityId).CheckPartTimerMode();
foreach (var (cityId, gameData) in GameDataManager.GameData.CityGameDataDict)
{
if (!gameData.IsFundingCompleted) return;
var market = CreateMarket(cityId);
market.CheckPartTimerMode();
market.SetLatestCity(cityId == latestCityId);
}
}
private Market CreateMarket(int cityId)
{
var market = Instantiate(marketPrefab, transform);
cityMarketDict.Add(Const.DefaultCityId, market);
market.Initialize(cityId);
cityMarketDict.Add(cityId, market);
return market;
}
public Market GetMarket(int cityId)
{
return cityMarketDict[Const.DefaultCityId];
return cityMarketDict[cityId];
}
public Market GetCurrentCityMarket()
{
return cityMarketDict[Const.DefaultCityId];
return cityMarketDict[GameDataManager.GameData.CurrentCityId];
}
/// <summary>
/// 選択中の都市と、最新の都市以外のMarketの動きを止める
/// </summary>
/// <param name="currentCityId"></param>
public void UpdateCurrentCity(int currentCityId)
{
var latestCityId = GameDataUtils.GetLatestCityId();
foreach (var (cityId, market) in cityMarketDict)
{
if (cityId == currentCityId || cityId == latestCityId)
{
market.IsPause.Value = false;
continue;
}
market.IsPause.Value = true;
}
}
public void SetActiveMarket(int cityId, bool active)
{
cityMarketDict[cityId].IsPause.Value = !active;
}
/// <summary>
@ -39,7 +87,10 @@ namespace MyGame.Scenes.marketing.Scripts
/// <param name="bonusList"></param>
public void UpdateBonus(Dictionary<ShopCustomizeBonusCategory, (int bonusLevel, int value)> bonusList)
{
cityMarketDict[Const.DefaultCityId].UpdateBonus(bonusList);
foreach (var (_, market) in cityMarketDict)
{
market.UpdateBonus(bonusList);
}
}
public void ResetGameData(GameData gameData)
@ -47,6 +98,7 @@ namespace MyGame.Scenes.marketing.Scripts
cityMarketDict[Const.DefaultCityId].ResetGameData(gameData);
}
[Conditional("UNITY_EDITOR"), Conditional("DEVELOPMENT_BUILD")]
public static void StockFlavorLog(int cityId = -1)
{
if (GameDataManager.GetCityGameData(cityId) is not {} cityGameData)