init
This commit is contained in:
@@ -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
|
||||
+16
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -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
|
||||
}
|
||||
}
|
||||
+3
@@ -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
|
||||
Reference in New Issue
Block a user