타이쿤 업데이트

This commit is contained in:
Nam Tae Gun 2025-02-18 06:47:56 +09:00
parent bf08756a77
commit 62f936092d
248 changed files with 59128 additions and 26776 deletions

File diff suppressed because it is too large Load Diff

View File

@ -26,12 +26,12 @@ namespace DDD.BehaviorTrees.Actions
return TaskStatus.Success;
}
var emptyServingTable = tycoonManager.ServingTableController.FindEmptyServingTable();
if (emptyServingTable)
{
_serverCrew.OnMission(emptyServingTable, null, ActionType.PlaceOnServingTable);
return TaskStatus.Success;
}
// var emptyServingTable = tycoonManager.ServingTableController.FindEmptyServingTable();
// if (emptyServingTable)
// {
// _serverCrew.OnMission(emptyServingTable, null, ActionType.PlaceOnServingTable);
// return TaskStatus.Success;
// }
return TaskStatus.Running;
}

View File

@ -1,6 +1,7 @@
using System;
using BehaviorDesigner.Runtime.Tasks;
using DDD.Npcs.Customers;
using DDD.Tycoons;
using UnityEngine;
using Action = BehaviorDesigner.Runtime.Tasks.Action;
@ -25,7 +26,7 @@ namespace DDD.BehaviorTrees.Actions
public override TaskStatus OnUpdate()
{
if (_elapsedTime <= _customer.CurrentLevelData.EatingTime)
if (_elapsedTime <= TycoonManager.Instance.TycoonStageController.StageDataSo.EatingTime)
{
_elapsedTime += Time.deltaTime;
return TaskStatus.Running;

View File

@ -81,7 +81,7 @@ namespace DDD.Npcs.Crews.Bartender
public void SetBartenderTable(BartenderTable bartenderTable)
{
MyBartenderTable = bartenderTable;
MyBartenderTable.Active();
//MyBartenderTable.Active();
}
public void SetOrderedCustomer(Customer orderedCustomer)
@ -111,7 +111,7 @@ namespace DDD.Npcs.Crews.Bartender
OrderedCustomer.CurrentBill.BartenderCompleteMakingCocktail();
}
MyBartenderTable.CompleteMakingCocktail(_makingCocktailData);
//MyBartenderTable.CompleteMakingCocktail(_makingCocktailData);
EventManager.InvokeCocktailCompleted(_makingCocktailData, false);
ResetMission();
}

View File

@ -8,8 +8,10 @@ using DDD.Items;
using DDD.Npcs.Crews;
using DDD.Npcs.Crews.Server;
using DDD.Players;
using DDD.ScriptableObjects;
using DDD.Tycoons;
using DDD.Uis;
using DDD.Uis.Tycoon;
using Pathfinding;
using PixelCrushers.DialogueSystem;
using Sirenix.OdinInspector;
@ -59,7 +61,7 @@ namespace DDD.Npcs.Customers
public enum CustomerInteractionType
{
None = 0,
ServedCocktail
OrderedCook
}
public enum CustomerSkin
@ -138,6 +140,9 @@ namespace DDD.Npcs.Customers
[field: SerializeField]
public CocktailData OrderedCocktailData { get; private set; }
[field: SerializeField]
public CraftRecipeData OrderedCraftRecipeData { get; private set; }
[field: SerializeField]
public Bill CurrentBill { get; private set; }
@ -345,61 +350,6 @@ namespace DDD.Npcs.Customers
};
VisualLook.localScale = localScale;
}
public void SetTableSeat(TableSeat tableSeat)
{
CurrentTableSeat = tableSeat;
}
public void SetCurrentDirection(Vector3 normalDirection) => CurrentDirection = normalDirection;
public void SetTableSeatPositionAndDirection()
{
transform.position = CurrentTableSeat.SeatTransform.position;
CurrentTableSeat.OccupySeat();
CurrentTableSeat.UnreserveSeat();
SetCurrentDirection(CurrentTableSeat.TableDirection);
}
public void ServedItem(CocktailData cocktailData)
{
CurrentTableSeat.MenuBalloonUi.ReceiveItem(cocktailData);
if (IsOrderedCorrected)
{
CurrentTableSeat.SetFood(cocktailData.Sprite);
StateMachineController.TransitionToState(HappyState, this);
int tip;
if (IsServedPlayer)
{
if (TycoonManager.Instance.TycoonStatus.ContainsPassiveCard(PassiveCard.ServingBonus))
{
TycoonManager.Instance.TycoonStageController.ServingBonus();
}
tip = (int)(CurrentLevelData.Gold * TycoonManager.Instance.TycoonStatus.TipMultiplier);
}
else
{
tip = (int)(CurrentLevelData.Gold * TycoonManager.Instance.TycoonStatus.ServerTipMultiplier);
}
if (tip > 0)
{
var payMoneyUi = Instantiate(_payMoneyUiObject, transform.position + _offset,
Quaternion.identity, TycoonUiManager.Instance.WorldCanvas.transform);
payMoneyUi.Initialize(tip, true);
}
}
else
{
StateMachineController.TransitionToState(UpsetState, this);
}
EventManager.InvokeCocktailServedToCustomer(cocktailData, IsServedPlayer);
EventManager.InvokeOrderResult(this, IsOrderedCorrected);
EventManager.InvokeSucceedServing(IsOrderedCorrected);
EventManager.InvokeCheckedSkin(CustomerSkin);
}
public void Interaction()
{
@ -407,14 +357,15 @@ namespace DDD.Npcs.Customers
{
case CustomerInteractionType.None:
break;
case CustomerInteractionType.ServedCocktail:
var currentPickupItem = GameManager.Instance.CurrentTycoonPlayer.TycoonPickupHandler.CurrentPickupItem;
case CustomerInteractionType.OrderedCook:
CraftRecipeData playerPickupCook = GameManager.Instance.CurrentTycoonPlayer.TycoonPickupHandler.CurrentCraftRecipeData;
//var servedCocktailData = ItemManager.Instance.CocktailDataSo.GetDataByIdx(currentPickupItem.Idx);
IsOrderedCorrected = currentPickupItem.Idx == OrderedCocktailData.Idx;
//IsOrderedCorrected = currentPickupItem.Idx == OrderedCocktailData.Idx;
IsReceivedItem = true;
IsServedPlayer = true;
AudioManager.Instance.PlaySfx(IsOrderedCorrected ? _succeedServingSfxName : _failedServingSfxName);
//ServedItem(servedCocktailData);
IsOrderedCorrected = true;
AudioManager.Instance.PlaySfx(_succeedServingSfxName);
ServedItem(playerPickupCook);
break;
default:
throw new ArgumentOutOfRangeException();
@ -429,9 +380,9 @@ namespace DDD.Npcs.Customers
{
case CustomerInteractionType.None:
return false;
case CustomerInteractionType.ServedCocktail:
var currentPickupItem = GameManager.Instance.CurrentTycoonPlayer.TycoonPickupHandler.CurrentPickupItem;
return currentPickupItem != null;
case CustomerInteractionType.OrderedCook:
CraftRecipeData playerPickupCook = GameManager.Instance.CurrentTycoonPlayer.TycoonPickupHandler.CurrentCraftRecipeData;
return playerPickupCook?.Idx == OrderedCraftRecipeData.Idx;
default:
throw new ArgumentOutOfRangeException();
}
@ -490,6 +441,85 @@ namespace DDD.Npcs.Customers
_customerInteractionType = CustomerInteractionType.None;
}
public void OrderCook()
{
IsReceivedItem = false;
OrderedCraftRecipeData = FindAnyObjectByType<MenuBoardUi>().GetRandomTodayMenu();
HurryTime = CurrentLevelData.HurryTime + TycoonManager.Instance.TycoonStatus.CustomerHurryTimeIncrease;
CurrentTableSeat.OrderCook(OrderedCraftRecipeData, isReverse:true);
_customerInteractionType = CustomerInteractionType.OrderedCook;
RegisterPlayerInteraction();
EventManager.InvokeOrderedCocktail(this);
// if (!ES3.Load(SaveData.TutorialB, false))
// {
// EventManager.InvokeTutorial(TutorialName.TutorialB);
// ES3.Save(SaveData.TutorialB, true);
// }
//
// if (!ES3.Load(SaveData.TutorialJ, false) && OrderedCocktailData.Idx == "Cocktail006")
// {
// EventManager.InvokeTutorial(TutorialName.TutorialJ);
// ES3.Save(SaveData.TutorialJ, true);
// }
}
public void SetTableSeat(TableSeat tableSeat)
{
CurrentTableSeat = tableSeat;
}
public void SetCurrentDirection(Vector3 normalDirection) => CurrentDirection = normalDirection;
public void SetTableSeatPositionAndDirection()
{
transform.position = CurrentTableSeat.SeatTransform.position;
CurrentTableSeat.OccupySeat();
CurrentTableSeat.UnreserveSeat();
SetCurrentDirection(CurrentTableSeat.TableDirection);
}
public void ServedItem(CraftRecipeData craftRecipeData)
{
CurrentTableSeat.MenuBalloonUi.ReceiveItem();
if (IsOrderedCorrected)
{
CurrentTableSeat.SetFood(craftRecipeData.Sprite);
StateMachineController.TransitionToState(HappyState, this);
// int tip;
// if (IsServedPlayer)
// {
// if (TycoonManager.Instance.TycoonStatus.ContainsPassiveCard(PassiveCard.ServingBonus))
// {
// TycoonManager.Instance.TycoonStageController.ServingBonus();
// }
//
// tip = (int)(CurrentLevelData.Gold * TycoonManager.Instance.TycoonStatus.TipMultiplier);
// }
// else
// {
// tip = (int)(CurrentLevelData.Gold * TycoonManager.Instance.TycoonStatus.ServerTipMultiplier);
// }
//
// if (tip > 0)
// {
// var payMoneyUi = Instantiate(_payMoneyUiObject, transform.position + _offset,
// Quaternion.identity, TycoonUiManager.Instance.WorldCanvas.transform);
// payMoneyUi.Initialize(tip, true);
// }
}
else
{
StateMachineController.TransitionToState(UpsetState, this);
}
EventManager.InvokeServedCookToCustomer();
EventManager.InvokeServedResult(this, IsOrderedCorrected);
//EventManager.InvokeSucceedServing(IsOrderedCorrected);
//EventManager.InvokeCheckedSkin(CustomerSkin);
}
public void Bark(string conversation, BarkOrder barkOrder = BarkOrder.Random)
{
@ -525,7 +555,7 @@ namespace DDD.Npcs.Customers
CurrentTableSeat.CleanTable();
}
GainExp();
//GainExp();
}
private void GainExp()
@ -541,11 +571,11 @@ namespace DDD.Npcs.Customers
_moneyCounter.AddCurrentGold(gold);
if (!ES3.Load(SaveData.TutorialC, false))
{
EventManager.InvokeTutorial(TutorialName.TutorialC);
ES3.Save(SaveData.TutorialC, true);
}
// if (!ES3.Load(SaveData.TutorialC, false))
// {
// EventManager.InvokeTutorial(TutorialName.TutorialC);
// ES3.Save(SaveData.TutorialC, true);
// }
}
public void Vomit()
@ -577,7 +607,7 @@ namespace DDD.Npcs.Customers
OrderedCocktailData = TycoonManager.Instance.TycoonIngredientController.GetRandomCocktailData();
HurryTime = CurrentLevelData.HurryTime + TycoonManager.Instance.TycoonStatus.CustomerHurryTimeIncrease;
CurrentTableSeat.OrderCocktail(OrderedCocktailData.Idx, CurrentLevelData.WaitTime, HurryTime, true);
_customerInteractionType = CustomerInteractionType.ServedCocktail;
_customerInteractionType = CustomerInteractionType.OrderedCook;
RegisterPlayerInteraction();
EventManager.InvokeOrderedCocktail(this);

