This commit is contained in:
2026-07-09 21:33:33 +02:00
commit 84a2a365f3
2364 changed files with 950134 additions and 0 deletions
@@ -0,0 +1,298 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Sirenix.Utilities;
using UnityEngine;
using VOID.Generic.Dict;
using VOID.Generic.Dict.Ability;
using VOID.Generic.Objects.Abstract;
using VOID.Generic.Objects.Unit.Actions.Exceptions;
using VOID.Generic.Objects.Unit.Events;
using VOID.Generic.Projectile;
using VOID.Generic.Util;
using VOID.ScriptableObjects;
using VOID.ScriptableObjects.Abilities;
using Object = UnityEngine.Object;
namespace VOID.Generic.Objects.Unit.Actions
{
/// <summary>
/// Makes <see cref="UnitObject"/> cast given <see cref="BasicAbility"/>.
/// <br/><br/>
/// <see cref="AbstractAction"/>:<br/>
/// <inheritdoc cref="AbstractAction"/>
/// </summary>
public class AbilityAction : AbstractAction
{
private class Target
{
public readonly AbstractObject targetObject;
public readonly Vector3 targetPosition;
public Target(AbstractObject targetObject, Vector3 targetPosition)
{
this.targetObject = targetObject;
this.targetPosition = targetPosition;
}
}
private readonly UnitObject _unit;
private readonly BasicAbility _ability;
private readonly Target[] _targets;
private int _projectilesEnded;
private AbilityCastEvent _abilityEvent;
public AbilityAction(UnitObject unit, BasicAbility ability)
: this(unit, ability, Array.Empty<Target>())
{
}
public AbilityAction(UnitObject unit, BasicAbility ability, Vector3 target)
: this(unit, ability, new[] { new Target(null, target) })
{
}
public AbilityAction(UnitObject unit, BasicAbility ability, AbstractObject target)
: this(unit, ability, new[] { new Target(target, target.transform.position + Vector3.up * target.basicData.height/2) })
{
}
private AbilityAction(UnitObject unit, BasicAbility ability, Target target)
: this(unit, ability, new[] { target })
{
}
public AbilityAction(UnitObject unit, BasicAbility ability, IEnumerable<Vector3> targets)
: this(unit, ability, targets.Select(p => new Target(null, p)).ToArray())
{
}
public AbilityAction(UnitObject unit, BasicAbility ability, IEnumerable<AbstractObject> targets)
: this(unit, ability, targets.Select(o => new Target(o, o.transform.position+ Vector3.up * o.basicData.height/2)).ToArray())
{
}
private AbilityAction(UnitObject unit, BasicAbility ability, Target[] targets)
{
_unit = unit;
_ability = ability;
_targets = targets;
}
public override bool IsInRange()
{
return _targets.IsNullOrEmpty() || _targets.All(target =>
target.targetObject
? RangeUtil.IsInRange(_unit, target.targetObject, _ability.range)
: RangeUtil.IsInRange(_unit, target.targetPosition, _ability.range));
}
public override bool CanBeStopped() => _abilityEvent is null || _abilityEvent.prevented;
public override void CanDoIt()
{
Check(
state == ActionState.Ready,
UnitActionErrorType.ActionStateIsNotReady);
if (_unit.basicState.turnManager)
{
Check(
_unit.unitState.isSelfTurn,
UnitActionErrorType.UnitSelfTurnNotActive);
Check(
_unit.unitData.currentResources.actionPoints >= _ability.actionPointCost,
UnitActionErrorType.UnitNotEnoughActionPoints);
Check(
_unit.unitData.currentResources.movePoints >= _ability.movePointCost,
UnitActionErrorType.UnitNotEnoughMovePoints);
}
Check(
_ability is not BasicAttackAbility || _unit.unitData.canAttack,
UnitActionErrorType.ThisUnitCantAttack);
Check(
_unit.unitState.isControllable,
UnitActionErrorType.UnitStateIsNotControllable);
Check(
IsInRange(),
UnitActionErrorType.NotInRange);
Check(
_ability.requirements.All(requirement => requirement.Check(_unit)),
UnitActionErrorType.RequirementsNotMeetToUseThatAbility);
Check(
_ability.projectileSteps.First().validTargets.All(validTarget =>
_targets.All(target => validTarget.IsValid(_unit, target.targetPosition, target.targetObject))),
UnitActionErrorType.WrongTargetsSelectedToUseThatAbility);
Check(
_ability.aimingType is AbilityAimingType.Blank || _ability.castUsages == _targets.Length,
UnitActionErrorType.WrongNumberOfTargetsToUseThatAbility);
}
protected override void OnDoIt()
{
if (_unit.basicState.turnManager)
{
_unit.unitData.UseResource(UnitResourceType.ActionPoints, _ability.actionPointCost);
_unit.unitData.UseResource(UnitResourceType.MovePoints, _ability.movePointCost);
}
_abilityEvent = new AbilityCastEvent
{
caster = _unit,
ability = _ability
};
_unit.unitEvents.onStartAbilityBefore.Invoke(_abilityEvent);
Check(!_abilityEvent.prevented, UnitActionErrorType.AbilityIsPrevented);
_unit.unitEvents.onStartAbilityAfter.Invoke(_abilityEvent);
if (_ability.castingType == AbilityCastingType.Instant)
{
DoAbility(null);
EndIt();
return;
}
var animationGenericEvent = new AnimationGenericEvent
{
animationType = AnimationType.Ability,
unit = _unit,
ability = _ability
};
if (_targets.Length > 0) new RotateAction(_unit, _targets[0].targetPosition).DoIt();
if (_ability.castingType is AbilityCastingType.Channel && _ability.castUsages > 0)
{
// When channeling - ability ends when all projectiles end
_unit.unitEvents.onAnimation[AnimationType.Ability].onPerform.AddListener(DoAbility);
_unit.unitAnimator.SetLoopAnimation(AnimationType.Ability, _ability.abilityLoopAnimationList);
_unit.unitAnimator.StartLoopAnimation(animationGenericEvent);
}
else
{
// Otherwise - ability ends with animation
_unit.unitEvents.onAnimation[AnimationType.Ability].onPerform.AddListener(DoAbility);
_unit.unitEvents.onAnimation[AnimationType.Ability].onEnd.AddListener(OnAbilityEnd);
_unit.unitAnimator.SetAnimation(AnimationType.Ability, _ability.abilityAnimationList);
_unit.unitAnimator.StartAnimation(animationGenericEvent);
}
}
private void DoAbility(AnimationGenericEvent tEvent)
{
BeforePerform();
if (_ability.applyOnCasterMoment is AbilityExecutionMoment.AfterCast) ApplyEffectsToCaster();
_targets.ForEach((target, index) =>
{
// Predefined object is only for visual things
// Else - new empty projectile object
var projectile = _ability.projectile
? Object.Instantiate(_ability.projectile.gameObject).GetComponent<ProjectileObject>()
: new GameObject().AddComponent<ProjectileObject>();
projectile.StartProjectile(index, _unit, _unit.unitData.castPosition.position, target.targetPosition, _ability.projectileSteps);
projectile.onHit.AddListener(OnProjectileHit);
projectile.onEnd.AddListener(OnProjectileEnd);
_unit.unitEvents.onAbilityProjectileStart.Invoke(new AbilityProjectileEvent
{
caster = _unit,
ability = _ability,
projectileIndex = index,
projectile = projectile
});
});
AfterPerform();
}
private void OnProjectileHit(ProjectileObject projectile, AbstractObject hitObject)
{
var abilityHitEvent = new AbilityHitEvent
{
caster = _unit,
target = hitObject,
ability = _ability
};
hitObject.basicEvents.onAbilityHitBefore.Invoke(abilityHitEvent);
_unit.unitEvents.onAbilityHitBefore.Invoke(abilityHitEvent);
// We cant run Check here, because this OnHit can be one of many - just do nothing more for this projectile
if (abilityHitEvent.prevented) return;
hitObject.basicEvents.onAbilityHitAfter.Invoke(abilityHitEvent);
_unit.unitEvents.onAbilityHitAfter.Invoke(abilityHitEvent);
ApplyEffectsToTarget(hitObject);
}
private void OnProjectileEnd(ProjectileObject projectile)
{
_projectilesEnded++;
_unit.unitEvents.onAbilityProjectileEnd.Invoke(new AbilityProjectileEvent
{
caster = _unit,
ability = _ability,
projectileIndex = projectile.index,
projectile = projectile
});
if (_ability.castingType is AbilityCastingType.Channel && _projectilesEnded == _ability.castUsages)
{
_unit.unitAnimator.EndLoopAnimation();
EndIt();
}
}
private void ApplyEffectsToTarget(AbstractObject target)
{
if (_ability.applyOnTarget.Count <= 0) return;
// Because ability have defined only effects we need create dummy status
// IMPORTANT - It is hidden and instantly starts and then ends!
var targetStatus = ScriptableObject.CreateInstance<BasicStatus>();
targetStatus.effects = _ability.applyOnTarget;
targetStatus.hidden = true;
target.statusManager.AddStatus(targetStatus, _unit, false);
}
private void ApplyEffectsToCaster()
{
if (_ability.applyOnCaster.Count <= 0) return;
// Because ability have defined only effects we need create dummy status
// IMPORTANT - It is hidden and instantly starts and then ends!
var casterStatus = ScriptableObject.CreateInstance<BasicStatus>();
casterStatus.effects = _ability.applyOnCaster;
casterStatus.hidden = true;
_unit.statusManager.AddStatus(casterStatus, _unit, false);
}
private void OnAbilityEnd(AnimationGenericEvent tEvent)
{
EndIt();
}
protected override void OnCancelIt()
{
_unit.unitAnimator.EndLoopAnimation();
_unit.unitEvents.onAnimation[AnimationType.Ability].onPerform.RemoveListener(DoAbility);
_unit.unitEvents.onAnimation[AnimationType.Ability].onEnd.RemoveListener(OnAbilityEnd);
_unit.unitEvents.onEndAbility.Invoke(_abilityEvent);
}
protected override void OnEndIt()
{
_unit.unitAnimator.EndLoopAnimation();
if (_ability.applyOnCasterMoment is AbilityExecutionMoment.AfterEnd) ApplyEffectsToCaster();
_unit.unitEvents.onAnimation[AnimationType.Ability].onPerform.RemoveListener(DoAbility);
_unit.unitEvents.onAnimation[AnimationType.Ability].onEnd.RemoveListener(OnAbilityEnd);
_unit.unitEvents.onEndAbility.Invoke(_abilityEvent);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f347d6a2844a436db125cd102e83d5de
timeCreated: 1677173609
@@ -0,0 +1,180 @@
using System;
using Sirenix.Utilities;
using UnityEngine;
using VOID.Generic.Objects.Unit.Actions.Exceptions;
namespace VOID.Generic.Objects.Unit.Actions
{
public enum ActionState
{
Ready,
Running,
Finished,
Cancelled
}
/// <summary>
/// Action for <see cref="UnitObject"/>.<br/>
///
/// Executing order when <see cref="DoIt"/> used:<br/>
/// <ul>
/// <li><see cref="CanDoIt"/></li>
/// <li><see cref="OnDo"/></li>
/// <li><see cref="OnDoIt"/></li>
/// <li>Inside OnDoIt: <see cref="OnBeforePerform"/></li>
/// <li>Inside OnDoIt: Action's logic here</li>
/// <li>Inside OnDoIt: <see cref="OnAfterPerform"/> - obligatory if action ends immediately</li>
/// </ul>
///
/// Executing order when <see cref="EndIt"/> used:<br/>
/// <ul>
/// <li><see cref="OnEndIt"/></li>
/// <li>Inside OnEndIt: <see cref="OnAfterPerform"/> - obligatory if not used in OnDoIt</li>
/// <li><see cref="OnEnd"/></li>
/// </ul>
///
/// Executing order when <see cref="CancelIt"/> used:<br/>
/// <ul>
/// <li><see cref="OnCancelIt"/></li>
/// <li>Inside OnCancelIt: <see cref="OnAfterPerform"/> - obligatory if not used in OnDoIt</li>
/// <li><see cref="OnCancel"/></li>
/// </ul>
/// </summary>
[Serializable]
public abstract class AbstractAction
{
/// <summary>Run after checking and before executing action.</summary>
public event Action OnDo;
/// <summary>Defined by referenced action. Usually right *before* main point of that action.</summary>
public event Action OnBeforePerform;
/// <summary>Defined by referenced action. Usually right *after* main point of that action.</summary>
public event Action OnAfterPerform;
/// <summary>Run after action ended.</summary>
public event Action OnEnd;
/// <summary>Run after action ended forcefully.</summary>
public event Action OnCancel;
/// <summary>Current state of action.</summary>
public ActionState state { get; protected set; } = ActionState.Ready;
/// <summary>If given, current action will be executed only if given one is finished successfully</summary>
public AbstractAction runAfterAction;
/// <summary>Simple check if unit is in range to execute this action.</summary>
public abstract bool IsInRange();
/// <summary>Determines whether this action CAN be executed INSTANTLY outside the queue.</summary>
public virtual bool CanSkipQueue() => false;
/// <summary>Determines whether this action CAN be stopped early, by something else besides itself.</summary>
public virtual bool CanBeStopped() => true;
/// <summary>Action's checks if action can be executed. <see cref="Check"/> have to be used here.</summary>
public abstract void CanDoIt();
/// <summary>Action's logic.</summary>
protected abstract void OnDoIt();
/// <summary>Action's logic when whole action ends successfully.</summary>
protected abstract void OnEndIt();
/// <summary>Action's logic when whole action is forced to end.</summary>
protected abstract void OnCancelIt();
public bool CanDoItBoolean()
{
try
{
CanDoIt();
return true;
}
catch (UnitActionErrorException)
{
return false;
}
}
/// <summary>
/// 1. Checking if action can be done by function in child: <see cref="CanDoIt"/><br/>
/// 2. Executing main login of this action
/// </summary>
public void DoIt()
{
Check(
runAfterAction == null || runAfterAction.state == ActionState.Finished,
UnitActionErrorType.PreviousActionNotFinished);
CanDoIt();
state = ActionState.Running;
OnDo?.Invoke();
OnDoIt();
}
/// <summary>
/// Executed by action itself when everything is done correctly.
/// </summary>
protected void EndIt()
{
if (state is ActionState.Finished or ActionState.Cancelled)
{
Debug.LogWarning($"{GetType().GetNiceName()} can't be ended. State: '{state}'");
return;
}
OnEndIt();
state = ActionState.Finished;
OnEnd?.Invoke();
}
/// <summary>
/// Executed by external source. Stopping this action forcefully.
/// </summary>
public void CancelIt()
{
// Cancel events only when action really started otherwise there will be nothing to cancel
if (state == ActionState.Running)
{
OnCancelIt();
OnCancel?.Invoke();
}
state = ActionState.Cancelled;
}
/// <summary>
/// Should be executed from child right before main logic is started, usually in <see cref="OnDoIt"/>
/// </summary>
protected void BeforePerform()
{
OnBeforePerform?.Invoke();
}
/// <summary>
/// Should be executed from child right after main logic is done, usually in <see cref="OnDoIt"/>
/// </summary>
protected void AfterPerform()
{
OnAfterPerform?.Invoke();
}
/// <summary>
/// Execute <see cref="Throw"/> if check is false
/// </summary>
protected void Check(bool condition, UnitActionErrorType elseError)
{
if (!condition) Throw(elseError);
}
/// <summary>
/// Cancels this Action and then throw <see cref="UnitActionErrorException"/>
/// </summary>
protected void Throw(UnitActionErrorType errorType)
{
CancelIt();
throw new UnitActionErrorException(this, errorType);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d54967e8cbfc4281ba14d76077012bf1
timeCreated: 1666646484
@@ -0,0 +1,104 @@
using System.Linq;
using VOID.Generic.Dict;
using VOID.Generic.Dict.Ability;
using VOID.Generic.Objects.Unit.Actions.Exceptions;
using VOID.Generic.Objects.Unit.Events;
using VOID.ScriptableObjects.Abilities;
namespace VOID.Generic.Objects.Unit.Actions
{
/// <summary>
/// Simply make <see cref="UnitObject"/> go into "casting" state allowing player or AI to aim and select targets.
/// <br/><br/>
/// <see cref="AbstractAction"/>:<br/>
/// <inheritdoc cref="AbstractAction"/>
/// </summary>
public class CastingAction : AbstractAction
{
private readonly UnitObject _unit;
private readonly BasicAbility _ability;
public CastingAction(UnitObject unit, BasicAbility ability)
{
_unit = unit;
_ability = ability;
}
public override bool IsInRange() => true;
public override void CanDoIt()
{
Check(
state == ActionState.Ready,
UnitActionErrorType.ActionStateIsNotReady);
if (_unit.basicState.turnManager)
{
Check(
_unit.unitState.isSelfTurn,
UnitActionErrorType.UnitSelfTurnNotActive);
Check(
_unit.unitData.currentResources.actionPoints >= _ability.actionPointCost,
UnitActionErrorType.UnitNotEnoughActionPoints);
Check(
_unit.unitData.currentResources.movePoints >= _ability.movePointCost,
UnitActionErrorType.UnitNotEnoughMovePoints);
}
Check(
_unit.unitState.isControllable,
UnitActionErrorType.UnitStateIsNotControllable);
Check(
_ability.requirements.All(requirement => requirement.Check(_unit)),
UnitActionErrorType.RequirementsNotMeetToUseThatAbility);
}
protected override void OnDoIt()
{
BeforePerform();
if (_ability.castingType is AbilityCastingType.Instant or AbilityCastingType.InstantCasting)
{
// Ending action early
AfterPerform();
EndIt();
// Make sure that there is no more actions after CASTING and before ABILITY
_unit.OrderStop(false);
// Instantly starting ability
_unit.Order(new AbilityAction(_unit, _ability));
return;
}
var animationGenericEvent = new AnimationGenericEvent
{
animationType = AnimationType.Casting,
unit = _unit,
ability = _ability
};
// Enables "casting" mode for this unit (usually only for player) to select targets before firing ability
_unit.unitEvents.onStartCasting.Invoke(new CastingEvent { caster = _unit, ability = _ability });
// Starting loop animation of selected ability
_unit.unitAnimator.SetLoopAnimation(AnimationType.Casting, _ability.castingAnimationList);
_unit.unitAnimator.StartLoopAnimation(animationGenericEvent);
}
protected override void OnEndIt()
{
AfterPerform();
// Instant abilities don't have casting - do nothing
if (_ability.castingType is AbilityCastingType.Instant or AbilityCastingType.InstantCasting) return;
// Somehow casting ended (no matter is by player or something else)
_unit.unitAnimator.EndLoopAnimation();
_unit.unitEvents.onEndCasting.Invoke(new CastingEvent { caster = _unit, ability = _ability });
}
protected override void OnCancelIt()
{
OnEndIt();
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6d459cfb11f942dd853b4314f8f70c1c
timeCreated: 1689964527
@@ -0,0 +1,47 @@
using VOID.Generic.Objects.Container;
using VOID.Generic.Objects.Container.Events;
using VOID.Generic.Objects.Unit.Actions.Exceptions;
namespace VOID.Generic.Objects.Unit.Actions
{
public class CloseContainerAction : AbstractAction
{
private readonly UnitObject _unit;
private readonly ContainerObject _container;
public CloseContainerAction(UnitObject unit, ContainerObject container)
{
_unit = unit;
_container = container;
}
public override bool IsInRange() => true;
public override bool CanSkipQueue() => true;
protected override void OnEndIt() {}
protected override void OnCancelIt() {}
public override void CanDoIt()
{
Check(
_container.containerState.openedBy.Contains(_unit),
UnitActionErrorType.ContainerIsNotOpenedByThisUnit);
}
protected override void OnDoIt()
{
var containerCloseEvent = new ContainerCloseEvent
{
closedBy = _unit,
container = _container
};
BeforePerform();
_container.containerEvents.onClose.Invoke(containerCloseEvent);
_unit.unitEvents.onContainerClose.Invoke(containerCloseEvent);
AfterPerform();
EndIt();
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4f799f6c37f44f70b1c8b3408771bbb6
timeCreated: 1694902221
@@ -0,0 +1,45 @@
using VOID.Generic.Objects.Unit.Actions.Exceptions;
using VOID.Generic.Objects.Unit.Events;
namespace VOID.Generic.Objects.Unit.Actions
{
public class CloseOtherUnitAction : AbstractAction
{
private readonly UnitObject _unit;
private readonly UnitObject _otherUnit;
public CloseOtherUnitAction(UnitObject unit, UnitObject otherUnit)
{
_unit = unit;
_otherUnit = otherUnit;
}
public override bool IsInRange() => true;
protected override void OnEndIt() {}
protected override void OnCancelIt() {}
public override void CanDoIt()
{
Check(
_otherUnit.unitState.openedBy.Contains(_unit),
UnitActionErrorType.OtherUnitIsNotOpenedByThisUnit);
}
protected override void OnDoIt()
{
var closeOtherUnitEvent = new CloseOtherUnitEvent()
{
closedBy = _unit,
otherUnit = _otherUnit
};
BeforePerform();
_otherUnit.unitEvents.onClosedByOtherUnit.Invoke(closeOtherUnitEvent);
_unit.unitEvents.onCloseOtherUnit.Invoke(closeOtherUnitEvent);
AfterPerform();
EndIt();
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f3fd8d298c2c47288cada9a8d6dc7a51
timeCreated: 1717948914
@@ -0,0 +1,31 @@
using System;
namespace VOID.Generic.Objects.Unit.Actions
{
public class CustomAction : AbstractAction
{
private event Action<UnitObject> Action;
private readonly UnitObject _unit;
public CustomAction(UnitObject unit, Action<UnitObject> actionToDo)
{
_unit = unit;
Action += actionToDo;
}
public override bool IsInRange() => true;
public override bool CanSkipQueue() => true;
protected override void OnCancelIt() {}
protected override void OnEndIt() {}
public override void CanDoIt() {}
protected override void OnDoIt()
{
BeforePerform();
Action?.Invoke(_unit);
AfterPerform();
EndIt();
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 09492cbb5b6646b0acc1ea577c114534
timeCreated: 1690487463
@@ -0,0 +1,116 @@
using UnityEngine;
using VOID.Generic.Dict;
using VOID.Generic.Objects.Item;
using VOID.Generic.Objects.Item.Events;
using VOID.Generic.Objects.Unit.Actions.Exceptions;
using VOID.Generic.Objects.Wearable;
using VOID.Generic.Objects.Wearable.Events;
using VOID.Generic.Util;
namespace VOID.Generic.Objects.Unit.Actions
{
public class DropAction : AbstractAction
{
private readonly UnitObject _unit;
private readonly ItemObject _item;
private readonly Vector3 _dropPosition;
public DropAction(UnitObject unit, ItemObject item)
{
_unit = unit;
_item = item;
_dropPosition = unit.transform.position;
}
public DropAction(UnitObject unit, ItemObject item, Vector3 dropPosition)
{
_unit = unit;
_item = item;
_dropPosition = dropPosition;
}
public override bool IsInRange()
{
return RangeUtil.IsInRange(_unit, _item, _unit.unitData.takeRange);
}
protected override void OnEndIt() {}
protected override void OnCancelIt() {}
public override void CanDoIt()
{
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(
_item.itemState.carriedBy == _unit,
UnitActionErrorType.UnitDontCarryThatItem);
Check(
IsInRange(),
UnitActionErrorType.NotInRange);
}
protected override void OnDoIt()
{
if (_unit.basicState.turnManager)
_unit.unitData.UseResource(UnitResourceType.ActionPoints, 1);
TryToUnEquip();
var dropEvent = new DropEvent
{
item = _item,
unit = _unit
};
_item.itemEvents.onDroppedBefore.Invoke(dropEvent);
_unit.unitEvents.onDropBefore.Invoke(dropEvent);
Check(!dropEvent.prevented, UnitActionErrorType.DropIsPrevented);
_unit.OrderInstantly(new RotateAction(_unit, _dropPosition));
BeforePerform();
_unit.unitBackpack.Drop(_item);
_item.transform.position = _dropPosition;
_item.itemEvents.onDroppedAfter.Invoke(dropEvent);
_unit.unitEvents.onDropAfter.Invoke(dropEvent);
AfterPerform();
EndIt();
}
private void TryToUnEquip()
{
if (_item is not WearableObject item) return;
if (!item.wearableState.wearerUnit) return;
var unEquipEvent = new UnEquipEvent
{
wearable = item,
unit = _unit
};
item.wearableEvents.onUnEquippedBefore.Invoke(unEquipEvent);
_unit.unitEvents.onUnEquipBefore.Invoke(unEquipEvent);
Check(!unEquipEvent.prevented, UnitActionErrorType.UnEquipIsPrevented);
_unit.unitEquipment.UnEquip(item);
_unit.unitBackpack.Take(item);
item.wearableEvents.onUnEquippedAfter.Invoke(unEquipEvent);
_unit.unitEvents.onUnEquipAfter.Invoke(unEquipEvent);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3039a96dd3034f6da5cc4d935e85fc8f
timeCreated: 1672679513
@@ -0,0 +1,40 @@
using VOID.Generic.Objects.Unit.Actions.Exceptions;
namespace VOID.Generic.Objects.Unit.Actions
{
public class EndTurnAction : AbstractAction
{
private readonly UnitObject _unit;
public EndTurnAction(UnitObject unit)
{
_unit = unit;
}
public override bool IsInRange() => true;
public override bool CanSkipQueue() => true;
protected override void OnEndIt() { }
protected override void OnCancelIt() { }
public override void CanDoIt()
{
Check(
state == ActionState.Ready,
UnitActionErrorType.ActionStateIsNotReady);
Check(
_unit.basicState.turnManager,
UnitActionErrorType.UnitNotInTurnManager);
Check(
_unit.unitState.isSelfTurn,
UnitActionErrorType.UnitSelfTurnNotActive);
}
protected override void OnDoIt()
{
_unit.unitActionQueue.StopQueue();
_unit.basicState.turnManager.NextTurn();
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bc0b140f8b9e48c9ab03ee75abd389fb
timeCreated: 1696970563
@@ -0,0 +1,147 @@
using System;
using System.Linq;
using VOID.Generic.Dict;
using VOID.Generic.Objects.Accessory;
using VOID.Generic.Objects.Armor;
using VOID.Generic.Objects.Unit.Actions.Exceptions;
using VOID.Generic.Objects.Weapon;
using VOID.Generic.Objects.Wearable;
using VOID.Generic.Objects.Wearable.Events;
using static VOID.Generic.Util.WearableUtils;
namespace VOID.Generic.Objects.Unit.Actions
{
public class EquipAction : AbstractAction
{
private readonly UnitObject _unit;
private readonly WearableObject _item;
private readonly int _slotIndex;
private readonly EquipmentSlotType _slot;
public EquipAction(UnitObject unit, WearableObject item, int slotIndex)
{
_unit = unit;
_item = item;
_slotIndex = slotIndex;
_slot = (EquipmentSlotType)slotIndex;
}
public EquipAction(UnitObject unit, WearableObject item)
{
_unit = unit;
_item = item;
_slot = FindEquipmentSlot();
_slotIndex = (int)_slot;
}
public override bool IsInRange() => true;
protected override void OnEndIt() {}
protected override void OnCancelIt() {}
public override void CanDoIt()
{
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.unitEquipment.CanEquipInSlot(_slotIndex, _item),
UnitActionErrorType.CannotEquipItemInThatSlot);
Check(
_unit.unitState.isControllable,
UnitActionErrorType.UnitStateIsNotControllable);
Check(
_item.itemState.carriedBy == _unit,
UnitActionErrorType.UnitDontCarryThatItem);
Check(
_item.wearableData.requirements.All(requirement => requirement.Check(_unit)),
UnitActionErrorType.RequirementsNotMeetToEquipThatItem);
}
protected override void OnDoIt()
{
if (_unit.basicState.turnManager)
_unit.unitData.UseResource(UnitResourceType.ActionPoints, 1);
var equipEvent = new EquipEvent
{
wearable = _item,
unit = _unit,
slotIndex = _slotIndex,
slotType = _slot
};
_item.wearableEvents.onEquippedBefore.Invoke(equipEvent);
_unit.unitEvents.onEquipBefore.Invoke(equipEvent);
Check(!equipEvent.prevented, UnitActionErrorType.EquipIsPrevented);
TryToUnEquip();
BeforePerform();
// Move item from Backpack to Equipment
_unit.unitBackpack.Drop(_item);
_unit.unitEquipment.Equip(_slotIndex, _item);
// Execute events
_item.wearableEvents.onEquippedAfter.Invoke(equipEvent);
_unit.unitEvents.onEquipAfter.Invoke(equipEvent);
AfterPerform();
EndIt();
}
private void TryToUnEquip()
{
var toUnEquip = _unit.unitEquipment.GetEquipped(_slotIndex);
if (toUnEquip) new UnEquipAction(_unit, toUnEquip).DoIt();
// All WearableObjects un-equip only this item where it will be equipped
// EXCEPT WeaponObject - these also can un-equip additionally mainHand or offHand, only when dealing with two-handed weapons
if (_item is not WeaponObject weapon) return;
var mainHand = _unit.unitEquipment.GetEquipped(EquipmentSlotType.MainHand) as WeaponObject;
var offHand = _unit.unitEquipment.GetEquipped(EquipmentSlotType.OffHand) as WeaponObject;
// UNEQUIP MAINHAND - if it is two-hand, we try to equip something in offhand
if (mainHand && _slot == EquipmentSlotType.OffHand && mainHand.weaponData.weaponCarryType is WeaponCarryType.TwoHand)
new UnEquipAction(_unit, mainHand).DoIt();
// UNEQUIP OFFHAND - if we try to equip something two-handed
if (offHand && weapon.weaponData.weaponCarryType == WeaponCarryType.TwoHand)
new UnEquipAction(_unit, offHand).DoIt();
}
private EquipmentSlotType FindEquipmentSlot()
{
var equippedRingOne = _unit.unitEquipment.GetEquipped(EquipmentSlotType.RingOne);
var equippedRingTwo = _unit.unitEquipment.GetEquipped(EquipmentSlotType.RingTwo);
return _item switch
{
WeaponObject when !IsWeaponCarryType(_item, WeaponCarryType.OneHandOff) => EquipmentSlotType.MainHand,
WeaponObject when IsWeaponCarryType(_item, WeaponCarryType.OneHandOff) => EquipmentSlotType.OffHand,
ArmorObject when IsType(_item, ArmorType.Helmet) => EquipmentSlotType.Helmet,
ArmorObject when IsType(_item, ArmorType.Armor) => EquipmentSlotType.Armor,
ArmorObject when IsType(_item, ArmorType.Pants) => EquipmentSlotType.Pants,
ArmorObject when IsType(_item, ArmorType.Belt) => EquipmentSlotType.Belt,
ArmorObject when IsType(_item, ArmorType.Boots) => EquipmentSlotType.Boots,
ArmorObject when IsType(_item, ArmorType.Gloves) => EquipmentSlotType.Gloves,
AccessoryObject when IsType(_item, AccessoryType.Necklace) => EquipmentSlotType.Necklace,
AccessoryObject when IsType(_item, AccessoryType.Ring) && (!equippedRingOne || equippedRingTwo) => EquipmentSlotType.RingOne,
AccessoryObject when IsType(_item, AccessoryType.Ring) && (equippedRingOne && !equippedRingTwo) => EquipmentSlotType.RingTwo,
_ => throw new ArgumentOutOfRangeException(nameof(_item))
};
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 12b6ec7b73134717a699ebfee51de603
timeCreated: 1672746279
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: fad3becb68f44f608f5c61b1fcf6fe1d
timeCreated: 1686666458
@@ -0,0 +1,16 @@
using System;
namespace VOID.Generic.Objects.Unit.Actions.Exceptions
{
public class UnitActionErrorException : Exception
{
public readonly AbstractAction action;
public readonly UnitActionErrorType unitActionErrorType;
public UnitActionErrorException(AbstractAction action, UnitActionErrorType unitActionErrorType)
{
this.action = action;
this.unitActionErrorType = unitActionErrorType;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 875cbf9757a34df9a5e9679dfa3247e6
timeCreated: 1686666485
@@ -0,0 +1,51 @@
using System.Collections.Generic;
namespace VOID.Generic.Objects.Unit.Actions.Exceptions
{
public static class UnitActionErrorMessage
{
private static readonly Dictionary<UnitActionErrorType, string> Messages = new()
{
[UnitActionErrorType.ActionStateIsNotReady] = "Can't do this action yet",
[UnitActionErrorType.NotInRange] = "Target is out of range",
[UnitActionErrorType.UnitStateIsNotControllable] = "Unit is busy",
[UnitActionErrorType.UnitDontCarryThatItem] = "Unit don't carry that item",
[UnitActionErrorType.UnitDontWearThatItem] = "Unit don't wear that item",
[UnitActionErrorType.ItemIsNotOnGround] = "Item is not on ground",
[UnitActionErrorType.RequirementsNotMeetToEquipThatItem] = "Unit don't meet requirement to equip that item",
[UnitActionErrorType.CannotEquipItemInThatSlot] = "That item can't be equipped in this equipment slot",
[UnitActionErrorType.RequirementsNotMeetToUseThatItem] = "Unit don't meet requirement to use that item",
[UnitActionErrorType.RequirementsNotMeetToUseThatAbility] = "Unit don't meet requirement to use that ability",
[UnitActionErrorType.UnEquipIsPrevented] = "UnEquip prevented",
[UnitActionErrorType.DropIsPrevented] = "Drop prevented",
[UnitActionErrorType.EquipIsPrevented] = "Equip prevented",
[UnitActionErrorType.PickIsPrevented] = "Pick prevented",
[UnitActionErrorType.UseIsPrevented] = "Use prevented",
[UnitActionErrorType.ContainerIsNotOpenedByThisUnit] = "Container is not opened by this unit",
[UnitActionErrorType.ItemIsNotMovable] = "That item can't be moved",
[UnitActionErrorType.ItemIsNotPickable] = "That item can't be picked",
[UnitActionErrorType.AbilityIsPrevented] = "Ability prevented",
[UnitActionErrorType.AbilityHitIsPrevented] = "Ability hit prevented",
[UnitActionErrorType.UsableNotEnoughStacks] = "Item don't have enough stacks to be used",
[UnitActionErrorType.PreviousActionNotFinished] = "Previous required action wasn't finished",
[UnitActionErrorType.UnitNotInTurnManager] = "Unit don't participate in any turn mechanics",
[UnitActionErrorType.UnitSelfTurnNotActive] = "It's not this unit's turn",
[UnitActionErrorType.UnitNotEnoughActionPoints] = "Not enough action points to do that",
[UnitActionErrorType.UnitNotEnoughMovePoints] = "Not enough move points to do that",
[UnitActionErrorType.TalkNotAvailableWhenTurnActive] = "Talking during turn mechanics not available",
[UnitActionErrorType.ThisUnitCantMove] = "This unit can't do Move action",
[UnitActionErrorType.ThisUnitCantAttack] = "This unit can't do Attack action",
[UnitActionErrorType.ThisUnitCantUse] = "This unit can't do Use action",
[UnitActionErrorType.ThisUnitCantTalk] = "This unit can't do Talk action",
[UnitActionErrorType.ThisUnitCantTake] = "This unit can't do Take action",
[UnitActionErrorType.ThisUnitCantInspect] = "This unit can't do Inspect action",
[UnitActionErrorType.OtherUnitCantBeInspected] = "Other unit can't be Inspected",
[UnitActionErrorType.OtherUnitCantBeTalked] = "Other unit can't be Talked with",
};
public static string Get(UnitActionErrorType errorType)
{
return Messages.GetValueOrDefault(errorType, errorType.ToString());
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 751eee10c5954993b708a8ec5bea1b6b
timeCreated: 1698959051
@@ -0,0 +1,49 @@
namespace VOID.Generic.Objects.Unit.Actions.Exceptions
{
public enum UnitActionErrorType
{
ActionStateIsNotReady,
NotInRange,
UnitStateIsNotControllable,
UnitDontCarryThatItem,
UnitDontWearThatItem,
ItemIsNotOnGround,
RequirementsNotMeetToEquipThatItem,
CannotEquipItemInThatSlot,
RequirementsNotMeetToUseThatItem,
RequirementsNotMeetToUseThatAbility,
WrongNumberOfTargetsToUseThatAbility,
WrongTargetsSelectedToUseThatAbility,
UnEquipIsPrevented,
DropIsPrevented,
EquipIsPrevented,
PickIsPrevented,
UseIsPrevented,
ContainerIsNotOpenedByThisUnit,
ItemIsNotMovable,
ItemIsNotPickable,
AbilityIsPrevented,
AbilityHitIsPrevented,
UsableNotEnoughStacks,
PreviousActionNotFinished,
UnitNotInTurnManager,
UnitSelfTurnNotActive,
UnitNotEnoughActionPoints,
UnitNotEnoughMovePoints,
TalkNotAvailableWhenTurnActive,
ContainerIsAlreadyOpenedByThisUnit,
EnemiesAreTooClose,
OtherUnitIsNotOpenedByThisUnit,
OtherUnitIsAlreadyOpenedByThisUnit,
NoPathToTarget,
ThisUnitCantMove,
ThisUnitCantAttack,
ThisUnitCantUse,
ThisUnitCantTalk,
ThisUnitCantTake,
ThisUnitCantInspect,
OtherUnitCantBeInspected,
OtherUnitCantBeTalked,
ThisUnitIsCasting
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 29d18411212c41ccbbebd94f8ff33538
timeCreated: 1686666706
@@ -0,0 +1,88 @@
using UnityEngine;
using VOID.Generic.Objects.Item;
using VOID.Generic.Objects.Item.Events;
using VOID.Generic.Objects.Unit.Actions.Exceptions;
using VOID.Generic.Objects.Wearable;
using VOID.Generic.Objects.Wearable.Events;
namespace VOID.Generic.Objects.Unit.Actions
{
public class ForcedDropAction : AbstractAction
{
private readonly UnitObject _unit;
private readonly ItemObject _item;
private readonly Vector3 _dropPosition;
public ForcedDropAction(UnitObject unit, ItemObject item)
{
_unit = unit;
_item = item;
_dropPosition = unit.transform.position;
}
public ForcedDropAction(UnitObject unit, ItemObject item, Vector3 dropPosition)
{
_unit = unit;
_item = item;
_dropPosition = dropPosition;
}
public override bool IsInRange() => true;
protected override void OnEndIt() {}
protected override void OnCancelIt() {}
public override void CanDoIt()
{
Check(
state == ActionState.Ready,
UnitActionErrorType.ActionStateIsNotReady);
Check(
_item.itemState.carriedBy == _unit,
UnitActionErrorType.UnitDontCarryThatItem);
}
protected override void OnDoIt()
{
TryToUnEquip();
var dropEvent = new DropEvent
{
item = _item,
unit = _unit
};
_item.itemEvents.onDroppedBefore.Invoke(dropEvent);
_unit.unitEvents.onDropBefore.Invoke(dropEvent);
BeforePerform();
_unit.unitBackpack.Drop(_item);
_item.transform.position = _dropPosition;
_item.itemEvents.onDroppedAfter.Invoke(dropEvent);
_unit.unitEvents.onDropAfter.Invoke(dropEvent);
AfterPerform();
EndIt();
}
private void TryToUnEquip()
{
if (_item is not WearableObject item) return;
if (!item.wearableState.wearerUnit) return;
var unEquipEvent = new UnEquipEvent
{
wearable = item,
unit = _unit
};
item.wearableEvents.onUnEquippedBefore.Invoke(unEquipEvent);
_unit.unitEvents.onUnEquipBefore.Invoke(unEquipEvent);
_unit.unitEquipment.UnEquip(item);
_unit.unitBackpack.Take(item);
item.wearableEvents.onUnEquippedAfter.Invoke(unEquipEvent);
_unit.unitEvents.onUnEquipAfter.Invoke(unEquipEvent);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c2ff2b3fa8644c2998c8ee9682e77aa4
timeCreated: 1717965358
@@ -0,0 +1,74 @@
using VOID.Generic.Dict;
using VOID.Generic.Objects.Item;
using VOID.Generic.Objects.Item.Events;
using VOID.Generic.Objects.Unit.Actions.Exceptions;
namespace VOID.Generic.Objects.Unit.Actions
{
public class ForcedTakeAction : AbstractAction
{
private readonly UnitObject _unit;
private readonly ItemObject _item;
private readonly int _slotIndex;
public ForcedTakeAction(UnitObject unit, ItemObject item)
{
_unit = unit;
_item = item;
}
public ForcedTakeAction(UnitObject unit, ItemObject item, int slotIndex) : this(unit, item)
{
_slotIndex = slotIndex;
}
public override bool IsInRange() => true;
protected override void OnEndIt() {}
protected override void OnCancelIt() {}
public override void CanDoIt()
{
Check(
_unit.unitData.canTake,
UnitActionErrorType.ThisUnitCantTake);
Check(
state == ActionState.Ready,
UnitActionErrorType.ActionStateIsNotReady);
Check(
_item.itemData.canBePicked && _item.itemData.canBeMoved,
UnitActionErrorType.ItemIsNotPickable);
Check(
!_item.itemState.carriedBy,
UnitActionErrorType.ItemIsNotOnGround);
Check(
IsInRange(),
UnitActionErrorType.NotInRange);
}
protected override void OnDoIt()
{
if (_unit.basicState.turnManager)
_unit.unitData.UseResource(UnitResourceType.ActionPoints, 1);
var pickEvent = new PickEvent
{
item = _item,
unit = _unit
};
_item.itemEvents.onPickedBefore.Invoke(pickEvent);
_unit.unitEvents.onTakeBefore.Invoke(pickEvent);
BeforePerform();
if (_slotIndex != default)
_unit.unitBackpack.Take(_slotIndex, _item);
else
_unit.unitBackpack.Take(_item);
_item.itemEvents.onPickedAfter.Invoke(pickEvent);
_unit.unitEvents.onTakeAfter.Invoke(pickEvent);
AfterPerform();
EndIt();
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9d90c417b2bb46fda4ece59b93cc9818
timeCreated: 1717965568
@@ -0,0 +1,63 @@
using VOID.Generic.Objects.Abstract;
using VOID.Generic.Objects.Unit.Actions.Exceptions;
using VOID.Generic.Objects.Unit.Events;
using VOID.Generic.Util;
namespace VOID.Generic.Objects.Unit.Actions
{
public class InspectAction : AbstractAction
{
private readonly UnitObject _unit;
private readonly AbstractObject _targetObject;
private bool _isInspectFinished;
public InspectAction(UnitObject unit, AbstractObject targetObject)
{
_unit = unit;
_targetObject = targetObject;
}
public override bool IsInRange()
{
return RangeUtil.IsInRange(_unit, _targetObject, _unit.unitData.inspectRange);
}
protected override void OnEndIt() { }
protected override void OnCancelIt() { }
public override void CanDoIt()
{
Check(
_targetObject.basicData.canBeInspected,
UnitActionErrorType.OtherUnitCantBeInspected);
Check(
_unit.unitData.canInspect,
UnitActionErrorType.ThisUnitCantInspect);
Check(
state == ActionState.Ready,
UnitActionErrorType.ActionStateIsNotReady);
if (_unit.basicState.turnManager)
{
Check(
_unit.unitState.isSelfTurn,
UnitActionErrorType.UnitSelfTurnNotActive);
}
Check(
_unit.unitState.isControllable,
UnitActionErrorType.UnitStateIsNotControllable);
Check(
IsInRange(),
UnitActionErrorType.NotInRange);
}
protected override void OnDoIt()
{
new RotateAction(_unit, _targetObject).DoIt();
BeforePerform();
// Tutaj inspekcja
AfterPerform();
EndIt();
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f258e7d8f43c447ca7d1dcbacb9e467e
timeCreated: 1666712540
@@ -0,0 +1,46 @@
using VOID.Generic.Objects.Unit.Actions.Exceptions;
namespace VOID.Generic.Objects.Unit.Actions
{
public class LeaveTurnAction : AbstractAction
{
private readonly UnitObject _unit;
public LeaveTurnAction(UnitObject unit)
{
_unit = unit;
}
public override bool IsInRange() => true;
public override bool CanSkipQueue() => true;
protected override void OnEndIt()
{
}
protected override void OnCancelIt()
{
}
public override void CanDoIt()
{
Check(
state == ActionState.Ready,
UnitActionErrorType.ActionStateIsNotReady);
Check(
_unit.basicState.turnManager,
UnitActionErrorType.UnitNotInTurnManager);
Check(
_unit.unitState.isSelfTurn,
UnitActionErrorType.UnitSelfTurnNotActive);
Check(
_unit.basicState.turnManager.CanObjectExit(_unit),
UnitActionErrorType.EnemiesAreTooClose);
}
protected override void OnDoIt()
{
_unit.basicState.turnManager.ObjectExit(_unit);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 473562657fd14538ac05d1303664b527
timeCreated: 1708521881
@@ -0,0 +1,114 @@
using UnityEngine;
using UnityEngine.AI;
using VOID.Generic.Objects.Abstract;
using VOID.Generic.Objects.Unit.Actions.Exceptions;
using VOID.Generic.Objects.Unit.Events;
using VOID.Generic.Util;
namespace VOID.Generic.Objects.Unit.Actions
{
public class MoveAction : AbstractAction
{
private readonly UnitObject _unit;
private readonly Vector3 _targetPosition;
private readonly AbstractObject _targetObject;
private readonly float _untilInRange;
public MoveAction(UnitObject unit, Vector3 targetPosition, float untilInRange = 0f)
{
_unit = unit;
_targetPosition = targetPosition;
_untilInRange = untilInRange;
}
public MoveAction(UnitObject unit, AbstractObject targetObject, float untilInRange = 0f)
: this(unit, targetObject.transform.position, untilInRange + targetObject.basicData.radius)
{
_targetObject = targetObject;
}
public override bool IsInRange()
{
// Dont let player ordering move too far away
var distanceBetween = Vector3.Distance(_unit.transform.position, _targetPosition);
return distanceBetween < 100f;
}
public override bool CanBeStopped()
{
return !_unit.unitState.isTraversing;
}
protected override void OnEndIt()
{
_unit.unitEvents.onMoveEnd.RemoveListener(OnMoveEnd);
}
protected override void OnCancelIt()
{
_unit.unitEvents.onMoveEnd.RemoveListener(OnMoveEnd);
_unit.unitNavAgent.Stop();
}
public override void CanDoIt()
{
Check(
_unit.unitData.canMove,
UnitActionErrorType.ThisUnitCantMove);
Check(
state == ActionState.Ready,
UnitActionErrorType.ActionStateIsNotReady);
Check(
!_unit.unitState.isCasting,
UnitActionErrorType.ThisUnitIsCasting);
if (_unit.basicState.turnManager)
{
Check(
_unit.unitState.isSelfTurn,
UnitActionErrorType.UnitSelfTurnNotActive);
Check(
_unit.unitData.currentResources.movePoints > 0.1f,
UnitActionErrorType.UnitNotEnoughMovePoints);
}
Check(
_unit.unitState.isControllable,
UnitActionErrorType.UnitStateIsNotControllable);
Check(
IsInRange(),
UnitActionErrorType.NotInRange);
_unit.unitNavAgent.CalculatePathTo(_targetPosition, _untilInRange);
Check(
_unit.unitNavAgent.GetPath().status is not NavMeshPathStatus.PathInvalid,
UnitActionErrorType.NoPathToTarget);
}
protected override void OnDoIt()
{
var isInRange = _targetObject
? RangeUtil.IsInRange(_unit, _targetObject, _untilInRange, false)
: RangeUtil.IsInRange(_unit, _targetPosition, _untilInRange, false);
if (isInRange)
{
EndIt();
return;
}
BeforePerform();
_unit.unitEvents.onMoveEnd.AddListener(OnMoveEnd);
var moveStarted = _targetObject
? _unit.unitNavAgent.Move(_targetObject, _untilInRange)
: _unit.unitNavAgent.Move(_targetPosition, _untilInRange);
// Unit didn't move for some reason (usually path is impossible or already at path destination)
if (!moveStarted) EndIt();
}
private void OnMoveEnd(MoveEvent moveEvent)
{
AfterPerform();
EndIt();
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d481a211739c4caa88711e3ae6bbef5d
timeCreated: 1666646839
@@ -0,0 +1,86 @@
using UnityEngine;
using VOID.Generic.Dict;
using VOID.Generic.Objects.Item;
using VOID.Generic.Objects.Item.Events;
using VOID.Generic.Objects.Unit.Actions.Exceptions;
using VOID.Generic.Util;
namespace VOID.Generic.Objects.Unit.Actions
{
public class MoveItemAction : AbstractAction
{
private readonly UnitObject _unit;
private readonly ItemObject _item;
private readonly Vector3 _toPosition;
public MoveItemAction(UnitObject unit, ItemObject item, Vector3 toPosition)
{
_unit = unit;
_item = item;
_toPosition = toPosition;
}
public override bool IsInRange()
{
return RangeUtil.IsInRange(_unit, _item, _unit.unitData.takeRange)
&& RangeUtil.IsInRange(_item, _toPosition, _unit.unitData.takeRange*2);
}
protected override void OnEndIt() {}
protected override void OnCancelIt() {}
public override void CanDoIt()
{
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(
_item.itemData.canBeMoved,
UnitActionErrorType.ItemIsNotMovable);
Check(
_unit.unitState.isControllable,
UnitActionErrorType.UnitStateIsNotControllable);
Check(
IsInRange(),
UnitActionErrorType.NotInRange);
}
protected override void OnDoIt()
{
if (_unit.basicState.turnManager)
_unit.unitData.UseResource(UnitResourceType.ActionPoints, 1);
var moveItemEvent = new MoveItemEvent
{
unit = _unit,
item = _item,
fromPosition = _item.transform.position,
toPosition = _toPosition,
};
_item.itemEvents.onMovedBefore.Invoke(moveItemEvent);
_unit.unitEvents.onMoveItemBefore.Invoke(moveItemEvent);
_unit.OrderInstantly(new RotateAction(_unit, _item));
BeforePerform();
Check(_item.Move(_toPosition), UnitActionErrorType.ItemIsNotMovable);
_item.itemEvents.onMovedAfter.Invoke(moveItemEvent);
_unit.unitEvents.onMoveItemAfter.Invoke(moveItemEvent);
AfterPerform();
EndIt();
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 56e325e16de846e08d48376bb2d31e28
timeCreated: 1694902221
@@ -0,0 +1,68 @@
using VOID.Generic.Objects.Container;
using VOID.Generic.Objects.Container.Events;
using VOID.Generic.Objects.Unit.Actions.Exceptions;
using VOID.Generic.Util;
namespace VOID.Generic.Objects.Unit.Actions
{
public class OpenContainerAction : AbstractAction
{
private readonly UnitObject _unit;
private readonly ContainerObject _container;
public OpenContainerAction(UnitObject unit, ContainerObject container)
{
_unit = unit;
_container = container;
}
public override bool IsInRange()
{
return RangeUtil.IsInRange(_unit, _container, _unit.unitData.takeRange);
}
protected override void OnEndIt() {}
protected override void OnCancelIt() {}
public override void CanDoIt()
{
Check(
state == ActionState.Ready,
UnitActionErrorType.ActionStateIsNotReady);
if (_unit.basicState.turnManager)
{
Check(
_unit.unitState.isSelfTurn || _container.itemState.carriedBy == _unit,
UnitActionErrorType.UnitSelfTurnNotActive);
}
Check(
_unit.unitState.isControllable,
UnitActionErrorType.UnitStateIsNotControllable);
Check(
IsInRange(),
UnitActionErrorType.NotInRange);
Check(
!_container.containerState.openedBy.Contains(_unit),
UnitActionErrorType.ContainerIsAlreadyOpenedByThisUnit);
}
protected override void OnDoIt()
{
var containerOpenEvent = new ContainerOpenEvent
{
openedBy = _unit,
container = _container
};
if (_container.itemState.carriedBy != _unit)
_unit.OrderInstantly(new RotateAction(_unit, _container));
BeforePerform();
_container.containerEvents.onOpen.Invoke(containerOpenEvent);
_unit.unitEvents.onContainerOpen.Invoke(containerOpenEvent);
AfterPerform();
EndIt();
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 53552ef81c0c4845afac57174071db3a
timeCreated: 1694902221
@@ -0,0 +1,69 @@
using VOID.Generic.Objects.Unit.Actions.Exceptions;
using VOID.Generic.Objects.Unit.Events;
using VOID.Generic.Util;
namespace VOID.Generic.Objects.Unit.Actions
{
public class OpenOtherUnitAction : AbstractAction
{
private readonly UnitObject _unit;
private readonly UnitObject _otherUnit;
public OpenOtherUnitAction(UnitObject unit, UnitObject otherUnit)
{
_unit = unit;
_otherUnit = otherUnit;
}
public override bool IsInRange()
{
return RangeUtil.IsInRange(_unit, _otherUnit, _unit.unitData.takeRange);
}
protected override void OnEndIt() {}
protected override void OnCancelIt() {}
public override void CanDoIt()
{
Check(
state == ActionState.Ready,
UnitActionErrorType.ActionStateIsNotReady);
if (_unit.basicState.turnManager)
{
Check(
_unit.unitState.isSelfTurn,
UnitActionErrorType.UnitSelfTurnNotActive);
}
Check(
_unit.unitState.isControllable,
UnitActionErrorType.UnitStateIsNotControllable);
Check(
IsInRange(),
UnitActionErrorType.NotInRange);
Check(
_otherUnit.basicState.isDead,
UnitActionErrorType.NotInRange);
Check(
!_otherUnit.unitState.openedBy.Contains(_unit),
UnitActionErrorType.OtherUnitIsAlreadyOpenedByThisUnit);
}
protected override void OnDoIt()
{
var openOtherUnitEvent = new OpenOtherUnitEvent()
{
openedBy = _unit,
otherUnit = _otherUnit
};
_unit.OrderInstantly(new RotateAction(_unit, _otherUnit));
BeforePerform();
_otherUnit.unitEvents.onOpenedByOtherUnit.Invoke(openOtherUnitEvent);
_unit.unitEvents.onOpenOtherUnit.Invoke(openOtherUnitEvent);
AfterPerform();
EndIt();
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6544441f582a408a99a829faa559acb7
timeCreated: 1717947141
@@ -0,0 +1,53 @@
using UnityEngine;
using VOID.Generic.Objects.Abstract;
using VOID.Generic.Objects.Unit.Actions.Exceptions;
namespace VOID.Generic.Objects.Unit.Actions
{
public class RotateAction : AbstractAction
{
private readonly UnitObject _unit;
private readonly float _targetYaw;
public RotateAction(UnitObject unit, float targetYaw)
{
_unit = unit;
_targetYaw = targetYaw;
}
public RotateAction(UnitObject unit, Vector3 lookAt)
{
_unit = unit;
_targetYaw = Vector3.SignedAngle(
Vector3.forward,
Vector3.Scale(lookAt - unit.transform.position, new Vector3(1,0,1)),
Vector3.up);
}
public RotateAction(UnitObject unit, AbstractObject lookAt) : this(unit, lookAt.transform.position) { }
public override bool IsInRange() => true;
public override bool CanSkipQueue() => true;
protected override void OnEndIt() { }
protected override void OnCancelIt() { }
public override void CanDoIt()
{
Check(
state == ActionState.Ready,
UnitActionErrorType.ActionStateIsNotReady);
}
protected override void OnDoIt()
{
BeforePerform();
var targetRotation = _unit.transform.rotation.eulerAngles;
targetRotation.y = _targetYaw;
_unit.transform.rotation = Quaternion.Euler(targetRotation);
AfterPerform();
EndIt();
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e83a38e3a7c34f959bfe53f430c23dae
timeCreated: 1696077331
@@ -0,0 +1,105 @@
using VOID.Generic.Dict;
using VOID.Generic.Objects.Item;
using VOID.Generic.Objects.Item.Events;
using VOID.Generic.Objects.Unit.Actions.Exceptions;
using VOID.Generic.Objects.Unit.Events;
using VOID.Generic.Util;
namespace VOID.Generic.Objects.Unit.Actions
{
public class TakeAction : AbstractAction
{
private readonly UnitObject _unit;
private readonly ItemObject _item;
private readonly int _slotIndex;
public TakeAction(UnitObject unit, ItemObject item)
{
_unit = unit;
_item = item;
}
public TakeAction(UnitObject unit, ItemObject item, int slotIndex) : this(unit, item)
{
_slotIndex = slotIndex;
}
public override bool IsInRange()
{
return RangeUtil.IsInRange(_unit, _item, _unit.unitData.takeRange);
}
protected override void OnEndIt()
{
}
protected override void OnCancelIt()
{
}
public override void CanDoIt()
{
Check(
_unit.unitData.canTake,
UnitActionErrorType.ThisUnitCantTake);
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(
_item.itemData.canBePicked && _item.itemData.canBeMoved,
UnitActionErrorType.ItemIsNotPickable);
Check(
!_item.itemState.carriedBy || _item.itemState.carriedBy.basicState.isDead,
UnitActionErrorType.ItemIsNotOnGround);
Check(
IsInRange(),
UnitActionErrorType.NotInRange);
}
protected override void OnDoIt()
{
if (_unit.basicState.turnManager)
_unit.unitData.UseResource(UnitResourceType.ActionPoints, 1);
_unit.OrderInstantly(new RotateAction(_unit, _item));
if (_item.itemState.carriedBy && _item.itemState.carriedBy.basicState.isDead)
new ForcedDropAction(_item.itemState.carriedBy, _item).DoIt();
Check(!_item.itemState.carriedBy, UnitActionErrorType.ItemIsNotOnGround);
var pickEvent = new PickEvent
{
item = _item,
unit = _unit
};
_item.itemEvents.onPickedBefore.Invoke(pickEvent);
_unit.unitEvents.onTakeBefore.Invoke(pickEvent);
Check(!pickEvent.prevented, UnitActionErrorType.PickIsPrevented);
BeforePerform();
if (_item.itemState.inContainer) _item.itemState.inContainer.containerContent.MoveOut(_item, _unit);
_unit.unitBackpack.Take(_slotIndex, _item);
_item.itemEvents.onPickedAfter.Invoke(pickEvent);
_unit.unitEvents.onTakeAfter.Invoke(pickEvent);
AfterPerform();
EndIt();
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3b1c26cd2b2449c6b6b692acac0d944a
timeCreated: 1666711181
@@ -0,0 +1,62 @@
using VOID.Generic.Objects.Abstract;
using VOID.Generic.Objects.Unit.Actions.Exceptions;
using VOID.Generic.Objects.Unit.Events;
using VOID.Generic.Util;
namespace VOID.Generic.Objects.Unit.Actions
{
public class TalkAction : AbstractAction
{
private readonly UnitObject _unit;
private readonly UnitObject _targetObject;
public TalkAction(UnitObject unit, UnitObject targetObject)
{
_unit = unit;
_targetObject = targetObject;
}
public override bool IsInRange()
{
return RangeUtil.IsInRange(_unit, _targetObject, _unit.unitData.talkRange);
}
protected override void OnEndIt() { }
protected override void OnCancelIt() { }
public override void CanDoIt()
{
Check(
_unit.unitData.canTalk,
UnitActionErrorType.ThisUnitCantTalk);
Check(
_targetObject.unitData.canBeTalked,
UnitActionErrorType.OtherUnitCantBeTalked);
Check(
state == ActionState.Ready,
UnitActionErrorType.ActionStateIsNotReady);
Check(
!_unit.basicState.turnManager,
UnitActionErrorType.TalkNotAvailableWhenTurnActive);
Check(
_unit.unitState.isControllable,
UnitActionErrorType.UnitStateIsNotControllable);
Check(
_unit.unitState.isControllable,
UnitActionErrorType.UnitStateIsNotControllable);
Check(
IsInRange(),
UnitActionErrorType.NotInRange);
}
protected override void OnDoIt()
{
new RotateAction(_unit, _targetObject).DoIt();
BeforePerform();
// Tutaj rozmowa
AfterPerform();
EndIt();
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 803ece80d3c045f980bc5ccf346cc211
timeCreated: 1666711074
@@ -0,0 +1,73 @@
using VOID.Generic.Dict;
using VOID.Generic.Objects.Item.Events;
using VOID.Generic.Objects.Unit.Actions.Exceptions;
using VOID.Generic.Objects.Wearable;
using VOID.Generic.Objects.Wearable.Events;
namespace VOID.Generic.Objects.Unit.Actions
{
public class UnEquipAction : AbstractAction
{
private readonly UnitObject _unit;
private readonly WearableObject _item;
public UnEquipAction(UnitObject unit, WearableObject item)
{
_unit = unit;
_item = item;
}
public override bool IsInRange() => true;
protected override void OnEndIt() {}
protected override void OnCancelIt() {}
public override void CanDoIt()
{
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(
_item.wearableState.wearerUnit == _unit,
UnitActionErrorType.UnitDontWearThatItem);
}
protected override void OnDoIt()
{
if (_unit.basicState.turnManager)
_unit.unitData.UseResource(UnitResourceType.ActionPoints, 1);
var unEquipEvent = new UnEquipEvent
{
wearable = _item,
unit = _unit
};
_item.wearableEvents.onUnEquippedBefore.Invoke(unEquipEvent);
_unit.unitEvents.onUnEquipBefore.Invoke(unEquipEvent);
Check(!unEquipEvent.prevented, UnitActionErrorType.UnEquipIsPrevented);
BeforePerform();
_unit.unitEquipment.UnEquip(_item);
_unit.unitBackpack.Take(_item);
_item.wearableEvents.onUnEquippedAfter.Invoke(unEquipEvent);
_unit.unitEvents.onUnEquipAfter.Invoke(unEquipEvent);
AfterPerform();
EndIt();
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 14701689e25d4ce2830058af6f2aa35d
timeCreated: 1672747135
@@ -0,0 +1,126 @@
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);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2a8ad83743854805ac80ebe801e80a0a
timeCreated: 1666710459