public void SetDir(TileDir tileDir, bool reorientate) { if (tileDir == this.tileDir) { if (reorientate && shown) { actor.transform.rotation *= Quaternion.AngleAxis(tileDir.ToAngle(), Vector3.up); } return; } if (removed) { this.tileDir = tileDir; return; } var orig = this.tileDir; this.tileDir = tileDir; if (reorientate && shown) { actor.transform.rotation = Quaternion.Euler(actor.transform.eulerAngles.x, tileDir.ToAngle(), actor.transform.eulerAngles.z); } using (var scope = new Hooks.Scope()) { this.hooks.ForEach <IOnChangeDirection_Unit>(scope, v => v.OnChangeDirection(orig, tileDir)); tile.hooks.ForEach <IOnChangeDirection_Tile>(scope, v => v.OnChangeDirection(this, orig, tileDir)); Game.hooks.ForEach <IOnChangeDirection_Game>(scope, v => v.OnChangeDirection(this, orig, tileDir)); } }
/// <summary> Called when the ability is actually cast. </summary> public virtual void OnCast() { isCasting = true; if (uses.enabled) { uses.current.value--; } if (charges.current == charges.max) { cooldown.Max(); } if (cooldown.current <= 0 && cooldown.max <= 0) { charges.Max(); } else { charges.current.value--; } unit.energy.current.value -= energyCost.current; unit.RefreshEnergy(); using (var scope = new Hooks.Scope()) { unit.hooks.ForEach <IOnAbilityCastStart_Unit>(scope, v => v.OnAbilityCastStart(this)); unit.tile.hooks.ForEach <IOnAbilityCastStart_Tile>(scope, v => v.OnAbilityCastStart(this)); Game.hooks.ForEach <IOnAbilityCastStart_Game>(scope, v => v.OnAbilityCastStart(this)); } }
/// <summary> Creates a Modifier based on the given source and attaches it to the master. </summary> public static T Create <T>(TSelf master, T source, Action <T> initializer = null) where T : RootModifier { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (!source.isSource) { throw new ArgumentException($"{nameof(source)} must be a source", nameof(source)); } var modifier = Instantiate(source); modifier.master = master; modifier.source = source; master.AttachModifier(modifier); Game.dataObjects.Add(modifier); Game.hooks.Hook(modifier); initializer?.Invoke(modifier); modifier.OnConfigureNonpersistent(true); modifier.OnCreate(); modifier.Show(); using (var scope = new Hooks.Scope()) Game.hooks.ForEach <IOnModifierCreate>(scope, v => v.OnModifierCreate(modifier)); return(modifier); }
/// <summary> Is this Edge considered to be passable from Tile "from" to Tile "to". </summary> public bool CanPass(Tile from, Tile to) { if (from is null) { throw new ArgumentNullException(nameof(from)); } if (to is null) { throw new ArgumentNullException(nameof(to)); } if (to != hex1 && to != hex2) { throw new ArgumentException("To must be one of the Tiles connected to the Edge.", nameof(to)); } if (from != hex1 && from != hex2) { throw new ArgumentException("From must be one of the Tiles connected to the Edge.", nameof(from)); } var value = to.passable.current.value; using (var scope = new Hooks.Scope()) { this.hooks.ForEach <IOnGetCanPass_Edge>(scope, v => v.OnGetCanPass(from, to, ref value)); Game.hooks.ForEach <IOnGetCanPass_Game>(scope, v => v.OnGetCanPass(from, this, to, ref value)); } return(value); }
protected override void OnCreate() { base.OnCreate(); using (var scope = new Hooks.Scope()) { tile.hooks.ForEach <IOnTileModifierCreate_Tile>(scope, v => v.OnTileModifierCreate(this)); Game.hooks.ForEach <IOnTileModifierCreate_Game>(scope, v => v.OnTileModifierCreate(this)); } }
protected override void OnRemove() { using (var scope = new Hooks.Scope()) { edge.hooks.ForEach <IOnEdgeModifierRemove_Edge>(scope, v => v.OnEdgeModifierRemove(this)); Game.hooks.ForEach <IOnEdgeModifierRemove_Game>(scope, v => v.OnEdgeModifierRemove(this)); } base.OnRemove(); }
public void Dispell() { using (var scope = new Hooks.Scope()) { this.hooks.ForEach <IOnDispell_Unit>(scope, v => v.OnDispell()); tile.hooks.ForEach <IOnDispell_Tile>(scope, v => v.OnDispell(this)); Game.hooks.ForEach <IOnDispell_Game>(scope, v => v.OnDispell(this)); } }
public void ExecuteMoveOff(Unit unit, Tile tile) { using (var scope = new Hooks.Scope()) { tile.hooks.ForEach <IOnMoveOff_Tile>(scope, v => v.OnMoveOff(this, unit)); unit.hooks.ForEach <IOnMoveOff_Unit>(scope, v => v.OnMoveOff(this, tile)); Game.hooks.ForEach <IOnMoveOff_Game>(scope, v => v.OnMoveOff(this, unit, tile)); } }
public void ExecuteMoveOver(Unit unit, Tile from, Edge edge, Tile to) { edge = from.EdgeBetween(to); using (var scope = new Hooks.Scope()) { edge.hooks.ForEach <IOnMoveOver_Edge>(scope, v => v.OnMoveOver(this, unit, from, to)); unit.hooks.ForEach <IOnMoveOver_Unit>(scope, v => v.OnMoveOver(this, from, edge, to)); Game.hooks.ForEach <IOnMoveOver_Game>(scope, v => v.OnMoveOver(this, unit, from, edge, to)); } }
protected override void OnRemove() { using (var scope = new Hooks.Scope()) { unit.hooks.ForEach <IOnUnitModifierRemove_Unit>(scope, v => v.OnUnitModifierRemove(this)); unit.tile.hooks.ForEach <IOnUnitModifierRemove_Tile>(scope, v => v.OnUnitModifierRemove(this)); Game.hooks.ForEach <IOnUnitModifierRemove_Game>(scope, v => v.OnUnitModifierRemove(this)); } base.OnRemove(); }
public void Heal(float heal) { using (var scope = new Hooks.Scope()) { this.hooks.ForEach <IOnHeal_Unit>(scope, v => v.OnHeal(ref heal)); tile.hooks.ForEach <IOnHeal_Tile>(scope, v => v.OnHeal(this, ref heal)); Game.hooks.ForEach <IOnHeal_Game>(scope, v => v.OnHeal(this, ref heal)); } health.current.value += Mathf.Max(0, heal); health.Clamp(); }
protected override void OnCreate() { base.OnCreate(); using (var scope = new Hooks.Scope()) Game.hooks.ForEach <IOnCombatLog>(scope, v => v.OnCombatLog($"Unit spawn: {Lang.GetStr($"{identifier}_DisplayName")} ({team})")); using (var scope = new Hooks.Scope()) { this.hooks.ForEach <IOnSpawn_Unit>(scope, v => v.OnSpawn()); tile.hooks.ForEach <IOnSpawn_Tile>(scope, v => v.OnSpawn(this)); Game.hooks.ForEach <IOnSpawn_Game>(scope, v => v.OnSpawn(this)); } }
/// <summary> Gets the estimated speed of this unit after a number of rounds have passed. </summary> public int GetEstimatedSpeed(int roundsAhead) { var speed = this.speed.current.raw; using (var scope = new Hooks.Scope()) { this.hooks.ForEach <IOnGetEstimatedSpeed_Unit>(scope, v => v.OnGetEstimatedSpeed(roundsAhead, ref speed)); tile.hooks.ForEach <IOnGetEstimatedSpeed_Tile>(scope, v => v.OnGetEstimatedSpeed(this, roundsAhead, ref speed)); Game.hooks.ForEach <IOnGetEstimatedSpeed_Game>(scope, v => v.OnGetEstimatedSpeed(this, roundsAhead, ref speed)); } return(speed); }
/// <summary> Calculates damage for later use. Amplifications and modifiers are applied to the ref values. </summary> public void CalculateDamage(ref float damage, ref DamageType damageType) { var abilityType = this.abilityType; using (var scope = new Hooks.Scope()) { var(_damage, _damageType) = (damage, damageType); unit.hooks.ForEach <IOnCalculateDamage_Unit>(scope, v => v.OnCalculateDamage(this, ref _damage, ref _damageType)); unit.tile.hooks.ForEach <IOnCalculateDamage_Tile>(scope, v => v.OnCalculateDamage(this, ref _damage, ref _damageType)); Game.hooks.ForEach <IOnCalculateDamage_Game>(scope, v => v.OnCalculateDamage(this, ref _damage, ref _damageType)); (damage, damageType) = (_damage, _damageType); } }
public virtual void OnAnimationEventEnd() { if (isCasting) { isCasting = false; //!!! Is work? No onFinishEvent before Hooks.onFinishEvent += () => { using (var scope = new Hooks.Scope()) { unit.hooks.ForEach <IOnAbilityCastEnd_Unit>(scope, v => v.OnAbilityCastEnd(this)); unit.tile.hooks.ForEach <IOnAbilityCastEnd_Tile>(scope, v => v.OnAbilityCastEnd(this)); Game.hooks.ForEach <IOnAbilityCastEnd_Game>(scope, v => v.OnAbilityCastEnd(this)); } }; } }
public override EventHandler GetHandler() { Debug.Log($"{this.GetType().Name}: Called"); var caster = ResolveCaster(); var ability = ResolveAbility(caster); var str = ability.CombatLog(this); if (str != null) { using (var scope = new Hooks.Scope()) Game.hooks.ForEach <IOnCombatLog>(scope, v => v.OnCombatLog(str)); } EventHandler <Ability> abilityHandler = ability.CreateHandler(this); ability.OnCast(); return(abilityHandler); }
/// <summary> The move cost over this Edge. </summary> public float MoveCost(Tile from, Tile to) { if (to != hex1 && to != hex2) { throw new ArgumentException("To must be one of the Tiles connected to the Edge.", nameof(to)); } if (from != hex1 && from != hex2) { throw new ArgumentException("From must be one of the Tiles connected to the Edge.", nameof(from)); } var value = to.moveCost.current.value; using (var scope = new Hooks.Scope()) { this.hooks.ForEach <IOnGetMoveCost_Edge>(scope, v => v.OnGetMoveCost(from, to, ref value)); Game.hooks.ForEach <IOnGetMoveCost_Game>(scope, v => v.OnGetMoveCost(from, this, to, ref value)); } return(Mathf.Max(0, value)); }
/// <summary> Removes this Modifier from the Master and the game. </summary> public void Remove() { if (removed) { return; } removed = true; Hide(); master.DetachModifier(this); Game.dataObjects.Remove(this); Game.hooks.Unhook(this); using (var scope = new Hooks.Scope()) Game.hooks.ForEach <IOnModifierRemove>(scope, v => v.OnModifierRemove(this)); OnConfigureNonpersistent(false); OnRemove(); }
public override EventHandler GetHandler() { Debug.Log($"{this.GetType().Name}: Called"); if (Game.game.started) { Debug.LogWarning("Readied after Game already started."); return(null); } foreach (var spawn in spawns) { var tile = Game.grid.tiles[spawn.position]; var unitData = App.library.GetById <Unit>(spawn.unit); var unit = Unit.Create(unitData, Game.grid.tiles[spawn.position], 0, team); unit.actor.gameObject.SetActive(team == Game.game.team); } if (!Game.game.readied.Contains(team)) { Game.game.readied.Add(team); } if (Game.game.readied.Count == Game.game.mode.teams.Count) { foreach (var spawnCtrl in FindObjectsOfType <SpawnControl>()) { Destroy(spawnCtrl.gameObject); } foreach (var unit in Game.dataObjects.Get <Unit>()) { unit.actor.gameObject.SetActive(true); } Game.game.StartGame(); } using (var scope = new Hooks.Scope()) Game.hooks.ForEach <IOnTeamReady>(scope, v => v.OnTeamReady(team)); return(null); }
public void SetTile(Tile tile, bool reposition) { if (tile == null) { throw new ArgumentNullException(nameof(tile)); } if (tile == this.tile) { if (reposition && actor) { actor.transform.position = this.tile.center; } return; } if (removed) { this.tile = tile; return; } var orig = this.tile; if (orig != null) { orig.units.Remove(this); } tile.units.Add(this); this.tile = tile; if (reposition && shown) { actor.transform.position = this.tile.center; } using (var scope = new Hooks.Scope()) { this.hooks.ForEach <IOnChangePosition_Unit>(scope, v => v.OnChangePosition(orig, tile)); tile.hooks.ForEach <IOnChangePosition_Tile>(scope, v => v.OnChangePosition(this, orig, tile)); Game.hooks.ForEach <IOnChangePosition_Game>(scope, v => v.OnChangePosition(this, orig, tile)); } }
/// <summary> Applies any statuses caused by energy deficit or excess </summary> public void RefreshEnergy() { var deficit = 0 - energy.current; if (deficit > 0) { using (var scope = new Hooks.Scope()) { this.hooks.ForEach <IOnEnergyDeficit_Unit>(scope, v => v.OnEnergyDeficit(deficit)); tile.hooks.ForEach <IOnEnergyDeficit_Tile>(scope, v => v.OnEnergyDeficit(this, deficit)); Game.hooks.ForEach <IOnEnergyDeficit_Game>(scope, v => v.OnEnergyDeficit(this, deficit)); } } var excess = energy.current - energy.max; if (excess > 0) { using (var scope = new Hooks.Scope()) { this.hooks.ForEach <IOnEnergyExcess_Unit>(scope, v => v.OnEnergyExcess(excess)); tile.hooks.ForEach <IOnEnergyExcess_Tile>(scope, v => v.OnEnergyExcess(this, excess)); Game.hooks.ForEach <IOnEnergyExcess_Game>(scope, v => v.OnEnergyExcess(this, excess)); } } energy.Clamp(); }
/// <summary> Deals damage that is calculated prior to calling this method by e.g. Ability.CalculateDamage(). </summary> public void DealCalculatedDamage(Modifier source, float damage, DamageType type) { using (var scope = new Hooks.Scope()) { switch (source) { case UnitModifier um: um.unit.hooks.ForEach <IOnDealDamage_Unit>(scope, v => v.OnDealDamage(um, this, damage, type)); Game.hooks.ForEach <IOnDealDamage_Game>(scope, v => v.OnDealDamage(um, this, damage, type)); break; case TileModifier tm: tm.tile.hooks.ForEach <IOnDealDamage_Tile>(scope, v => v.OnDealDamage(tm, this, damage, type)); Game.hooks.ForEach <IOnDealDamage_Game>(scope, v => v.OnDealDamage(tm, this, damage, type)); break; case EdgeModifier em: em.edge.hooks.ForEach <IOnDealDamage_Edge>(scope, v => v.OnDealDamage(em, this, damage, type)); Game.hooks.ForEach <IOnDealDamage_Game>(scope, v => v.OnDealDamage(source, this, damage, type)); break; } } using (var scope = new Hooks.Scope()) { this.hooks.ForEach <IOnTakeDamage_Unit>(scope, v => v.OnTakeDamage(source, ref damage, ref type)); tile.hooks.ForEach <IOnTakeDamage_Tile>(scope, v => v.OnTakeDamage(this, source, ref damage, ref type)); Game.hooks.ForEach <IOnTakeDamage_Game>(scope, v => v.OnTakeDamage(this, source, ref damage, ref type)); } switch (type) { case DamageType.Physical: health.current.value -= (1 - defense.current / 100f) * damage; health.Clamp(); break; case DamageType.Magical: health.current.value -= (1 - resistance.current / 100f) * damage; health.Clamp(); break; case DamageType.Pure: health.current.value -= damage; health.Clamp(); break; default: health.current.value -= damage; health.Clamp(); Debug.LogWarning($"Damage type was either unknown or None. Damage was applied as {DamageType.Pure}"); break; } if (health.current <= 0) { using (var scope = new Hooks.Scope()) Game.hooks.ForEach <IOnCombatLog>(scope, v => v.OnCombatLog($"Unit death: {Lang.GetStr($"{identifier}_DisplayName")} ({team})")); using (var scope = new Hooks.Scope()) { this.hooks.ForEach <IOnDeath_Unit>(scope, v => v.OnDeath()); tile.hooks.ForEach <IOnDeath_Tile>(scope, v => v.OnDeath(this)); Game.hooks.ForEach <IOnDeath_Game>(scope, v => v.OnDeath(this)); } Remove(); } }