View File

@ -70,6 +70,14 @@ namespace DDD.Players.Tycoons
{
return TycoonPlayerSpineAnimation.AttackLimeTree;
}
if (character.IsCookingFried)
{
return TycoonPlayerSpineAnimation.CookingFried;
}
if (character.IsCookingStew)
{
return TycoonPlayerSpineAnimation.CookingStew;
}
return null;
}

View File

@ -1,4 +1,5 @@
using DDD.Interfaces;
using DDD.ScriptableObjects;
using Sirenix.OdinInspector;
using UnityEngine;
@ -15,7 +16,11 @@ namespace DDD.Players.Tycoons
[field: SerializeField]
public bool IsPickedUpItem { get; private set; }
[field: SerializeField]
public bool IsPickedUpCook { get; private set; }
public IPickup CurrentPickupItem { get; private set; }
public CraftRecipeData CurrentCraftRecipeData { get; private set; }
private void Awake()
{
@ -107,5 +112,59 @@ namespace DDD.Players.Tycoons
CurrentPickupItem = item;
EventManager.InvokeChangedPickupItem(CurrentPickupItem?.Idx);
}
public bool PickupCook(CraftRecipeData craftRecipeData)
{
if (IsPickedUpCook)
{
Debug.Log("이미 밀키트를 들고 있습니다.");
return false;
}
SetCurrentCraftRecipeData(craftRecipeData);
IsUnfinishedCocktailPickedUp = false;
_itemRenderer.enabled = false;
//_itemRenderer.sprite = item.Sprite;
IsPickedUpCook = true;
return true;
}
public void InteractionCraftingTool()
{
CurrentCraftRecipeData.CraftingToolQueue.Dequeue();
if (CurrentCraftRecipeData.CraftingToolQueue.Count <= 0)
{
// TODO : 요리 완성 처리
EventManager.InvokeChangedCraftingTool(null);
}
else
{
EventManager.InvokeChangedCraftingTool(CurrentCraftRecipeData.CraftingToolQueue.Peek());
}
}
public void DiscardCook()
{
SetCurrentCraftRecipeData(null);
_itemRenderer.sprite = null;
IsPickedUpCook = false;
}
public void SetCurrentCraftRecipeData(CraftRecipeData craftRecipeData)
{
CurrentCraftRecipeData = craftRecipeData;
EventManager.InvokeChangedPickupItem(CurrentCraftRecipeData?.Idx);
if (CurrentCraftRecipeData == null || CurrentCraftRecipeData.CraftingToolQueue.Count <= 0)
{
EventManager.InvokeChangedCraftingTool(null);
}
else
{
EventManager.InvokeChangedCraftingTool(CurrentCraftRecipeData.CraftingToolQueue.Peek());
}
}
}
}

View File

