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(); 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); } } }