Files
TheAuction-GS/Assets/Customer/CustomerController.cs

206 lines
6.1 KiB
C#

using System;
using Customer;
using UnityEngine;
using UnityEngine.AI;
using static Customer.MoodState;
using Random = UnityEngine.Random;
public class CustomerController : MonoBehaviour, IObjectParentHolder {
private NavMeshAgent _navMeshAgent;
private Vector3 _target;
public SellCounter TargetCounter { get; private set; }
[Header("WaitTime")] [SerializeField] private float _minWaitTime = 5.0f;
[SerializeField] private float _maxWaitTime = 10.0f;
[Header("BuyChace")] [SerializeField] private float _buyChance = 0.5f;
[SerializeField] private float _buyChanceIncrease = 0.1f;
[SerializeField] private float _buyChanceDecrease = 0.1f;
[SerializeField] private Transform _objectHolder;
private Object _currentObject;
private float _waitTime;
private CustomerVisibleController _visibleController;
public MoodState State => _visibleController.GetState();
private Vector3 _exitPosition;
public event Action<SellCounter, CustomerController> OnCustomerLeft;
private CustomerState _state = CustomerState.GoingToCounter;
//enum
public enum CustomerState {
GoingToCounter,
WaitingToBuy,
Buying,
WalkingToExit
}
private void Awake() {
_navMeshAgent = GetComponent<NavMeshAgent>();
_visibleController = GetComponent<CustomerVisibleController>();
_visibleController.SetState(Normal);
}
private void Update() {
switch (_state) {
case CustomerState.GoingToCounter:
if (_navMeshAgent.remainingDistance <= _navMeshAgent.stoppingDistance) {
OnDestinationReached();
}
break;
case CustomerState.WaitingToBuy:
WaitToBuy();
break;
case CustomerState.Buying:
BuyItem();
break;
case CustomerState.WalkingToExit:
CheckIfReachedExit();
break;
default:
throw new ArgumentOutOfRangeException();
}
}
private void CheckIfReachedExit() {
if (_navMeshAgent.remainingDistance <= _navMeshAgent.stoppingDistance) {
Debug.Log("Bye :p");
CustomerManager.Instance.CustomerDies(this);
Destroy(this.gameObject);
}
}
private bool ShouldBuyItem() {
//This should be a function that checks if a customer should buy an item
//For example, if the item is worth 10 bucks, and the player sets the price to 20, the customer should not buy it since its too expensive
//if an item is prices higher then X% of the base price, the customer should not buy it
Object obj = TargetCounter.GetObject();
if (obj == null) {
Debug.LogError("Counter has no object");
return false;
}
float price = obj.ObjectSo.basePrice;
float sellPrice = TargetCounter.GetSellingPrice();
bool isBroken = obj.IsBroken;
float difference = Mathf.Abs(price - sellPrice);
float percentage = difference / price;
//Log this for now
Debug.Log("Difference: " + difference + " Percentage: " + percentage);
//Random differnece between 0.1 and 0.2;
float diff = Random.Range(_buyChanceDecrease, _buyChanceIncrease);
var calculatedBuyChance = _buyChance;
if (isBroken) {
//Customer should be less likely to buy broken items
calculatedBuyChance -= 0.1f;
}
if (percentage > calculatedBuyChance + diff) {
return false;
}
return true;
}
public void SetDestination(Vector3 position) {
_target = position;
_navMeshAgent.SetDestination(_target);
}
public void SetTargetCounter(SellCounter counter) {
TargetCounter = counter;
float angle = Random.Range(0, 360);
Vector3 offset = new Vector3(Mathf.Cos(angle), 0, Mathf.Sin(angle));
this.SetDestination(counter.transform.position + offset);
}
private void BuyItem() {
if (TargetCounter == null) {
Debug.LogError("Customer has no target counter");
return;
}
if (!ShouldBuyItem()) {
Debug.Log("Customer should not buy item");
this.SetDestination(_exitPosition);
_state = CustomerState.WalkingToExit;
_visibleController.SetState(Angry);
SoundFXController.Instance.PlayVillagerAngryFX();
return;
}
Debug.Log("Customer bought item: " + TargetCounter.GetObject().ObjectSo.objectName + " for: " +
TargetCounter.GetSellingPrice());
_visibleController.SetState(Normal);
TargetCounter.SellItem(this);
SoundFXController.Instance.PlayItemBoughtFX();
SoundFXController.Instance.PlayVillagerHappyFX();
this.SetDestination(_exitPosition);
_state = CustomerState.WalkingToExit;
OnCustomerLeft?.Invoke(TargetCounter, this); //Notify the customer manager that the customer left
}
private void OnDestinationReached() {
//should tell the counter there is a customer waiting;
Debug.Log("Customer reached destination for Counter: " + TargetCounter.name);
_state = CustomerState.WaitingToBuy;
_waitTime = Random.Range(_minWaitTime, _maxWaitTime);
}
void OnDrawGizmosSelected() {
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(_target, 0.5f);
}
void WaitToBuy() {
_waitTime -= Time.deltaTime;
if (_waitTime <= 0) {
_state = CustomerState.Buying;
}
}
public Transform GetHolderTransform() {
return _objectHolder;
}
public void SetObject(Object obj) {
_currentObject = obj;
}
public Object GetObject() {
return _currentObject;
}
public void ClearObject() {
_currentObject = null;
}
public bool HasObject() {
return _currentObject != null;
}
public void SetExitPosition(Vector3 position) {
_exitPosition = position;
}
public void SetState(CustomerState state) {
_state = state;
}
}