Files
VOIDRPG/Assets/90 - Scripts/Generic/Objects/Unit/Actions/UseAction.cs
T
2026-07-09 21:33:33 +02:00

126 lines
4.2 KiB
C#

using System.Linq;
using UnityEngine;
using VOID.Generic.Dict;
using VOID.Generic.Objects.Abstract;
using VOID.Generic.Objects.Door;
using VOID.Generic.Objects.Item;
using VOID.Generic.Objects.Unit.Actions.Exceptions;
using VOID.Generic.Objects.Unit.Events;
using VOID.Generic.Objects.Usable;
using VOID.Generic.Objects.Usable.Events;
using VOID.Generic.Util;
using VOID.ScriptableObjects;
namespace VOID.Generic.Objects.Unit.Actions
{
public class UseAction : AbstractAction
{
private readonly UnitObject _unit;
private readonly AbstractObject _targetObject;
public UseAction(UnitObject unit, AbstractObject targetObject)
{
_unit = unit;
_targetObject = targetObject;
}
public override bool IsInRange()
{
return RangeUtil.IsInRange(_unit, _targetObject, _unit.unitData.useRange);
}
protected override void OnEndIt() { }
protected override void OnCancelIt() { }
public override void CanDoIt()
{
Check(
_unit.unitData.canUse,
UnitActionErrorType.ThisUnitCantUse);
Check(
state == ActionState.Ready,
UnitActionErrorType.ActionStateIsNotReady);
if (_unit.basicState.turnManager)
{
Check(
_unit.unitState.isSelfTurn,
UnitActionErrorType.UnitSelfTurnNotActive);
Check(
_unit.unitData.currentResources.actionPoints >= 1,
UnitActionErrorType.UnitNotEnoughActionPoints);
}
Check(
_unit.unitState.isControllable,
UnitActionErrorType.UnitStateIsNotControllable);
Check(
IsInRange(),
UnitActionErrorType.NotInRange);
Check(
_targetObject is not UsableObject usable || usable.usableData.requirements.All(requirement => requirement.Check(_unit)),
UnitActionErrorType.RequirementsNotMeetToUseThatItem);
}
protected override void OnDoIt()
{
if (_unit.basicState.turnManager)
_unit.unitData.UseResource(UnitResourceType.ActionPoints, 1);
if (_targetObject is not ItemObject item || item.itemState.carriedBy != _unit)
_unit.OrderInstantly(new RotateAction(_unit, _targetObject));
BeforePerform();
switch (_targetObject)
{
case UsableObject usable:
UseUsable(usable);
break;
case DoorObject door:
UseDoor(door);
break;
default:
Debug.LogWarning($"Object '{nameof(_targetObject)}' cant be used.");
break;
}
AfterPerform();
EndIt();
}
private void UseUsable(UsableObject usable)
{
var useEvent = new UseEvent
{
usedBy = _unit,
usedObject = usable
};
Check(usable.itemData.stackSize >= usable.usableData.stacksPerUse, UnitActionErrorType.UsableNotEnoughStacks);
useEvent.usedBy.unitEvents.onUseBefore.Invoke(useEvent);
useEvent.usedObject.usableEvents.onUsedBefore.Invoke(useEvent);
Check(!useEvent.prevented, UnitActionErrorType.UseIsPrevented);
var equipStatus = ScriptableObject.CreateInstance<BasicStatus>();
equipStatus.effects = usable.usableData.applyOnUse;
equipStatus.hidden = true;
_unit.statusManager.AddStatus(equipStatus, _unit, false);
useEvent.usedBy.unitEvents.onUseAfter.Invoke(useEvent);
useEvent.usedObject.usableEvents.onUsedAfter.Invoke(useEvent);
usable.itemData.stackSize -= usable.usableData.stacksPerUse;
if (usable.itemData.stackSize <= 0) usable.Remove();
}
private void UseDoor(DoorObject door)
{
if (door.doorState.isOpen)
door.Close(_unit);
else
door.Open(_unit);
}
}
}