ZZLU6UG75ALN7BYLP4SLGT4SIHDKJPFZPMNSYST25RQT3KLTFHPAC
ETEF4UXJYHL5BG775IMDIBI5EZIFNS62IF6VOJGCB4LG6WEL7OUAC
G4XIS2NEM4WHRP2775YBCLFDT7JZZS52CMEHY3PA43QSXL45XNDAC
62YQ7EMUYX7GS3AB6FAJDKNX53LVG6T2EH6NMVS6JV36J5VCOKIAC
VZRSH4U473FCZOP5EXURPXXN5J6F3ZLT435YY7A2JHLG2ZZB5KLQC
M2C63XUU3TKYAUPPSPEFVF4CMBQMCVLZATANFWQW35MMYNRB2SEAC
DGC7DHJWSP6BZMDKZ6FG6YS7P2RXZWKFROBYHEX4KZCG7HFBLSUQC
RZAMG2H2NY73KZJIV4VXLJHJVSRGJDRWWZJERAI6O7AVDW64JEQQC
S5OSCH7CRN2YEKVTCTJXNLYR2B3PEGCCBUGTN2M6QOCKBNJR62NAC
6BA5NHNF3UWSL65KCWSXLRTPGYVS4N4NORDJ4FZTZ5SRRDPI4YZAC
HXTSBPAP75A7EC4RKWYQMVPPHPNZFPHUORBZWDHGEB6MPAGI7G7AC
MHN2B5YZ2Y4G3O7UOZJKFQ3SSP5HTNJCXFKCO3KYY46I2GHM3TIQC
GRTHEQW3VTYOB4CSVAB4VBEAW6MRVAJRV4CBXOIRSUFMO7SK3GCAC
QOAVQCDV2MRAPUX62ZLDTUB6AXYSAGEEWIEZIG4TGIQKCLP5T5GAC
KAROCU3SAOGWWSFXGCLE5OW76VTDJR4HDIVTK62BIAESN5SOHVDAC
WKHLLZ3K732M7VJ5KWDSLRWZUARDNDP6ODAXD6SW43CHCT5DX5SAC
S256EPZUSOF4TV2KGOFZDJXUFDD57GZFYTCARFJ3SD24RPC56PHAC
IA2O33JCJVSJ3IVBBHX2XQU4BCPL3X6JDDZ2R2KNGUFPWXAUKO7QC
QZXURLSF73UL67TIXDHMVS7DCFZLQJAPJ6BAGRGXOHH46VMNKGPQC
2ICHN37Z2OZ455ALKTMXTV5JOULQBN5UN46OM6JCHMF3CPNHFF3AC
5YUI4V7A6ONEYREG5CXWHMBYCOP6Q3GMMQD2OTHXZAGKCGM4FWBAC
2SLVO3SYIJQOEV2YNSD73BSUSWQNZVROQCGHJCPCDSMCCNKZTQFQC
EF6FXKYIVJCURLSC2CLS27FCTECIIIU2EEPI352ZTCIKYKW5VOBQC
N6YTMLNYZLR4BEDGYC7RJQ43KJ3XZFILZ6ODN26Z7RF3LZ6LVUOQC
A6K2SVTQ3JQ3TC3F44H3ERSX47TRQ6R5EJGIRJKFGKZG6I4HOATQC
NQXDEYOPZBO7AZJHBEBNMBR3QFE4OAQFK4FHOIGKD7TXE256X23AC
2ZZM2HIS7HNIMK3Q6ALHIMQYLKNIHUOL6FJ57O6SR77VAMEINLWAC
O236B5LO6PHJ4TPZGYXDVSLB5EGXXRRLYYVWI46DPL5LEGXEIHZQC
XF52N4U7HWXOF4PDSCR7LCUENLTSXLWEZGS2IJ6562KYI567Z2GAC
XIPU27GAVXMAKDP42DDSYNA6DSN5WBHH6AG4EK6YIIM43AQQHQAAC
NZIEX6J6Q6DSJKNSCTHNIA6EJDQEGMK3ZSP3LKX2UAEDHURQPRVQC
CD5FF75KTOBTMVMTMCKMR6F5DFKOF26I5K43ITNHGBI3ZAZHA4RAC
4PLSNSVW4VOQW5ZXXZGUWB56WI33SXTGWOCD7PNE36OWDGD7NRJAC
5I5QA3YK5G5QQCXMSDOEAX3A74LVXV7PYWAIHMLFANR2GUFWMKGQC
LTG4LQJEMFY22QOI6E5HM3U4OE3JCYRFJ6VGW3KI3AFTMHZCTWRAC
P5O6MKCMZL3DK7ZO5SBWTCHOQB6O2MZA5VPSCQX6X4LJQVOWYV7AC
HUULCHM5GFGZ7GKLCULFHC333LQ3LBI62VKII3YL5O4C5CDGCT4AC
OXMN3LHBNH7CWHEZRPSZTN244O3ACTOEKZEAKQNKFXQ7VQSM26YQC
DIEGZM3YMQCKTQW3NLESFZBOGMWW6FT6TZOUL7IUAJD2X5IISUYAC
4JF2MUNF23IFAVVECZNP3JJLFPEB36V7FDRQOKIZNF6Q2FAGOFRQC
3JTZIZGE6WPLZCIWXXLG3SQA2LVSVP26P7U52YBMBTY2VCC6LBLAC
FIMVA3BI72IWMBRN5T3PKDCKSJW667BH25INKDWSPWGHLRKCNAPAC
JCJJQHBBV2KJGV46NWH3RHF5XSFVZUB56DVGR5XTCUOXHWD2KCJAC
MQD6ISMHW27RCHAGJUINEULYXSY3JQ3UKVQPEM5PYDMM32TUYAYQC
5VVJCVERFU6ZMLSEW5TWRUHOLYL2ATFLNMWAEEJBXCG2RM3MJGSAC
S6LIARO3HIMP67ZDRIPPU3NC4GM6JQQODDIFGZH5HBN75JHFFSQAC
ROTMK5LNNK7T5YXVOMUODVMCQWIHPZYOME4WDIAMZJ4VXD7SOEBAC
4JF64OZ2FPMTXL5XV3Z6HCEKKGCLXPLMNV3YCNX35RL5CXL42VNQC
VUAVVMQEUYSXHBIUJHGRX237EZFT5MCB73ZKVWMGJDRHYZH4XZKAC
R475KN7MR3OG7EBLVNOO7QRIKXDGY2PIDXXV3HW4KBD5QM7B5OJQC
FNS4LRFQNFM4BCB23CYHOWA2N4MG2DEUMNK6D55BQ26TX6OJLIBQC
577EKAKIUP5R4STCPLRNJT6IJR6G232FAJ2T7DSCK2LOJZ5EG55QC
MML56TWYWB6SUY5JEWHG2PNLAH3JY72PGCEXIGOYE54EAC2WSWBAC
VPXUP5WZTVC3OVD73TNKPK43IAGFXGUGCEJT56JM4IT4APYQXUHAC
[SerializeField] Inventory _inventory;
[SerializeField] List<CombatFormRef> _knownForms;
Weapon _equippedWeapon;
CombatForm _equippedForm;
Dictionary<Weapon, CombatForm> _preferedCombatFormByWeapon = new();
Line<IAction> _plannedActions = new(capacity: 6);
public class Weaver : MonoBehaviour
{
[SerializeField] Inventory _inventory;
[SerializeField] List<CombatFormRef> _knownForms;
Weapon _equippedWeapon;
CombatForm _equippedForm;
Dictionary<Weapon, CombatForm> _preferedCombatFormByWeapon = new();
Line<IAction> _plannedActions = new(capacity: 6);
public event EventHandler<WeaponEquippedEventArgs> WeaponEquipped;
public event EventHandler<CombatFormEquippedEventArgs> CombatFormEquipped;
public event EventHandler<TakeActionEventArgs> ActionTaken;
public event EventHandler<UnitActionEventArgs> PlannedActionsChanged;
public event EventHandler<WeaponEquippedEventArgs> WeaponEquipping;
public event EventHandler<WeaponEquippedEventArgs> WeaponEquipped;
public event EventHandler<CombatFormEquippedEventArgs> CombatFormEquipped;
public event EventHandler<TakeActionEventArgs> ActionTaken;
public event EventHandler<UnitActionEventArgs> PlannedActionsChanged;
protected void OnActionTaken(TakeActionEventArgs e) {
ActionTaken?.Invoke(this, e);
}
protected void OnPlannedActionsChanged(UnitActionEventArgs e) {
PlannedActionsChanged?.Invoke(this, e);
}
protected void OnCombatFormEquipped(CombatFormEquippedEventArgs e) {
CombatFormEquipped?.Invoke(this, e);
}
protected void OnActionTaken(TakeActionEventArgs e) {
ActionTaken?.Invoke(this, e);
}
protected void OnPlannedActionsChanged(UnitActionEventArgs e) {
PlannedActionsChanged?.Invoke(this, e);
}
protected void Start() {
EquipAnyWeapon();
}
protected void Update() {
if (_plannedActions.TryPeek(out var action)) {
var actionState = action.Advance();
OnActionTaken(new(actionState));
if (!actionState.IsAdvanced) {
action.Dispose();
_plannedActions.TryGetFirstOutOfLine(out var _);
OnPlannedActionsChanged(new(transform));
}
}
}
if (!actionState.IsAdvanced) {
action.Cancel();
_plannedActions.TryGetFirstOutOfLine(out var _);
bool PlanAction(IAction action) {
var success = false;
if (_plannedActions.TryWaitInLine(action)) {
bool PlanAction(IAction action) {
var success = false;
if (_plannedActions.TryWaitInLine(action)) {
OnPlannedActionsChanged(new(transform));
success = true;
void SetCombatForm(CombatForm combatForm) {
_equippedForm = combatForm;
OnCombatFormEquipped(new(_equippedForm, this));
void SetCombatForm(CombatForm combatForm) {
_equippedForm = combatForm;
OnCombatFormEquipped(new(_equippedForm, this));
}
void EquipPreferredCombatFormOfWeapon(Weapon weapon) {
_preferedCombatFormByWeapon.TryGetValue(weapon, out var tryEquipForm);
SetCombatForm(tryEquipForm);
}
void EquipPreferredCombatFormOfWeapon(Weapon weapon) {
_preferedCombatFormByWeapon.TryGetValue(weapon, out var tryEquipForm);
SetCombatForm(tryEquipForm);
}
void EquipAnyWeapon() {
var tryEquipWeapon = _inventory.GetAvailableWeapons().First();
if (tryEquipWeapon != null) {
TryDrawWeapon(tryEquipWeapon.Name);
}
}
public bool TryDrawWeapon(string weaponName) {
var isWeaponInInventory = false;
if (_inventory) {
isWeaponInInventory = _inventory.TryGetWeaponByName(weaponName, out var tryEquipWeapon);
if (isWeaponInInventory) {
ClearActionPlan();
_equippedWeapon = tryEquipWeapon;
OnWeaponEquipped(new(_equippedWeapon, this));
EquipPreferredCombatFormOfWeapon(_equippedWeapon);
void EquipAnyWeapon() {
var tryEquipWeapon = _inventory.GetAvailableWeapons().First();
if (tryEquipWeapon != null) {
TryDrawWeapon(tryEquipWeapon.Name);
return isWeaponInInventory;
}
public bool TryEquipCombatForm(string combatFormName) {
CombatForm combatForm = GetAvailableCombatFormsForEquipedWeapon().Where(combatForm => combatForm.name == combatFormName).FirstOrDefault();
_preferedCombatFormByWeapon[_equippedWeapon] = combatForm;
SetCombatForm(combatForm);
public bool TryDrawWeapon(string weaponName) {
var isWeaponInInventory = false;
if (_inventory) {
isWeaponInInventory = _inventory.TryGetWeaponByName(weaponName, out var tryEquipWeapon);
if (isWeaponInInventory) {
ClearActionPlan();
var previousWeapon = _equippedWeapon;
_equippedWeapon = tryEquipWeapon;
OnWeaponEquipping(new(previousWeapon, _equippedWeapon, this));
EquipPreferredCombatFormOfWeapon(_equippedWeapon);
OnWeaponEquipped(new(previousWeapon, _equippedWeapon, this));
}
}
return combatForm != null;
}
return isWeaponInInventory;
}
public bool TryEquipCombatForm(string combatFormName) {
CombatForm combatForm = GetAvailableCombatFormsForEquipedWeapon().Where(combatForm => combatForm.name == combatFormName).FirstOrDefault();
_preferedCombatFormByWeapon[_equippedWeapon] = combatForm;
SetCombatForm(combatForm);
public bool TryQueueWeave(RuneWeavingContainer weaving, Transform target) {
WeaveAction weaveAction = new(this, weaving, target, _equippedWeapon.GetRange());
var success = PlanAction(weaveAction);
return success;
}
return combatForm != null;
}
public bool TryQueueFollow(Transform target) {
FollowAction followAction = new(this, target, _equippedWeapon.GetRange());
var success = PlanAction(followAction);
return success;
}
public bool TryQueueWeave(RuneWeavingContainer weaving, Transform target) {
WeaveAction weaveAction = new(this, weaving, target, GetComponent<Resources.Range>());
var success = PlanAction(weaveAction);
return success;
}
public bool TryQueueMove(Vector3 target) {
MoveToAction moveToAction = new(this, target);
var success = PlanAction(moveToAction);
return success;
}
public bool TryQueueFollow(Transform target) {
FollowAction followAction = new(this, target);
var success = PlanAction(followAction);
return success;
}
public void ClearActionPlan() {
foreach (var action in _plannedActions) {
action.Cancel();
public bool TryQueueMove(Vector3 target) {
MoveToAction moveToAction = new(this, target);
var success = PlanAction(moveToAction);
return success;
public bool TryRemoveActionFromPlan(int index) {
var success = false;
if (_plannedActions.TryRemoveAt(index, out var _)) {
success = true;
public void ClearActionPlan() {
foreach (var action in _plannedActions) {
action.Dispose();
}
_plannedActions.Clear();
return success;
}
public bool TryRemoveActionFromPlan(int index) {
var success = false;
if (_plannedActions.TryRemoveAt(index, out var _)) {
success = true;
OnPlannedActionsChanged(new(transform));
}
return success;
}
public bool CanUseWeave(RuneWeaving weave) {
var weaponMoveSet = _equippedWeapon.GetCombatMoveSetRef().CombatMoveSet.CombatMoves();
var weaveMoveSet = weave.MartialSequence.GetSequence().Select(moveRef => moveRef.CombatMove);
return weaveMoveSet.All(weaveMove => weaponMoveSet.Any(weaponMove => weaveMove.MoveName == weaponMove.CombatMove.MoveName));
}
public bool CanUseWeave(RuneWeaving weave) {
var weaponMoveSet = _equippedWeapon.GetCombatMoveSetRef().CombatMoveSet.CombatMoves();
var weaveMoveSet = weave.MartialSequence.GetSequence().Select(moveRef => moveRef.CombatMove);
return weaveMoveSet.All(weaveMove => weaponMoveSet.Any(weaponMove => weaveMove.MoveName == weaponMove.CombatMove.MoveName));
}
public Weapon EquippedWeapon => _equippedWeapon;
public CombatForm EquippedForm => _equippedForm;
public IEnumerable<Weapon> GetWeaponsInInventory() => _inventory.GetAvailableWeapons();
public IEnumerable<CombatFormRef> GetAvailableCombatFormsForEquipedWeapon() => _knownForms.Select(combatFormRef => combatFormRef).Intersect(_equippedWeapon.GetCompatibleFormRefs());
public IEnumerable<IAction> GetPlannedActions() => _plannedActions;
public Weapon EquippedWeapon => _equippedWeapon;
public CombatForm EquippedForm => _equippedForm;
public IEnumerable<Weapon> GetWeaponsInInventory() => _inventory.GetAvailableWeapons();
public IEnumerable<CombatFormRef> GetAvailableCombatFormsForEquipedWeapon() => _knownForms.Select(combatFormRef => combatFormRef).Intersect(_equippedWeapon.GetCompatibleFormRefs());
public IEnumerable<IAction> GetPlannedActions() => _plannedActions;
public class WeaponEquippedEventArgs : EventArgs
{
public Weapon Weapon { get; }
public Weaver Weaver { get; }
public WeaponEquippedEventArgs(Weapon weapon, Weaver weaver) {
Weapon = weapon;
Weaver = weaver;
public class WeaponEquippedEventArgs : EventArgs
{
public Weapon PreviousWeapon { get; }
public Weapon CurrentWeapon { get; }
public Weaver Weaver { get; }
public WeaponEquippedEventArgs(Weapon previousWeapon, Weapon currentWeapon, Weaver weaver) {
PreviousWeapon = previousWeapon;
CurrentWeapon = currentWeapon;
Weaver = weaver;
}
}
public class CombatFormEquippedEventArgs : EventArgs
{
public CombatForm CombatForm { get; }
public Weaver Weaver { get; }
public CombatFormEquippedEventArgs(CombatForm combatForm, Weaver weaver) {
CombatForm = combatForm;
Weaver = weaver;
public class CombatFormEquippedEventArgs : EventArgs
{
public CombatForm CombatForm { get; }
public Weaver Weaver { get; }
public CombatFormEquippedEventArgs(CombatForm combatForm, Weaver weaver) {
CombatForm = combatForm;
Weaver = weaver;
}
public class TakeActionEventArgs : EventArgs
{
public IActionState ActionState { get; }
public TakeActionEventArgs(IActionState actionState) {
ActionState = actionState;
public class TakeActionEventArgs : EventArgs
{
public IActionState ActionState { get; }
public TakeActionEventArgs(IActionState actionState) {
ActionState = actionState;
}
[SerializeField] List<WeaponSet> _weaponSets;
int _currentActiveSet = -1;
Weaver _watchedWeaver;
[RequireComponent(typeof(Weaver))]
public class WeaponSwap : MonoBehaviour
{
[SerializeField] List<WeaponSet> _weaponSets;
int _currentActiveSet = -1;
Weaver _watchedWeaver;
void SetWatchedWeaver(Weaver weaver) {
if (_watchedWeaver != null) {
_watchedWeaver.WeaponEquipping -= OnWeaponEquipping;
}
_watchedWeaver = weaver;
void SetWatchedWeaver(Weaver weaver) {
if (_watchedWeaver != null) {
_watchedWeaver.WeaponEquipped -= OnWeaponEquipped;
if (_watchedWeaver != null) {
_watchedWeaver.WeaponEquipping += OnWeaponEquipping;
}
}
protected void Awake() {
SetWatchedWeaver(GetComponent<Weaver>());
if (_watchedWeaver != null) {
_watchedWeaver.WeaponEquipped += OnWeaponEquipped;
void ApplyItemEffects(Weapon item) {
Debug.Log($"ApplyItemEffects on {_watchedWeaver}");
var context = new EffectContext(new EffectSystem(GameObject.Find("RippleOutVfx").GetComponent<ParticleSystem>())) {
EffectLocation = _watchedWeaver.transform,
Caster = _watchedWeaver.transform
};
foreach (var effect in item.MainHandEffects()) {
effect.Mode.ImmediateAction(context, effect.Effect);
}
}
protected void Awake() {
SetWatchedWeaver(GetComponent<Weaver>());
}
protected void OnDestroy() {
SetWatchedWeaver(null);
}
void OnWeaponEquipped(object sender, Weaver.WeaponEquippedEventArgs e) {
ChangeActiveWeaponSet(e.Weapon.Name);
}
void ChangeActiveWeaponSet(string weaponName) {
var newActiveSet = _weaponSets.FindIndex(set => set.Weapon.Value.Name == weaponName);
if (newActiveSet == -1) {
print($"WeaponSwap {weaponName} cannot be found");
return;
}
if (newActiveSet != _currentActiveSet) {
foreach (var weapon in _weaponSets[newActiveSet].WeaponProps) {
weapon.SetActive(true);
void ChangeActiveWeaponSet(string weaponName) {
var newActiveSet = _weaponSets.FindIndex(set => set.Weapon.Value.Name == weaponName);
if (newActiveSet == -1) {
print($"WeaponSwap {weaponName} cannot be found");
return;
[Serializable]
public class WeaponSet
{
public WeaponRef Weapon;
public List<GameObject> WeaponProps;
[Serializable]
public class WeaponSet
{
public WeaponRef Weapon;
public List<GameObject> WeaponProps;
}
[SerializeField] List<WeaponRef> _availableWeapons;
Dictionary<string, Weapon> _availableWeaponsByName;
[CreateAssetMenu(fileName = "Inventory", menuName = "Combat/Inventory")]
public class Inventory : ScriptableObject
{
[SerializeField] List<WeaponRef> _availableWeapons;
Dictionary<string, Weapon> _availableWeaponsByName;
protected void OnEnable() {
if (_availableWeapons?.Any() == true) {
_availableWeaponsByName = _availableWeapons.Distinct().ToDictionary(weaponRef => weaponRef.Value.Name, weaponRef => weaponRef.Value);
protected void OnEnable() {
if (_availableWeapons?.Any() == true) {
_availableWeaponsByName = _availableWeapons.Distinct().ToDictionary(weaponRef => weaponRef.Value.Name, weaponRef => weaponRef.Value);
}
public bool TryGetWeaponByName(string weaponName, out Weapon weapon) {
var isWeaponInInventory = false;
weapon = null;
if (_availableWeaponsByName != null) {
isWeaponInInventory = _availableWeaponsByName.TryGetValue(weaponName, out weapon);
public bool TryGetWeaponByName(string weaponName, out Weapon weapon) {
var isWeaponInInventory = false;
weapon = null;
if (_availableWeaponsByName != null) {
isWeaponInInventory = _availableWeaponsByName.TryGetValue(weaponName, out weapon);
}
return isWeaponInInventory;
List<string> _idleStatesNames = new();
string _idleStateName;
string _runStateName;
[RequireComponent(typeof(Weaver))]
public class AnimationManager : MonoBehaviour
{
List<string> _idleStatesNames = new();
string _idleStateName;
string _runStateName;
Animator _animator;
AnimatorOverrideController _animatorOverrideController;
List<KeyValuePair<AnimationClip, AnimationClip>> _clipOverrides;
Animator _animator;
AnimatorOverrideController _animatorOverrideController;
List<KeyValuePair<AnimationClip, AnimationClip>> _clipOverrides;
[SerializeField] AnimationClipSetBank _animationBank;
Dictionary<string, string> _moveToStateMap = new();
Dictionary<string, float> _animationLengths = new();
[SerializeField] AnimationClipSetBank _animationBank;
Dictionary<string, string> _moveToStateMap = new();
Dictionary<string, float> _animationLengths = new();
void SetWatchedWeaver(Weaver weaver) {
if (_watchedWeaver != null) {
_watchedWeaver.WeaponEquipped -= OnWeaponEquipped;
_watchedWeaver.ActionTaken -= OnActionTaken;
}
void SetWatchedWeaver(Weaver weaver) {
if (_watchedWeaver != null) {
_watchedWeaver.WeaponEquipped -= OnWeaponEquipped;
_watchedWeaver.ActionTaken -= OnActionTaken;
}
if (_watchedWeaver != null) {
_watchedWeaver.WeaponEquipped += OnWeaponEquipped;
_watchedWeaver.ActionTaken += OnActionTaken;
if (_watchedWeaver != null) {
_watchedWeaver.WeaponEquipped += OnWeaponEquipped;
_watchedWeaver.ActionTaken += OnActionTaken;
}
}
protected void Awake() {
_animator = GetComponentInChildren<Animator>();
_currentActionState = default(IdleState);
_nextActionState = default(IdleState);
protected void Awake() {
_animator = GetComponentInChildren<Animator>();
_currentActionState = default(IdleState);
_nextActionState = default(IdleState);
SetWatchedWeaver(GetComponent<Weaver>());
}
protected void OnDestroy() {
SetWatchedWeaver(null);
}
SetWatchedWeaver(GetComponent<Weaver>());
}
protected void OnDestroy() {
SetWatchedWeaver(null);
}
void OnActionTaken(object sender, Weaver.TakeActionEventArgs e) {
SetActionState(e.ActionState);
}
void OnActionTaken(object sender, Weaver.TakeActionEventArgs e) {
SetActionState(e.ActionState);
}
void OnWeaponEquipped(object sender, Weaver.WeaponEquippedEventArgs e) {
ChangeClipSet(e.Weapon.Name);
}
void OnWeaponEquipped(object sender, Weaver.WeaponEquippedEventArgs e) {
ChangeClipSet(e.CurrentWeapon.Name);
}
void ChangeClipSet(string weaponName) {
var weaponIdx = _animationBank.AnimationClipSets.FindIndex(set => set.Weapon.Value.Name == weaponName);
void ChangeClipSet(string weaponName) {
var weaponIdx = _animationBank.AnimationClipSets.FindIndex(set => set.Weapon.Value.Name == weaponName);
if (weaponIdx != -1) {
PopulateAnimations(_animationBank.AnimationClipSets[weaponIdx].ClipSet);
ResetNextState();
_idleStateName = GetNewIdleState();
_animator.Play(_idleStateName, _layer, 0f);
if (weaponIdx != -1) {
PopulateAnimations(_animationBank.AnimationClipSets[weaponIdx].ClipSet);
ResetNextState();
_idleStateName = GetNewIdleState();
_animator.Play(_idleStateName, _layer, 0f);
}
void PopulateAnimations(AnimationClipSet animationClipSet) {
_animationLengths.Clear();
_moveToStateMap.Clear();
_idleStatesNames.Clear();
void PopulateAnimations(AnimationClipSet animationClipSet) {
_animationLengths.Clear();
_moveToStateMap.Clear();
_idleStatesNames.Clear();
_animatorOverrideController = new AnimatorOverrideController(_animator.runtimeAnimatorController);
_animator.runtimeAnimatorController = _animatorOverrideController;
_clipOverrides = new List<KeyValuePair<AnimationClip, AnimationClip>>(_animatorOverrideController.overridesCount);
_animatorOverrideController.GetOverrides(_clipOverrides);
_animatorOverrideController = new AnimatorOverrideController(_animator.runtimeAnimatorController);
_animator.runtimeAnimatorController = _animatorOverrideController;
_clipOverrides = new List<KeyValuePair<AnimationClip, AnimationClip>>(_animatorOverrideController.overridesCount);
_animatorOverrideController.GetOverrides(_clipOverrides);
for (var i = 0; i < _clipOverrides.Count; ++i) {
var clipOverride = _clipOverrides[i];
var overrideClip = clipOverride.Value;
// Assuming State name and Clip Key Name are the same
var stateName = clipOverride.Key.name;
if (stateName.Contains("Idle")) {
if (_idleStatesNames.Count < animationClipSet.Idle.Count) {
_idleStatesNames.Add(stateName);
overrideClip = animationClipSet.Idle[_idleStatesNames.Count - 1];
for (var i = 0; i < _clipOverrides.Count; ++i) {
var clipOverride = _clipOverrides[i];
var overrideClip = clipOverride.Value;
// Assuming State name and Clip Key Name are the same
var stateName = clipOverride.Key.name;
if (stateName.Contains("Idle")) {
if (_idleStatesNames.Count < animationClipSet.Idle.Count) {
_idleStatesNames.Add(stateName);
overrideClip = animationClipSet.Idle[_idleStatesNames.Count - 1];
}
}
else if (stateName.Contains("Run")) {
_runStateName = stateName;
overrideClip = animationClipSet.Run;
}
else if (stateName.Contains("Attack")) {
var attackCount = _moveToStateMap.Count;
if (attackCount < animationClipSet.Attacks.Count) {
var moveName = animationClipSet.Attacks[attackCount].CombatMove.Value.MoveName;
overrideClip = animationClipSet.Attacks[attackCount].AttackAnimation;
_moveToStateMap[moveName] = stateName;
_animationLengths[moveName] = overrideClip.length;
else if (stateName.Contains("Run")) {
_runStateName = stateName;
overrideClip = animationClipSet.Run;
}
else if (stateName.Contains("Attack")) {
var attackCount = _moveToStateMap.Count;
if (attackCount < animationClipSet.Attacks.Count) {
var moveName = animationClipSet.Attacks[attackCount].CombatMove.Value.MoveName;
overrideClip = animationClipSet.Attacks[attackCount].AttackAnimation;
_moveToStateMap[moveName] = stateName;
_animationLengths[moveName] = overrideClip.length;
}
_animatorOverrideController.ApplyOverrides(_clipOverrides);
}
void SetActionState(IActionState nextActionState) {
_nextActionState = nextActionState.IsAdvanced ? nextActionState : default(IdleState);
}
void SetActionState(IActionState nextActionState) {
_nextActionState = nextActionState.IsAdvanced ? nextActionState : default(IdleState);
}
void ResetNextState() {
_nextActionState = default(IdleState);
}
void ResetNextState() {
_nextActionState = default(IdleState);
}
void HandleIdleState() {
switch (_nextActionState) {
case IdleState:
if (_animator.GetCurrentAnimatorStateInfo(0).normalizedTime >= 0.99) {
var newIdle = GetNewIdleState();
if (_idleStateName != newIdle) {
_idleStateName = newIdle;
_animator.Play(_idleStateName, _layer, 0f);
void HandleIdleState() {
switch (_nextActionState) {
case IdleState:
if (_animator.GetCurrentAnimatorStateInfo(0).normalizedTime >= 0.99) {
var newIdle = GetNewIdleState();
if (_idleStateName != newIdle) {
_idleStateName = newIdle;
_animator.Play(_idleStateName, _layer, 0f);
}
}
break;
case MoveToAction.State:
_animator.Play(_runStateName, _layer, 0f);
break;
case WeaveAction.State weave:
StartWeave(weave);
break;
break;
case MoveToAction.State:
_animator.Play(_runStateName, _layer, 0f);
break;
case WeaveAction.State weave:
StartWeave(weave);
break;
}
}
void HandleMoveToState() {
switch (_nextActionState) {
case IdleState:
_animator.Update(-Mathf.Floor(_animator.GetCurrentAnimatorStateInfo(_layer).normalizedTime));
_animator.CrossFade(_idleStateName, 0.25f, _layer);
break;
case MoveToAction.State:
break;
case WeaveAction.State weave:
StartWeave(weave);
break;
void HandleMoveToState() {
switch (_nextActionState) {
case IdleState:
_animator.Update(-Mathf.Floor(_animator.GetCurrentAnimatorStateInfo(_layer).normalizedTime));
_animator.CrossFade(_idleStateName, 0.25f, _layer);
break;
case MoveToAction.State:
break;
case WeaveAction.State weave:
StartWeave(weave);
break;
void HandleWeaveState(WeaveAction.State currentWeave) {
switch (_nextActionState) {
case IdleState:
_animator.Play(_idleStateName, _layer, 0f);
break;
case MoveToAction.State:
_animator.Update(-Mathf.Floor(_animator.GetCurrentAnimatorStateInfo(_layer).normalizedTime));
_animator.CrossFade(_runStateName, 0.25f, _layer);
break;
case WeaveAction.State weave:
if (weave.CompletionStatus < 1) {
TransitionWeave(currentWeave, weave);
}
break;
void HandleWeaveState(WeaveAction.State currentWeave) {
switch (_nextActionState) {
case IdleState:
_animator.Play(_idleStateName, _layer, 0f);
break;
case MoveToAction.State:
_animator.Update(-Mathf.Floor(_animator.GetCurrentAnimatorStateInfo(_layer).normalizedTime));
_animator.CrossFade(_runStateName, 0.25f, _layer);
break;
case WeaveAction.State weave:
if (weave.CompletionStatus < 1) {
TransitionWeave(currentWeave, weave);
}
break;
}
void ApplyActionState() {
switch (_currentActionState) {
case IdleState:
HandleIdleState();
break;
case MoveToAction.State:
HandleMoveToState();
break;
case WeaveAction.State currentWeave:
HandleWeaveState(currentWeave);
break;
void ApplyActionState() {
switch (_currentActionState) {
case IdleState:
HandleIdleState();
break;
case MoveToAction.State:
HandleMoveToState();
break;
case WeaveAction.State currentWeave:
HandleWeaveState(currentWeave);
break;
}
_currentActionState = _nextActionState;
void StartWeave(WeaveAction.State nextWeave) {
var moveName = nextWeave.Move.MoveName;
var moveStateName = _moveToStateMap[moveName];
_animator.Update(-Mathf.Floor(_animator.GetCurrentAnimatorStateInfo(_layer).normalizedTime));
if (_animator.GetCurrentAnimatorStateInfo(_layer).normalizedTime > 0.9f) {
_animator.Play(moveStateName);
void StartWeave(WeaveAction.State nextWeave) {
var moveName = nextWeave.Move.MoveName;
var moveStateName = _moveToStateMap[moveName];
_animator.Update(-Mathf.Floor(_animator.GetCurrentAnimatorStateInfo(_layer).normalizedTime));
if (_animator.GetCurrentAnimatorStateInfo(_layer).normalizedTime > 0.9f) {
_animator.Play(moveStateName);
}
else {
_animator.CrossFade(moveStateName, 0.1f, _layer);
}
var animationLength = _animationLengths[moveName];
if (nextWeave.Move.Speed > 0) {
var desiredSpeed = animationLength / nextWeave.Move.Speed;
_animator.SetFloat($"Speed", desiredSpeed);
}
var animationLength = _animationLengths[moveName];
if (nextWeave.Move.Speed > 0) {
var desiredSpeed = animationLength / nextWeave.Move.Speed;
_animator.SetFloat($"Speed", desiredSpeed);
}
}
void TransitionWeave(WeaveAction.State currentWeave, WeaveAction.State nextWeave) {
if (currentWeave.Move != nextWeave.Move) {
StartWeave(nextWeave);
string GetNewIdleState() {
var idleAnimationIndex = Random.Range(0, _idleStatesNames.Count);
return _idleStatesNames[idleAnimationIndex];
string GetNewIdleState() {
var idleAnimationIndex = Random.Range(0, _idleStatesNames.Count);
return _idleStatesNames[idleAnimationIndex];
}
internal readonly struct IdleState : IActionState
{
public bool IsAdvanced { get; }
public float CompletionStatus { get; }
public bool IsMoving { get; }
internal readonly struct IdleState : IActionState
{
public bool IsAdvanced { get; }
public float CompletionStatus { get; }
public bool IsMoving { get; }
public IdleState(bool isAdvanced, float completionStatus) {
IsAdvanced = isAdvanced;
CompletionStatus = completionStatus;
IsMoving = false;
public IdleState(bool isAdvanced, float completionStatus) {
IsAdvanced = isAdvanced;
CompletionStatus = completionStatus;
IsMoving = false;
}
[FormerlySerializedAs("animationClipSets")]
public List<AnimationClipSetContainer> AnimationClipSets;
}
[CreateAssetMenu(fileName = "AnimationClipSetBank", menuName = "RPG/Animation/AnimationClipSetBank")]
public class AnimationClipSetBank : ScriptableObject
{
[FormerlySerializedAs("animationClipSets")]
public List<AnimationClipSetContainer> AnimationClipSets;
}
FollowAction _followAction;
Transform _target;
Weaver _weaver;
RuneWeavingContainer _runeWeaving;
float _range;
bool _startedWeaving = false;
static State s_resetState = new(true, 1f, false, default);
public class WeaveAction : IAction
{
FollowAction _followAction;
Transform _target;
Weaver _weaver;
RuneWeavingContainer _runeWeaving;
Resources.Range _range;
bool _startedWeaving = false;
static State s_resetState = new(true, 1f, false, default);
bool _disposed = false;
int _lastRange;
public WeaveAction(Weaver unit, RuneWeavingContainer runeWeaving, Transform target, Resources.Range range) {
if (range is null) {
throw new ArgumentNullException("range");
}
_target = target;
_range = range;
_weaver = unit;
_runeWeaving = runeWeaving;
var currentRange = _range.GetCurrent();
_lastRange = currentRange.AsPrimitive();
_followAction = new(_weaver, _target, currentRange.ToMeter());
_range.ResourceChanged += OnResourceChanged;
if (IsInAttackRange()) {
if (_startedWeaving == false) {
Debug.Log("Target got in range, weaving");
void OnResourceChanged(object sender, ResourceChangeArgs e) {
if (_lastRange != e.Current) {
_followAction.Dispose();
_followAction = new(_weaver, _target, _range.GetCurrent().ToMeter());
_lastRange = e.Current;
else {
if (_startedWeaving) {
Debug.Log("Target escaped");
stateToReturn = new State(false, CompletionStatus(), stateToReturn.IsMoving, _runeWeaving.RuneWeaving.GetCurrentMove());
public IActionState Advance() {
var stateToReturn = _followAction.Advance();
if (IsInAttackRange()) {
if (_startedWeaving == false) {
Debug.Log("Target got in range, weaving");
}
_startedWeaving = true;
var isAdvanced = _runeWeaving.RuneWeaving.Advance(Time.deltaTime);
stateToReturn = new State(isAdvanced, CompletionStatus(), false, _runeWeaving.RuneWeaving.GetCurrentMove());
}
else {
if (_startedWeaving) {
Debug.Log("Target escaped");
stateToReturn = new State(false, CompletionStatus(), stateToReturn.IsMoving, _runeWeaving.RuneWeaving.GetCurrentMove());
}
public override string ToString() {
return $"{_runeWeaving.WeaveName} -> {_target.name}";
}
bool IsInAttackRange() {
// Incorrect in case there are hills. should calc range from feet.
Vector3 source = new(_weaver.transform.position.x, 0, _weaver.transform.position.z);
Vector3 target = new(_target.position.x, 0, _target.position.z);
return Vector3.Distance(source, target) <= _range;
}
public readonly struct State : IActionState
{
public bool IsAdvanced { get; }
public float CompletionStatus { get; }
public bool IsMoving { get; }
public override string ToString() {
return $"{_runeWeaving.WeaveName} -> {_target.name}";
}
bool IsInAttackRange() {
// Incorrect in case there are hills. should calc range from feet.
Vector3 source = new(_weaver.transform.position.x, 0, _weaver.transform.position.z);
Vector3 target = new(_target.position.x, 0, _target.position.z);
return Vector3.Distance(source, target) <= _range.GetCurrent().ToMeter();
}
public CombatMove Move { get; }
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing) {
if (!_disposed) {
if (disposing) {
Cancel();
_followAction.Dispose();
_followAction = null;
_range.ResourceChanged -= OnResourceChanged;
_range = null;
_runeWeaving = null;
_target = null;
_weaver = null;
}
_disposed = true;
}
}
public State(bool isAdvanced, float completionStatus, bool isMoving, CombatMove move) {
IsAdvanced = isAdvanced;
CompletionStatus = completionStatus;
IsMoving = isMoving;
Move = move;
public readonly struct State : IActionState
{
public bool IsAdvanced { get; }
public float CompletionStatus { get; }
public bool IsMoving { get; }
public CombatMove Move { get; }
public State(bool isAdvanced, float completionStatus, bool isMoving, CombatMove move) {
IsAdvanced = isAdvanced;
CompletionStatus = completionStatus;
IsMoving = isMoving;
Move = move;
}
Vector3 _lastTargetPosition;
NavMeshAgent _agent;
float _originalStoppingDistance;
float _desiredStoppingDistance;
bool _isFirstAdvance = true;
static State s_resetState = new(false, 0f, false);
public class MoveToAction : IAction
{
Vector3 _lastTargetPosition;
NavMeshAgent _agent;
float _originalStoppingDistance;
float _desiredStoppingDistance;
bool _isFirstAdvance = true;
static State s_resetState = new(false, 0f, false);
bool _disposed = false;
_lastTargetPosition = target;
_desiredStoppingDistance = _agent.stoppingDistance;
}
public MoveToAction(Weaver unit, Vector3 target, float stoppingDistance) {
if (unit == null) {
throw new ArgumentNullException("unit");
_lastTargetPosition = target;
_desiredStoppingDistance = _agent.stoppingDistance;
if (unit.TryGetComponent(out _agent) == false) {
throw new ArgumentException("Missing NavMeshAgent", "unit");
if (unit.TryGetComponent(out _agent) == false) {
throw new ArgumentException("Missing NavMeshAgent", "unit");
}
_lastTargetPosition = target;
_desiredStoppingDistance = stoppingDistance;
}
public bool SetDestination(Vector3 target) {
_lastTargetPosition = target;
return _agent.SetDestination(target);
_lastTargetPosition = target;
_desiredStoppingDistance = stoppingDistance;
}
public bool SetDestination(Vector3 target) {
_lastTargetPosition = target;
return _agent.SetDestination(target);
}
public IActionState Advance() {
if (_isFirstAdvance) {
_originalStoppingDistance = _agent.stoppingDistance;
public void SetStoppingDistance(float stoppingDistance) {
if (stoppingDistance < 0) {
throw new ArgumentException("Cannot be < 0", "stoppingDistance");
}
_desiredStoppingDistance = stoppingDistance;
var isAdvanced = _agent.pathPending || _agent.remainingDistance > _agent.stoppingDistance;
return new State(isAdvanced, CompletionStatus(), isAdvanced);
}
public IActionState Advance() {
if (_isFirstAdvance) {
_originalStoppingDistance = _agent.stoppingDistance;
_agent.stoppingDistance = _desiredStoppingDistance;
_agent.isStopped = false;
_agent.SetDestination(_lastTargetPosition);
_isFirstAdvance = false;
}
public IActionState Cancel() {
_agent.isStopped = true;
_agent.stoppingDistance = _originalStoppingDistance;
_agent.ResetPath();
_isFirstAdvance = true;
var isAdvanced = _agent.pathPending || _agent.remainingDistance > _agent.stoppingDistance;
return new State(isAdvanced, CompletionStatus(), isAdvanced);
}
return s_resetState;
}
IActionState Cancel() {
_agent.isStopped = true;
_agent.stoppingDistance = _originalStoppingDistance;
_agent.ResetPath();
_isFirstAdvance = true;
public readonly struct State : IActionState
{
public bool IsAdvanced { get; }
public float CompletionStatus { get; }
public bool IsMoving { get; }
public float CompletionStatus() {
return 0;
}
public override string ToString() {
return $"Move -> {_lastTargetPosition}";
}
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing) {
if (!_disposed) {
if (disposing) {
Cancel();
_agent = null;
}
_disposed = true;
}
}
public readonly struct State : IActionState
{
public bool IsAdvanced { get; }
public float CompletionStatus { get; }
public bool IsMoving { get; }
public State(bool isAdvanced, float completionStatus, bool isMoving) {
IsAdvanced = isAdvanced;
CompletionStatus = completionStatus;
IsMoving = isMoving;
public State(bool isAdvanced, float completionStatus, bool isMoving) {
IsAdvanced = isAdvanced;
CompletionStatus = completionStatus;
IsMoving = isMoving;
}
public interface IAction
{
public IActionState Advance();
public IActionState Cancel();
public float CompletionStatus();
}
using System;
public bool IsAdvanced { get; }
public float CompletionStatus { get; }
public bool IsMoving { get; }
public interface IAction : IDisposable
{
public IActionState Advance();
public float CompletionStatus();
}
public interface IActionState
{
public bool IsAdvanced { get; }
public float CompletionStatus { get; }
public bool IsMoving { get; }
}
MoveToAction _moveAction;
Transform _target;
Vector3 _lastTargetPosition;
public class FollowAction : IAction
{
MoveToAction _moveAction;
Transform _target;
Vector3 _lastTargetPosition;
bool _disposed = false;
public FollowAction(Weaver unit, Transform target, float stoppingDistance) {
_target = target ?? throw new ArgumentNullException("targetToFollow");
_lastTargetPosition = target.position;
_moveAction = new(unit, _lastTargetPosition, stoppingDistance);
}
public IActionState Advance() {
if (_lastTargetPosition != _target.position) {
_lastTargetPosition = _target.position;
_moveAction.SetDestination(_lastTargetPosition);
public FollowAction(Weaver unit, Transform target) {
_target = target ?? throw new ArgumentNullException("targetToFollow");
_lastTargetPosition = target.position;
_moveAction = new(unit, _lastTargetPosition);
return _moveAction.Advance();
}
public FollowAction(Weaver unit, Transform target, float stoppingDistance) {
_target = target ?? throw new ArgumentNullException("targetToFollow");
_lastTargetPosition = target.position;
_moveAction = new(unit, _lastTargetPosition, stoppingDistance);
}
public IActionState Cancel() {
return _moveAction.Cancel();
}
public void SetStoppingDistance(float stoppingDistance) {
_moveAction.SetStoppingDistance(stoppingDistance);
}
public IActionState Advance() {
if (_lastTargetPosition != _target.position) {
_lastTargetPosition = _target.position;
_moveAction.SetDestination(_lastTargetPosition);
}
public float CompletionStatus() {
return 0;
}
public override string ToString() {
return $"Follow {_target.name}";
return _moveAction.Advance();
}
public float CompletionStatus() {
return 0;
}
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing) {
if (!_disposed) {
if (disposing) {
_moveAction.Dispose();
_moveAction = null;
_target = null;
}
_disposed = true;
}
}
public override string ToString() {
return $"Follow {_target.name}";
}
[SerializeField] Transform _selectionUI;
// [SerializeField] float scale = 1.25f;
Transform _selected;
[SerializeField] EventAggregator _eventAggregator;
public class TargetIndicator : MonoBehaviour
{
[SerializeField] Transform _selectionUI;
// [SerializeField] float scale = 1.25f;
Transform _selected;
[SerializeField] EventAggregator _eventAggregator;
protected void Awake() {
_selectionUI.gameObject.SetActive(false);
}
protected void OnDestroy() {
_eventAggregator.TargetSelected -= OnTargetSelected;
}
protected void Update() {
SetUnitVisual(_selected);
}
protected void Start() {
_eventAggregator.TargetSelected += OnTargetSelected;
}
protected void Awake() {
_selectionUI.gameObject.SetActive(false);
}
protected void OnDestroy() {
_eventAggregator.TargetSelected -= OnTargetSelected;
}
protected void Update() {
SetUnitVisual(_selected);
}
protected void Start() {
_eventAggregator.TargetSelected += OnTargetSelected;
}
void OnTargetSelected(object sender, UnitActionEventArgs e) {
SetSelectedTransform(e.UnitTransform);
}
void OnTargetSelected(object sender, UnitActionEventArgs e) {
SetSelectedTransform(e.UnitTransform);
}
void SetSelectedTransform(Transform selected) {
_selected = selected;
_selectionUI.gameObject.SetActive(true);
SetUnitVisual(_selected);
}
void SetSelectedTransform(Transform selected) {
_selected = selected;
_selectionUI.gameObject.SetActive(true);
SetUnitVisual(_selected);
}
void SetUnitVisual(Transform selected) {
if (selected) {
var bounds = selected.GetComponent<Renderer>().bounds;
transform.position = new Vector3(bounds.center.x, 0, bounds.center.z);
//this.transform.localScale = new Vector3(bounds.size.x, bounds.size.y, bounds.size.z) * scale;
void SetUnitVisual(Transform selected) {
if (selected) {
var bounds = selected.GetComponent<Renderer>().bounds;
transform.position = new Vector3(bounds.center.x, 0, bounds.center.z);
//this.transform.localScale = new Vector3(bounds.size.x, bounds.size.y, bounds.size.z) * scale;
}
[SerializeField] Transform _selectionUI;
[SerializeField] EventAggregator _eventAggregator;
public class SelectionIndicator : MonoBehaviour
{
[SerializeField] Transform _selectionUI;
[SerializeField] EventAggregator _eventAggregator;
// [SerializeField] float scale = 1.25f;
Transform _selected;
protected void Awake() {
_selectionUI.gameObject.SetActive(false);
}
// [SerializeField] float scale = 1.25f;
Transform _selected;
protected void Awake() {
_selectionUI.gameObject.SetActive(false);
}
protected void OnDestroy() {
_eventAggregator.UnitSelected -= OnUnitSelected;
_eventAggregator.PartyMemberSelected -= OnPartyMemberSelected;
}
protected void Update() {
SetUnitVisual(_selected);
}
protected void Start() {
_eventAggregator.UnitSelected += OnUnitSelected;
_eventAggregator.PartyMemberSelected += OnPartyMemberSelected;
}
protected void OnDestroy() {
_eventAggregator.UnitSelected -= OnUnitSelected;
_eventAggregator.PartyMemberSelected -= OnPartyMemberSelected;
}
protected void Update() {
SetUnitVisual(_selected);
}
protected void Start() {
_eventAggregator.UnitSelected += OnUnitSelected;
_eventAggregator.PartyMemberSelected += OnPartyMemberSelected;
}
void OnPartyMemberSelected(object sender, EventAggregator.PartyMemberSelectedEventArgs e) {
SetSelectedTransform(e.PartyMember.transform);
}
void OnPartyMemberSelected(object sender, EventAggregator.PartyMemberSelectedEventArgs e) {
SetSelectedTransform(e.PartyMember.transform);
}
void OnUnitSelected(object sender, UnitActionEventArgs e) {
SetSelectedTransform(e.UnitTransform);
}
void OnUnitSelected(object sender, UnitActionEventArgs e) {
SetSelectedTransform(e.UnitTransform);
}
void SetSelectedTransform(Transform selected) {
_selected = selected;
_selectionUI.gameObject.SetActive(true);
SetUnitVisual(_selected);
}
void SetSelectedTransform(Transform selected) {
_selected = selected;
_selectionUI.gameObject.SetActive(true);
SetUnitVisual(_selected);
}
void SetUnitVisual(Transform selected) {
if (selected) {
var bounds = selected.GetComponent<Renderer>().bounds;
transform.position = new Vector3(bounds.center.x, 0, bounds.center.z);
//this.transform.localScale = new Vector3(bounds.size.x, bounds.size.y, bounds.size.z) * scale;
void SetUnitVisual(Transform selected) {
if (selected) {
var bounds = selected.GetComponent<Renderer>().bounds;
transform.position = new Vector3(bounds.center.x, 0, bounds.center.z);
//this.transform.localScale = new Vector3(bounds.size.x, bounds.size.y, bounds.size.z) * scale;
}
public Transform UnitTransform { get; }
public UnitActionEventArgs(Transform unitTransform) {
UnitTransform = unitTransform;
public class UnitActionEventArgs : EventArgs
{
public Transform UnitTransform { get; }
public UnitActionEventArgs(Transform unitTransform) {
UnitTransform = unitTransform;
}
public class UnitMoveEventArgs : EventArgs
{
public Vector3 Point { get; }
public UnitMoveEventArgs(Vector3 point) {
Point = point;
public class UnitMoveEventArgs : EventArgs
{
public Vector3 Point { get; }
public UnitMoveEventArgs(Vector3 point) {
Point = point;
}
public class PlayerKeyActions : MonoBehaviour
{
[SerializeField] CameraController _cameraController;
[SerializeField] LayerMask _unitSelectionLayerMask;
[SerializeField] LayerMask _unitMovementLayerMask;
[SerializeField] EventAggregator _eventAggregator;
public class PlayerKeyActions : MonoBehaviour
{
[SerializeField] CameraController _cameraController;
[SerializeField] LayerMask _unitSelectionLayerMask;
[SerializeField] LayerMask _unitMovementLayerMask;
[SerializeField] EventAggregator _eventAggregator;
protected void Update() {
if (_anyGameWorldHidden == false) {
HandleTimeDilation();
HandleCameraMovement();
HandleCameraRotation();
HandleUnitActions();
protected void Update() {
if (_anyGameWorldHidden == false) {
HandleTimeDilation();
HandleCameraMovement();
HandleCameraRotation();
HandleUnitActions();
}
HandleAdditionalKeyboadClicks();
HandleMouseClick();
void HandleAdditionalKeyboadClicks() {
if (Input.GetKeyDown(KeyCode.R)) {
if (Input.GetKey(KeyCode.LeftControl)) {
_eventAggregator.OnWeaveBuilderScreenToggleSelected(this, EventArgs.Empty);
_anyGameWorldHidden = !_anyGameWorldHidden;
void HandleAdditionalKeyboadClicks() {
if (Input.GetKeyDown(KeyCode.R)) {
if (Input.GetKey(KeyCode.LeftControl)) {
_eventAggregator.OnWeaveBuilderScreenToggleSelected(this, EventArgs.Empty);
_anyGameWorldHidden = !_anyGameWorldHidden;
}
void HandleMouseClick() {
if (!EventSystem.current.IsPointerOverGameObject()) {
if (Input.GetKeyDown(KeyCode.Mouse0)) {
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
void HandleMouseClick() {
if (!EventSystem.current.IsPointerOverGameObject()) {
if (Input.GetKeyDown(KeyCode.Mouse0)) {
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out var hit)) {
var objectHit = hit.transform;
if (_unitSelectionLayerMask.IsLayerInMask(objectHit.gameObject.layer)) {
_eventAggregator.OnUnitSelected(this, new(objectHit));
if (Physics.Raycast(ray, out var hit)) {
var objectHit = hit.transform;
if (_unitSelectionLayerMask.IsLayerInMask(objectHit.gameObject.layer)) {
_eventAggregator.OnUnitSelected(this, new(objectHit));
}
}
else if (Input.GetKeyDown(KeyCode.Mouse1)) {
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
else if (Input.GetKeyDown(KeyCode.Mouse1)) {
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out var hit)) {
var objectHit = hit.transform;
if (_unitSelectionLayerMask.IsLayerInMask(objectHit.gameObject.layer)) {
_eventAggregator.OnTargetSelected(this, new(objectHit));
}
else if (_unitMovementLayerMask.IsLayerInMask(objectHit.gameObject.layer)) {
if (Input.GetKey(KeyCode.LeftControl)) {
_eventAggregator.OnUnitMove(this, new(hit.point));
if (Physics.Raycast(ray, out var hit)) {
var objectHit = hit.transform;
if (_unitSelectionLayerMask.IsLayerInMask(objectHit.gameObject.layer)) {
_eventAggregator.OnTargetSelected(this, new(objectHit));
else {
_eventAggregator.OnPlannedActionsClearSelected(this, EventArgs.Empty);
_eventAggregator.OnUnitMove(this, new(hit.point));
else if (_unitMovementLayerMask.IsLayerInMask(objectHit.gameObject.layer)) {
if (Input.GetKey(KeyCode.LeftControl)) {
_eventAggregator.OnUnitMove(this, new(hit.point));
}
else {
_eventAggregator.OnPlannedActionsClearSelected(this, EventArgs.Empty);
_eventAggregator.OnUnitMove(this, new(hit.point));
}
void HandleTimeDilation() {
if (Input.GetKeyDown(KeyCode.Period)) {
_eventAggregator.OnTimeDilationSpeedUp(this, EventArgs.Empty);
}
if (Input.GetKeyDown(KeyCode.Comma)) {
_eventAggregator.OnTimeDilationSpeedDown(this, EventArgs.Empty);
}
if (Input.GetKeyDown(KeyCode.Slash)) {
_eventAggregator.OnTimeDilationSpeedReset(this, EventArgs.Empty);
void HandleTimeDilation() {
if (Input.GetKeyDown(KeyCode.Period)) {
_eventAggregator.OnTimeDilationSpeedUp(this, EventArgs.Empty);
}
if (Input.GetKeyDown(KeyCode.Comma)) {
_eventAggregator.OnTimeDilationSpeedDown(this, EventArgs.Empty);
}
if (Input.GetKeyDown(KeyCode.Slash)) {
_eventAggregator.OnTimeDilationSpeedReset(this, EventArgs.Empty);
}
}
void HandleCameraMovement() {
if (Input.GetKey(KeyCode.W)) {
_cameraController.MoveForward();
}
if (Input.GetKey(KeyCode.A)) {
_cameraController.MoveLeft();
}
if (Input.GetKey(KeyCode.S)) {
_cameraController.MoveBack();
}
if (Input.GetKey(KeyCode.D)) {
_cameraController.MoveRight();
}
if (Input.GetKey(KeyCode.A)) {
_cameraController.MoveLeft();
void HandleCameraRotation() {
if (Input.GetKey(KeyCode.Q)) {
_cameraController.RotateLeft();
}
if (Input.GetKey(KeyCode.E)) {
_cameraController.RotateRight();
}
if (Input.GetKey(KeyCode.S)) {
_cameraController.MoveBack();
}
if (Input.GetKey(KeyCode.D)) {
_cameraController.MoveRight();
}
}
}
void HandleCameraRotation() {
if (Input.GetKey(KeyCode.Q)) {
_cameraController.RotateLeft();
}
if (Input.GetKey(KeyCode.E)) {
_cameraController.RotateRight();
public static class LayerMaskExtensions
{
public static bool IsLayerInMask(this LayerMask layerMask, int layer) {
return layerMask == (layerMask | (1 << layer));
}
public static class LayerMaskExtensions
{
public static bool IsLayerInMask(this LayerMask layerMask, int layer) {
return layerMask == (layerMask | (1 << layer));
}
fileFormatVersion: 2
guid: 3637ce6e45f295d47863202e7233aedf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System;
namespace TagFighter.Resources
{
[Serializable]
public sealed class Range : Resource<Centimeter> { }
public static class CentimeterExtensions
{
public static float ToMeter(this Unit<Centimeter> source) {
return source.AsPrimitive() * 0.01f;
}
}
}
public event EventHandler<UnitActionEventArgs> UnitSelected;
public event EventHandler<UnitMoveEventArgs> UnitMove;
public event EventHandler<TryRemovePlannedActionEventArgs> RemovePlannedActionSelected;
public event EventHandler<UnitActionEventArgs> TargetSelected;
[CreateAssetMenu(fileName = "NewEventAggregator", menuName = "Combat/EventAggregator")]
public class EventAggregator : ScriptableObject
{
public event EventHandler<PartyMemberSelectedEventArgs> PartyMemberSelected;
public event EventHandler<WeaponSelectedEventArgs> WeaponSelected;
public event EventHandler<CombatFormSelectedEventArgs> CombatFormSelected;
public event EventHandler<UnitActionEventArgs> UnitSelected;
public event EventHandler<UnitMoveEventArgs> UnitMove;
public event EventHandler<TryRemovePlannedActionEventArgs> RemovePlannedActionSelected;
public event EventHandler<UnitActionEventArgs> TargetSelected;
public event EventHandler TimeDilationSpeedUp;
public event EventHandler TimeDilationSpeedDown;
public event EventHandler TimeDilationSpeedReset;
public event EventHandler TimeDilationSpeedPause;
public event EventHandler<WeaponSelectedEventArgs> WeaponSelected;
public event EventHandler<CombatFormSelectedEventArgs> CombatFormSelected;
public event EventHandler WeaveBuilderScreenToggleSelected;
public event EventHandler TimeDilationSpeedUp;
public event EventHandler TimeDilationSpeedDown;
public event EventHandler TimeDilationSpeedReset;
public event EventHandler TimeDilationSpeedPause;
public void OnPartyMemberSelected(object sender, PartyMemberSelectedEventArgs e) {
PartyMemberSelected?.Invoke(sender, e);
}
public void OnUnitSelected(object sender, UnitActionEventArgs e) {
UnitSelected?.Invoke(sender, e);
}
public void OnUnitMove(object sender, UnitMoveEventArgs e) {
UnitMove?.Invoke(sender, e);
}
public void OnWeaponSelected(object sender, WeaponSelectedEventArgs e) {
WeaponSelected?.Invoke(sender, e);
}
public void InvokeOnCombatFormSelected(object sender, CombatFormSelectedEventArgs e) {
CombatFormSelected?.Invoke(sender, e);
}
public void OnRemovePlannedActionSelected(object sender, TryRemovePlannedActionEventArgs e) {
RemovePlannedActionSelected?.Invoke(sender, e);
}
public void OnTargetSelected(object sender, UnitActionEventArgs e) {
TargetSelected?.Invoke(sender, e);
}
public void OnTimeDilationSpeedUp(object sender, EventArgs e) {
TimeDilationSpeedUp?.Invoke(sender, e);
}
public void OnTimeDilationSpeedDown(object sender, EventArgs e) {
TimeDilationSpeedDown?.Invoke(sender, e);
}
public void OnTimeDilationSpeedReset(object sender, EventArgs e) {
TimeDilationSpeedReset?.Invoke(sender, e);
}
public void OnTimeDilationSpeedPause(object sender, EventArgs e) {
TimeDilationSpeedPause?.Invoke(sender, e);
}
public void OnWeaveBuilderScreenToggleSelected(object sender, EventArgs e) {
WeaveBuilderScreenToggleSelected?.Invoke(sender, e);
}
public void OnRuneWeavingBankChanged(object sender, RuneWeavingBankChangedEventArgs e) {
RuneWeavingBankChanged?.Invoke(sender, e);
}
public void OnRuneWeavingCastSelected(object sender, WeaveCastEventArgs e) {
RuneWeavingCastSelected?.Invoke(sender, e);
}
public void OnPlannedActionsClearSelected(object sender, EventArgs e) {
PlannedActionsClearSelected?.Invoke(sender, e);
}
public void OnPartyMemberSelected(object sender, PartyMemberSelectedEventArgs e) {
PartyMemberSelected?.Invoke(sender, e);
}
public void OnUnitSelected(object sender, UnitActionEventArgs e) {
UnitSelected?.Invoke(sender, e);
}
public void OnUnitMove(object sender, UnitMoveEventArgs e) {
UnitMove?.Invoke(sender, e);
}
public void OnWeaponSelected(object sender, WeaponSelectedEventArgs e) {
WeaponSelected?.Invoke(sender, e);
}
public void InvokeOnCombatFormSelected(object sender, CombatFormSelectedEventArgs e) {
CombatFormSelected?.Invoke(sender, e);
}
public void OnRemovePlannedActionSelected(object sender, TryRemovePlannedActionEventArgs e) {
RemovePlannedActionSelected?.Invoke(sender, e);
}
public void OnTargetSelected(object sender, UnitActionEventArgs e) {
TargetSelected?.Invoke(sender, e);
}
public void OnTimeDilationSpeedUp(object sender, EventArgs e) {
TimeDilationSpeedUp?.Invoke(sender, e);
}
public void OnTimeDilationSpeedDown(object sender, EventArgs e) {
TimeDilationSpeedDown?.Invoke(sender, e);
}
public void OnTimeDilationSpeedReset(object sender, EventArgs e) {
TimeDilationSpeedReset?.Invoke(sender, e);
}
public void OnTimeDilationSpeedPause(object sender, EventArgs e) {
TimeDilationSpeedPause?.Invoke(sender, e);
}
public void OnWeaveBuilderScreenToggleSelected(object sender, EventArgs e) {
WeaveBuilderScreenToggleSelected?.Invoke(sender, e);
}
public void OnRuneWeavingBankChanged(object sender, RuneWeavingBankChangedEventArgs e) {
RuneWeavingBankChanged?.Invoke(sender, e);
}
#region events
public class TryRemovePlannedActionEventArgs : EventArgs
{
public int Index { get; }
public TryRemovePlannedActionEventArgs(int index) {
if (index < 0) {
throw new IndexOutOfRangeException("index");
public void OnRuneWeavingCastSelected(object sender, WeaveCastEventArgs e) {
RuneWeavingCastSelected?.Invoke(sender, e);
}
public void OnPlannedActionsClearSelected(object sender, EventArgs e) {
PlannedActionsClearSelected?.Invoke(sender, e);
}
#region events
public class TryRemovePlannedActionEventArgs : EventArgs
{
public int Index { get; }
public TryRemovePlannedActionEventArgs(int index) {
if (index < 0) {
throw new IndexOutOfRangeException("index");
}
Index = index;
}
public class WeaveCastEventArgs : EventArgs
{
public RuneWeavingContainer Weave { get; }
public WeaveCastEventArgs(RuneWeavingContainer weave) {
Weave = weave;
public class WeaveCastEventArgs : EventArgs
{
public RuneWeavingContainer Weave { get; }
public WeaveCastEventArgs(RuneWeavingContainer weave) {
Weave = weave;
}
}
public class RuneWeavingBankChangedEventArgs : EventArgs
{
public RuneWeavingBank Bank { get; }
public RuneWeavingBankChangedEventArgs(RuneWeavingBank bank) {
Bank = bank;
public class RuneWeavingBankChangedEventArgs : EventArgs
{
public RuneWeavingBank Bank { get; }
public RuneWeavingBankChangedEventArgs(RuneWeavingBank bank) {
Bank = bank;
}
}
public class PartyMemberSelectedEventArgs : EventArgs
{
public PartyMember PartyMember { get; }
public PartyMemberSelectedEventArgs(PartyMember partyMember) {
PartyMember = partyMember;
public class PartyMemberSelectedEventArgs : EventArgs
{
public PartyMember PartyMember { get; }
public PartyMemberSelectedEventArgs(PartyMember partyMember) {
PartyMember = partyMember;
}
}
public class WeaponSelectedEventArgs : EventArgs
{
public Weapon Weapon { get; }
public WeaponSelectedEventArgs(Weapon weapon) {
Weapon = weapon;
public class WeaponSelectedEventArgs : EventArgs
{
public Weapon Weapon { get; }
public WeaponSelectedEventArgs(Weapon weapon) {
Weapon = weapon;
}
}
public class CombatFormSelectedEventArgs : EventArgs
{
public CombatForm CombatForm { get; }
public CombatFormSelectedEventArgs(CombatForm combatForm) {
CombatForm = combatForm;
public class CombatFormSelectedEventArgs : EventArgs
{
public CombatForm CombatForm { get; }
public CombatFormSelectedEventArgs(CombatForm combatForm) {
CombatForm = combatForm;
}
[SerializeField] EventAggregator _eventAggregator;
Transform _targetUnit;
Transform TargetUnit {
get {
return _targetUnit;
}
set {
if (_targetUnit != null) {
TryUnregisterRuneWeavingCast();
public class UnitController : MonoBehaviour
{
[SerializeField] EventAggregator _eventAggregator;
Transform _targetUnit;
Transform TargetUnit {
get {
return _targetUnit;
}
Weaver _selectedWeaver;
Weaver SelectedWeaver {
get {
return _selectedWeaver;
}
set {
if (_selectedWeaver != null) {
_eventAggregator.PlannedActionsClearSelected -= OnPlannedActionsClearSelected;
_eventAggregator.RemovePlannedActionSelected -= OnRemovePlannedActionSelected;
_eventAggregator.CombatFormSelected -= OnCombatFormSelected;
_eventAggregator.UnitMove -= OnUnitMove;
_eventAggregator.WeaponSelected -= OnWeaponSelected;
TryUnregisterRuneWeavingCast();
Weaver _selectedWeaver;
Weaver SelectedWeaver {
get {
return _selectedWeaver;
_selectedWeaver = value;
set {
if (_selectedWeaver != null) {
_eventAggregator.PlannedActionsClearSelected -= OnPlannedActionsClearSelected;
_eventAggregator.RemovePlannedActionSelected -= OnRemovePlannedActionSelected;
_eventAggregator.CombatFormSelected -= OnCombatFormSelected;
_eventAggregator.UnitMove -= OnUnitMove;
_eventAggregator.WeaponSelected -= OnWeaponSelected;
TryUnregisterRuneWeavingCast();
}
_selectedWeaver = value;
if (_selectedWeaver != null) {
_eventAggregator.PlannedActionsClearSelected += OnPlannedActionsClearSelected;
_eventAggregator.RemovePlannedActionSelected += OnRemovePlannedActionSelected;
_eventAggregator.CombatFormSelected += OnCombatFormSelected;
_eventAggregator.UnitMove += OnUnitMove;
_eventAggregator.WeaponSelected += OnWeaponSelected;
TryRegisterRuneWeavingCast();
if (_selectedWeaver != null) {
_eventAggregator.PlannedActionsClearSelected += OnPlannedActionsClearSelected;
_eventAggregator.RemovePlannedActionSelected += OnRemovePlannedActionSelected;
_eventAggregator.CombatFormSelected += OnCombatFormSelected;
_eventAggregator.UnitMove += OnUnitMove;
_eventAggregator.WeaponSelected += OnWeaponSelected;
TryRegisterRuneWeavingCast();
}
protected void Start() {
_eventAggregator.UnitSelected += OnUnitSelected;
_eventAggregator.PartyMemberSelected += OnPartyMemberSelected;
protected void Start() {
_eventAggregator.UnitSelected += OnUnitSelected;
_eventAggregator.PartyMemberSelected += OnPartyMemberSelected;
protected void OnDestroy() {
_eventAggregator.UnitSelected -= OnUnitSelected;
_eventAggregator.PartyMemberSelected -= OnPartyMemberSelected;
protected void OnDestroy() {
_eventAggregator.UnitSelected -= OnUnitSelected;
_eventAggregator.PartyMemberSelected -= OnPartyMemberSelected;
bool TryUnregisterRuneWeavingCast() {
var unregistered = false;
if (SelectedWeaver && TargetUnit) {
_eventAggregator.RuneWeavingCastSelected -= OnRuneWeavingCastSelected;
unregistered = true;
bool TryUnregisterRuneWeavingCast() {
var unregistered = false;
if (SelectedWeaver && TargetUnit) {
_eventAggregator.RuneWeavingCastSelected -= OnRuneWeavingCastSelected;
unregistered = true;
}
return unregistered;
return unregistered;
}
bool TryRegisterRuneWeavingCast() {
var registered = false;
if (SelectedWeaver && TargetUnit) {
_eventAggregator.RuneWeavingCastSelected += OnRuneWeavingCastSelected;
registered = true;
bool TryRegisterRuneWeavingCast() {
var registered = false;
if (SelectedWeaver && TargetUnit) {
_eventAggregator.RuneWeavingCastSelected += OnRuneWeavingCastSelected;
registered = true;
}
return registered;
void OnPlannedActionsClearSelected(object sender, EventArgs e) {
SelectedWeaver.ClearActionPlan();
}
void OnPlannedActionsClearSelected(object sender, EventArgs e) {
SelectedWeaver.ClearActionPlan();
}
void OnRemovePlannedActionSelected(object sender, EventAggregator.TryRemovePlannedActionEventArgs e) {
SelectedWeaver.TryRemoveActionFromPlan(e.Index);
}
void OnRemovePlannedActionSelected(object sender, EventAggregator.TryRemovePlannedActionEventArgs e) {
SelectedWeaver.TryRemoveActionFromPlan(e.Index);
}
void OnRuneWeavingCastSelected(object sender, EventAggregator.WeaveCastEventArgs e) {
SelectedWeaver.TryQueueWeave(new(e.Weave, SelectedWeaver.transform, TargetUnit), TargetUnit);
}
void OnRuneWeavingCastSelected(object sender, EventAggregator.WeaveCastEventArgs e) {
SelectedWeaver.TryQueueWeave(new(e.Weave, SelectedWeaver.transform, TargetUnit), TargetUnit);
}
void OnCombatFormSelected(object sender, EventAggregator.CombatFormSelectedEventArgs e) {
SelectedWeaver.TryEquipCombatForm(e.CombatForm.Name);
}
void OnCombatFormSelected(object sender, EventAggregator.CombatFormSelectedEventArgs e) {
SelectedWeaver.TryEquipCombatForm(e.CombatForm.Name);
}
void OnWeaponSelected(object sender, EventAggregator.WeaponSelectedEventArgs e) {
SelectedWeaver.TryDrawWeapon(e.Weapon.Name);
}
void OnWeaponSelected(object sender, EventAggregator.WeaponSelectedEventArgs e) {
SelectedWeaver.TryDrawWeapon(e.Weapon.Name);
}
void OnUnitMove(object sender, UnitMoveEventArgs e) {
SelectedWeaver.TryQueueMove(e.Point);
}
void OnTargetSelected(object sender, UnitActionEventArgs e) {
TargetUnit = e.UnitTransform;
}
void OnPartyMemberSelected(object sender, EventAggregator.PartyMemberSelectedEventArgs e) {
if (e.PartyMember.TryGetComponent<Weaver>(out var weaver)) {
SelectedWeaver = weaver;
void OnUnitMove(object sender, UnitMoveEventArgs e) {
SelectedWeaver.TryQueueMove(e.Point);
}
void OnTargetSelected(object sender, UnitActionEventArgs e) {
TargetUnit = e.UnitTransform;
}
void OnPartyMemberSelected(object sender, EventAggregator.PartyMemberSelectedEventArgs e) {
if (e.PartyMember.TryGetComponent<Weaver>(out var weaver)) {
SelectedWeaver = weaver;
}
}
void OnUnitSelected(object sender, UnitActionEventArgs e) {
if (e.UnitTransform.TryGetComponent<Weaver>(out var weaver)) {
SelectedWeaver = weaver;
void OnUnitSelected(object sender, UnitActionEventArgs e) {
if (e.UnitTransform.TryGetComponent<Weaver>(out var weaver)) {
SelectedWeaver = weaver;
}
[SerializeField] float _dilationStep = 0.25f;
public const float MaxTimeDilation = 4f;
const float MinTimeDilation = 0f;
const int TimeDilationPercision = 2;
float _baseTimeScale;
[SerializeField] EventAggregator _eventAggregator;
public class TimeDilationController : MonoBehaviour
{
[SerializeField] float _dilationStep = 0.25f;
public const float MaxTimeDilation = 4f;
const float MinTimeDilation = 0f;
const int TimeDilationPercision = 2;
float _baseTimeScale;
[SerializeField] EventAggregator _eventAggregator;
protected void Start() {
_eventAggregator.TimeDilationSpeedUp += OnTimeDilationSpeedUp;
_eventAggregator.TimeDilationSpeedDown += OnTimeDilationSpeedDown;
_eventAggregator.TimeDilationSpeedReset += OnTimeDilationSpeedReset;
_eventAggregator.TimeDilationSpeedPause += OnTimeDilationSpeedPause;
_baseTimeScale = Time.timeScale;
}
protected void Start() {
_eventAggregator.TimeDilationSpeedUp += OnTimeDilationSpeedUp;
_eventAggregator.TimeDilationSpeedDown += OnTimeDilationSpeedDown;
_eventAggregator.TimeDilationSpeedReset += OnTimeDilationSpeedReset;
_eventAggregator.TimeDilationSpeedPause += OnTimeDilationSpeedPause;
_baseTimeScale = Time.timeScale;
}
protected void OnDestroy() {
_eventAggregator.TimeDilationSpeedUp -= OnTimeDilationSpeedUp;
_eventAggregator.TimeDilationSpeedDown -= OnTimeDilationSpeedDown;
_eventAggregator.TimeDilationSpeedReset -= OnTimeDilationSpeedReset;
_eventAggregator.TimeDilationSpeedPause -= OnTimeDilationSpeedPause;
}
protected void OnDestroy() {
_eventAggregator.TimeDilationSpeedUp -= OnTimeDilationSpeedUp;
_eventAggregator.TimeDilationSpeedDown -= OnTimeDilationSpeedDown;
_eventAggregator.TimeDilationSpeedReset -= OnTimeDilationSpeedReset;
_eventAggregator.TimeDilationSpeedPause -= OnTimeDilationSpeedPause;
}
void OnTimeDilationSpeedPause(object sender, EventArgs e) {
Time.timeScale = 0;
}
void OnTimeDilationSpeedReset(object sender, EventArgs e) {
Time.timeScale = _baseTimeScale;
}
void OnTimeDilationSpeedPause(object sender, EventArgs e) {
Time.timeScale = 0;
}
void OnTimeDilationSpeedReset(object sender, EventArgs e) {
Time.timeScale = _baseTimeScale;
}
void OnTimeDilationSpeedDown(object sender, EventArgs e) {
Time.timeScale = MathF.Max(MinTimeDilation, MathF.Round(Time.timeScale - _dilationStep, TimeDilationPercision));
}
void OnTimeDilationSpeedDown(object sender, EventArgs e) {
Time.timeScale = MathF.Max(MinTimeDilation, MathF.Round(Time.timeScale - _dilationStep, TimeDilationPercision));
}
void OnTimeDilationSpeedUp(object sender, EventArgs e) {
Time.timeScale = MathF.Min(MaxTimeDilation, MathF.Round(Time.timeScale + _dilationStep, TimeDilationPercision));
}
public void AddWeave(RuneWeaving runeWeaving, ValidWeaveName weaveName) {
_runeWeavings.Add(new RuneWeavingContainer(weaveName, runeWeaving));
_eventAggregator.OnRuneWeavingBankChanged(this, new EventAggregator.RuneWeavingBankChangedEventArgs(this));
}
[CreateAssetMenu(fileName = "RuneWeavingBank", menuName = "Combat/RuneWeavingBank")]
public class RuneWeavingBank : ScriptableObject
{
[SerializeField] EventAggregator _eventAggregator;
[SerializeField] List<RuneWeavingContainer> _runeWeavings = new();
public bool TryDeleteWeaveByName(ValidWeaveName weaveName) {
var found = false;
var weaveIndex = _runeWeavings.FindIndex(weave => weave.WeaveName == weaveName);
found = weaveIndex != -1;
if (found == true) {
_runeWeavings.RemoveAt(weaveIndex);
_eventAggregator.OnRuneWeavingBankChanged(this, new(this));
public void AddWeave(RuneWeaving runeWeaving, ValidWeaveName weaveName) {
_runeWeavings.Add(new RuneWeavingContainer(weaveName, runeWeaving));
_eventAggregator.OnRuneWeavingBankChanged(this, new EventAggregator.RuneWeavingBankChangedEventArgs(this));
public bool TryGetWeaveByName(ValidWeaveName weaveName, out RuneWeavingContainer runeWeavingContainer) {
var found = false;
var weaveIndex = _runeWeavings.FindIndex(weave => weave.WeaveName == weaveName);
found = weaveIndex != -1;
if (found == true) {
runeWeavingContainer = _runeWeavings[weaveIndex];
}
else {
runeWeavingContainer = null;
public bool TryDeleteWeaveByName(ValidWeaveName weaveName) {
var found = false;
var weaveIndex = _runeWeavings.FindIndex(weave => weave.WeaveName == weaveName);
found = weaveIndex != -1;
if (found == true) {
_runeWeavings.RemoveAt(weaveIndex);
_eventAggregator.OnRuneWeavingBankChanged(this, new(this));
}
return found;
public IEnumerable<RuneWeavingContainer> GetWeaves() => _runeWeavings;
}
public bool TryGetWeaveByName(ValidWeaveName weaveName, out RuneWeavingContainer runeWeavingContainer) {
var found = false;
var weaveIndex = _runeWeavings.FindIndex(weave => weave.WeaveName == weaveName);
found = weaveIndex != -1;
if (found == true) {
runeWeavingContainer = _runeWeavings[weaveIndex];
}
else {
runeWeavingContainer = null;
}
return found;
}
[Serializable]
public class RuneWeavingContainer
{
public RuneWeaving RuneWeaving;
public ValidWeaveName WeaveName;
public RuneWeavingContainer(ValidWeaveName weaveName, RuneWeaving runeWeaving) {
WeaveName = weaveName;
RuneWeaving = runeWeaving;
}
public RuneWeavingContainer(RuneWeavingContainer toCopy, Transform caster, Transform target) {
RuneWeaving = new RuneWeaving(toCopy.RuneWeaving.MartialSequence.GetSequence(), toCopy.RuneWeaving.RuneBindingSequence.GetSequence(), caster, target);
WeaveName = toCopy.WeaveName;
public IEnumerable<RuneWeavingContainer> GetWeaves() => _runeWeavings;
[Serializable]
public record ValidWeaveName
{
[SerializeField] string _weaveName;
ValidWeaveName(string weaveName) {
_weaveName = weaveName;
[Serializable]
public class RuneWeavingContainer
{
public RuneWeaving RuneWeaving;
public ValidWeaveName WeaveName;
public RuneWeavingContainer(ValidWeaveName weaveName, RuneWeaving runeWeaving) {
WeaveName = weaveName;
RuneWeaving = runeWeaving;
}
public RuneWeavingContainer(RuneWeavingContainer toCopy, Transform caster, Transform target) {
RuneWeaving = new RuneWeaving(toCopy.RuneWeaving.MartialSequence.GetSequence(), toCopy.RuneWeaving.RuneBindingSequence.GetSequence(), caster, target);
WeaveName = toCopy.WeaveName;
}
public bool TrySetName(string weaveName) {
var validName = IsWeaveNameValid(weaveName);
if (validName) {
[Serializable]
public record ValidWeaveName
{
[SerializeField] string _weaveName;
ValidWeaveName(string weaveName) {
public static bool TryParse(string weaveName, out ValidWeaveName validWeaveName) {
var validName = IsWeaveNameValid(weaveName);
if (validName) {
validWeaveName = new ValidWeaveName(weaveName);
public static bool TryParse(string weaveName, out ValidWeaveName validWeaveName) {
var validName = IsWeaveNameValid(weaveName);
if (validName) {
validWeaveName = new ValidWeaveName(weaveName);
}
else {
validWeaveName = null;
}
return validName;
public static bool IsWeaveNameValid(string weaveName) {
return weaveName.Length > 0;
}
public static implicit operator string(ValidWeaveName validWeaveName) => validWeaveName._weaveName;
ApplyTrigger.TriggerConditionMet -= ApplyTrigger_OnTriggerConditionMet;
ApplyTrigger.UnRegister();
EndTrigger.TriggerConditionMet -= EndTrigger_OnTriggerConditionMet;
EndTrigger.UnRegister();
if (ApplyTrigger != null) {
ApplyTrigger.Unregister();
ApplyTrigger.TriggerConditionMet -= ApplyTrigger_OnTriggerConditionMet;
}
if (EndTrigger != null) {
EndTrigger.Unregister();
EndTrigger.TriggerConditionMet -= EndTrigger_OnTriggerConditionMet;
}
}
}
[Serializable]
public class OnApply : ITrigger
{
public event EventHandler<ConditionTriggerArgs> TriggerConditionMet;
public void Register(PawnCondition condition) {
OnTriggerConditionMet(new());
}
public ITrigger ShallowCopy() {
return (ITrigger)MemberwiseClone();
}
public void Unregister() {
}
protected void OnTriggerConditionMet(ConditionTriggerArgs e) {
TriggerConditionMet?.Invoke(this, e);
}
[Serializable]
public class OnEquip : ITrigger
{
public WeaponRef WatchedWeapon;
public event EventHandler<ConditionTriggerArgs> TriggerConditionMet;
Weaver _watchedWeaver;
public void Register(PawnCondition condition) {
_watchedWeaver = condition.GetComponent<Weaver>();
if (_watchedWeaver != null) {
_watchedWeaver.WeaponEquipped += OnWeaponEquipped;
}
}
void OnWeaponEquipped(object sender, Weaver.WeaponEquippedEventArgs e) {
if (WatchedWeapon.Value == e.CurrentWeapon) {
OnTriggerConditionMet(new());
}
}
public ITrigger ShallowCopy() {
return (ITrigger)MemberwiseClone();
}
public void Unregister() {
if (_watchedWeaver != null) {
_watchedWeaver.WeaponEquipped -= OnWeaponEquipped;
_watchedWeaver = null;
WatchedWeapon = null;
}
}
protected void OnTriggerConditionMet(ConditionTriggerArgs e) {
TriggerConditionMet?.Invoke(this, e);
}
}
[Serializable]
public class OnUnequip : ITrigger
{
public WeaponRef WatchedWeapon;
public event EventHandler<ConditionTriggerArgs> TriggerConditionMet;
Weaver _watchedWeaver;
public void Register(PawnCondition condition) {
_watchedWeaver = condition.GetComponent<Weaver>();
if (_watchedWeaver != null) {
_watchedWeaver.WeaponEquipped += OnWeaponEquipped;
}
}
void OnWeaponEquipped(object sender, Weaver.WeaponEquippedEventArgs e) {
if (WatchedWeapon.Value == e.PreviousWeapon) {
OnTriggerConditionMet(new());
}
}
public ITrigger ShallowCopy() {
return (ITrigger)MemberwiseClone();
}
public void Unregister() {
if (_watchedWeaver != null) {
_watchedWeaver.WeaponEquipped -= OnWeaponEquipped;
_watchedWeaver = null;
WatchedWeapon = null;
}
}
protected void OnTriggerConditionMet(ConditionTriggerArgs e) {
TriggerConditionMet?.Invoke(this, e);
}
}
}
[SerializeField] Weapon _weapon;
public static implicit operator Weapon(WeaponRef weaponRef) => weaponRef.Value;
[CreateAssetMenu(fileName = "Weapon", menuName = "Combat/Weapon")]
[Serializable]
public class WeaponRef : ScriptableObject
{
[SerializeField] Weapon _weapon;
public static implicit operator Weapon(WeaponRef weaponRef) => weaponRef.Value;
public string Name;
[SerializeField] float _range;
[SerializeField] CombatMoveSetRef _weaponMoveSet;
[SerializeField] List<CombatFormRef> _compatibleCombatForms;
public interface IItem
{
public IEnumerable<EffectTypePair> MainHandEffects();
}
public IEnumerable<CombatFormRef> GetCompatibleFormRefs() {
return _compatibleCombatForms;
[Flags]
public enum ItemSlot
{
None = 0,
Head = 1 << 0,
Shoulder = 1 << 1,
Body = 1 << 2,
Arms = 1 << 3,
MainHand = 1 << 4,
OffHand = 1 << 5,
Leg = 1 << 6,
Foot = 1 << 7
public CombatMoveSetRef GetCombatMoveSetRef() => _weaponMoveSet;
public float GetRange() => _range;
[Serializable]
public class Weapon : IItem
{
public string Name;
[SerializeField] CombatMoveSetRef _weaponMoveSet;
[SerializeField] List<CombatFormRef> _compatibleCombatForms;
[SerializeField] List<ItemEffectSlot> _effects;
public IEnumerable<CombatFormRef> GetCompatibleFormRefs() {
return _compatibleCombatForms;
}
public CombatMoveSetRef GetCombatMoveSetRef() => _weaponMoveSet;
public IEnumerable<EffectTypePair> MainHandEffects() {
return GetEffects(ItemSlot.MainHand);
}
protected virtual IEnumerable<EffectTypePair> GetEffects(ItemSlot slots) {
return _effects.Where(effectSlot => effectSlot.Slot.HasFlag(slots)).Select(itemEffectSlot => itemEffectSlot.Effect);
}
}
_effects:
- Slot: 16
Effect:
Mode:
rid: 6090675012705714188
Effect:
rid: 6090675012705714189
- Slot: -1
Effect:
Mode:
rid: 6090675012705714193
Effect:
rid: 6090675012705714197
references:
version: 2
RefIds:
- rid: -2
type: {class: , ns: , asm: }
- rid: 6090675012705714188
type: {class: DelayedEffect, ns: TagFighter.Effects, asm: Assembly-CSharp}
- rid: 6090675012705714189
type: {class: UnaryResourceEffect, ns: TagFighter.Effects, asm: Assembly-CSharp}
data:
From:
Resource:
rid: -2
Location:
rid: -2
Multiplier: 1
Addend: 0
To:
Resource:
rid: 6090675012705714190
Location:
rid: 6090675012705714191
Multiplier: 1
Addend: 150
- rid: 6090675012705714190
type: {class: Range, ns: TagFighter.Effects.ResourceTypeAccessors, asm: Assembly-CSharp}
- rid: 6090675012705714191
type: {class: Pawn, ns: TagFighter.Effects.ResourceLocationAccessors.Set, asm: Assembly-CSharp}
data:
Property:
rid: 6090675012705714192
- rid: 6090675012705714192
type: {class: Current, ns: TagFighter.Effects.ResourceLocationAccessors.PawnProperties,
asm: Assembly-CSharp}
- rid: 6090675012705714193
type: {class: PeriodicWeave, ns: TagFighter.Effects, asm: Assembly-CSharp}
data:
AreaOfEffect:
rid: 6090675012705714194
ApplyTrigger:
rid: 6090675012705714195
EndTrigger:
rid: 6090675012705714196
IsPermanent: 0
- rid: 6090675012705714194
type: {class: Single, ns: TagFighter.Effects.AoeShapes, asm: Assembly-CSharp}
- rid: 6090675012705714195
type: {class: OnEquip, ns: TagFighter.Effects.Triggers, asm: Assembly-CSharp}
data:
WatchedWeapon: {fileID: 11400000}
- rid: 6090675012705714196
type: {class: OnUnequip, ns: TagFighter.Effects.Triggers, asm: Assembly-CSharp}
data:
WatchedWeapon: {fileID: 11400000}
- rid: 6090675012705714197
type: {class: AoeEffect, ns: TagFighter.Effects, asm: Assembly-CSharp}
data:
Shape:
rid: 6090675012705714198
- rid: 6090675012705714198
type: {class: Single, ns: TagFighter.Effects.AoeShapes, asm: Assembly-CSharp}
_effects:
- Slot: 16
Effect:
Mode:
rid: 6090675012705714176
Effect:
rid: 6090675012705714177
- Slot: -1
Effect:
Mode:
rid: 6090675012705714181
Effect:
rid: 6090675012705714184
references:
version: 2
RefIds:
- rid: -2
type: {class: , ns: , asm: }
- rid: 6090675012705714176
type: {class: DelayedEffect, ns: TagFighter.Effects, asm: Assembly-CSharp}
- rid: 6090675012705714177
type: {class: UnaryResourceEffect, ns: TagFighter.Effects, asm: Assembly-CSharp}
data:
From:
Resource:
rid: -2
Location:
rid: -2
Multiplier: 1
Addend: 0
To:
Resource:
rid: 6090675012705714178
Location:
rid: 6090675012705714179
Multiplier: 1
Addend: 200
- rid: 6090675012705714178
type: {class: Range, ns: TagFighter.Effects.ResourceTypeAccessors, asm: Assembly-CSharp}
- rid: 6090675012705714179
type: {class: Pawn, ns: TagFighter.Effects.ResourceLocationAccessors.Set, asm: Assembly-CSharp}
data:
Property:
rid: 6090675012705714180
- rid: 6090675012705714180
type: {class: Current, ns: TagFighter.Effects.ResourceLocationAccessors.PawnProperties,
asm: Assembly-CSharp}
- rid: 6090675012705714181
type: {class: PeriodicWeave, ns: TagFighter.Effects, asm: Assembly-CSharp}
data:
AreaOfEffect:
rid: 6090675012705714182
ApplyTrigger:
rid: 6090675012705714187
EndTrigger:
rid: 6090675012705714186
IsPermanent: 0
- rid: 6090675012705714182
type: {class: Single, ns: TagFighter.Effects.AoeShapes, asm: Assembly-CSharp}
- rid: 6090675012705714184
type: {class: AoeEffect, ns: TagFighter.Effects, asm: Assembly-CSharp}
data:
Shape:
rid: 6090675012705714185
- rid: 6090675012705714185
type: {class: Single, ns: TagFighter.Effects.AoeShapes, asm: Assembly-CSharp}
- rid: 6090675012705714186
type: {class: OnUnequip, ns: TagFighter.Effects.Triggers, asm: Assembly-CSharp}
data:
WatchedWeapon: {fileID: 11400000}
- rid: 6090675012705714187
type: {class: OnEquip, ns: TagFighter.Effects.Triggers, asm: Assembly-CSharp}
data:
WatchedWeapon: {fileID: 11400000}
--- !u!114 &1095075979
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1095075963}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3637ce6e45f295d47863202e7233aedf, type: 3}
m_Name:
m_EditorClassIdentifier:
_current:
_base:
_value: 50
_capacity:
_base:
_value: 1000
--- !u!114 &1460840159
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1460840143}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3637ce6e45f295d47863202e7233aedf, type: 3}
m_Name:
m_EditorClassIdentifier:
_current:
_base:
_value: 50
_capacity:
_base:
_value: 1000
- component: {fileID: 2775200704764093959}
- component: {fileID: 2775200704764093958}
- component: {fileID: 2775200704764093957}
- component: {fileID: 2775200704764094072}
- component: {fileID: 5381362345172573048}
--- !u!33 &2775200704764093959
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2775200704764093955}
m_Mesh: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &2775200704764093958
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2775200704764093955}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!136 &2775200704764093957
CapsuleCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2775200704764093955}
m_Material: {fileID: 0}
m_IsTrigger: 0
m_Enabled: 1
m_Radius: 0.5
m_Height: 2
m_Direction: 1
m_Center: {x: 0, y: 0, z: 0}
--- !u!195 &2775200704764094072
NavMeshAgent:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2775200704764093955}
m_Enabled: 1
m_AgentTypeID: 0
m_Radius: 0.5
m_Speed: 10
m_Acceleration: 1000
avoidancePriority: 50
m_AngularSpeed: 120
m_StoppingDistance: 0.1
m_AutoTraverseOffMeshLink: 1
m_AutoBraking: 1
m_AutoRepath: 1
m_Height: 2
m_BaseOffset: 1
m_WalkableMask: 4294967295
m_ObstacleAvoidanceType: 4
--- !u!33 &2775200704764093959
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2775200704764093955}
m_Mesh: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &2775200704764093958
MeshRenderer:
--- !u!114 &5381362345172573048
MonoBehaviour:
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!136 &2775200704764093957
CapsuleCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2775200704764093955}
m_Material: {fileID: 0}
m_IsTrigger: 0
m_Enabled: 1
m_Radius: 0.5
m_Height: 2
m_Direction: 1
m_Center: {x: 0, y: 0, z: 0}
--- !u!195 &2775200704764094072
NavMeshAgent:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2775200704764093955}
m_Enabled: 1
m_AgentTypeID: 0
m_Radius: 0.5
m_Speed: 10
m_Acceleration: 1000
avoidancePriority: 50
m_AngularSpeed: 120
m_StoppingDistance: 0.1
m_AutoTraverseOffMeshLink: 1
m_AutoBraking: 1
m_AutoRepath: 1
m_Height: 2
m_BaseOffset: 1
m_WalkableMask: 4294967295
m_ObstacleAvoidanceType: 4
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3637ce6e45f295d47863202e7233aedf, type: 3}
m_Name:
m_EditorClassIdentifier:
_current:
_base:
_value: 200
_capacity:
_base:
_value: 1000