@ -1,5 +1,6 @@
using DDD.Interfaces;
using DDD.Items;
using DDD.ScriptableObjects;
using DDD.Tycoons;
using DDD.Uis;
using Sirenix.OdinInspector;
@ -11,16 +12,18 @@ namespace DDD.Players.Tycoons
public static class TycoonPlayerSpineAnimation
{
public const string Idle = "Idle";
public const string Walking = "Run";
public const string ServingIdle = "ServingIdle";
public const string Serving = "Serving";
public const string Walking = "RunFast";
public const string ServingIdle = "Serving/ServingIdle";
public const string Serving = "Serving/ServingFast";
public const string Dash = "Dash";
public const string CleaningFloor = "CleaningFloor";
public const string CleaningTable = "CleaningTable";
public const string CleaningFloor = "Cleaning/CleaningFloor";
public const string CleaningTable = "Cleaning/CleaningTable";
public const string MakingCocktail = "BeerMaker";
public const string Pumping = "AttackWhip";
public const string AttackSlime = "AttackSlime";
public const string AttackLimeTree = "AttackBat";
public const string Pumping = "Attack/AttackWhip";
public const string AttackSlime = "Attack/AttackSlime";
public const string AttackLimeTree = "Attack/AttackBat";
public const string CookingFried = "Cooking/CookingFried";
public const string CookingStew = "Cooking/CookingStew";
}
[DefaultExecutionOrder(-1)]
@ -75,6 +78,8 @@ namespace DDD.Players.Tycoons
public bool IsPumping { get; set; }
public bool IsInteractedSlimeGarnish { get; set; }
public bool IsInteractedLimeTreeGarnish { get; set; }
public bool IsCookingFried { get; set; }
public bool IsCookingStew { get; set; }
// State
public StateMachineController<TycoonPlayer> StateMachineController { get; private set; }
@ -107,6 +112,10 @@ namespace DDD.Players.Tycoons
EventManager.OnChangedRandomCocktail += ChangeCocktail;
EventManager.OnPickupCocktail += PickupCocktail;
EventManager.OnPlaceOnServingTable += PlaceOnServingTable;
// 밀키트 이벤트
EventManager.OnPickupMealKit += PickupCook;
EventManager.OnServedCookToCustomer += ServedCook;
TycoonMovement.OnSucceedDash += DashSucceed;
@ -139,6 +148,10 @@ namespace DDD.Players.Tycoons
EventManager.OnPickupCocktail -= PickupCocktail;
EventManager.OnPlaceOnServingTable -= PlaceOnServingTable;
// 밀키트 이벤트
EventManager.OnPickupMealKit -= PickupCook;
EventManager.OnServedCookToCustomer -= ServedCook;
TycoonMovement.OnSucceedDash -= DashSucceed;
}
@ -200,6 +213,21 @@ namespace DDD.Players.Tycoons
TycoonPickupHandler.PickupItem(cocktailData, true);
InteractionCanvas.BalloonUi.SetItemImage(cocktailData);
}
public void PickupCook(CraftRecipeData craftRecipeData)
{
bool succeedPickUp = TycoonPickupHandler.PickupCook(craftRecipeData);
if (succeedPickUp)
{
InteractionCanvas.BalloonUi.SetItemImage(craftRecipeData.Sprite);
}
}
public void ServedCook()
{
TycoonPickupHandler.DiscardCook();
InteractionCanvas.BalloonUi.DiscardItem();
}
public void PlaceOnServingTable()
{
@ -237,7 +265,7 @@ namespace DDD.Players.Tycoons
public bool IsInteracting()
{
return IsMakingCocktail || IsCleaningFloor || IsCleaningTable || IsCleaningMold || IsPumping ||
IsInteractedSlimeGarnish || IsInteractedLimeTreeGarnish;
IsInteractedSlimeGarnish || IsInteractedLimeTreeGarnish || IsCookingFried || IsCookingStew;
}
#endregion

View File

@ -9,61 +9,61 @@ namespace DDD.Tycoons
{
public class BartenderTable : ServingTable
{
[SerializeField]
private Sprite _activeSprite;
// [SerializeField]
// private Sprite _activeSprite;
//
// [SerializeField]
// private Sprite _inactiveSprite;
//
// protected override void Awake()
// {
// base.Awake();
//
// VisualLook.sprite = _inactiveSprite;
// }
//
// public void Active()
// {
// VisualLook.sprite = _activeSprite;
// }
//
// public override void Interaction()
// {
// // 테이블의 칵테일을 가져가는 경우
// if (CurrentPickupItem != null)
// {
// //CocktailData currentCocktailData = ItemManager.Instance.CocktailDataSo.GetDataByIdx(CurrentPickupItem.Idx);
// //EventManager.InvokePickupCocktail(currentCocktailData);
// CocktailGlassImage.sprite = null;
// CocktailGlassImage.enabled = false;
// // InteractionCanvas.BalloonUi.DiscardItem();
// CurrentPickupItem = null;
// OrderedCustomer = null;
// }
// }
[SerializeField]
private Sprite _inactiveSprite;
protected override void Awake()
{
base.Awake();
VisualLook.sprite = _inactiveSprite;
}
public void Active()
{
VisualLook.sprite = _activeSprite;
}
public override void Interaction()
{
// 테이블의 칵테일을 가져가는 경우
if (CurrentPickupItem != null)
{
//CocktailData currentCocktailData = ItemManager.Instance.CocktailDataSo.GetDataByIdx(CurrentPickupItem.Idx);
//EventManager.InvokePickupCocktail(currentCocktailData);
CocktailGlassImage.sprite = null;
CocktailGlassImage.enabled = false;
// InteractionCanvas.BalloonUi.DiscardItem();
CurrentPickupItem = null;
OrderedCustomer = null;
}
}
// public override bool CanInteraction()
// {
// return CurrentPickupItem != null && !CurrentTycoonPlayer.TycoonPickupHandler.IsPickedUpAnything();
// }
public override bool CanInteraction()
{
return CurrentPickupItem != null && !CurrentTycoonPlayer.TycoonPickupHandler.IsPickedUpAnything();
}
public override bool CanInteractionCrew(Crew crew = null)
{
var servingCrew = (ServerCrew)crew;
if (!servingCrew)
{
throw new Exception("상호작용 오브젝트 오류");
}
return servingCrew.CurrentActionType == ActionType.TakeCocktail && CurrentPickupItem != null && OrderedCustomer;
}
public void CompleteMakingCocktail(IPickup cocktailData)
{
CurrentPickupItem = cocktailData;
CocktailGlassImage.sprite = CurrentPickupItem.Sprite;
CocktailGlassImage.enabled = true;
// InteractionCanvas.BalloonUi.SetItemImage(CurrentPickupItem);
}
// public override bool CanInteractionCrew(Crew crew = null)
// {
// var servingCrew = (ServerCrew)crew;
// if (!servingCrew)
// {
// throw new Exception("상호작용 오브젝트 오류");
// }
//
// return servingCrew.CurrentActionType == ActionType.TakeCocktail && CurrentPickupItem != null && OrderedCustomer;
// }
//
// public void CompleteMakingCocktail(IPickup cocktailData)
// {
// CurrentPickupItem = cocktailData;
// CocktailGlassImage.sprite = CurrentPickupItem.Sprite;
// CocktailGlassImage.enabled = true;
// // InteractionCanvas.BalloonUi.SetItemImage(CurrentPickupItem);
// }
}
}

View File

@ -178,7 +178,7 @@ namespace DDD.Tycoons
{
if (IsMoldy)
{
UpdateLocalizedString("InteractionMold");
InteractionMessage = Utils.GetLocalizedString("InteractionMold");
}
else
{

View File

@ -1,184 +0,0 @@
using System;
using System.Collections;
using DDD.Audios;
using DDD.Interfaces;
using DDD.Items;
using DDD.Npcs.Crews;
using DDD.Npcs.Crews.Server;
using DDD.Npcs.Customers;
using DDD.Utility;
using UnityEngine;
using UnityEngine.Serialization;
namespace DDD.Tycoons
{
public class ServingTable : InteractionFurniture, ICrewInteraction
{
[FormerlySerializedAs("_cocktailGlassImage")]
[SerializeField]
protected SpriteRenderer CocktailGlassImage;
[SerializeField]
private string _putDownSfxName = "PutDownCocktail";
// 서빙 테이블 기준 아이템이 있는지 없는지
private IPickup _currentPickupItem;
public IPickup CurrentPickupItem
{
get => _currentPickupItem;
protected set
{
_currentPickupItem = value;
if (_currentPickupItem != null)
{
Utils.StartUniqueCoroutine(this, ref _findCustomerMatchingItemInstance, FindCustomerMatchingItem());
}
else
{
if (_findCustomerMatchingItemInstance != null)
{
StopCoroutine(_findCustomerMatchingItemInstance);
_findCustomerMatchingItemInstance = null;
}
if (_findServerCrewInstance != null)
{
StopCoroutine(_findServerCrewInstance);
_findServerCrewInstance = null;
}
}
}
}
protected Customer OrderedCustomer;
private Material _originalCocktailGlassMaterial;
private Coroutine _findCustomerMatchingItemInstance;
private Coroutine _findServerCrewInstance;
public event Action OnInteractionCompleted;
protected override void Awake()
{
base.Awake();
_originalCocktailGlassMaterial = CocktailGlassImage.material;
CocktailGlassImage.sprite = null;
CocktailGlassImage.enabled = false;
}
public override void Interaction()
{
// 테이블의 칵테일을 가져가는 경우
if (CurrentPickupItem != null)
{
//CocktailData currentCocktailData = ItemManager.Instance.CocktailDataSo.GetDataByIdx(CurrentPickupItem.Idx);
//EventManager.InvokePickupCocktail(currentCocktailData);
CocktailGlassImage.sprite = null;
CocktailGlassImage.enabled = false;
// InteractionCanvas.BalloonUi.DiscardItem();
CurrentPickupItem = null;
OrderedCustomer = null;
}
// 테이블에 칵테일을 놓는 경우
else
{
AudioManager.Instance.PlaySfx(_putDownSfxName);
CurrentPickupItem = CurrentTycoonPlayer.TycoonPickupHandler.CurrentPickupItem;
CocktailGlassImage.sprite = CurrentPickupItem.Sprite;
CocktailGlassImage.enabled = true;
// InteractionCanvas.BalloonUi.SetItemImage(CurrentPickupItem);
EventManager.InvokePlaceOnServingTable();
}
}
public override bool CanInteraction()
{
// 1. 테이블에 칵테일이 있고, 플레이어가 칵테일을 들고 있지 않은 경우
// 2. 테이블에 칵테일이 없고, 플레이어가 칵테일을 들고 있는 경우 (정상적인 칵테일만)
return (CurrentPickupItem != null && !CurrentTycoonPlayer.TycoonPickupHandler.IsPickedUpAnything()) ||
(CurrentPickupItem == null && CurrentTycoonPlayer.TycoonPickupHandler.IsServablePickupItem());
}
public override void ShowInteractionUi()
{
if (CurrentPickupItem != null)
{
UpdateLocalizedString("InteractionServingTablePickUp");
}
else
{
UpdateLocalizedString("InteractionServingTablePutDown");
}
base.ShowInteractionUi();
CocktailGlassImage.material = OutlineMaterial;
}
public override void HideInteractionUi()
{
base.HideInteractionUi();
CocktailGlassImage.material = _originalCocktailGlassMaterial;
}
public void InteractionCrew(Crew crew)
{
// 종업원이 테이블의 칵테일을 가져가는 경우
if (CurrentPickupItem != null)
{
var serverCrew = (ServerCrew)crew;
serverCrew.TakeFromServingTable(CurrentPickupItem, OrderedCustomer);
CocktailGlassImage.enabled = false;
// InteractionCanvas.BalloonUi.DiscardItem();
CurrentPickupItem = null;
OrderedCustomer = null;
}
// 종업원이 테이블에 칵테일을 놓는 경우
else
{
var serverCrew = (ServerCrew)crew;
CurrentPickupItem = serverCrew.CurrentPickupItem;
CocktailGlassImage.sprite = CurrentPickupItem.Sprite;
CocktailGlassImage.enabled = true;
// InteractionCanvas.BalloonUi.SetItemImage(CurrentPickupItem);
serverCrew.ResetMission();
}
}
public void CancelInteractionCrew()
{
throw new NotImplementedException();
}
public virtual bool CanInteractionCrew(Crew crew = null)
{
var servingCrew = (ServerCrew)crew;
if (!servingCrew)
{
throw new Exception("상호작용 오브젝트 오류");
}
return (servingCrew.CurrentActionType == ActionType.TakeCocktail && CurrentPickupItem != null && OrderedCustomer) ||
servingCrew.CurrentActionType == ActionType.PlaceOnServingTable && CurrentPickupItem == null;
}
private IEnumerator FindCustomerMatchingItem()
{
var waitTime = new WaitForSeconds(2f);
while (true)
{
OrderedCustomer = TycoonManager.Instance.CustomerController.FindCustomerMatchingItem(_currentPickupItem);
if (OrderedCustomer && OrderedCustomer.CanInteractionCrew())
{
var crewController = TycoonManager.Instance.CrewController;
Utils.StartUniqueCoroutine(this, ref _findServerCrewInstance,
crewController.FindClosestCrewCoroutine(CenterTransform.position, crewController.ServerCrews,
crew => crew.OnMission(this, OrderedCustomer, ActionType.TakeCocktail)));
}
yield return waitTime;
}
}
}
}

View File

@ -2,6 +2,7 @@ using DDD.Audios;
using DDD.Interfaces;
using DDD.Items;
using DDD.Players;
using DDD.Utility;
using Sirenix.OdinInspector;
using UnityEngine;
@ -169,11 +170,11 @@ namespace DDD.Tycoons
{
if (_isChanged)
{
UpdateLocalizedString("InteractionTrashCanChange");
InteractionMessage = Utils.GetLocalizedString("InteractionTrashCanChange");
}
else
{
UpdateLocalizedString("InteractionTrashCanDiscard");
InteractionMessage = Utils.GetLocalizedString("InteractionTrashCanDiscard");
}
_spineController.EnableCustomMaterial();

View File

@ -172,7 +172,7 @@ namespace DDD.Tycoons
foreach (var element in BartenderCrews)
{
if (element.MyBartenderTable.CurrentPickupItem != null || element.IsOnMission) continue;
// if (element.MyBartenderTable.CurrentPickupItem != null || element.IsOnMission) continue;
var orderedCocktailIngredients = orderedCocktailData.ValidIngredients;
if (!tycoonIngredientController.IsMakingCocktail(orderedCocktailIngredients)) break;

View File

@ -27,11 +27,11 @@ namespace DDD.Tycoons
if (_customerTableRoot)
{
_customerTables = _customerTableRoot.GetComponentsInChildren<CustomerTable>().ToList();
_customerTables = _customerTableRoot.GetComponentsInChildren<CustomerTable>(false).ToList();
for (var i = 0; i < _customerTables.Count; i++)
{
HideCustomerTable(i);
ShowCustomerTable(i);
}
}
}

View File

@ -17,9 +17,9 @@ namespace DDD.Tycoons
//_servingTables = _servingTableRoot.GetComponentsInChildren<ServingTable>().ToList();
}
public ServingTable FindEmptyServingTable()
{
return _servingTables.FirstOrDefault(element => element.CurrentPickupItem == null);
}
// public ServingTable FindEmptyServingTable()
// {
// return _servingTables.FirstOrDefault(element => element.CurrentPickupItem == null);
// }
}
}

View File

@ -8,6 +8,12 @@ namespace DDD.Tycoons
[field: SerializeField]
public float WaitTimeInStarted { get; private set; } = 5f;
[field: SerializeField]
public float CustomerDelay { get; private set; } = 5f;
[field: SerializeField]
public float EatingTime { get; private set; } = 10f;
[field: SerializeField]
public float VomitingPercent { get; private set; } = 10f;

View File

@ -2,6 +2,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
using DDD.Items;
using DDD.Uis.Tycoon;
using DDD.Utility;
using Sirenix.OdinInspector;
using UnityEngine;
@ -34,6 +35,7 @@ namespace DDD.Tycoons
private bool _isClosedTime;
private TycoonManager _tycoonManager;
private MenuBoardUi _menuBoardUi;
private Coroutine _startStageCoroutineInstance;
private TimeSpan _closedTime;
@ -41,6 +43,8 @@ namespace DDD.Tycoons
private void Awake()
{
_menuBoardUi = FindAnyObjectByType<MenuBoardUi>();
EventManager.OnTycoonGameStarted += StartStage;
EventManager.OnMakeCocktailCompleted += AddInstanceCocktail;
EventManager.OnCocktailServedToCustomer += RemoveInstanceCocktail;
@ -78,13 +82,13 @@ namespace DDD.Tycoons
private IEnumerator StartStageCoroutine()
{
yield return new WaitForSeconds(StageDataSo.WaitTimeInStarted);
while (true)
int orderedCount = _menuBoardUi.GetTodayMenusCount();
while (orderedCount > 0)
{
var currentLevelData = _tycoonManager.GetCurrentLevelData();
EventManager.InvokeCreateCustomer();
orderedCount--;
yield return new WaitForSeconds(currentLevelData.CustomerRespawn);
yield return new WaitForSeconds(StageDataSo.CustomerDelay);
}
}

View File

@ -1,6 +1,8 @@
using System;
using DDD.Interfaces;
using DDD.Items;
using DDD.Managers;
using DDD.ScriptableObjects;
using DG.Tweening;
using Sirenix.OdinInspector;
using UnityEngine;
@ -47,6 +49,7 @@ namespace DDD.Uis
private bool _isItemReceived;
public CocktailData OrderCocktailData { get; private set; }
public CraftRecipeData OrderedCraftRecipeData { get; private set; }
private Tween _fillTween;
private Color _previousColor;
@ -82,6 +85,12 @@ namespace DDD.Uis
SetItemSprite(item.Sprite);
ShowUi();
}
public void SetItemImage(Sprite sprite)
{
SetItemSprite(sprite);
ShowUi();
}
private void ResetUi()
{
@ -108,13 +117,27 @@ namespace DDD.Uis
ResetUi();
}
public void OrderItem(string itemIdx, float waitTime, float hurryTime, bool isReverse = false)
public void OrderCook(CraftRecipeData orderedCraftRecipeData, float waitTime, float hurryTime, bool isReverse = false)
{
//OrderCocktailData = ItemManager.Instance.CocktailDataSo.GetDataByIdx(itemIdx);
OrderedCraftRecipeData = orderedCraftRecipeData;
_isOrdered = true;
_isWaitTimeOver = false;
_isItemReceived = false;
SetItemImage(OrderCocktailData);
SetItemImage(OrderedCraftRecipeData.Sprite);
_fillImage.fillAmount = 1f;
UpdateFillColor(_fillImage.fillAmount);
// SetTween(waitTime, hurryTime, isReverse);
}
public void OrderItem(string itemIdx, float waitTime, float hurryTime, bool isReverse = false)
{
//OrderCocktailData
_isOrdered = true;
_isWaitTimeOver = false;
_isItemReceived = false;
//SetItemSprite(itemIdx);
ShowUi();
SetTween(waitTime, hurryTime, isReverse);
}
@ -132,12 +155,13 @@ namespace DDD.Uis
public void OrderItem(float waitTime, float hurryTime, bool isReverse = false)
{
_fillImage.fillAmount = 1f;
_isOrdered = true;
_isWaitTimeOver = false;
_isItemReceived = false;
ShowUi();
SetTween(waitTime, hurryTime, isReverse);
//SetTween(waitTime, hurryTime, isReverse);
}
public void SetTween(float waitTime, float hurryTime, bool isReverse = false)
@ -182,7 +206,7 @@ namespace DDD.Uis
public bool IsWaitServing() => !_isItemReceived && _isOrdered && !_isWaitTimeOver;
public bool IsFoodReceive() => _isItemReceived;
public void ReceiveItem(IPickup pickupItem)
public void ReceiveItem()
{
HideUi();
SetEmpty();

View File

@ -82,7 +82,7 @@ namespace DDD
_maxDistance = Vector3.Distance(_rect.anchoredPosition, billInfoPosition0);
_slider.value = 1f;
_slider.gameObject.SetActive(true);
_orderImage.sprite = customer.OrderedCocktailData.Sprite;
_orderImage.sprite = customer.OrderedCraftRecipeData.Sprite;
_orderImage.gameObject.SetActive(true);
_makingCocktailPivotObject.SetActive(false);
_checkImageObject.SetActive(false);
@ -90,7 +90,7 @@ namespace DDD
_tableNumberText.text = customer.CurrentTableSeat.TableNumber.ToString();
_tableNumberImageObject.SetActive(true);
SetTween(customer.CurrentLevelData.WaitTime, customer.HurryTime);
// SetTween(customer.CurrentLevelData.WaitTime, customer.HurryTime);
}
public void SetTween(int waitTime, int hurryTime)

View File

@ -48,6 +48,9 @@ namespace DDD.Uis
_customerBills.ItemRemoved += UpdateBillInfo;
EventManager.OnOrderedCocktail += OrderedCocktail;
EventManager.OnOrderResult += OrderResult;
EventManager.OnOrderedCook += OrderedCook;
EventManager.OnServedResult += OrderResult;
}
private void OnDestroy()
@ -56,6 +59,9 @@ namespace DDD.Uis
_customerBills.ItemRemoved -= UpdateBillInfo;
EventManager.OnOrderedCocktail -= OrderedCocktail;
EventManager.OnOrderResult -= OrderResult;
EventManager.OnOrderedCook -= OrderedCook;
EventManager.OnServedResult -= OrderResult;
}
private void OrderedCocktail(Customer customer)
@ -67,6 +73,16 @@ namespace DDD.Uis
instance.Initialize(customer, _spawnPosition, _billInfos[0].Position, () => _customerBills.Remove(newKeyValuePair));
customer.SetCurrentBill(instance);
}
private void OrderedCook(Customer customer)
{
var instance = Instantiate(_billPrefab, _spawnLocation);
var newKeyValuePair = new KeyValuePair<Customer, Bill>(customer, instance);
_customerBills.Add(newKeyValuePair);
instance.Initialize(customer, _spawnPosition, _billInfos[0].Position, () => _customerBills.Remove(newKeyValuePair));
customer.SetCurrentBill(instance);
}
private void OrderResult(Customer customer, bool isCorrected)
{

View File

@ -112,10 +112,10 @@ namespace DDD.Uis
AudioManager.Instance.PlayBgm(_dailyBgm);
}
if (!ES3.Load(SaveData.TutorialA, false))
{
Invoke(nameof(InvokeTutorialA), 1f);
}
// if (!ES3.Load(SaveData.TutorialA, false))
// {
// Invoke(nameof(InvokeTutorialA), 1f);
// }
});
});
});

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8f1a3dacb5e0a8948a7c8753fb197253
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 712e72dfac34cb544ab0a4b2ee5adb47
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 74b25efeacf2e3848aa1b38d2ca181f1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,38 @@
using System;
using BehaviorDesigner.Runtime.Tasks;
using DDD.Npcs.Customers;
using UnityEngine;
using Action = BehaviorDesigner.Runtime.Tasks.Action;
namespace DDD.BehaviorTrees.Actions
{
[TaskCategory("Custom/Npc/Customer")]
[Serializable]
public class EatCook : Action
{
private Customer _customer;
private float _elapsedTime;
public override void OnAwake()
{
_customer = GetComponent<Customer>();
}
public override void OnStart()
{
_elapsedTime = 0;
}
public override TaskStatus OnUpdate()
{
if (_elapsedTime <= _customer.CurrentLevelData.EatingTime)
{
_elapsedTime += Time.deltaTime;
return TaskStatus.Running;
}
_customer.FinishFood();
return TaskStatus.Success;
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 27e3b22e25bcbe247b86ff05d1d29a4d

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e60a123943f8cc44c87c627d6a44f534
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,32 @@
using System;
using BehaviorDesigner.Runtime.Tasks;
using DDD.Npcs.Customers;
namespace DDD.BehaviorTrees.Actions
{
[TaskCategory("Custom/Npc/Customer")]
[Serializable]
public class OrderCook : Conditional
{
private Customer _customer;
public override void OnAwake()
{
_customer = GetComponent<Customer>();
}
public override void OnStart()
{
_customer.OrderCook();
}
public override TaskStatus OnUpdate()
{
if (!_customer.IsReceivedItem) return TaskStatus.Running;
_customer.UnregisterPlayerInteraction();
return TaskStatus.Success;
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 1ad0550de46d2ae4496d3411913ea34c

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ea9d737d86859d040908dc9c73174024
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 26bfedb32002cfd4c85c4af23a8d5214
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -63,8 +63,8 @@ namespace DDD.Tycoons
public void Show()
{
_collider.enabled = true;
_carpetRenderer.sprite = _carpetOnSprite;
//_collider.enabled = true;
//_carpetRenderer.sprite = _carpetOnSprite;
_visualLookObject.SetActive(true);
foreach (var element in TableSeats)
@ -78,8 +78,8 @@ namespace DDD.Tycoons
public void Hide()
{
_collider.enabled = false;
_carpetRenderer.sprite = _carpetOffSprite;
//_collider.enabled = false;
//_carpetRenderer.sprite = _carpetOffSprite;
_visualLookObject.SetActive(false);
}
}

View File

@ -0,0 +1,91 @@
using System;
using System.Collections;
using System.Threading.Tasks;
using DDD.ScriptableObjects;
using Sirenix.OdinInspector;
using UnityEngine;
namespace DDD.Tycoons
{
[Serializable]
public class Frying : InteractionFurniture
{
[SerializeField]
private AnimationController _animationController;
[Title("연출")]
[SerializeField]
private Color _enableColor = Color.white;
[SerializeField]
private Color _disableColor = Color.gray;
private Material _instanceMaterial;
private CraftingTool _craftingTool = CraftingTool.Frying;
private const string IsEnabledHash = "isEnabled";
protected override void Start()
{
base.Start();
HoldingAction = SuccessHoldingAction;
_instanceMaterial = VisualLook.material;
VisualLook.material = Instantiate(_instanceMaterial);
EventManager.OnChangedCraftingTool += ChangeColor;
}
protected override void OnDestroy()
{
base.OnDestroy();
EventManager.OnChangedCraftingTool -= ChangeColor;
}
public override void Interaction()
{
base.Interaction();
GameManager.Instance.CurrentTycoonPlayer.IsCookingFried = true;
//_animationController.SetAnimationParameter(IsEnabledHash, true);
}
public override void CancelInteraction()
{
base.CancelInteraction();
GameManager.Instance.CurrentTycoonPlayer.IsCookingFried = false;
//_animationController.SetAnimationParameter(IsEnabledHash, false);
}
public override bool CanInteraction()
{
CraftRecipeData playerCraftRecipeData = CurrentTycoonPlayer.TycoonPickupHandler.CurrentCraftRecipeData;
if (playerCraftRecipeData == null || playerCraftRecipeData.CraftingToolQueue.Count <= 0) return false;
CraftingTool playerCraftingTool = playerCraftRecipeData.CraftingToolQueue.Peek();
return IsOpened && playerCraftingTool == _craftingTool;
}
private void SuccessHoldingAction()
{
CurrentTycoonPlayer.TycoonPickupHandler.InteractionCraftingTool();
CancelInteraction();
}
private async void ChangeColor(CraftingTool? playerCraftingTool)
{
await Task.Delay(100);
if (playerCraftingTool == null)
{
VisualLook.material.color = _enableColor;
}
else
{
VisualLook.material.color = (CraftingTool)playerCraftingTool == _craftingTool ? _enableColor : _disableColor;
}
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 79123d5b4a061a4448855b69ca24e1c6

View File

@ -1,11 +1,9 @@
using System;
using System.Collections;
using DDD.Interfaces;
using DDD.Players.Tycoons;
using DDD.Uis;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.Localization.Components;
namespace DDD.Tycoons
{
@ -24,9 +22,6 @@ namespace DDD.Tycoons
[field: SerializeField, BoxGroup("컴포넌트")]
public Material OutlineMaterial { get; private set; }
[field: SerializeField, BoxGroup("컴포넌트")]
public LocalizeStringEvent LocalizeStringEvent { get; protected set; }
[BoxGroup("변수")]
[field: SerializeField, BoxGroup("변수")]
public bool EnableInteraction { get; private set; } = true;
@ -37,6 +32,13 @@ namespace DDD.Tycoons
[field: SerializeField, BoxGroup("변수")]
public string InteractionMessage { get; set; }
[BoxGroup("상호작용")]
[field: SerializeField, BoxGroup("상호작용")]
public bool EnableHoldingInteraction;
[field: SerializeField, BoxGroup("상호작용")]
public float PlayerHoldingTime = 1f;
[Title("실시간 데이터")]
[SerializeField]
protected bool IsOpened;
@ -45,7 +47,9 @@ namespace DDD.Tycoons
protected Material OriginalMaterial;
protected bool IsQuitting;
protected bool IsShowing;
protected bool IsPlayerInteracting;
protected float HoldingElapsedTime;
protected Action HoldingAction;
private void OnDrawGizmosSelected()
{
@ -77,7 +81,36 @@ namespace DDD.Tycoons
{
}
protected void FixedUpdate()
{
if (!EnableHoldingInteraction) return;
if (IsShowing)
{
EventManager.InvokeHoldInteracting(HoldingElapsedTime);
}
if (HoldingElapsedTime > PlayerHoldingTime)
{
HoldingElapsedTime -= PlayerHoldingTime;
HoldingAction?.Invoke();
}
float playerHoldingDeltaTime = Time.deltaTime / PlayerHoldingTime;
if (IsPlayerInteracting)
{
HoldingElapsedTime += playerHoldingDeltaTime;
}
else
{
if (HoldingElapsedTime > 0f)
{
HoldingElapsedTime -= playerHoldingDeltaTime;
}
}
}
protected virtual void OnDisable()
{
if (IsQuitting) return;
@ -108,20 +141,28 @@ namespace DDD.Tycoons
VisualLook = transform.Find("VisualLook").GetComponent<SpriteRenderer>();
InteractionCanvas = transform.Find("InteractionCanvas").GetComponent<InteractionCanvas>();
LocalizeStringEvent = transform.GetComponent<LocalizeStringEvent>();
CurrentTycoonPlayer = GameManager.Instance.CurrentTycoonPlayer;
}
public abstract void Interaction();
public virtual void Interaction()
{
IsPlayerInteracting = true;
}
public virtual void CancelInteraction() { }
public virtual void CancelInteraction()
{
IsPlayerInteracting = false;
}
public virtual bool CanInteraction() => true;
public virtual void ShowInteractionUi()
{
VisualLook.material = OutlineMaterial;
if (OutlineMaterial)
{
VisualLook.material = OutlineMaterial;
}
EventManager.InvokeShowInteractionUi(InteractionMessage);
EventManager.InvokeHoldInteracting(HoldingElapsedTime);
IsShowing = true;
@ -129,7 +170,7 @@ namespace DDD.Tycoons
public virtual void HideInteractionUi()
{
if (VisualLook)
if (OutlineMaterial && VisualLook)
{
VisualLook.material = OriginalMaterial;
}
@ -162,30 +203,5 @@ namespace DDD.Tycoons
{
IsOpened = false;
}
protected void UpdateLocalizedString(string entryName)
{
if (!LocalizeStringEvent) return;
LocalizeStringEvent.StringReference.TableReference = "StringDataTable";
LocalizeStringEvent.StringReference.TableEntryReference = entryName;
StartCoroutine(LoadLocalizedString());
}
protected IEnumerator LoadLocalizedString()
{
var getLocalizedStringOperation = LocalizeStringEvent.StringReference.GetLocalizedStringAsync();
yield return getLocalizedStringOperation;
if (getLocalizedStringOperation.IsDone)
{
InteractionMessage = getLocalizedStringOperation.Result;
}
else
{
Debug.LogError("Failed to load localized string.");
}
}
}
}

View File

@ -17,6 +17,8 @@ namespace DDD.Tycoons
public override void Interaction()
{
base.Interaction();
_menuBoardUi.Open();
}

View File

@ -0,0 +1,89 @@
using System;
using System.Threading.Tasks;
using DDD.ScriptableObjects;
using Sirenix.OdinInspector;
using UnityEngine;
namespace DDD.Tycoons
{
[Serializable]
public class Pot : InteractionFurniture
{
[SerializeField]
private AnimationController _animationController;
[Title("연출")]
[SerializeField]
private Color _enableColor = Color.white;
[SerializeField]
private Color _disableColor = Color.gray;
private Material _instanceMaterial;
private CraftingTool _craftingTool = CraftingTool.Pot;
private const string IsEnabledHash = "isEnabled";
protected override void Start()
{
base.Start();
HoldingAction = SuccessHoldingAction;
_instanceMaterial = VisualLook.material;
VisualLook.material = Instantiate(_instanceMaterial);
EventManager.OnChangedCraftingTool += ChangeColor;
}
protected override void OnDestroy()
{
base.OnDestroy();
EventManager.OnChangedCraftingTool -= ChangeColor;
}
public override void Interaction()
{
base.Interaction();
GameManager.Instance.CurrentTycoonPlayer.IsCookingStew = true;
_animationController.SetAnimationParameter(IsEnabledHash, true);
}
public override void CancelInteraction()
{
base.CancelInteraction();
GameManager.Instance.CurrentTycoonPlayer.IsCookingStew = false;
_animationController.SetAnimationParameter(IsEnabledHash, false);
}
public override bool CanInteraction()
{
CraftRecipeData playerCraftRecipeData = CurrentTycoonPlayer.TycoonPickupHandler.CurrentCraftRecipeData;
if (playerCraftRecipeData == null || playerCraftRecipeData.CraftingToolQueue.Count <= 0) return false;
CraftingTool playerCraftingTool = playerCraftRecipeData.CraftingToolQueue.Peek();
return IsOpened && playerCraftingTool == _craftingTool;
}
private void SuccessHoldingAction()
{
CurrentTycoonPlayer.TycoonPickupHandler.InteractionCraftingTool();
CancelInteraction();
}
private async void ChangeColor(CraftingTool? playerCraftingTool)
{
await Task.Delay(100);
if (playerCraftingTool == null)
{
VisualLook.material.color = _enableColor;
}
else
{
VisualLook.material.color = (CraftingTool)playerCraftingTool == _craftingTool ? _enableColor : _disableColor;
}
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 31db3e16bd7611d46899027f48aa0349

View File

@ -0,0 +1,25 @@
using System;
using DDD.Uis.Tycoon;
using UnityEngine;
namespace DDD.Tycoons
{
[Serializable]
public class Refrigerator : InteractionFurniture
{
[SerializeField]
private MealKitUi _mealKitUi;
public override void Interaction()
{
base.Interaction();
_mealKitUi.Open();
}
public override bool CanInteraction()
{
return IsOpened && _mealKitUi.CanOpen() && !CurrentTycoonPlayer.TycoonPickupHandler.IsPickedUpCook;
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 699ff6e4c09966148b659b8a1595c0e4

View File

@ -0,0 +1,11 @@
using System.Collections.Generic;
using UnityEngine;
namespace DDD.Tycoons
{
public class ServingTable : MonoBehaviour
{
[field: SerializeField]
public List<ServingTableSeat> ServingTableSeats { get; private set; } = new(2);
}
}

View File

@ -0,0 +1,93 @@
using System.Collections.Generic;
using DDD.Audios;
using DDD.ScriptableObjects;
using DDD.Utility;
using UnityEngine;
namespace DDD.Tycoons
{
public class ServingTableSeat : InteractionFurniture
{
[SerializeField]
private List<SpriteRenderer> _outlineRenderers = new();
[SerializeField]
private string _putDownSfxName = "PutDownCocktail";
public CraftRecipeData CurrentCraftRecipeData { get; private set; }
private List<Material> _originalMaterials;
protected override void Awake()
{
base.Awake();
VisualLook.sprite = null;
VisualLook.enabled = false;
_originalMaterials = new List<Material>(_outlineRenderers.Count);
for (int i = 0; i < _outlineRenderers.Count; i++)
{
_originalMaterials.Add(_outlineRenderers[i].material);
}
}
public override void Interaction()
{
// 테이블의 칵테일을 가져가는 경우
if (CurrentCraftRecipeData != null)
{
CurrentTycoonPlayer.PickupCook(CurrentCraftRecipeData);
VisualLook.sprite = null;
VisualLook.enabled = false;
CurrentCraftRecipeData = null;
}
// 테이블에 칵테일을 놓는 경우
else
{
AudioManager.Instance.PlaySfx(_putDownSfxName);
CurrentCraftRecipeData = CurrentTycoonPlayer.TycoonPickupHandler.CurrentCraftRecipeData;
VisualLook.sprite = CurrentCraftRecipeData.Sprite;
VisualLook.enabled = true;
CurrentTycoonPlayer.ServedCook();
}
}
public override bool CanInteraction()
{
// 1. 테이블에 음식이 있고, 플레이어가 음식을 들고 있지 않은 경우
// 2. 테이블에 음식이 없고, 플레이어가 음식을 들고 있는 경우
return (CurrentCraftRecipeData != null && !CurrentTycoonPlayer.TycoonPickupHandler.IsPickedUpCook) ||
(CurrentCraftRecipeData == null && CurrentTycoonPlayer.TycoonPickupHandler.IsPickedUpCook);
}
public override void ShowInteractionUi()
{
if (CurrentCraftRecipeData != null)
{
InteractionMessage = Utils.GetLocalizedString("InteractionServingTablePickUp");
}
else
{
InteractionMessage = Utils.GetLocalizedString("InteractionServingTablePutDown");
}
base.ShowInteractionUi();
for (int i = 0; i < _outlineRenderers.Count; i++)
{
_outlineRenderers[i].material = OutlineMaterial;
}
}
public override void HideInteractionUi()
{
base.HideInteractionUi();
for (int i = 0; i < _outlineRenderers.Count; i++)
{
_outlineRenderers[i].material = _originalMaterials[i];
}
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d627e8f515556f74eb5297b0bec9819c

View File

@ -3,6 +3,7 @@ using DDD.Audios;
using DDD.Interfaces;
using DDD.Npcs.Crews;
using DDD.Npcs.Crews.Cleaner;
using DDD.ScriptableObjects;
using DDD.Uis;
using DDD.Utility;
using Sirenix.OdinInspector;
@ -222,9 +223,9 @@ namespace DDD.Tycoons
InteractionCanvas.BalloonUi.OrderItem(0, TycoonManager.Instance.TycoonStageController.StageDataSo.DirtyTableWaitTime);
IsCleaned = false;
var crewController = TycoonManager.Instance.CrewController;
Utils.StartUniqueCoroutine(this, ref _findCleanerCrewInstance,
crewController.FindClosestCrewCoroutine(CenterTransform.position, crewController.CleanerCrews, crew => crew.OnMission(this)));
// var crewController = TycoonManager.Instance.CrewController;
// Utils.StartUniqueCoroutine(this, ref _findCleanerCrewInstance,
// crewController.FindClosestCrewCoroutine(CenterTransform.position, crewController.CleanerCrews, crew => crew.OnMission(this)));
}
public void Purify()
@ -263,6 +264,12 @@ namespace DDD.Tycoons
CleanTable();
}
public void OrderCook(CraftRecipeData orderedCraftRecipeData, float waitTime = float.PositiveInfinity, float hurryTime = float.PositiveInfinity, bool isReverse = false)
{
MenuBalloonUi.OrderCook(orderedCraftRecipeData, waitTime, hurryTime, isReverse);
ChangeMenuColor(GameManager.Instance.CurrentTycoonPlayer.TycoonPickupHandler.CurrentCraftRecipeData?.Idx);
}
public void OrderCocktail(string itemIdx, float waitTime, float hurryTime, bool isReverse = false)
{
@ -274,7 +281,7 @@ namespace DDD.Tycoons
{
if (MenuBalloonUi.gameObject.activeInHierarchy)
{
if (idx == null || (MenuBalloonUi.IsWaitServing() && MenuBalloonUi.OrderCocktailData?.Idx == idx))
if (idx == null || (MenuBalloonUi.IsWaitServing() && MenuBalloonUi.OrderedCraftRecipeData?.Idx == idx))
{
ChangeMenuOriginalColor();
}

View File

@ -0,0 +1,30 @@
using System;
using DDD.Uis.Tycoon;
namespace DDD.Tycoons
{
[Serializable]
public class TycoonSwitch : InteractionFurniture
{
private MenuBoardUi _menuBoardUi;
protected override void Awake()
{
base.Awake();
_menuBoardUi = FindAnyObjectByType<MenuBoardUi>();
}
public override void Interaction()
{
base.Interaction();
EventManager.InvokeTycoonGameStarted();
}
public override bool CanInteraction()
{
return !IsOpened && _menuBoardUi.CanOpen();
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 9bf1e24eedd5ff848967d5e84b77e145

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using DDD.Interfaces;
using DDD.Uis.Tycoon;
using Newtonsoft.Json;
@ -68,6 +69,10 @@ namespace DDD.ScriptableObjects
[field: SerializeField, Tooltip("제작 순서"), BoxGroup("Json 데이터 영역")]
public int CraftOrder { get; set; }
[JsonProperty]
[field: SerializeField, Tooltip("해시 태그"), BoxGroup("Json 데이터 영역")]
public string HashTag { get; set; }
[BoxGroup("직접 추가하는 영역")]
[JsonIgnore]
[field: SerializeField, BoxGroup("직접 추가하는 영역")]
@ -75,12 +80,36 @@ namespace DDD.ScriptableObjects
[JsonIgnore]
[field: SerializeField]
public List<CraftingIngredient> ValidIngredients { get; set; } = new(3);
public List<CraftingIngredient> ValidIngredients { get; set; }
[JsonIgnore]
[field: ShowInInspector]
public Queue<CraftingTool> CraftingToolQueue { get; set; } = new(4);
public Queue<CraftingTool> CraftingToolQueue { get; set; }
[JsonIgnore]
[field: SerializeField]
public List<string> ValidHashTags { get; set; }
public CraftRecipeData(CraftRecipeData copy)
{
Idx = copy.Idx;
Name = copy.Name;
Description = copy.Description;
Price = copy.Price;
IngredientIdx1 = copy.IngredientIdx1;
IngredientCount1 = copy.IngredientCount1;
IngredientIdx2 = copy.IngredientIdx2;
IngredientCount2 = copy.IngredientCount2;
IngredientIdx3 = copy.IngredientIdx3;
IngredientCount3 = copy.IngredientCount3;
CraftOrder = copy.CraftOrder;
HashTag = copy.HashTag;
Sprite = copy.Sprite;
ValidIngredients = new List<CraftingIngredient>(copy.ValidIngredients);
CraftingToolQueue = new Queue<CraftingTool>(copy.CraftingToolQueue);
ValidHashTags = new List<string>(copy.ValidHashTags);
}
public List<CraftingIngredient> GetValidIngredients()
{
List<CraftingIngredient> newList = new List<CraftingIngredient>();
@ -119,5 +148,14 @@ namespace DDD.ScriptableObjects
}
return newQueue;
}
public List<string> GetValidHashTags()
{
List<string> newList = new List<string>(3);
newList = HashTag.Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList();
return newList;
}
}
}

View File

@ -13,6 +13,7 @@ namespace DDD.ScriptableObjects
{
element.ValidIngredients = element.GetValidIngredients();
element.CraftingToolQueue = element.GetCraftingToolQueue();
element.ValidHashTags = element.GetValidHashTags();
}
}
}

View File

@ -26,10 +26,14 @@ MonoBehaviour:
<IngredientIdx3>k__BackingField:
<IngredientCount3>k__BackingField: 0
<CraftOrder>k__BackingField: 12
<HashTag>k__BackingField: HashTag001, HashTag002
<Sprite>k__BackingField: {fileID: 0}
<ValidIngredients>k__BackingField:
- <Idx>k__BackingField: Ingredient001
<Count>k__BackingField: 1
<ValidHashTags>k__BackingField:
- HashTag001
- HashTag002
- <Key>k__BackingField: CraftRecipe002
<Value>k__BackingField:
<Idx>k__BackingField: CraftRecipe002
@ -43,12 +47,17 @@ MonoBehaviour:
<IngredientIdx3>k__BackingField:
<IngredientCount3>k__BackingField: 0
<CraftOrder>k__BackingField: 3
<Sprite>k__BackingField: {fileID: 0}
<HashTag>k__BackingField: HashTag003, HashTag004, HashTag005
<Sprite>k__BackingField: {fileID: 21300000, guid: 471f30d31984bb64d929cf9cd729f5f3, type: 3}
<ValidIngredients>k__BackingField:
- <Idx>k__BackingField: Ingredient002
<Count>k__BackingField: 1
- <Idx>k__BackingField: Ingredient004
<Count>k__BackingField: 2
<ValidHashTags>k__BackingField:
- HashTag003
- HashTag004
- HashTag005
- <Key>k__BackingField: CraftRecipe003
<Value>k__BackingField:
<Idx>k__BackingField: CraftRecipe003
@ -62,6 +71,7 @@ MonoBehaviour:
<IngredientIdx3>k__BackingField: Ingredient001
<IngredientCount3>k__BackingField: 1
<CraftOrder>k__BackingField: 34
<HashTag>k__BackingField: HashTag006, HashTag007
<Sprite>k__BackingField: {fileID: 0}
<ValidIngredients>k__BackingField:
- <Idx>k__BackingField: Ingredient003
@ -70,6 +80,9 @@ MonoBehaviour:
<Count>k__BackingField: 2
- <Idx>k__BackingField: Ingredient001
<Count>k__BackingField: 1
<ValidHashTags>k__BackingField:
- HashTag006
- HashTag007
- <Key>k__BackingField: CraftRecipe004
<Value>k__BackingField:
<Idx>k__BackingField: CraftRecipe004
@ -82,7 +95,8 @@ MonoBehaviour:
<IngredientCount2>k__BackingField: 2
<IngredientIdx3>k__BackingField: Ingredient008
<IngredientCount3>k__BackingField: 1
<CraftOrder>k__BackingField: 34
<CraftOrder>k__BackingField: 32
<HashTag>k__BackingField: HashTag006, HashTag007, HashTag008
<Sprite>k__BackingField: {fileID: 21300000, guid: 12a978bb397d4194a9795a3daf6fad84, type: 3}
<ValidIngredients>k__BackingField:
- <Idx>k__BackingField: Ingredient006
@ -91,6 +105,10 @@ MonoBehaviour:
<Count>k__BackingField: 2
- <Idx>k__BackingField: Ingredient008
<Count>k__BackingField: 1
<ValidHashTags>k__BackingField:
- HashTag006
- HashTag007
- HashTag008
- <Key>k__BackingField: CraftRecipe005
<Value>k__BackingField:
<Idx>k__BackingField: CraftRecipe005
@ -103,11 +121,15 @@ MonoBehaviour:
<IngredientCount2>k__BackingField: 0
<IngredientIdx3>k__BackingField:
<IngredientCount3>k__BackingField: 0
<CraftOrder>k__BackingField: 12
<CraftOrder>k__BackingField: 23
<HashTag>k__BackingField: HashTag009, HashTag010
<Sprite>k__BackingField: {fileID: 21300000, guid: 1002a5b83127f3c43a8cfdf2f8567473, type: 3}
<ValidIngredients>k__BackingField:
- <Idx>k__BackingField: Ingredient011
<Count>k__BackingField: 1
<ValidHashTags>k__BackingField:
- HashTag009
- HashTag010
- <Key>k__BackingField: CraftRecipe006
<Value>k__BackingField:
<Idx>k__BackingField: CraftRecipe006
@ -121,9 +143,13 @@ MonoBehaviour:
<IngredientIdx3>k__BackingField:
<IngredientCount3>k__BackingField: 0
<CraftOrder>k__BackingField: 3
<HashTag>k__BackingField: HashTag011, HashTag012
<Sprite>k__BackingField: {fileID: 21300000, guid: 1921548edfb697e4c813502ad856e15d, type: 3}
<ValidIngredients>k__BackingField:
- <Idx>k__BackingField: Ingredient008
<Count>k__BackingField: 1
- <Idx>k__BackingField: Ingredient0010
- <Idx>k__BackingField: Ingredient010
<Count>k__BackingField: 2
<ValidHashTags>k__BackingField:
- HashTag011
- HashTag012

View File

@ -1,16 +0,0 @@
using UnityEngine;
public class MenuIngre : MonoBehaviour
{
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}

View File

@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: aa95d22b420ae1d41bd189e9efaf3ac8

View File

@ -209,8 +209,6 @@ namespace DDD.Uis.Tycoon
DataManager.Instance.Inventory.RemoveItem(slot, CraftableCount * ingredient.Count);
}
EventManager.OnAddedTodayMenu?.Invoke(CurrentCraftRecipeData, CraftableCount);
Close();
}
}

View File

@ -242,7 +242,6 @@ namespace DDD.Uis.Tycoon
public override void Open()
{
print("add 오픈");
AddedCount = 1;
if (_currentTodayMenu.IsAddedMenu)
{
@ -293,7 +292,6 @@ namespace DDD.Uis.Tycoon
{
if (IsAddedMenu)
{
print("메뉴 등록");
// 메뉴 등록
if (IsCraftable)
{
@ -304,7 +302,6 @@ namespace DDD.Uis.Tycoon
}
else
{
print("레시피 선택");
// 레시피 선택
_menuButton.onClick.Invoke();
}
@ -359,6 +356,19 @@ namespace DDD.Uis.Tycoon
_nameText.text = AddedCraftRecipeData.Name;
_descriptionText.text = Utils.GetLocalizedString(AddedCraftRecipeData.Description);
_countText.text = $"{AddedCount}/{_maxCraftingCount}";
int validHashTagCount = AddedCraftRecipeData.ValidHashTags.Count;
for (int i = 0; i < _maxHashTagCount; i++)
{
if (i >= validHashTagCount)
{
_menuHashTags[i].HideUi();
continue;
}
_menuHashTags[i].SetTag(AddedCraftRecipeData.ValidHashTags[i]);
_menuHashTags[i].ShowUi();
}
IsAddedMenu = true;
}

View File

@ -33,6 +33,7 @@ namespace DDD.Uis.Tycoon
private AddIngredientUi _addIngredientUi;
[Title("오늘의 메뉴")]
[SerializeField]
private int _maxTodayMenuCount = 6;
[Title("실시간 데이터")]

View File

@ -1,6 +1,5 @@
using DDD.ScriptableObjects;
using Sirenix.OdinInspector;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
@ -9,9 +8,9 @@ namespace DDD.Uis.Tycoon
{
public class CraftRecipeButton : MonoBehaviour
{
[Title("컴포넌트")]
[SerializeField]
private Button _button;
[field: Title("컴포넌트")]
[field: SerializeField]
public Button Button { get; private set; }
[SerializeField]
private Image _image;
@ -30,14 +29,14 @@ namespace DDD.Uis.Tycoon
public void RegisterButtonListener(UnityAction clickAction)
{
_clickAction = clickAction;
_button.onClick.AddListener(_clickAction);
Button.onClick.AddListener(_clickAction);
}
private void UnregisterButtonListener()
{
if (_clickAction == null) return;
_button.onClick.RemoveListener(_clickAction);
Button.onClick.RemoveListener(_clickAction);
_clickAction = null;
}
@ -53,7 +52,7 @@ namespace DDD.Uis.Tycoon
public void OnClicked()
{
_button.onClick.Invoke();
Button.onClick.Invoke();
}
private void UpdateIngredients()

View File

@ -65,6 +65,8 @@ namespace DDD.Uis.Tycoon
craftRecipeButton.SetCraftRecipeData(craftRecipeData);
_craftRecipeButtons.Add(craftRecipeButton);
}
SetNavigationCraftRecipeButtons();
_panel.SetActive(false);
}
@ -121,7 +123,6 @@ namespace DDD.Uis.Tycoon
private void OnInteractionE(InputAction.CallbackContext context)
{
print("레시피 선택 E키");
if (!EventSystem.current) return;
GameObject currentObject = EventSystem.current.currentSelectedGameObject;
@ -132,10 +133,54 @@ namespace DDD.Uis.Tycoon
private void OnClickedCraftRecipe(CraftRecipeButton clickedCraftRecipeButton)
{
print("레시피 선택 버튼 클릭");
CurrentCraftRecipeButton = clickedCraftRecipeButton;
Close();
}
private void SetNavigationCraftRecipeButtons()
{
int columnCount = 4;
int totalCount = ItemManager.Instance.AcquiredCraftRecipeDatas.Count;
for (int i = 0; i < totalCount; i++)
{
Navigation navigation = _craftRecipeButtons[i].Button.navigation;
navigation.mode = Navigation.Mode.Explicit;
// 상(Up) 버튼 설정
int upIndex = i - columnCount;
if (upIndex >= 0)
{
navigation.selectOnUp = _craftRecipeButtons[upIndex].Button;
}
// 하(Down) 버튼 설정
int downIndex = i + columnCount;
if (downIndex < totalCount)
{
navigation.selectOnDown = _craftRecipeButtons[downIndex].Button;
}
// 좌(Left) 버튼 설정
int leftIndex = i - 1;
// 같은 행(=i/columnCount)이면 연결, 그렇지 않다면 연결 X
if (leftIndex >= 0 && (leftIndex / columnCount) == (i / columnCount))
{
navigation.selectOnLeft = _craftRecipeButtons[leftIndex].Button;
}
// 우(Right) 버튼 설정
int rightIndex = i + 1;
// 같은 행(=i/columnCount)이면 연결, 그렇지 않다면 연결 X
if (rightIndex < totalCount && (rightIndex / columnCount) == (i / columnCount))
{
navigation.selectOnRight = _craftRecipeButtons[rightIndex].Button;
}
// 설정한 내비게이션 정보를 버튼에 반영
_craftRecipeButtons[i].Button.navigation = navigation;
}
}
public void SetSelectRecipeAction(UnityAction selectRecipeAction) => _selectRecipeAction = selectRecipeAction;
}

View File

@ -0,0 +1,87 @@
using DDD.ScriptableObjects;
using Sirenix.OdinInspector;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
namespace DDD.Uis.Tycoon
{
public class MealKitButton : MonoBehaviour
{
[field: Title("컴포넌트")]
[field: SerializeField]
public Button Button { get; private set; }
[SerializeField]
private Image _image;
[SerializeField]
private TMP_Text _countText;
[Title("연출")]
[SerializeField]
private Color _enableColor = Color.white;
[SerializeField]
private Color _disableColor = Color.gray;
[field: Title("레시피 데이터")]
[field: SerializeField]
public CraftRecipeData CraftRecipeData { get; private set; }
[field: SerializeField]
public int Count { get; private set; }
private UnityAction _clickAction;
private void OnDestroy()
{
UnregisterButtonListener();
}
public void RegisterButtonListener(UnityAction clickAction)
{
_clickAction = clickAction;
Button.onClick.AddListener(_clickAction);
}
private void UnregisterButtonListener()
{
if (_clickAction == null) return;
Button.onClick.RemoveListener(_clickAction);
_clickAction = null;
}
public void SetMealKit(CraftRecipeData craftRecipeData, int count)
{
CraftRecipeData = craftRecipeData;
Count = count;
UpdateUi();
}
private void UpdateUi()
{
Button.interactable = Count > 0;
_image.sprite = CraftRecipeData?.Sprite;
_countText.text = Count.ToString();
Button.targetGraphic.color = Button.interactable ? _enableColor : _disableColor;
_image.color = Button.interactable ? _enableColor : _disableColor;
}
public bool CanInteraction()
{
return CraftRecipeData != null && Count > 0 && Button.interactable;
}
public void PickupMealKit()
{
Count--;
UpdateUi();
}
public void ShowUi() => gameObject.SetActive(true);
public void HideUi() => gameObject.SetActive(false);
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 0f9e325c61194864da05f41c9ded8809

View File

@ -0,0 +1,277 @@
using System.Collections.Generic;
using System.Linq;
using DDD.ScriptableObjects;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
using UnityEngine.UI;
namespace DDD.Uis.Tycoon
{
public class MealKitUi : PopupUi
{
[Title("프리팹")]
[SerializeField]
private MealKitButton _mealKitButtonPrefab;
[Title("컴포넌트")]
[SerializeField]
private GameObject _panel;
[SerializeField]
private GameObject _mealKitsLocation;
[Title("클래스")]
[SerializeField]
private UiEventsController _uiEventsController;
[Title("데이터")]
[SerializeField]
private int _maxMealKitCount = 6;
[Title("실시간 데이터")]
[SerializeField]
private List<MealKitButton> _mealKitButtons;
private InputAction _interactionEAction;
private InputAction _cancelAction;
private InputAction _pressFAction;
private void Awake()
{
// 더미 데이터 삭제
foreach (Transform element in _mealKitsLocation.transform)
{
if (element)
{
Destroy(element.gameObject);
}
}
}
private void Start()
{
EventManager.OnAddedMealKit += SetTodayMenus;
_interactionEAction =
PlayerInputKeyManager.Instance.GetAction(InputActionMaps.TycoonUi, TycoonUiActions.InteractionE);
_cancelAction = PlayerInputKeyManager.Instance.GetAction(InputActionMaps.TycoonUi, TycoonUiActions.Cancel);
_pressFAction = PlayerInputKeyManager.Instance.GetAction(InputActionMaps.TycoonUi, TycoonUiActions.PressF);
_mealKitButtons = new List<MealKitButton>(_maxMealKitCount);
for (int i = 0; i < _maxMealKitCount; i++)
{
MealKitButton mealKitButton = Instantiate(_mealKitButtonPrefab, _mealKitsLocation.transform);
mealKitButton.RegisterButtonListener(() => OnClickedMealKit(mealKitButton));
_mealKitButtons.Add(mealKitButton);
}
_panel.SetActive(false);
}
private void OnDestroy()
{
EventManager.OnAddedMealKit -= SetTodayMenus;
}
private void OnClickedMealKit(MealKitButton mealKitButton)
{
if (mealKitButton.CanInteraction())
{
CraftRecipeData newCraftRecipeData = new CraftRecipeData(mealKitButton.CraftRecipeData);
EventManager.InvokePickupMealKit(newCraftRecipeData);
mealKitButton.PickupMealKit();
Close();
}
}
public bool CanOpen()
{
return _mealKitButtons.Any(mealKitButton => mealKitButton.CanInteraction());
}
public override void Open()
{
base.Open();
_panel.SetActive(true);
PlayerInputKeyManager.Instance.SwitchCurrentActionMap(InputActionMaps.TycoonUi);
SortMealKitButtons();
_uiEventsController.SetSelectObject(_mealKitButtons[0].gameObject);
EventSystem.current.SetSelectedGameObject(_uiEventsController.SelectObject);
}
public void OnClose(InputAction.CallbackContext context)
{
Close();
}
public override void Close()
{
_panel.SetActive(false);
base.Close();
if (PopupUiController.IsPopupListEmpty() || !PopupUiController.IsPausedPopupList())
{
PlayerInputKeyManager.Instance.SwitchCurrentActionMap(InputActionMaps.Tycoon);
}
}
public override void EnableInput()
{
_interactionEAction.performed += OnInteractionE;
_cancelAction.performed += OnClose;
_pressFAction.performed += OnClose;
_uiEventsController.EnableAutoNavigate();
}
public override void DisableInput()
{
_interactionEAction.performed -= OnInteractionE;
_cancelAction.performed -= OnClose;
_pressFAction.performed -= OnClose;
_uiEventsController.DisableAutoNavigate();
}
private void OnInteractionE(InputAction.CallbackContext context)
{
if (!EventSystem.current) return;
EventSystem.current.currentSelectedGameObject.GetComponent<Button>()?.onClick.Invoke();
}
private void SetTodayMenus(List<TodayMenu> todayMenus)
{
for (int i = 0; i < _maxMealKitCount; i++)
{
_mealKitButtons[i].SetMealKit(todayMenus[i].AddedCraftRecipeData, todayMenus[i].AddedCount);
if (todayMenus[i].AddedCraftRecipeData == null)
{
_mealKitButtons[i].HideUi();
}
else
{
_mealKitButtons[i].ShowUi();
}
}
}
private void SortMealKitButtons()
{
// 1) 임시 리스트에 인터랙션 가능한 버튼만 먼저 담는다(Stable).
List<MealKitButton> sortedList = new List<MealKitButton>(_mealKitButtons.Count);
foreach (var mealKitButton in _mealKitButtons)
{
if (mealKitButton.CanInteraction())
{
sortedList.Add(mealKitButton);
}
}
// 2) 그 다음 인터랙션 불가능한 버튼들을 뒤에 붙인다.
foreach (var mealKitButton in _mealKitButtons)
{
if (!mealKitButton.CanInteraction())
{
sortedList.Add(mealKitButton);
}
}
// 3) 재배치한 리스트를 원본 리스트에 반영
_mealKitButtons = sortedList;
// 4) 실제 UI 계층(트랜스폼) 순서도 변경하여 GridLayoutGroup이 의도한 순서로 그리도록 설정
for (int i = 0; i < _mealKitButtons.Count; i++)
{
// i번째 순서대로 형제 인덱스(Sibling Index)를 지정
_mealKitButtons[i].transform.SetSiblingIndex(i);
}
// 5) 정렬 이후, 내비게이션도 재설정 (정렬 순서가 바뀌었으므로)
SetNavigationMealKitButtons();
}
private bool IsButtonValid(MealKitButton mealKitButton)
{
return mealKitButton != null
&& mealKitButton.gameObject.activeInHierarchy
&& mealKitButton.Button != null
&& mealKitButton.Button.interactable;
}
private void SetNavigationMealKitButtons()
{
int columnCount = 3;
int count = _mealKitButtons.Count;
for (int i = 0; i < count; i++)
{
MealKitButton currentMealKit = _mealKitButtons[i];
Button currentButton = currentMealKit.Button;
// 새로운 Navigation 객체 생성 및 Explicit 모드 설정
Navigation nav = new Navigation { mode = Navigation.Mode.Explicit };
// 현재 버튼이 비활성(혹은 인터랙션 불가능)하면 내비게이션 항목은 모두 null 처리
if (!IsButtonValid(currentMealKit))
{
currentButton.navigation = nav; // 모든 방향 null
continue;
}
// 상(Up) 이웃 버튼: 인덱스 i - columnCount
int upIndex = i - columnCount;
if (upIndex >= 0 && IsButtonValid(_mealKitButtons[upIndex]))
{
nav.selectOnUp = _mealKitButtons[upIndex].Button;
}
else
{
nav.selectOnUp = null;
}
// 하(Down) 이웃 버튼: 인덱스 i + columnCount
int downIndex = i + columnCount;
if (downIndex < count && IsButtonValid(_mealKitButtons[downIndex]))
{
nav.selectOnDown = _mealKitButtons[downIndex].Button;
}
else
{
nav.selectOnDown = null;
}
// 좌(Left) 이웃 버튼: 인덱스 i - 1 (같은 행인지 체크)
int leftIndex = i - 1;
if (leftIndex >= 0
&& (i / columnCount == leftIndex / columnCount)
&& IsButtonValid(_mealKitButtons[leftIndex]))
{
nav.selectOnLeft = _mealKitButtons[leftIndex].Button;
}
else
{
nav.selectOnLeft = null;
}
// 우(Right) 이웃 버튼: 인덱스 i + 1 (같은 행인지 체크)
int rightIndex = i + 1;
if (rightIndex < count
&& (i / columnCount == rightIndex / columnCount)
&& IsButtonValid(_mealKitButtons[rightIndex]))
{
nav.selectOnRight = _mealKitButtons[rightIndex].Button;
}
else
{
nav.selectOnRight = null;
}
// 최종 Navigation 할당
currentButton.navigation = nav;
}
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: ab45660cb40d6c34c8172959f9c74c8b

View File

@ -1,4 +1,6 @@
using System.Collections.Generic;
using System.Linq;
using DDD.ScriptableObjects;
using DG.Tweening;
using Sirenix.OdinInspector;
using UnityEngine;
@ -78,6 +80,8 @@ namespace DDD.Uis.Tycoon
private void Start()
{
EventManager.OnTycoonGameStarted += AddMealKit;
_interactionEAction = PlayerInputKeyManager.Instance.GetAction(InputActionMaps.TycoonUi, TycoonUiActions.InteractionE);
_cancelAction = PlayerInputKeyManager.Instance.GetAction(InputActionMaps.TycoonUi, TycoonUiActions.Cancel);
_pressFAction = PlayerInputKeyManager.Instance.GetAction(InputActionMaps.TycoonUi, TycoonUiActions.PressF);
@ -114,6 +118,8 @@ namespace DDD.Uis.Tycoon
private void OnDestroy()
{
EventManager.OnTycoonGameStarted -= AddMealKit;
_openAddMenuUiSequence?.Kill();
_closeAddMenuUiSequence?.Kill();
_interactionEAction = null;
@ -148,7 +154,7 @@ namespace DDD.Uis.Tycoon
public override void EnableInput()
{
//_interactionEAction.performed += OnInteractionE;
_interactionEAction.performed += OnInteractionE;
_cancelAction.performed += OnClose;
_pressFAction.performed += OnClose;
_uiEventsController.EnableAutoNavigate();
@ -167,7 +173,7 @@ namespace DDD.Uis.Tycoon
public override void DisableInput()
{
//_interactionEAction.performed -= OnInteractionE;
_interactionEAction.performed -= OnInteractionE;
_cancelAction.performed -= OnClose;
_pressFAction.performed -= OnClose;
_uiEventsController.DisableAutoNavigate();
@ -209,5 +215,50 @@ namespace DDD.Uis.Tycoon
}
}
}
public bool CanOpen()
{
bool canOpen = false;
foreach (TodayMenu todayMenu in _todayMenus)
{
if (!todayMenu.IsAddedMenu) continue;
canOpen = true;
break;
}
return canOpen;
}
private void AddMealKit()
{
EventManager.InvokeAddedMealKit(_todayMenus);
}
public int GetTodayMenusCount()
{
return _todayMenus.Sum(menu => menu.AddedCount);
}
public CraftRecipeData GetRandomTodayMenu()
{
List<TodayMenu> availableMenus = _todayMenus.Where(menu => menu.CanOrderMenu()).ToList();
if (availableMenus.Count == 0)
{
Debug.LogError("주문 가능한 메뉴가 없습니다");
return null;
}
// 랜덤으로 하나의 메뉴를 선택합니다.
int randomIndex = Random.Range(0, availableMenus.Count);
TodayMenu selectedMenu = availableMenus[randomIndex];
// 선택한 메뉴에 대해 주문 처리를 진행합니다.
selectedMenu.OrderMenu();
// 선택된 메뉴의 CraftRecipeData를 반환합니다.
return selectedMenu.AddedCraftRecipeData;
}
}
}

View File

@ -1,3 +1,4 @@
using System.Collections.Generic;
using DDD.ScriptableObjects;
using Sirenix.OdinInspector;
using TMPro;
@ -44,6 +45,9 @@ namespace DDD.Uis.Tycoon
[Title("데이터")]
[SerializeField]
private Sprite _emptySprite;
[SerializeField]
private int _maxHashTagCount = 3;
[Title("실시간 데이터")]
[SerializeField, DisableIf("@true")]
@ -72,6 +76,9 @@ namespace DDD.Uis.Tycoon
public CraftRecipeData AddedCraftRecipeData { get; private set; }
public int AddedCount { get; private set; }
[SerializeField]
private List<MenuHashTag> _menuHashTags;
private UnityAction _clickAction;
@ -86,6 +93,14 @@ namespace DDD.Uis.Tycoon
}
}
_menuHashTags = new List<MenuHashTag>(_maxHashTagCount);
for (int i = 0; i < _maxHashTagCount; i++)
{
MenuHashTag menuHashTag = Instantiate(_menuHashTagPrefab, _menuHashTagsPanel.transform);
menuHashTag.HideUi();
_menuHashTags.Add(menuHashTag);
}
SetEmpty();
}
@ -125,6 +140,19 @@ namespace DDD.Uis.Tycoon
_priceText.text = (craftRecipeData.Price * AddedCount).ToString();
_countText.text = AddedCount.ToString();
int validHashTagCount = AddedCraftRecipeData.ValidHashTags.Count;
for (int i = 0; i < _maxHashTagCount; i++)
{
if (i >= validHashTagCount)
{
_menuHashTags[i].HideUi();
continue;
}
_menuHashTags[i].SetTag(AddedCraftRecipeData.ValidHashTags[i]);
_menuHashTags[i].ShowUi();
}
}
public void SetEmpty()
@ -136,9 +164,24 @@ namespace DDD.Uis.Tycoon
_countText.text = null;
_nameText.text = null;
for (int i = 0; i < _maxHashTagCount; i++)
{
_menuHashTags[i].HideUi();
}
_isAddedMenu = false;
_menuInformationPanel.SetActive(false);
}
public bool CanOrderMenu()
{
return AddedCraftRecipeData != null && AddedCount > 0;
}
public void OrderMenu()
{
AddedCount--;
}
}
}

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using DDD;
using DDD.Items;
using DDD.Npcs.Crews.Bartender;
@ -6,6 +7,7 @@ using DDD.Npcs.Crews.Cleaner;
using DDD.Npcs.Crews.Server;
using DDD.Npcs.Customers;
using DDD.ScriptableObjects;
using DDD.Uis.Tycoon;
using UnityEngine;
public static class EventManager
@ -96,7 +98,6 @@ public static class EventManager
// 타이쿤 시작 이벤트
public static Action OnTycoonGameStarted;
public static void InvokeTycoonGameStarted()
{
OnTycoonGameStarted?.Invoke();
@ -194,7 +195,6 @@ public static class EventManager
// Npc
// 손님 생성 이벤트
public static Action OnCreateCustomer;
public static void InvokeCreateCustomer()
{
OnCreateCustomer?.Invoke();
@ -430,12 +430,46 @@ public static class EventManager
// Tycoon
// 메뉴를 추가할 때 이벤트
public static Action<CraftRecipeData, int> OnAddedTodayMenu;
public static void InvokeAddedTodayMenu(CraftRecipeData addedCraftRecipeData, int count)
// 게임 시작할 때, 밀키트를 추가하는 이벤트
public static Action<List<TodayMenu>> OnAddedMealKit;
public static void InvokeAddedMealKit(List<TodayMenu> todayMenus)
{
OnAddedTodayMenu?.Invoke(addedCraftRecipeData, count);
OnAddedMealKit?.Invoke(todayMenus);
}
// 플레이어가 밀키트를 냉장고에서 꺼내는 이벤트
public static Action<CraftRecipeData> OnPickupMealKit;
public static void InvokePickupMealKit(CraftRecipeData craftRecipeData)
{
OnPickupMealKit?.Invoke(craftRecipeData);
}
// 플레이어가 들고 있는 요리 도구 정보가 바뀌는 경우
public static Action<CraftingTool?> OnChangedCraftingTool;
public static void InvokeChangedCraftingTool(CraftingTool? craftingTool)
{
OnChangedCraftingTool?.Invoke(craftingTool);
}
// 손님이 음식을 주문하는 이벤트
public static Action<Customer> OnOrderedCook;
public static void InvokeOrderedCook(Customer orderedCustomer)
{
OnOrderedCook?.Invoke(orderedCustomer);
}
// 손님이 음식을 받을때 이벤트
public static Action OnServedCookToCustomer;
public static void InvokeServedCookToCustomer()
{
OnServedCookToCustomer?.Invoke();
}
// 손님이 음식을 받을때 결과 이벤트
public static Action<Customer, bool> OnServedResult;
public static void InvokeServedResult(Customer orderedCustomer, bool orderedCorrected)
{
OnServedResult?.Invoke(orderedCustomer, orderedCorrected);
}
#endregion

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 87c01d94bd1f8c947bf23c08f4a0a233
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b37ca68d525e1d343b4fe58b472e0f24
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

Before

Width:  |  Height:  |  Size: 142 KiB

After

Width:  |  Height:  |  Size: 142 KiB

View File

Before

Width:  |  Height:  |  Size: 149 KiB

After

Width:  |  Height:  |  Size: 149 KiB

View File

Before

Width:  |  Height:  |  Size: 159 KiB

After

Width:  |  Height:  |  Size: 159 KiB

View File

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 104 KiB

View File

Before

Width:  |  Height:  |  Size: 500 KiB

After

Width:  |  Height:  |  Size: 500 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 KiB

View File

@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 2e134437be9e8bc419ac54ce318fb735
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 9
spritePivot: {x: 0.5, y: 0.07}
spritePixelsToUnits: 512
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: iOS
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: WindowsStoreApps
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 1537655665
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show More