/// <summary> /// /// </summary> /// <param name="castInfos"></param> /// <returns></returns> public FightActionResultEnum TryApplyEffect(CastInfos castInfos) { if (!m_effects.ContainsKey(castInfos.EffectType)) { Logger.Debug("EffectManager::TryApplyEffect unknow effect : " + castInfos.EffectType); return(FightActionResultEnum.RESULT_NOTHING); } return(m_effects[castInfos.EffectType].ApplyEffect(castInfos)); }
/// <summary> /// /// </summary> /// <param name="Effect"></param> public AbstractSpellBuff(CastInfos castInfos, AbstractFighter target, ActiveType activeType, DecrementType decrementType) { CastInfos = castInfos; Duration = target.Fight.CurrentFighter == target ? castInfos.Duration + 1 : castInfos.Duration; Caster = castInfos.Caster; Target = target; ActiveType = activeType; DecrementType = decrementType; switch (castInfos.EffectType) { case EffectEnum.ReflectSpell: Target.Fight.Dispatch(WorldMessage.FIGHT_EFFECT_INFORMATION(CastInfos.EffectType, Target.Id, CastInfos.Value2.ToString(), CastInfos.Value2.ToString(), "10", CastInfos.Value2.ToString(), CastInfos.Duration.ToString(), CastInfos.SpellId.ToString())); break; case EffectEnum.EcaflipChance: case EffectEnum.AddChatiment: Target.Fight.Dispatch(WorldMessage.FIGHT_EFFECT_INFORMATION(CastInfos.EffectType, Target.Id, CastInfos.Value1.ToString(), CastInfos.Value2.ToString(), CastInfos.Value3.ToString(), "", CastInfos.Duration.ToString(), CastInfos.SpellId.ToString())); break; case EffectEnum.PandaCarrier: break; default: Target.Fight.Dispatch(WorldMessage.FIGHT_EFFECT_INFORMATION(CastInfos.EffectType, Target.Id, CastInfos.Value1.ToString(), "", "", "", CastInfos.Duration.ToString(), CastInfos.SpellId.ToString())); break; } }
/// <summary> /// /// </summary> /// <param name="Effect"></param> public AbstractSpellBuff(CastInfos castInfos, AbstractFighter target, ActiveType activeType, DecrementType decrementType) { CastInfos = castInfos; Duration = target.Fight.CurrentFighter == target ? castInfos.Duration + 1 : castInfos.Duration; Caster = castInfos.Caster; Target = target; ActiveType = activeType; DecrementType = decrementType; switch (castInfos.EffectType) { case EffectEnum.ReflectSpell: Target.Fight.Dispatch(WorldMessage.FIGHT_EFFECT_INFORMATION(CastInfos.EffectType, Target.Id, CastInfos.Value2.ToString(), CastInfos.Value2.ToString(), "10", CastInfos.Value2.ToString(), CastInfos.Duration.ToString(), CastInfos.SpellId.ToString())); break; case EffectEnum.EcaflipChance: case EffectEnum.AddChatiment: Target.Fight.Dispatch(WorldMessage.FIGHT_EFFECT_INFORMATION(CastInfos.EffectType, Target.Id, CastInfos.Value1.ToString(), CastInfos.Value2.ToString(), CastInfos.Value3.ToString(), "", CastInfos.Duration.ToString(), CastInfos.SpellId.ToString())); break; case EffectEnum.PandaCarrier: break; default: Target.Fight.Dispatch(WorldMessage.FIGHT_EFFECT_INFORMATION(CastInfos.EffectType, Target.Id, CastInfos.Value1.ToString(), "", "", "", CastInfos.Duration.ToString(), CastInfos.SpellId.ToString())); break; } }
/// <summary> /// /// </summary> /// <param name="type"></param> /// <param name="activeType"></param> /// <param name="fight"></param> /// <param name="caster"></param> /// <param name="castInfos"></param> /// <param name="cell"></param> /// <param name="duration"></param> /// <param name="actionId"></param> /// <param name="canGoThrough"></param> /// <param name="canStack"></param> /// <param name="hide"></param> protected AbstractActivableObject(FightObstacleTypeEnum type, ActiveType activeType, AbstractFight fight, AbstractFighter caster, CastInfos castInfos, int cell, int duration, int actionId, bool canGoThrough, bool canStack, bool hide = false) { m_fight = fight; m_caster = caster; m_spellId = castInfos.SpellId; m_actionSpell = SpellManager.Instance.GetTemplate(castInfos.Value1); m_actionEffect = m_actionSpell.GetLevel(castInfos.Value2); Cell = fight.GetCell(cell); ObstacleType = type; ActivationType = activeType; CanGoThrough = canGoThrough; CanStack = canStack; Color = castInfos.Value3; Targets = new List<AbstractFighter>(); Length = Pathfinding.GetDirection(castInfos.RangeType[1]); AffectedCells = new List<FightCell>(); Duration = duration; ActionId = actionId; Hide = hide; foreach(var effect in m_actionEffect.Effects) { if(CastInfos.IsDamageEffect(effect.TypeEnum)) { Priority--; } } // On ajout l'objet a toutes les cells qu'il affecte foreach (var cellId in CellZone.GetCircleCells(fight.Map, cell, Length)) { var fightCell = m_fight.GetCell(cellId); if (fightCell != null) { fightCell.AddObject(this); AffectedCells.Add(fightCell); } } if (Hide) Appear(caster.Team); else AppearForAll(); }
/// <summary> /// /// </summary> /// <param name="ActiveType"></param> public virtual FightActionResultEnum ApplyEffect(ref int damageValue, CastInfos damageInfos = null) { return Caster.Fight.TryKillFighter(Target, Caster); }
/// <summary> /// /// </summary> /// <param name="castInfos"></param> /// <returns></returns> public abstract FightActionResultEnum ApplyEffect(CastInfos castInfos);
/// <summary> /// /// </summary> /// <param name="fight"></param> /// <param name="caster"></param> /// <param name="effect"></param> /// <param name="cell"></param> /// <param name="duration"></param> public FightGlyph(AbstractFight fight, AbstractFighter caster, CastInfos effect, int cell, int duration) : base(FightObstacleTypeEnum.TYPE_GLYPH, ActiveType.ACTIVE_BEGINTURN, fight, caster, effect, cell, duration, 307, true, true) { }
/// <summary> /// /// </summary> /// <param name="ActiveType"></param> public virtual FightActionResultEnum ApplyEffect(ref int damageValue, CastInfos damageInfos = null) { return(Caster.Fight.TryKillFighter(Target, Caster)); }
/// <summary> /// /// </summary> /// <param name="fighter"></param> /// <param name="castInfos"></param> public void CheckSpell(AbstractFighter fighter, CastInfos castInfos) { foreach (var challenge in m_challenges) challenge.CheckSpell(fighter, castInfos); }
/// <summary> /// /// </summary> /// <param name="castInfos"></param> /// <returns></returns> public abstract FightActionResultEnum ApplyEffect(CastInfos castInfos);
/// <summary> /// /// </summary> /// <param name="fight"></param> /// <param name="caster"></param> /// <param name="effect"></param> /// <param name="cell"></param> public FightTrap(AbstractFight fight, AbstractFighter caster, CastInfos effect, int cell) : base(FightObstacleTypeEnum.TYPE_TRAP, ActiveType.ACTIVE_ENDMOVE, fight, caster, effect, cell, 0, 306, true, false, true) { }
/// <summary> /// /// </summary> /// <param name="fighter"></param> /// <param name="castInfos"></param> public virtual void CheckSpell(AbstractFighter fighter, CastInfos castInfos) { }
/// <summary> /// /// </summary> /// <param name="fighter"></param> /// <param name="castInfos"></param> public override void CheckSpell(AbstractFighter fighter, CastInfos castInfos) { if(castInfos.EffectType == EffectEnum.AddLife && castInfos.Target != null && castInfos.Target.Team == fighter.Team) base.OnFailed(fighter.Name); }
/// <summary> /// /// </summary> /// <param name="infos"></param> public void AddProcessingTarget(CastInfos infos) { if(infos.Target == null) { Logger.Debug("AddProcessingTarget first (Null target)"); m_processingTargets.AddFirst(infos); } else if (CurrentProcessingFighter == infos.Target) { Logger.Debug("AddProcessingTarget first (CurrentProcessingFighter) : " + infos.Target.Name); m_processingTargets.AddFirst(infos); } else if (CurrentProcessingFighter == null && CurrentFighter == infos.Target) { Logger.Debug("AddProcessingTarget first (CurrentFighter) : " + infos.Target.Name); m_processingTargets.AddFirst(infos); } else { Logger.Debug("AddProcessingTarget last : " + infos.Target.Name); m_processingTargets.AddLast(infos); } }
/// <summary> /// /// </summary> /// <param name="fighter"></param> /// <param name="spellId"></param> /// <param name="castCellId"></param> public void TryLaunchSpell(AbstractFighter fighter, int spellId, int castCellId, int actionTime = 5000) { AddMessage(() => { if (LoopState == FightLoopStateEnum.STATE_WAIT_END || LoopState == FightLoopStateEnum.STATE_ENDED) { fighter.Dispatch(WorldMessage.BASIC_NO_OPERATION()); return; } if (State != FightStateEnum.STATE_FIGHTING) { Logger.Debug("Fight::TryLaunchSpell fight is not in fighting state : " + fighter.Name); fighter.Dispatch(WorldMessage.BASIC_NO_OPERATION()); return; } if (m_currentApCost != -1) { Logger.Debug("Fight::TryLaunchSpell fight already processing spell launch and not finished : " + fighter.Name); fighter.Dispatch(WorldMessage.BASIC_NO_OPERATION()); return; } if (fighter.SpellBook == null) { Logger.Debug("Fight::TryLaunchSpell empty spellbook : " + fighter.Name); fighter.Dispatch(WorldMessage.BASIC_NO_OPERATION()); return; } var spellLevel = fighter.SpellBook.GetSpellLevel(spellId); if (spellLevel == null) { Logger.Debug("Fight::TryLaunchSpell unnknow spellId : " + fighter.Name); fighter.Dispatch(WorldMessage.BASIC_NO_OPERATION()); return; } var launchResult = CanLaunchSpell(fighter, spellLevel, spellId, fighter.Cell.Id, castCellId); if (launchResult != FightSpellLaunchResultEnum.RESULT_OK) { Logger.Debug("Fight::TryLaunchSpell unable to launch spell : " + fighter.Name + " reason=" + launchResult); fighter.Dispatch(WorldMessage.BASIC_NO_OPERATION()); return; } var isMelee = Pathfinding.GoalDistance(Map, fighter.Cell.Id, castCellId) == 1; fighter.UsedAP += spellLevel.APCost; base.Dispatch(WorldMessage.FIGHT_ACTION_START(CurrentFighter.Id)); var isEchec = false; if (spellLevel.ECSRate != 0) { var echecRate = spellLevel.ECSRate - fighter.Statistics.GetTotal(EffectEnum.AddEchecCritic); if (echecRate < 2) echecRate = 2; if (Util.Next(0, echecRate) == 0) isEchec = true; if (isEchec) { CachedBuffer = true; Dispatch(WorldMessage.GAME_ACTION(GameActionTypeEnum.FIGHT_CRITICAL_FAILURE, fighter.Id, spellId.ToString())); Dispatch(WorldMessage.GAME_ACTION(GameActionTypeEnum.FIGHT_PA_LOST, fighter.Id, fighter.Id + ",-" + spellLevel.APCost)); Dispatch(WorldMessage.FIGHT_ACTION_FINISHED(CurrentFighter.Id)); CachedBuffer = false; if (spellLevel.IsECSEndTurn == 1) { CurrentFighter.TurnPass = true; } return; } } var target = GetFighterOnCell(castCellId); if (target != null) { fighter.SpellManager.Actualize(spellLevel, spellId, target.Id); } var isCritic = false; if (spellLevel.CSRate != 0 && spellLevel.CriticalEffects.Count > 0) { var criticalHitRate = spellLevel.CSRate - fighter.Statistics.GetTotal(EffectEnum.AddDamageCritic); fighter.CalculCriticalHitRate(ref criticalHitRate); if (criticalHitRate < 2) criticalHitRate = 2; if (Util.Next(0, criticalHitRate) == 0) isCritic = true; } if (isCritic) Dispatch(WorldMessage.GAME_ACTION(GameActionTypeEnum.FIGHT_CRITICAL_HIT, fighter.Id, spellId.ToString())); var effects = isCritic ? spellLevel.CriticalEffects : spellLevel.Effects; var targetLists = new Dictionary<SpellEffect, List<AbstractFighter>>(); var effectIndex = 0; foreach (var effect in effects) { targetLists.Add(effect, new List<AbstractFighter>()); var targetType = spellLevel.Template.Targets != null ? spellLevel.Template.Targets.Count > effectIndex ? spellLevel.Template.Targets[effectIndex] : -1 : -1; if (effect.TypeEnum != EffectEnum.UseGlyph && effect.TypeEnum != EffectEnum.UseTrap) { foreach (var currentCellId in CellZone.GetCells(Map, castCellId, fighter.Cell.Id, spellLevel.RangeType)) { var fightCell = GetCell(currentCellId); if (fightCell != null) { foreach (var fighterObject in fightCell.FightObjects.OfType<AbstractFighter>()) { if (targetType != -1) { // affect caster : 32 if (((((targetType >> 5) & 1) == 1) && (fighter.Id != fighterObject.Id))) { if (!targetLists[effect].Contains(fighter)) targetLists[effect].Add(fighter); continue; } // doesnt affect team mates : 1 if (((targetType & 1) == 1) && fighter.Team == fighterObject.Team) continue; // doesnt affect the caster : 2 if ((((targetType >> 1) & 1) == 1) && fighter.Id == fighterObject.Id) continue; // doesnt affect ennemies : 4 if ((((targetType >> 2) & 1) == 1) && fighter.Team != fighterObject.Team) continue; // only invocation : 8 if (((((targetType >> 3) & 1) == 1) && (fighterObject.Invocator == null))) continue; // doesnt affect invocs : 16 if (((((targetType >> 4) & 1) == 1) && (fighterObject.Invocator != null))) continue; } if (!targetLists[effect].Contains(fighterObject)) targetLists[effect].Add(fighterObject); } } } } effectIndex++; } LoopState = FightLoopStateEnum.STATE_WAIT_ACTION; var template = SpellManager.Instance.GetTemplate(spellId); fighter.LaunchSpell(castCellId, spellId, spellLevel.Level, template.Sprite.ToString(), template.SpriteInfos, actionTime, () => { if (LoopState == FightLoopStateEnum.STATE_WAIT_END || LoopState == FightLoopStateEnum.STATE_ENDED) { fighter.Dispatch(WorldMessage.BASIC_NO_OPERATION()); return; } var actualChance = 0; foreach (var effect in effects) { if (effect.Chance > 0) { if (Util.Next(0, 100) > (effect.Chance + actualChance)) { actualChance += effect.Chance; continue; } actualChance -= 100; } targetLists[effect].RemoveAll(affectedTarget => affectedTarget.IsFighterDead); if (targetLists[effect].Count == 0) { var castInfos = new CastInfos( effect.TypeEnum, spellId, castCellId, effect.Value1, effect.Value2, effect.Value3, effect.Chance, effect.Duration, fighter, null, spellLevel.RangeType, 0, spellLevel.Level, isMelee); AddProcessingTarget(castInfos); CurrentFighter.Team.CheckSpell(CurrentFighter, castInfos); } else { foreach (var effectTarget in targetLists[effect]) { var castInfos = new CastInfos( effect.TypeEnum, spellId, castCellId, effect.Value1, effect.Value2, effect.Value3, effect.Chance, effect.Duration, fighter, effectTarget, spellLevel.RangeType, effectTarget.Cell.Id, spellLevel.Level, isMelee); AddProcessingTarget(castInfos); CurrentFighter.Team.CheckSpell(CurrentFighter, castInfos); } } } m_currentApCost = spellLevel.APCost; }); }); }
/// <summary> /// /// </summary> /// <param name="castInfos"></param> /// <param name="damageValue"></param> public FightActionResultEnum OnAttackedBeforeJet(CastInfos castInfos, ref int damageValue) { foreach (var buff in ActiveBuffs[ActiveType.ACTIVE_ATTACKED_BEFORE_JET].ToArray()) { var result = buff.ApplyEffect(ref damageValue, castInfos); if(result != FightActionResultEnum.RESULT_NOTHING) return result; } return m_fighter.Fight.TryKillFighter(m_fighter, m_fighter); }