public static string GetName(TargetAction action) { if (action == TargetAction.Unknown) { return((string)null); } switch (action) { case TargetAction.Bandage: return("a bandage"); case TargetAction.Bola: return("a bola"); case TargetAction.PurplePotion: return("an explosion potion"); default: string str = action.ToString(); for (int index = 0; index < str.Length; ++index) { if (index > 0 && (int)str[index] >= 65 && (int)str[index] <= 90) { str = str.Insert(index++, " "); } } return(str.ToLowerInvariant()); } }
/// <summary> /// Checks if target has Defense skill activated and makes the necessary /// changes to the actions, stun times, and damage. /// </summary> /// <param name="aAction"></param> /// <param name="tAction"></param> /// <param name="damage"></param> /// <returns></returns> public static bool Handle(AttackerAction aAction, TargetAction tAction, ref float damage) { var activeSkill = tAction.Creature.Skills.ActiveSkill; if (activeSkill == null || activeSkill.Info.Id != SkillId.Defense || activeSkill.State != SkillState.Ready) { return(false); } activeSkill.State = SkillState.Used; // Update actions tAction.Flags = CombatActionType.Defended; tAction.Stun = DefenseTargetStun; aAction.Stun = DefenseAttackerStun; // Reduce damage damage = Math.Max(1, damage - activeSkill.RankData.Var3); // Updating unlock because of the updating lock for pre-renovation // Other skills actually unlock automatically on the client, // I guess this isn't the case for Defense because it's never // *explicitly* used. if (!AuraData.FeaturesDb.IsEnabled("TalentRenovationCloseCombat")) { tAction.Creature.Unlock(Locks.Run, true); } Send.SkillUseStun(tAction.Creature, SkillId.Defense, DefenseTargetStun, 0); return(true); }
/// <summary> /// Handles knock back/stun/death. /// </summary> protected virtual void HandleKnockBack(Creature attacker, Creature target, TargetAction tAction) { if (target.IsDead) { tAction.Set(TargetOptions.FinishingKnockDown); attacker.Shove(target, KnockbackDistance); } else { // If knocked down, instant recovery, // if repeat hit, knock down, // otherwise potential knock back. if (target.IsKnockedDown) { tAction.Stun = 0; } else if (target.IsUnstable) { tAction.Set(TargetOptions.KnockDown); } else { target.Stability -= StabilityReduction; if (target.IsUnstable) { tAction.Set(TargetOptions.KnockBack); attacker.Shove(target, KnockbackDistance); } } } }
/// <summary> /// Checks if target has Defense skill activated and makes the necessary /// changes to the actions, stun times, and damage. /// </summary> /// <param name="aAction"></param> /// <param name="tAction"></param> /// <param name="damage"></param> /// <returns></returns> public static bool Handle(AttackerAction aAction, TargetAction tAction, ref float damage) { // Defense if (!tAction.Creature.Skills.IsReady(SkillId.Defense)) { return(false); } // Update actions tAction.Type = CombatActionType.Defended; tAction.SkillId = SkillId.Defense; tAction.Stun = DefenseTargetStun; aAction.Stun = DefenseAttackerStun; // Reduce damage var defenseSkill = tAction.Creature.Skills.Get(SkillId.Defense); if (defenseSkill != null) { damage -= defenseSkill.RankData.Var3; } Send.SkillUseStun(tAction.Creature, SkillId.Defense, DefenseTargetStun, 0); return(true); }
/// <summary> /// Called when a player attacks someone (training). /// </summary> /// <param name="action"></param> protected virtual void OnCreatureAttackedByPlayer(TargetAction action) { // Check for instrument in attacker's right hand if (action.Attacker == null || action.Attacker.RightHand == null || action.Attacker.RightHand.Data.Type != ItemType.Instrument) { return; } // Get skill var skill = action.Attacker.Skills.Get(SkillId.PlayingInstrument); if (skill == null) { return; } // Equip an instrument and attack an enemy. if (skill.Info.Rank >= SkillRank.RF && skill.Info.Rank <= SkillRank.RE) { skill.Train(6); } else if (skill.Info.Rank >= SkillRank.RD && skill.Info.Rank <= SkillRank.R6) { skill.Train(5); } else if (skill.Info.Rank >= SkillRank.R7 && skill.Info.Rank <= SkillRank.R2) { skill.Train(4); } else if (skill.Info.Rank == SkillRank.R1) { skill.Train(3); } }
public static void Invoke(TargetAction action, CleanupOptions cleanupOptions) { try { var projects = DteServiceProvider.Instance.ActiveSolutionProjects as Array; var currentProject = projects.GetValue(0) as Project; if (currentProject.ProjectItems == null) { return; } if (currentProject.FullName.EndsWith(".shproj", StringComparison.OrdinalIgnoreCase)) { System.Windows.MessageBox .Show("Clean up can't be called direlctly on Shared Project", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } for (var i = 1; i <= currentProject.ProjectItems.Count; i++) { ActionCSharpOnProjectItem.Action(currentProject.ProjectItems.Item(i), action, cleanupOptions); } } catch (Exception e) { ErrorNotification.WriteErrorToOutputWindow(e); ErrorNotification.WriteErrorToFile(e); ProcessActions.GeeksProductivityToolsProcess(); } }
public static void Invoke(TargetAction action, CleanupOptions cleanupOptions) { try { var projects = SolutionActions.FindProjects(DteServiceProvider.Instance); for (var i = 0; i < projects.Count; i++) { var currentProject = projects[i]; if (currentProject.ProjectItems == null) { continue; } if (currentProject.FullName.ToLower().EndsWith(".shproj")) { continue; } for (var j = 1; j < currentProject.ProjectItems.Count; j++) { ActionCSharpOnProjectItem.Action(currentProject.ProjectItems.Item(j), action, cleanupOptions); } } } catch (Exception e) { ErrorNotification.EmailError(e); ProcessActions.GeeksProductivityToolsProcess(); } }
/// <summary> /// Bolt specific use code. /// </summary> /// <param name="attacker"></param> /// <param name="skill"></param> /// <param name="target"></param> protected override void UseSkillOnTarget(Creature attacker, Skill skill, Creature mainTarget) { // Create actions var aAction = new AttackerAction(CombatActionType.RangeHit, attacker, skill.Info.Id, mainTarget.EntityId); aAction.Set(AttackerOptions.Result); var cap = new CombatActionPack(attacker, skill.Info.Id, aAction); var targets = new List<Creature>(); targets.Add(mainTarget); targets.AddRange(mainTarget.Region.GetCreaturesInRange(mainTarget.GetPosition(), SplashRange).Where(a => a != mainTarget && attacker.CanTarget(a) && attacker.CanAttack(a))); // Damage var damage = this.GetDamage(attacker, skill); var max = Math.Min(targets.Count, skill.Stacks); for (int i = 0; i < max; ++i) { var target = targets[i]; var targetDamage = damage; target.StopMove(); var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Info.Id); tAction.Set(TargetOptions.Result); tAction.Stun = TargetStun; // Full damage for the first target, -10% for every subsequent one. targetDamage -= (targetDamage * 0.1f) * i; // Reduce damage var maxDamage = damage; //Damage without Defense and Protection // Reduce damage Defense.Handle(aAction, tAction); SkillHelper.HandleMagicDefenseProtection(target, ref targetDamage); ManaShield.Handle(target, ref targetDamage, tAction, maxDamage, true); // Deal damage if (targetDamage > 0) target.TakeDamage(tAction.Damage = targetDamage, attacker); if (target == mainTarget) target.Aggro(attacker); // Death/Knockback this.HandleKnockBack(attacker, target, tAction); cap.Add(tAction); } // Override stun set by defense aAction.Stun = AttackerStun; Send.Effect(attacker, Effect.UseMagic, EffectSkillName); Send.SkillUseStun(attacker, skill.Info.Id, aAction.Stun, 1); this.BeforeHandlingPack(attacker, skill); cap.Handle(); }
/// <summary> /// Handles skill usage. /// </summary> /// <param name="attacker"></param> /// <param name="skill"></param> /// <param name="targetAreaEntityId"></param> public void Use(Creature attacker, Skill skill, long targetAreaEntityId) { Send.Effect(attacker, 5, (byte)1, targetAreaEntityId); var cap = new CombatActionPack(attacker, skill.Info.Id); var aAction = new AttackerAction(CombatActionType.Attacker, attacker, targetAreaEntityId); aAction.Options |= AttackerOptions.Result; aAction.Stun = UseStun; cap.Add(aAction); // Get targets in skill area var targets = SkillHelper.GetTargetableCreaturesInSkillArea(attacker, LaserRectHeight, LaserRectWidth); // Attack targets foreach (var target in targets) { var targetPosition = target.GetPosition(); var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Info.Id); tAction.Options = TargetOptions.Result | TargetOptions.KnockDown; tAction.Stun = TargetStun; tAction.Delay = 1200; cap.Add(tAction); // Var2: 300/1000, based on rank. Could be damage? var damage = skill.RankData.Var2; // Modify damage CriticalHit.Handle(attacker, attacker.GetTotalCritChance(target.Protection), ref damage, tAction); SkillHelper.HandleDefenseProtection(target, ref damage); SkillHelper.HandleConditions(attacker, target, ref damage); ManaShield.Handle(target, ref damage, tAction); // Apply damage if (damage > 0) { target.TakeDamage(tAction.Damage = 300, attacker); SkillHelper.HandleInjury(attacker, target, damage); } target.Stability = Creature.MinStability; // Aggro target.Aggro(attacker); // Check death if (target.IsDead) { tAction.Options |= TargetOptions.FinishingKnockDown; } // Knock back attacker.Shove(target, KnockbackDistance); } cap.Handle(); Send.SkillUse(attacker, skill.Info.Id, 0); }
public static void Invoke(TargetAction action, Definition.CodeCleanerType[] type) { try { var projects = DteServiceProvider.Instance.ActiveSolutionProjects as Array; var currentProject = projects.GetValue(0) as Project; if (currentProject.ProjectItems == null) { return; } if (currentProject.FullName.ToLower().EndsWith(".shproj")) { MessageBox.Show("Clean up can't be called direlctly on Shared Project", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } for (var i = 1; i <= currentProject.ProjectItems.Count; i++) { ActionCSharpOnProjectItem.Action(currentProject.ProjectItems.Item(i), action, type); } } catch (Exception e) { ErrorNotification.EmailError(e); ProcessActions.GeeksProductivityToolsProcess(); } }
public TargetAction selectTargetAction() { TargetAction targetAction = new TargetAction(); targetAction.target = selectTarget(); targetAction.action = selectAction(); return targetAction; }
public static void Invoke(TargetAction action, CleanupOptions cleanupOptions) { try { var projects = SolutionActions.FindProjects(DteServiceProvider.Instance); for (var i = 0; i < projects.Count; i++) { var currentProject = projects[i]; if (currentProject.ProjectItems == null) { continue; } if (currentProject.FullName.EndsWith(".shproj", StringComparison.OrdinalIgnoreCase)) { continue; } for (var j = 1; j < currentProject.ProjectItems.Count; j++) { ActionCSharpOnProjectItem.Action(currentProject.ProjectItems.Item(j), action, cleanupOptions); } } } catch (Exception e) { ErrorNotification.WriteErrorToFile(e); ErrorNotification.WriteErrorToOutputWindow(e); ProcessActions.GeeksProductivityToolsProcess(); } }
/// <summary> /// Checks if target's Mana Shield is active, calculates mana /// damage, and sets target action's Mana Damage property if applicable. /// </summary> /// <param name="target"></param> /// <param name="damage"></param> /// <param name="tAction"></param> public static void Handle(Creature target, ref float damage, TargetAction tAction) { // Mana Shield active? if (!target.Conditions.Has(ConditionsA.ManaShield)) return; // Get Mana Shield skill to get the rank's vars var manaShield = target.Skills.Get(SkillId.ManaShield); if (manaShield == null) // Checks for things that should never ever happen, yay. return; // Var 1 = Efficiency var manaDamage = damage / manaShield.RankData.Var1; if (target.Mana >= manaDamage) { // Damage is 0 if target's mana is enough to cover it damage = 0; } else { // Set mana damage to target's mana and reduce the remaining // damage from life if the mana is not enough. damage -= (manaDamage - target.Mana) * manaShield.RankData.Var1; manaDamage = target.Mana; } // Reduce mana target.Mana -= manaDamage; if (target.Mana <= 0) ChannelServer.Instance.SkillManager.GetHandler<StartStopSkillHandler>(SkillId.ManaShield).Stop(target, manaShield); tAction.ManaDamage = manaDamage; }
protected override async Task <bool> InitializeInternal() { await base.InitializeInternal(); SetInitializationState(ScenarioInitializationValue.Initializing); try { var instanceManager = Singleton.Resolve <IInstanceManager>(); foreach (var action in TargetAction.GetAllActionsFlat()) { if (action != null) { instanceManager.PrepareInstance(action, this); action.Initialize(); } } SetIsAvailable(true); return(true); } catch (Exception e) { Log.ErrorFormat(e, "Во время инициализации сценария [{0}] возникла ошибка", Name); SetIsAvailable(false); return(false); } finally { SetInitializationState(ScenarioInitializationValue.Initialized); } }
private void ClickObject_OnClick(ClickObject obj) { if (_action != null) { if (obj.isCreature) { _action.Init(obj.GetComponent <CreatureStats>()); MatchSystem.instance.RunAction(_action); _action = null; return; } } if (obj.isCreature) { CreatureStats creature = obj.GetComponent <CreatureStats>(); if (_action == null) { //MatchSystem.instance.RunAction(new AttackAction(null,creature)); } } else if (obj.isTreasure) { Treasure treasure = obj.GetComponent <Treasure>(); if (_action == null) { //MatchSystem.instance.RunAction(new PickTreasureAction(null, treasure)); } } }
private void MatchSystem_OnActionEnd(IGameAction action) { if ((object)action == _action) { _action = null; } }
// ------------------------------------------------------------------ /// <summary> /// Called when creature is hit. /// </summary> /// <param name="action"></param> public virtual void OnHit(TargetAction action) { // Aggro attacker if there is not current target, // or if there is a target but it's not a player, and the attacker is one, // or if the current target is not aggroed yet. //if (this.Creature.Target == null || (this.Creature.Target != null && action.Attacker != null && !this.Creature.Target.IsPlayer && action.Attacker.IsPlayer) || _state != AiState.Aggro) //{ // this.AggroCreature(action.Attacker); //} var activeSkillWas = SkillId.None; if (this.Creature.Skills.ActiveSkill != null) { activeSkillWas = this.Creature.Skills.ActiveSkill.Info.Id; this.SharpMind(this.Creature.Skills.ActiveSkill.Info.Id, SharpMindStatus.Cancelling); } lock (_reactions) { if (activeSkillWas == SkillId.Defense && _reactions[_state].ContainsKey(AiEvent.DefenseHit)) { this.SwitchAction(_reactions[_state][AiEvent.DefenseHit]); } else if (action.Has(TargetOptions.KnockDown) && _reactions[_state].ContainsKey(AiEvent.KnockDown)) { this.SwitchAction(_reactions[_state][AiEvent.KnockDown]); } else if (_reactions[_state].ContainsKey(AiEvent.Hit)) { this.SwitchAction(_reactions[_state][AiEvent.Hit]); } } }
public void RemoveLastAddedActionsFromTarget(TargetAction targetAction, int actionCount) { switch (targetAction) { case TargetAction.Other: return; case TargetAction.AddTask: { var lastGroup = TasksGroups.Last(); for (int i = 0; i < actionCount; i++) { var lastTask = lastGroup.Tasks.Last(); lastGroup.Tasks.Remove(lastTask); if (lastGroup.Tasks.Count == 0) { TasksGroups.Remove(lastGroup); } } return; } case TargetAction.AddDependency: { for (int i = 0; i < actionCount; i++) { _dependencies.Remove(_dependencies.Keys.Last()); } return; } } }
/// <summary> /// Handles training based on what happened in the combat action. /// </summary> /// <param name="tAction"></param> private void OnCreatureAttack(TargetAction tAction) { if (!tAction.Has(TargetOptions.Critical)) { return; } var attackerSkill = tAction.Attacker.Skills.Get(SkillId.CriticalHit); var targetSkill = tAction.Creature.Skills.Get(SkillId.CriticalHit); if (attackerSkill.Info.Rank == SkillRank.Novice) { if (tAction.Is(CombatActionType.CounteredHit2)) { attackerSkill.Train(1); // Novice -> RF } } else { attackerSkill.Train(1); // Land a critical hit. if (tAction.Creature.IsDead) { attackerSkill.Train(3); // Finish off with critical hit. } } if (targetSkill != null && targetSkill.Info.Rank >= SkillRank.RF) { attackerSkill.Train(2); // Learn from enemy's critical hit. } }
/// <summary> /// Handles the majority of the skill training. /// </summary> /// <param name="tAction"></param> private void OnCreatureAttacks(TargetAction tAction) { if (tAction.AttackerSkillId != SkillId.MagnumShot) { return; } var attackerSkill = tAction.Attacker.Skills.Get(SkillId.MagnumShot); if (attackerSkill != null) { attackerSkill.Train(1); // Attack an enemy. if (tAction.Has(TargetOptions.Critical)) { attackerSkill.Train(2); } if (tAction.Creature.IsDead) // Kill an enemy. { attackerSkill.Train(3); if (tAction.Has(TargetOptions.Critical)) { attackerSkill.Train(4); } } } }
/// <summary> /// Skill training, called when someone attacks something /// </summary> /// <param name="action"></param> public void OnCreatureAttackedByPlayer(TargetAction action) { // Check skill if (action.AttackerSkillId != SkillId.ChargingStrike) { return; } // Get skill var attackerSkill = action.Attacker.Skills.Get(SkillId.ChargingStrike); if (attackerSkill == null) { return; } // Training switch (attackerSkill.Info.Rank) { case SkillRank.Novice: attackerSkill.Train(1); // Use the skill successfully. break; case SkillRank.RF: case SkillRank.RE: case SkillRank.RD: case SkillRank.RC: case SkillRank.RB: case SkillRank.RA: case SkillRank.R9: case SkillRank.R8: case SkillRank.R7: case SkillRank.R6: case SkillRank.R5: case SkillRank.R4: case SkillRank.R3: attackerSkill.Train(1); // Use the skill successfully. if (action.Has(TargetOptions.Critical)) { attackerSkill.Train(2); // Get a Critical Hit with Charging Strike. } break; case SkillRank.R2: if (action.Creature.HasTag("/ogre/")) { attackerSkill.Train(1); // Use the skill successfully on an Ogre. } break; case SkillRank.R1: attackerSkill.Train(1); // Use the skill successfully. if (action.Has(TargetOptions.Critical)) { attackerSkill.Train(2); // Get a Critical Hit with Charging Strike. } break; } }
/// <summary> /// Custom cancelation. /// </summary> /// <param name="creature"></param> /// <param name="tAction"></param> public void CustomHitCancel(Creature creature, TargetAction tAction) { // Cancelation on knock down was removed in G19. if (!AuraData.FeaturesDb.IsEnabled("TalentRenovationCloseCombat")) { creature.Skills.CancelActiveSkill(); } }
private static void DoActionForItems(ProjectItems projectItems, TargetAction action, CleanupOptions cleanupOptions) { for (int subItemIndex = 1; subItemIndex <= projectItems.Count; subItemIndex++) { var subItem = projectItems.Item(subItemIndex); ActionCSharpOnProjectItem.Action(subItem, action, cleanupOptions); } }
public AutoTargetSession(object entity, TargetAction action) { this.m_Entity = entity; this.m_Action = action; this.m_Timer = new Timer(new OnTick(Engine.AutoTarget_Expire), 0x9c4, 1); this.m_Timer.SetTag("Session", this); this.m_Timer.Start(false); }
public StratusTurnBasedTargetAction(CombatController source, CombatController target, TargetAction onExecute, TargetAction onUndo) : base(source) { this.target = target; this.onExecute = onExecute; this.onUndo = onUndo; }
/// <summary> /// Handles knock back/stun/death. /// </summary> protected override void HandleKnockBack(Creature attacker, Creature target, TargetAction tAction, bool overcharge) { attacker.Shove(target, KnockbackDistance); if (target.IsDead) tAction.Set(TargetOptions.FinishingKnockDown); else tAction.Set(TargetOptions.KnockDown); }
private static void DoActionForItems(ProjectItems projectItems, TargetAction action, CodeCleanerType[] type) { for (int subItemIndex = 1; subItemIndex <= projectItems.Count; subItemIndex++) { var subItem = projectItems.Item(subItemIndex); ActionCSharpOnProjectItem.Action(subItem, action, type); } }
public static ServerTargetFlags GetFlags(TargetAction action) { if (action < TargetAction.DetectHidden) { if (action >= TargetAction.Bola) { return ServerTargetFlags.Harmful; } if (action >= TargetAction.Bandage) { return ServerTargetFlags.Beneficial; } switch (action) { case TargetAction.Clumsy: case TargetAction.Feeblemind: case TargetAction.MagicArrow: case TargetAction.Weaken: case TargetAction.Harm: case TargetAction.Fireball: case TargetAction.Poison: case TargetAction.Curse: case TargetAction.Lightning: case TargetAction.ManaDrain: case TargetAction.MindBlast: case TargetAction.Paralyze: case TargetAction.Dispel: case TargetAction.EnergyBolt: case TargetAction.Explosion: case TargetAction.FlameStrike: case TargetAction.ManaVampire: return ServerTargetFlags.Harmful; case TargetAction.Heal: case TargetAction.Agility: case TargetAction.Cunning: case TargetAction.Cure: case TargetAction.Strength: case TargetAction.Bless: case TargetAction.GreaterHeal: case TargetAction.Invisibility: case TargetAction.Resurrection: return ServerTargetFlags.Beneficial; case TargetAction.ArchCure: case TargetAction.ArchProtection: case TargetAction.FireField: case TargetAction.PoisonField: case TargetAction.ParalyzeField: case TargetAction.Reveal: case TargetAction.ChainLightning: case TargetAction.EnergyField: case TargetAction.MeteorSwarm: return ServerTargetFlags.None; } } return ServerTargetFlags.None; }
public static ServerTargetFlags GetFlags(TargetAction action) { if (action < TargetAction.DetectHidden) { if (action >= TargetAction.Bola) { return(ServerTargetFlags.Harmful); } if (action >= TargetAction.Bandage) { return(ServerTargetFlags.Beneficial); } switch (action) { case TargetAction.Clumsy: case TargetAction.Feeblemind: case TargetAction.MagicArrow: case TargetAction.Weaken: case TargetAction.Harm: case TargetAction.Fireball: case TargetAction.Poison: case TargetAction.Curse: case TargetAction.Lightning: case TargetAction.ManaDrain: case TargetAction.MindBlast: case TargetAction.Paralyze: case TargetAction.Dispel: case TargetAction.EnergyBolt: case TargetAction.Explosion: case TargetAction.FlameStrike: case TargetAction.ManaVampire: return(ServerTargetFlags.Harmful); case TargetAction.Heal: case TargetAction.Agility: case TargetAction.Cunning: case TargetAction.Cure: case TargetAction.Strength: case TargetAction.Bless: case TargetAction.GreaterHeal: case TargetAction.Invisibility: case TargetAction.Resurrection: return(ServerTargetFlags.Beneficial); case TargetAction.ArchCure: case TargetAction.ArchProtection: case TargetAction.FireField: case TargetAction.PoisonField: case TargetAction.ParalyzeField: case TargetAction.Reveal: case TargetAction.ChainLightning: case TargetAction.EnergyField: case TargetAction.MeteorSwarm: return(ServerTargetFlags.None); } } return(ServerTargetFlags.None); }
public void Start(string logSystem, string Method, TargetAction Action, string UID) { _starttime = DateTime.Now; _method = Method; _OSUserName = UID; _logSystem = logSystem; _action = Action; }
/// <summary> /// Handles usage of the skill. /// </summary> /// <param name="attacker"></param> /// <param name="target"></param> public void Use(Creature attacker, Creature target) { // Updating unlock because of the updating lock for pre-renovation // Has to be done here because we can't have an updating unlock // after the combat action, it resets the stun. if (!AuraData.FeaturesDb.IsEnabled("TalentRenovationCloseCombat")) { attacker.Unlock(Locks.Move, true); } var skill = attacker.Skills.Get(SkillId.Counterattack); var aAction = new AttackerAction(CombatActionType.RangeHit, attacker, target.EntityId); aAction.Options |= AttackerOptions.Result | AttackerOptions.KnockBackHit2; var tAction = new TargetAction(CombatActionType.CounteredHit2, target, attacker, target.Skills.IsReady(SkillId.Smash) ? SkillId.Smash : SkillId.CombatMastery); tAction.Options |= TargetOptions.Result | TargetOptions.Smash; var cap = new CombatActionPack(attacker, skill.Info.Id); cap.Add(aAction, tAction); var damage = (attacker.GetRndTotalDamage() * (skill.RankData.Var2 / 100f)) + (target.GetRndTotalDamage() * (skill.RankData.Var1 / 100f)); var critChance = attacker.GetTotalCritChance(target.Protection) + skill.RankData.Var3; CriticalHit.Handle(attacker, critChance, ref damage, tAction, true); SkillHelper.HandleDefenseProtection(target, ref damage, true, true); target.TakeDamage(tAction.Damage = damage, attacker); target.Aggro(attacker); if (target.IsDead) { tAction.Options |= TargetOptions.FinishingKnockDown; } aAction.Stun = StunTime; tAction.Stun = StunTime; target.Stability = Creature.MinStability; attacker.Shove(target, KnockbackDistance); // Update both weapons SkillHelper.UpdateWeapon(attacker, target, attacker.RightHand, attacker.LeftHand); Send.SkillUseStun(attacker, skill.Info.Id, StunTime, 1); this.Training(aAction, tAction); cap.Handle(); }
/// <summary> /// Handles explosion. /// </summary> /// <param name="attacker"></param> /// <param name="skill"></param> /// <param name="fireballProp"></param> private void Impact(Creature attacker, Skill skill, Prop fireballProp) { var regionId = attacker.RegionId; var propPos = fireballProp.GetPosition(); var targetLocation = new Location(regionId, propPos); var targets = attacker.GetTargetableCreaturesAround(propPos, ExplosionRadius); var aAction = new AttackerAction(CombatActionType.SpecialHit, attacker, targetLocation.ToLocationId(), skill.Info.Id); aAction.Set(AttackerOptions.UseEffect); aAction.PropId = fireballProp.EntityId; var cap = new CombatActionPack(attacker, skill.Info.Id, aAction); foreach (var target in targets) { target.StopMove(); var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Info.Id); tAction.Set(TargetOptions.Result | TargetOptions.KnockDown); tAction.Stun = TargetStun; tAction.Delay = 200; tAction.EffectFlags = EffectFlags.SpecialRangeHit; cap.Add(tAction); // Damage var damage = this.GetDamage(attacker, skill); // Elements damage *= this.GetElementalDamageMultiplier(attacker, target); // Critical Hit var critChance = attacker.GetTotalCritChance(target.Protection, true); CriticalHit.Handle(attacker, critChance, ref damage, tAction); // Reduce damage SkillHelper.HandleMagicDefenseProtection(target, ref damage); SkillHelper.HandleConditions(attacker, target, ref damage); ManaShield.Handle(target, ref damage, tAction); ManaDeflector.Handle(attacker, target, ref damage, tAction); // Deal damage if (damage > 0) target.TakeDamage(tAction.Damage = damage, attacker); target.Aggro(attacker); // Knockback target.Stability = Creature.MinStability; target.GetShoved(fireballProp, KnockbackDistance); if (target.IsDead) tAction.Set(TargetOptions.FinishingKnockDown); this.Train(skill, tAction); } cap.Handle(); }
public ActionViewModel( TargetAction config, TargetInfoModel model) { this.config = config ?? Settings.Instance.TargetAction; this.model = model ?? TargetInfoModel.Instance; this.Initialize(); }
/// <summary> /// Called when creature is hit while Firebolt is active. /// </summary> /// <param name="creature"></param> /// <param name="tAction"></param> public override void CustomHitCancel(Creature creature, TargetAction tAction) { // Lose no stacks on r1 var skill = creature.Skills.ActiveSkill; if (skill.Info.Rank < SkillRank.R1) { creature.Skills.CancelActiveSkill(); return; } }
public static void Identify(TargetAction action) { ServerTargetHandler targetHandler = Engine.TargetHandler as ServerTargetHandler; if (((targetHandler != null) && ((targetHandler.Creation + MarginOfError) > DateTime.Now)) && (targetHandler.Flags == GetFlags(action))) { targetHandler.Action = action; } m_Lookahead = TargetAction.Unknown; }
/// <summary> /// Bolt specific use code. /// </summary> /// <param name="attacker"></param> /// <param name="skill"></param> /// <param name="target"></param> protected override void UseSkillOnTarget(Creature attacker, Skill skill, Creature target) { attacker.StopMove(); target.StopMove(); // Create actions var aAction = new AttackerAction(CombatActionType.RangeHit, attacker, target.EntityId); aAction.Set(AttackerOptions.Result); var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Info.Id); tAction.Set(TargetOptions.Result); tAction.Stun = TargetStun; var cap = new CombatActionPack(attacker, skill.Info.Id, aAction, tAction); // Damage var damage = this.GetDamage(attacker, skill); // Elements damage *= this.GetElementalDamageMultiplier(attacker, target); // Reduce damage SkillHelper.HandleMagicDefenseProtection(target, ref damage); ManaShield.Handle(target, ref damage, tAction); ManaDeflector.Handle(attacker, target, ref damage, tAction); // Deal damage if (damage > 0) target.TakeDamage(tAction.Damage = damage, attacker); target.Aggro(attacker); // Knock down on deadly if (target.Conditions.Has(ConditionsA.Deadly)) { tAction.Set(TargetOptions.KnockDown); tAction.Stun = TargetStun; } // Death/Knockback attacker.Shove(target, KnockbackDistance); if (target.IsDead) tAction.Set(TargetOptions.FinishingKnockDown); else tAction.Set(TargetOptions.KnockDown); // Override stun set by defense aAction.Stun = AttackerStun; Send.Effect(attacker, Effect.UseMagic, EffectSkillName); Send.SkillUseStun(attacker, skill.Info.Id, aAction.Stun, 1); skill.Stacks = 0; cap.Handle(); }
/// <summary> /// Training, called when someone attacks something. /// </summary> /// <param name="action"></param> public void OnCreatureAttackedByPlayer(TargetAction action) { // Check if skill used is LightningRod if (action.AttackerSkillId != SkillId.LightningRod) { return; } // Get skill var attackerSkill = action.Attacker.Skills.Get(SkillId.LightningRod); if (attackerSkill == null) { return; // Should be impossible. } // Learning by attacking switch (attackerSkill.Info.Rank) { case SkillRank.RF: case SkillRank.RE: attackerSkill.Train(2); // Attack an enemy break; case SkillRank.RD: case SkillRank.RC: attackerSkill.Train(2); // Attack an enemy if (action.Attacker.Temp.LightningRodFullCharge) { attackerSkill.Train(3); // Attack an Enemy with a Max Charge } break; case SkillRank.RB: case SkillRank.RA: case SkillRank.R9: case SkillRank.R8: case SkillRank.R7: case SkillRank.R6: case SkillRank.R5: case SkillRank.R4: case SkillRank.R3: case SkillRank.R2: case SkillRank.R1: if (action.Creature.IsDead) { attackerSkill.Train(2); // Defeat an enemy } if (action.Creature.IsDead && action.Attacker.Temp.LightningRodFullCharge) { attackerSkill.Train(3); // Defeat an Enemy with a Max Charge } break; } }
/// <summary> /// Called when creature is hit while Healing is active. /// </summary> /// <param name="creature"></param> /// <param name="tAction"></param> public void CustomHitCancel(Creature creature, TargetAction tAction) { // Lose only 2 stacks if r1 var skill = creature.Skills.ActiveSkill; if (skill.Info.Rank < SkillRank.R1 || skill.Stacks <= 2) { creature.Skills.CancelActiveSkill(); return; } skill.Stacks -= 2; Send.Effect(creature, Effect.StackUpdate, "healing_stack", (byte)skill.Stacks, (byte)0); }
public override SkillResults Start(MabiCreature creature, MabiSkill skill) { creature.Activate(CreatureConditionB.Demigod); creature.StopMove(); // Spawn eruption { var pos = creature.GetPosition(); var targets = WorldManager.Instance.GetAttackableCreaturesInRange(creature, EruptionRadius); var cap = new CombatActionPack(creature, skill.Id); var aAction = new AttackerAction(CombatActionType.SpecialHit, creature, skill.Id, SkillHelper.GetAreaTargetID(creature.Region, pos.X, pos.Y)); aAction.Options |= AttackerOptions.KnockBackHit1 | AttackerOptions.UseEffect; cap.Add(aAction); foreach (var target in targets) { target.StopMove(); // Officials use CM skill id. var tAction = new TargetAction(CombatActionType.TakeHit, target, creature, skill.Id); tAction.StunTime = EruptionStun; tAction.Delay = 1000; // Supposedly it's magic damage tAction.Damage = creature.GetMagicDamage(null, EruptionDamage); target.TakeDamage(tAction.Damage); tAction.OldPosition = CombatHelper.KnockBack(target, creature, EruptionKnockBack); if (target.IsDead) tAction.Options |= TargetOptions.FinishingKnockDown; cap.Add(tAction); } WorldManager.Instance.HandleCombatActionPack(cap); } Send.EffectDelayed(Effect.AwakeningOfLight1, 800, creature); Send.EffectDelayed(Effect.AwakeningOfLight2, 800, creature); Send.UseMotion(creature, 67, 3, false, false); creature.StatRegens.Add(creature.Temp.DemiHpRegen = new MabiStatRegen(Stat.Life, skill.RankInfo.Var3, creature.LifeMax)); creature.StatRegens.Add(creature.Temp.DemiMpRegen = new MabiStatRegen(Stat.Mana, skill.RankInfo.Var4, creature.ManaMax)); creature.StatRegens.Add(creature.Temp.DemiStmRegen = new MabiStatRegen(Stat.Stamina, skill.RankInfo.Var5, creature.StaminaMax)); WorldManager.Instance.CreatureStatsUpdate(creature); return SkillResults.Okay; }
/// <summary> /// Checks if target's Mana Shield is active, calculates mana /// damage, and sets target action's Mana Damage property if applicable. /// </summary> /// <param name="target"></param> /// <param name="damage"></param> /// <param name="tAction"></param> public static void Handle(Creature target, ref float damage, TargetAction tAction, float maxDamage, bool magic = false, bool killWhileDeadly = true) { // Mana Shield active? if (!target.Conditions.Has(ConditionsA.ManaShield)) return; // Get Mana Shield skill to get the rank's vars var manaShield = target.Skills.Get(SkillId.ManaShield); if (manaShield == null) // Checks for things that should never ever happen, yay. return; // Var 1 = Efficiency var manaDamage = 0f; if (magic) { manaDamage = maxDamage / manaShield.RankData.Var1; SkillHelper.HandleMagicDefenseProtection(target, ref manaDamage, false, true); } else { manaDamage = (maxDamage - (target.LeftHand != null ? target.LeftHand.Data.DefenseBonusMeleePassive : 0)) / manaShield.RankData.Var1; } if (target.Mana >= manaDamage) { // Damage is 0 if target's mana is enough to cover it damage = 0; } else { // Set mana damage to target's mana and reduce the remaining // damage from life if the mana is not enough. manaDamage = target.Mana; damage = Math.Max(1f, damage - manaDamage); } if (damage <= 0 && target.Life <= 0 && killWhileDeadly) { damage = 1; } // Reduce mana target.Mana -= manaDamage; if (target.Mana <= 0) ChannelServer.Instance.SkillManager.GetHandler<StartStopSkillHandler>(SkillId.ManaShield).Stop(target, manaShield); tAction.ManaDamage = manaDamage; }
/// <summary> /// Checks if attacker has Critical Hit and applies crit bonus /// by chance. Also sets the target action's critical option if a /// crit happens. /// </summary> /// <param name="attacker"></param> /// <param name="critChance"></param> /// <param name="damage"></param> /// <param name="tAction"></param> public static void Handle(Creature attacker, float critChance, ref float damage, TargetAction tAction, bool bypassNoviceCheck = false) { // Check if attacker actually has critical hit var critSkill = attacker.Skills.Get(SkillId.CriticalHit); if (critSkill == null || (critSkill.Info.Rank == SkillRank.Novice && !bypassNoviceCheck)) return; // Cancel if crit doesn't happen if (RandomProvider.Get().Next(100) >= critChance) return; // Add crit bonus var bonus = critSkill.RankData.Var1 / 100f; damage = damage + (damage * bonus); // Set target option tAction.Set(TargetOptions.Critical); }
/// <summary> /// Training, called when someone attacks something. /// </summary> /// <param name="tAction"></param> public void OnCreatureAttackedByPlayer(TargetAction tAction) { // Only train if used skill was Smash if (tAction.AttackerSkillId != SkillId.Smash) return; // Get skill var attackerSkill = tAction.Attacker.Skills.Get(SkillId.Smash); if (attackerSkill == null) return; // Should be impossible. // Learning by attacking switch (attackerSkill.Info.Rank) { case SkillRank.RF: case SkillRank.RE: attackerSkill.Train(1); // Use the skill successfully. if (tAction.Has(TargetOptions.Critical)) attackerSkill.Train(2); // Critical Hit with Smash. if (tAction.Creature.IsDead) attackerSkill.Train(3); // Finishing blow with Smash. break; case SkillRank.RD: case SkillRank.RC: case SkillRank.RB: case SkillRank.RA: case SkillRank.R9: case SkillRank.R8: case SkillRank.R7: if (tAction.Has(TargetOptions.Critical) && tAction.Creature.IsDead) attackerSkill.Train(4); // Finishing blow with Critical Hit. goto case SkillRank.RF; case SkillRank.R6: case SkillRank.R5: case SkillRank.R4: case SkillRank.R3: case SkillRank.R2: case SkillRank.R1: if (tAction.Has(TargetOptions.Critical)) attackerSkill.Train(1); // Critical Hit with Smash. if (tAction.Creature.IsDead) attackerSkill.Train(2); // Finishing blow with Smash. if (tAction.Has(TargetOptions.Critical) && tAction.Creature.IsDead) attackerSkill.Train(3); // Finishing blow with Critical Hit. break; } }
/// <summary> /// Checks if target has Defense skill activated and makes the necessary /// changes to the actions, stun times, and damage. /// </summary> /// <param name="aAction"></param> /// <param name="tAction"></param> /// <param name="damage"></param> /// <returns></returns> public static bool Handle(AttackerAction aAction, TargetAction tAction, ref float damage) { var defendingCreature = tAction.Creature; var activeSkill = defendingCreature.Skills.ActiveSkill; if (activeSkill == null || activeSkill.Info.Id != SkillId.Defense || activeSkill.State != SkillState.Ready) return false; activeSkill.State = SkillState.Used; // Update actions tAction.Flags = CombatActionType.Defended; tAction.Stun = DefenseTargetStun; aAction.Stun = DefenseAttackerStun; // Reduce damage damage = Math.Max(1, damage - activeSkill.RankData.Var3); // Proficiency var shield = defendingCreature.LeftHand; if (shield != null && shield.IsShield && shield.Durability != 0) { var amount = Item.GetProficiencyGain(defendingCreature.Age, ProficiencyGainType.Defend); defendingCreature.Inventory.AddProficiency(shield, amount); } // Updating unlock because of the updating lock for pre-renovation // Other skills actually unlock automatically on the client, // I guess this isn't the case for Defense because it's never // *explicitly* used. if (!AuraData.FeaturesDb.IsEnabled("TalentRenovationCloseCombat")) defendingCreature.Unlock(Locks.Run, true); Send.SkillUseStun(defendingCreature, SkillId.Defense, DefenseTargetStun, 0); return true; }
/// <summary> /// Handles training based on what happened in the combat action. /// </summary> /// <param name="tAction"></param> private void OnCreatureAttack(TargetAction tAction) { if (!tAction.Has(TargetOptions.Critical)) return; var attackerSkill = tAction.Attacker.Skills.Get(SkillId.CriticalHit); var targetSkill = tAction.Creature.Skills.Get(SkillId.CriticalHit); if (attackerSkill.Info.Rank == SkillRank.Novice) { if (tAction.Is(CombatActionType.CounteredHit2)) attackerSkill.Train(1); // Novice -> RF } else { attackerSkill.Train(1); // Land a critical hit. if (tAction.Creature.IsDead) attackerSkill.Train(3); // Finish off with critical hit. } if (targetSkill != null && targetSkill.Info.Rank >= SkillRank.RF) attackerSkill.Train(2); // Learn from enemy's critical hit. }
/// <summary> /// Handles attack training. /// </summary> /// <param name="tAction"></param> private void OnCreatureAttackedByPlayer(TargetAction tAction) { var target = tAction.Creature; var attacker = tAction.Attacker; var isBoltMagic = (tAction.AttackerSkillId == SkillId.Icebolt || tAction.AttackerSkillId == SkillId.Firebolt || tAction.AttackerSkillId == SkillId.Lightningbolt); var isAdvMagic = (tAction.AttackerSkillId == SkillId.Thunder || tAction.AttackerSkillId == SkillId.Fireball || tAction.AttackerSkillId == SkillId.IceSpear || tAction.AttackerSkillId == SkillId.Blaze); if (!isBoltMagic && !isAdvMagic) return; var attackerSkill = attacker.Skills.Get(SkillId.MagicMastery); if (attackerSkill == null) return; var rating = attacker.GetPowerRating(tAction.Creature); if (attackerSkill.Info.Rank == SkillRank.Novice) { if (isBoltMagic) attackerSkill.Train(1); // Attack any monster with bolt magic. } else if (attackerSkill.Info.Rank >= SkillRank.RF && attackerSkill.Info.Rank <= SkillRank.RD) { if (isBoltMagic) { attackerSkill.Train(1); // Attack any monster with bolt magic. if (tAction.IsKnockBack) attackerSkill.Train(2); // Knock back a monster with bolt magic. if (target.IsDead) attackerSkill.Train(3); // Kill a monster with bolt magic. } } else if (attackerSkill.Info.Rank >= SkillRank.RC && attackerSkill.Info.Rank <= SkillRank.RB) { if (isBoltMagic && rating == PowerRating.Normal) { attackerSkill.Train(1); // Attack any monster of equal level with bolt magic. if (target.IsDead) attackerSkill.Train(2); // Kill a monster of equal level with bolt magic. } } else if (attackerSkill.Info.Rank >= SkillRank.RA && attackerSkill.Info.Rank <= SkillRank.R9) { if (isBoltMagic && rating == PowerRating.Strong) { attackerSkill.Train(1); // Attack a Strong monster with bolt magic. if (target.IsDead) attackerSkill.Train(2); // Kill a Strong monster with bolt magic. } } else if (attackerSkill.Info.Rank >= SkillRank.R8 && attackerSkill.Info.Rank <= SkillRank.R7) { if (isBoltMagic && rating == PowerRating.Awful) { attackerSkill.Train(1); // Attack an Awful monster with bolt magic. if (target.IsDead) attackerSkill.Train(2); // Kill an Awful monster with bolt magic. } } else if (attackerSkill.Info.Rank >= SkillRank.R6 && attackerSkill.Info.Rank <= SkillRank.R6) { if (isBoltMagic && rating == PowerRating.Boss) { attackerSkill.Train(1); // Attack a Boss monster with bolt magic. if (target.IsDead) attackerSkill.Train(2); // Kill a Boss monster with bolt magic. } } else if (attackerSkill.Info.Rank >= SkillRank.R5 && attackerSkill.Info.Rank <= SkillRank.R4) { if (isBoltMagic && rating == PowerRating.Boss) { attackerSkill.Train(1); // Attack a Boss monster with bolt magic. if (target.IsDead) attackerSkill.Train(2); // Kill a Boss monster with bolt magic. } if (rating == PowerRating.Strong && target.IsDead) { switch (attackerSkill.Info.Id) { case SkillId.Thunder: attackerSkill.Train(3); break; // Kill a Strong monster with Thunder. case SkillId.Fireball: attackerSkill.Train(4); break; // Kill a Strong monster with Fireball. case SkillId.IceSpear: if (!attacker.IsGiant) attackerSkill.Train(5); break; // Kill a Strong monster with Ice Spear. case SkillId.Blaze: if (!attacker.IsGiant) attackerSkill.Train(6); break; // Kill a Strong monster with Blaze. } } } else if (attackerSkill.Info.Rank == SkillRank.R3) { if (isBoltMagic && rating == PowerRating.Boss) { attackerSkill.Train(1); // Attack a Boss monster with bolt magic. if (target.IsDead) attackerSkill.Train(2); // Kill a Boss monster with bolt magic. } if (rating == PowerRating.Awful && target.IsDead) { switch (attackerSkill.Info.Id) { case SkillId.Thunder: attackerSkill.Train(3); break; // Kill an Awful monster with Thunder. case SkillId.Fireball: attackerSkill.Train(4); break; // Kill an Awful monster with Fireball. case SkillId.IceSpear: if (!attacker.IsGiant) attackerSkill.Train(5); break; // Kill an Awful monster with Ice Spear. case SkillId.Blaze: if (!attacker.IsGiant) attackerSkill.Train(6); break; // Kill an Awful monster with Blaze. } } } else if (attackerSkill.Info.Rank >= SkillRank.R2 && attackerSkill.Info.Rank <= SkillRank.R1) { if (isBoltMagic && rating == PowerRating.Boss) { attackerSkill.Train(1); // Attack a Boss monster with bolt magic. if (target.IsDead) attackerSkill.Train(2); // Kill a Boss monster with bolt magic. } if (rating == PowerRating.Boss && target.IsDead) { switch (attackerSkill.Info.Id) { case SkillId.Thunder: attackerSkill.Train(3); break; // Kill a Boss monster with Thunder. case SkillId.Fireball: attackerSkill.Train(4); break; // Kill a Boss monster with Fireball. case SkillId.IceSpear: if (!attacker.IsGiant) attackerSkill.Train(5); break; // Kill a Boss monster with Ice Spear. case SkillId.Blaze: if (!attacker.IsGiant) attackerSkill.Train(6); break; // Kill a Boss monster with Blaze. } } } }
/// <summary> /// Bolt specific use code. /// </summary> /// <param name="attacker"></param> /// <param name="skill"></param> /// <param name="target"></param> protected override void UseSkillOnTarget(Creature attacker, Skill skill, Creature mainTarget) { // Create actions var aAction = new AttackerAction(CombatActionType.RangeHit, attacker, mainTarget.EntityId); aAction.Set(AttackerOptions.Result); var cap = new CombatActionPack(attacker, skill.Info.Id, aAction); // Get targets // Add the main target as first target, so it gets the first hit, // and the full damage. var targets = new List<Creature>(); targets.Add(mainTarget); var inSplashRange = attacker.GetTargetableCreaturesAround(mainTarget.GetPosition(), SplashRange); targets.AddRange(inSplashRange.Where(a => a != mainTarget)); // Damage var damage = this.GetDamage(attacker, skill); var max = Math.Min(targets.Count, skill.Stacks); for (int i = 0; i < max; ++i) { var target = targets[i]; var targetDamage = damage; target.StopMove(); var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Info.Id); tAction.Set(TargetOptions.Result); tAction.Stun = TargetStun; // Full damage for the first target, -10% for every subsequent one. targetDamage -= (targetDamage * 0.1f) * i; // Critical Hit var critChance = attacker.GetTotalCritChance(target.Protection, true); CriticalHit.Handle(attacker, critChance, ref damage, tAction); // Reduce damage Defense.Handle(aAction, tAction, ref targetDamage); SkillHelper.HandleMagicDefenseProtection(target, ref targetDamage); SkillHelper.HandleConditions(attacker, target, ref damage); ManaShield.Handle(target, ref targetDamage, tAction); // Mana Deflector var mdResult = ManaDeflector.Handle(attacker, target, ref targetDamage, tAction); var delayReduction = mdResult.DelayReduction; var pinged = mdResult.Pinged; // Deal damage if (targetDamage > 0) target.TakeDamage(tAction.Damage = targetDamage, attacker); if (target == mainTarget) target.Aggro(attacker); // Reduce stun, based on ping if (pinged && delayReduction > 0) tAction.Stun = (short)Math.Max(0, tAction.Stun - (tAction.Stun / 100 * delayReduction)); // Death/Knockback if (target.IsDead) { tAction.Set(TargetOptions.FinishingKnockDown); } else { // If knocked down, instant recovery, // if repeat hit, knock down, // otherwise potential knock back. if (target.IsKnockedDown) { tAction.Stun = 0; } else if (target.Stability < MinStability) { tAction.Set(TargetOptions.KnockDown); } else { // If number of stacks is greater than the number of // targets hit, the targets are knocked back, which is // done by reducing the stability to min here. // Targets with high enough Mana Deflector might // negate this knock back, by reducing the stability // reduction to 0. var stabilityReduction = (skill.Stacks > targets.Count ? OverchargeStabilityReduction : StabilityReduction); // Reduce reduction, based on ping // While the Wiki says that "the Knockdown Gauge [does not] // build up", tests show that it does. However, it's // reduced, assumedly based on the MD rank. if (delayReduction > 0) stabilityReduction = (short)Math.Max(0, stabilityReduction - (stabilityReduction / 100 * delayReduction)); target.Stability -= stabilityReduction; if (target.IsUnstable) { tAction.Set(TargetOptions.KnockBack); } } } if (tAction.IsKnockBack) attacker.Shove(target, KnockbackDistance); cap.Add(tAction); } // Override stun set by defense aAction.Stun = AttackerStun; Send.Effect(attacker, Effect.UseMagic, EffectSkillName); Send.SkillUseStun(attacker, skill.Info.Id, aAction.Stun, 1); skill.Stacks = 0; // Update current weapon SkillHelper.UpdateWeapon(attacker, targets.FirstOrDefault(), ProficiencyGainType.Melee, attacker.RightHand); cap.Handle(); }
/// <summary> /// Uses the skill. /// </summary> /// <param name="attacker"></param> /// <param name="skill"></param> /// <param name="targetEntityId"></param> /// <returns></returns> public CombatSkillResult Use(Creature attacker, Skill skill, long targetEntityId) { // Get target var target = attacker.Region.GetCreature(targetEntityId); if (target == null) return CombatSkillResult.InvalidTarget; // "Cancels" the skill // 800 = old load time? == aAction.Stun? Varies? Doesn't seem to be a stun. Send.SkillUse(attacker, skill.Info.Id, AttackerStun, 1); var chance = attacker.AimMeter.GetAimChance(target); var rnd = RandomProvider.Get().NextDouble() * 100; var successfulHit = (rnd < chance); // Actions var cap = new CombatActionPack(attacker, skill.Info.Id); var aAction = new AttackerAction(CombatActionType.RangeHit, attacker, targetEntityId); aAction.Set(AttackerOptions.Result); aAction.Stun = AttackerStun; cap.Add(aAction); // Target action if hit if (successfulHit) { target.StopMove(); var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Info.Id); tAction.Set(TargetOptions.Result); tAction.Stun = TargetStun; cap.Add(tAction); // Damage var damage = attacker.GetRndRangedDamage() * (skill.RankData.Var1 / 100f); // Elementals damage *= attacker.CalculateElementalDamageMultiplier(target); // More damage with fire arrow if (attacker.Temp.FireArrow) damage *= FireBonus; // Critical Hit var critChance = attacker.GetRightCritChance(target.Protection); CriticalHit.Handle(attacker, critChance, ref damage, tAction); // Subtract target def/prot SkillHelper.HandleDefenseProtection(target, ref damage); // Defense Defense.Handle(aAction, tAction, ref damage); // Mana Shield ManaShield.Handle(target, ref damage, tAction); // Natural Shield var delayReduction = NaturalShield.Handle(attacker, target, ref damage, tAction); // Deal with it! if (damage > 0) { target.TakeDamage(tAction.Damage = damage, attacker); SkillHelper.HandleInjury(attacker, target, damage); } // Aggro target.Aggro(attacker); // Knock down on deadly if (target.Conditions.Has(ConditionsA.Deadly)) tAction.Set(TargetOptions.KnockDown); // Death/Knockback if (target.IsDead) tAction.Set(TargetOptions.FinishingKnockDown); // Knock Back if (tAction.IsKnockBack) attacker.Shove(target, KnockBackDistance); // Reduce stun, based on ping if (delayReduction > 0) tAction.Stun = (short)Math.Max(0, tAction.Stun - (tAction.Stun / 100 * delayReduction)); // TODO: "Weakened" state (G12S2 gfSupportShotRenewal) } // Reduce arrows if (attacker.Magazine != null && !ChannelServer.Instance.Conf.World.InfiniteArrows && !attacker.Magazine.HasTag("/unlimited_arrow/")) attacker.Inventory.Decrement(attacker.Magazine); cap.Handle(); // Disable fire arrow effect if (attacker.Temp.FireArrow) Send.Effect(attacker, Effect.FireArrow, false); return CombatSkillResult.Okay; }
/// <summary> /// Handles skill usage. /// </summary> /// <param name="attacker"></param> /// <param name="skill"></param> /// <param name="packet"></param> public void Use(Creature attacker, Skill skill, Packet packet) { var targetAreaEntityId = packet.GetLong(); Send.Effect(attacker, 5, (byte)1, targetAreaEntityId); var cap = new CombatActionPack(attacker, skill.Info.Id); var aAction = new AttackerAction(CombatActionType.Attacker, attacker, skill.Info.Id, targetAreaEntityId); aAction.Options |= AttackerOptions.Result; aAction.Stun = UseStun; cap.Add(aAction); var attackerPosition = attacker.GetPosition(); // Calculate rectangular target area var targetAreaPos = new Position(targetAreaEntityId); var poe = targetAreaPos.GetRelative(attackerPosition, -800); var r = (Math.PI / 2) + Math.Atan2(attackerPosition.Y - targetAreaPos.Y, attackerPosition.X - targetAreaPos.X); var pivot = new Point(poe.X, poe.Y); var p1 = new Point(pivot.X - LaserRectWidth / 2, pivot.Y - LaserRectHeight / 2); var p2 = new Point(pivot.X - LaserRectWidth / 2, pivot.Y + LaserRectHeight / 2); var p3 = new Point(pivot.X + LaserRectWidth / 2, pivot.Y + LaserRectHeight / 2); var p4 = new Point(pivot.X + LaserRectWidth / 2, pivot.Y - LaserRectHeight / 2); p1 = this.RotatePoint(p1, pivot, r); p2 = this.RotatePoint(p2, pivot, r); p3 = this.RotatePoint(p3, pivot, r); p4 = this.RotatePoint(p4, pivot, r); // Attack targets var targets = attacker.Region.GetCreaturesInPolygon(p1, p2, p3, p4); foreach (var target in targets.Where(cr => !cr.IsDead && !cr.Has(CreatureStates.NamedNpc))) { var targetPosition = target.GetPosition(); var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Info.Id); tAction.Options = TargetOptions.Result | TargetOptions.KnockDown; tAction.Stun = TargetStun; tAction.Delay = 1200; cap.Add(tAction); // Var2: 300/1000, based on rank. Could be damage? var damage = skill.RankData.Var2; // Increase damage CriticalHit.Handle(attacker, attacker.GetTotalCritChance(target.Protection), ref damage, tAction); // Reduce damage SkillHelper.HandleDefenseProtection(target, ref damage); ManaShield.Handle(target, ref damage, tAction); // Apply damage target.TakeDamage(tAction.Damage = 300, attacker); target.Stability = Creature.MinStability; // Aggro target.Aggro(attacker); // Check death if (target.IsDead) tAction.Options |= TargetOptions.FinishingKnockDown; // Knock back attacker.Shove(target, KnockbackDistance); } cap.Handle(); Send.SkillUse(attacker, skill.Info.Id, 0); }
/// <summary> /// Uses LightningRod /// </summary> /// <param name="attacker"></param> /// <param name="skill"></param> /// <param name="packet"></param> public void Use(Creature attacker, Skill skill, Packet packet) { // Set full charge variable attacker.Temp.LightningRodFullCharge = (DateTime.Now >= attacker.Temp.LightningRodPrepareTime.AddMilliseconds(skill.RankData.Var3)); // Get direction for target Area var direction = Mabi.MabiMath.ByteToRadian(attacker.Direction); var attackerPos = attacker.GetPosition(); // Calculate polygon points var r = MabiMath.ByteToRadian(attacker.Direction); var poe = attackerPos.GetRelative(r, 800); var pivot = new Point(poe.X, poe.Y); var p1 = new Point(pivot.X - SkillLength / 2, pivot.Y - SkillWidth / 2); var p2 = new Point(pivot.X - SkillLength / 2, pivot.Y + SkillWidth / 2); var p3 = new Point(pivot.X + SkillLength / 2, pivot.Y + SkillWidth / 2); var p4 = new Point(pivot.X + SkillLength / 2, pivot.Y - SkillWidth / 2); p1 = this.RotatePoint(p1, pivot, r); p2 = this.RotatePoint(p2, pivot, r); p3 = this.RotatePoint(p3, pivot, r); p4 = this.RotatePoint(p4, pivot, r); // TargetProp var lProp = new Prop(280, attacker.RegionId, poe.X, poe.Y, MabiMath.ByteToRadian(attacker.Direction), 1f, 0f, "single"); attacker.Region.AddProp(lProp); // Prepare Combat Actions var cap = new CombatActionPack(attacker, skill.Info.Id); var targetAreaId = new Location(attacker.RegionId, poe).ToLocationId(); var aAction = new AttackerAction(CombatActionType.SpecialHit, attacker, targetAreaId); aAction.Set(AttackerOptions.KnockBackHit1 | AttackerOptions.UseEffect); aAction.PropId = lProp.EntityId; cap.Add(aAction); // Get targets in Polygon - includes collission check var targets = attacker.Region.GetCreaturesInPolygon(p1, p2, p3, p4).Where(x => attacker.CanTarget(x) && !attacker.Region.Collisions.Any(attacker.GetPosition(), x.GetPosition())).ToList(); var rnd = RandomProvider.Get(); // Check crit var crit = false; var critSkill = attacker.Skills.Get(SkillId.CriticalHit); if (critSkill != null && critSkill.Info.Rank > SkillRank.Novice) { var critChance = Math2.Clamp(0, 30, attacker.GetTotalCritChance(0)); if (rnd.NextDouble() * 100 < critChance) crit = true; } foreach (var target in targets) { var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, SkillId.CombatMastery); tAction.Set(TargetOptions.None); tAction.AttackerSkillId = skill.Info.Id; cap.Add(tAction); var damage = attacker.GetRndMagicDamage(skill, skill.RankData.Var1, skill.RankData.Var2); // Add damage if the skill is fully charged var dmgMultiplier = skill.RankData.Var4 / 100f; if (attacker.Temp.LightningRodFullCharge) { damage += (damage * dmgMultiplier); } // Critical Hit if (crit) { var bonus = critSkill.RankData.Var1 / 100f; damage = damage + (damage * bonus); tAction.Set(TargetOptions.Critical); } // MDef and MProt SkillHelper.HandleMagicDefenseProtection(target, ref damage); // Conditions SkillHelper.HandleConditions(attacker, target, ref damage); // Mana Deflector var delayReduction = ManaDeflector.Handle(attacker, target, ref damage, tAction); // Mana Shield ManaShield.Handle(target, ref damage, tAction); // Apply Damage target.TakeDamage(tAction.Damage = damage, attacker); // Stun Time tAction.Stun = TargetStun; // Death or Knockback if (target.IsDead) { tAction.Set(TargetOptions.FinishingKnockDown); attacker.Shove(target, KnockbackDistance); } else { // Always knock down if (target.Is(RaceStands.KnockDownable)) { tAction.Set(TargetOptions.KnockDown); attacker.Shove(target, KnockbackDistance); } } } // Update current weapon SkillHelper.UpdateWeapon(attacker, targets.FirstOrDefault(), ProficiencyGainType.Melee, attacker.RightHand); cap.Handle(); Send.Effect(attacker, Effect.LightningRod, (int)LightningRodEffect.Attack, poe.X, poe.Y); Send.SkillUse(attacker, skill.Info.Id, targetAreaId, 0, 1); skill.Train(1); // Use the Skill attacker.Region.RemoveProp(lProp); }
/// <summary> /// Handles the skill training. /// </summary> /// <param name="tAction"></param> private void OnCreatureAttacks(TargetAction tAction) { if (tAction.AttackerSkillId != SkillId.SupportShot) return; var skill = tAction.Attacker.Skills.Get(SkillId.SupportShot); if (skill == null) return; var powerRating = tAction.Attacker.GetPowerRating(tAction.Creature); if (skill.Info.Rank >= SkillRank.RF && skill.Info.Rank <= SkillRank.RA) { skill.Train(1); // Successfully use the skill. if (!tAction.IsKnockBack) skill.Train(2); // Successfully use Support Shot without knocking down the enemy. if (tAction.Has(TargetOptions.Critical)) skill.Train(3); // Succeed in a Critical Hit with Support Shot. } else if (skill.Info.Rank == SkillRank.R9) { if (powerRating == PowerRating.Normal) skill.Train(1); // Successfully use the skill on a similarly ranked enemy. if (powerRating == PowerRating.Strong) { skill.Train(2); // Successfully use the skill on a Strong enemy. if (tAction.Has(TargetOptions.Critical)) skill.Train(4); // Succeed in a Critical Hit against a Strong enemy. } if (!tAction.IsKnockBack) skill.Train(3); // Successfully use Support Shot without knocking down the enemy. } else if (skill.Info.Rank >= SkillRank.R8 && skill.Info.Rank <= SkillRank.R4) { if (powerRating == PowerRating.Strong) skill.Train(1); // Successfully use the skill on a Strong enemy. if (powerRating == PowerRating.Awful) { skill.Train(2); // Successfully use the skill on a Awful enemy. if (tAction.Has(TargetOptions.Critical)) skill.Train(4); // Succeed in a Critical Hit against a Awful enemy. } if (!tAction.IsKnockBack) skill.Train(3); // Successfully use Support Shot without knocking down the enemy. } else if (skill.Info.Rank >= SkillRank.R3 && skill.Info.Rank <= SkillRank.R1) { if (powerRating == PowerRating.Awful) skill.Train(1); // Successfully use the skill on a Awful enemy. if (powerRating == PowerRating.Boss) { skill.Train(2); // Successfully use the skill on a Boss enemy. if (tAction.Has(TargetOptions.Critical)) skill.Train(4); // Succeed in a Critical Hit against a Boss enemy. } if (!tAction.IsKnockBack) skill.Train(3); // Successfully use Support Shot without knocking down the enemy. } }
/// <summary> /// Uses the skill. /// </summary> /// <param name="attacker"></param> /// <param name="skill"></param> /// <param name="targetEntityId"></param> /// <returns></returns> public CombatSkillResult Use(Creature attacker, Skill skill, long targetEntityId) { // Get target var target = attacker.Region.GetCreature(targetEntityId); if (target == null) return CombatSkillResult.InvalidTarget; if (target.IsNotReadyToBeHit) return CombatSkillResult.Okay; var targetPos = target.GetPosition(); var attackerPos = attacker.GetPosition(); // Check range //if (!attackerPos.InRange(targetPos, attacker.RightHand.OptionInfo.EffectiveRange + 100)) // return CombatSkillResult.OutOfRange; // Actions var cap = new CombatActionPack(attacker, skill.Info.Id); var aAction = new AttackerAction(CombatActionType.RangeHit, attacker, skill.Info.Id, targetEntityId); aAction.Set(AttackerOptions.Result); aAction.Stun = AttackerStun; cap.Add(aAction); // Hit by chance var chance = attacker.AimMeter.GetAimChance(target); var rnd = RandomProvider.Get(); if (rnd.NextDouble() * 100 < chance) { var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Info.Id); tAction.Set(TargetOptions.Result); tAction.Stun = TargetStun; cap.Add(tAction); // Damage var damage = attacker.GetRndRangedDamage(); // More damage with fire arrow if (attacker.Temp.FireArrow) damage *= FireBonus; // Critical Hit var critShieldReduction = (target.LeftHand != null ? target.LeftHand.Data.DefenseBonusCrit : 0); var critChance = attacker.GetRightCritChance(target.Protection + critShieldReduction); CriticalHit.Handle(attacker, critChance, ref damage, tAction); var maxDamage = damage; //Damage without Defense and Protection // Subtract target def/prot SkillHelper.HandleDefenseProtection(target, ref damage); // Defense Defense.Handle(aAction, tAction, ref damage, true); // Mana Shield ManaShield.Handle(target, ref damage, tAction, maxDamage); // Deal with it! if (damage > 0) target.TakeDamage(tAction.Damage = damage, attacker); // Aggro target.Aggro(attacker); // Death/Knockback if (target.IsDead) { tAction.Set(TargetOptions.FinishingKnockDown); attacker.Shove(target, KnockBackDistance); } else { // Insta-recover in knock down // TODO: Tied to stability? if (target.IsKnockedDown) { tAction.Stun = 0; } // Knock down if hit repeatedly else if (target.Stability < 30) { tAction.Set(TargetOptions.KnockDown); } // Normal stability reduction else { target.Stability -= StabilityReduction; if (target.IsUnstable) { tAction.Set(TargetOptions.KnockBack); attacker.Shove(target, KnockBackDistance); } } } } // Skill training if (skill.Info.Rank == SkillRank.Novice || skill.Info.Rank == SkillRank.RF) skill.Train(1); // Try ranged attack. // Reduce arrows if (attacker.Magazine != null && !ChannelServer.Instance.Conf.World.InfiniteArrows) attacker.Inventory.Decrement(attacker.Magazine); // Disable fire arrow effect if (attacker.Temp.FireArrow) Send.Effect(attacker, Effect.FireArrow, false); // "Cancels" the skill // 800 = old load time? == aAction.Stun? Varies? Doesn't seem to be a stun. Send.SkillUse(attacker, skill.Info.Id, 800, 1); cap.Handle(); return CombatSkillResult.Okay; }
/// <summary> /// Handles the majority of the skill training. /// </summary> /// <param name="obj"></param> private void OnCreatureAttacks(TargetAction tAction) { if (tAction.SkillId != SkillId.RangedAttack) return; var attackerSkill = tAction.Attacker.Skills.Get(SkillId.RangedAttack); var targetSkill = tAction.Creature.Skills.Get(SkillId.RangedAttack); var targetPowerRating = tAction.Attacker.GetPowerRating(tAction.Creature); var attackerPowerRating = tAction.Creature.GetPowerRating(tAction.Attacker); if (attackerSkill != null) { if (attackerSkill.Info.Rank == SkillRank.RF) { attackerSkill.Train(2); // Attack an enemy. if (tAction.Has(TargetOptions.KnockDown)) attackerSkill.Train(3); // Down the enemy with continuous hit. if (tAction.Creature.IsDead) attackerSkill.Train(4); // Kill an enemy. } else if (attackerSkill.Info.Rank == SkillRank.RE) { if (targetPowerRating == PowerRating.Normal) attackerSkill.Train(3); // Attack a same level enemy. if (tAction.Has(TargetOptions.KnockDown)) { attackerSkill.Train(1); // Down the enemy with continuous hit. if (targetPowerRating == PowerRating.Normal) attackerSkill.Train(4); // Down a same level enemy. if (targetPowerRating == PowerRating.Strong) attackerSkill.Train(6); // Down a strong enemy. } if (tAction.Creature.IsDead) { attackerSkill.Train(2); // Kill an enemy. if (targetPowerRating == PowerRating.Normal) attackerSkill.Train(5); // Kill a same level enemy. if (targetPowerRating == PowerRating.Strong) attackerSkill.Train(7); // Kill a strong enemy. } } else if (attackerSkill.Info.Rank == SkillRank.RD) { attackerSkill.Train(1); // Attack any enemy. if (targetPowerRating == PowerRating.Normal) attackerSkill.Train(4); // Attack a same level enemy. if (tAction.Has(TargetOptions.KnockDown)) { attackerSkill.Train(2); // Down the enemy with continuous hit. if (targetPowerRating == PowerRating.Normal) attackerSkill.Train(5); // Down a same level enemy. if (targetPowerRating == PowerRating.Strong) attackerSkill.Train(7); // Down a strong enemy. } if (tAction.Creature.IsDead) { attackerSkill.Train(3); // Kill an enemy. if (targetPowerRating == PowerRating.Normal) attackerSkill.Train(6); // Kill a same level enemy. if (targetPowerRating == PowerRating.Strong) attackerSkill.Train(8); // Kill a strong enemy. } } else if (attackerSkill.Info.Rank >= SkillRank.RC && attackerSkill.Info.Rank <= SkillRank.RB) { if (targetPowerRating == PowerRating.Normal) attackerSkill.Train(1); // Attack a same level enemy. if (tAction.Has(TargetOptions.KnockDown)) { if (targetPowerRating == PowerRating.Normal) attackerSkill.Train(2); // Down a same level enemy. if (targetPowerRating == PowerRating.Strong) attackerSkill.Train(4); // Down a strong enemy. if (targetPowerRating == PowerRating.Awful) attackerSkill.Train(6); // Down an awful enemy. } if (tAction.Creature.IsDead) { if (targetPowerRating == PowerRating.Normal) attackerSkill.Train(3); // Kill a same level enemy. if (targetPowerRating == PowerRating.Strong) attackerSkill.Train(5); // Kill a strong enemy. if (targetPowerRating == PowerRating.Awful) attackerSkill.Train(7); // Kill an awful enemy. } } else if (attackerSkill.Info.Rank >= SkillRank.RA && attackerSkill.Info.Rank <= SkillRank.R8) { if (tAction.Has(TargetOptions.KnockDown)) { if (targetPowerRating == PowerRating.Normal) attackerSkill.Train(1); // Down a same level enemy. if (targetPowerRating == PowerRating.Strong) attackerSkill.Train(3); // Down a strong enemy. if (targetPowerRating == PowerRating.Awful) attackerSkill.Train(5); // Down an awful enemy. if (targetPowerRating == PowerRating.Boss && attackerSkill.Info.Rank == SkillRank.R8) attackerSkill.Train(7); // Down a boss level enemy. } if (tAction.Creature.IsDead) { if (targetPowerRating == PowerRating.Normal) attackerSkill.Train(2); // Kill a same level enemy. if (targetPowerRating == PowerRating.Strong) attackerSkill.Train(4); // Kill a strong enemy. if (targetPowerRating == PowerRating.Awful) attackerSkill.Train(6); // Kill an awful enemy. if (targetPowerRating == PowerRating.Boss && attackerSkill.Info.Rank == SkillRank.R8) attackerSkill.Train(8); // Kill a boss level enemy. } } else if (attackerSkill.Info.Rank >= SkillRank.R7 && attackerSkill.Info.Rank <= SkillRank.R1) { if (tAction.Has(TargetOptions.KnockDown)) { if (targetPowerRating == PowerRating.Strong) attackerSkill.Train(1); // Down a strong enemy. if (targetPowerRating == PowerRating.Awful) attackerSkill.Train(3); // Down an awful enemy. if (targetPowerRating == PowerRating.Boss) attackerSkill.Train(5); // Down a boss level enemy. } if (tAction.Creature.IsDead) { if (targetPowerRating == PowerRating.Strong) attackerSkill.Train(2); // Kill a strong enemy. if (targetPowerRating == PowerRating.Awful) attackerSkill.Train(4); // Kill an awful enemy. if (targetPowerRating == PowerRating.Boss) attackerSkill.Train(6); // Kill a boss level enemy. } } } if (targetSkill != null) { if (targetSkill.Info.Rank == SkillRank.RF) { if (tAction.Has(TargetOptions.KnockDown)) targetSkill.Train(5); // Learn by falling down. if (tAction.Creature.IsDead) targetSkill.Train(6); // Learn through losing. } else if (targetSkill.Info.Rank == SkillRank.RD) { if (attackerPowerRating == PowerRating.Strong) targetSkill.Train(8); // Receive a powerful attack from a powerful enemy. } else if (targetSkill.Info.Rank == SkillRank.R7) { if (attackerPowerRating == PowerRating.Strong) targetSkill.Train(7); // Receive a powerful attack from a powerful enemy. } } }
/// <summary> /// Trains skill based on target action. /// </summary> /// <param name="tAction"></param> /// <param name="attackerSkill"></param> protected virtual void Train(TargetAction tAction, Skill attackerSkill) { var rating = tAction.Attacker.GetPowerRating(tAction.Creature); if (attackerSkill.Info.Rank == SkillRank.RF) { attackerSkill.Train(1); // Attack anything. attackerSkill.Train(2); // Attack an enemy. if (tAction.Has(TargetOptions.KnockDown)) attackerSkill.Train(3); // Knock down an enemy using combo attack. if (tAction.Creature.IsDead) attackerSkill.Train(4); // Defeat an enemy. return; } if (attackerSkill.Info.Rank == SkillRank.RE) { if (tAction.Has(TargetOptions.KnockDown)) attackerSkill.Train(1); // Knock down an enemy using combo attack. if (tAction.Creature.IsDead) attackerSkill.Train(2); // Defeat an enemy. if (rating == PowerRating.Normal) { attackerSkill.Train(3); // Attack a similar-ranked enemy. if (tAction.Has(TargetOptions.KnockDown)) attackerSkill.Train(4); // Knock down a similar-ranked enemy. if (tAction.Creature.IsDead) attackerSkill.Train(5); // Defeat a similar-ranked enemy. } else if (rating == PowerRating.Strong) { if (tAction.Has(TargetOptions.KnockDown)) attackerSkill.Train(6); // Knock down a powerful enemy. if (tAction.Creature.IsDead) attackerSkill.Train(7); // Defeat a powerful enemy. } return; } if (attackerSkill.Info.Rank == SkillRank.RD) { attackerSkill.Train(1); // Defeat an enemy (They probably mean attack?) if (tAction.Has(TargetOptions.KnockDown)) attackerSkill.Train(2); // Knock down an enemy using combo attack. if (tAction.Creature.IsDead) attackerSkill.Train(3); // Defeat an enemy. if (rating == PowerRating.Normal) { attackerSkill.Train(4); // Attack a similar-ranked enemy. if (tAction.Has(TargetOptions.KnockDown)) attackerSkill.Train(5); // Knock down a similar-ranked enemy. if (tAction.Creature.IsDead) attackerSkill.Train(6); // Defeat a similar-ranked enemy. } else if (rating == PowerRating.Strong) { if (tAction.Has(TargetOptions.KnockDown)) attackerSkill.Train(7); // Knock down a powerful enemy. if (tAction.Creature.IsDead) attackerSkill.Train(8); // Defeat a powerful enemy. } return; } if (attackerSkill.Info.Rank >= SkillRank.RC && attackerSkill.Info.Rank <= SkillRank.RB) { if (rating == PowerRating.Normal) { attackerSkill.Train(1); // Attack a similar-ranked enemy. if (tAction.Has(TargetOptions.KnockDown)) attackerSkill.Train(2); // Knock down a similar-ranked enemy. if (tAction.Creature.IsDead) attackerSkill.Train(3); // Defeat a similar-ranked enemy. } else if (rating == PowerRating.Strong) { if (tAction.Has(TargetOptions.KnockDown)) attackerSkill.Train(4); // Knock down a powerful enemy. if (tAction.Creature.IsDead) attackerSkill.Train(5); // Defeat a powerful enemy. } else if (rating == PowerRating.Awful) { if (tAction.Has(TargetOptions.KnockDown)) attackerSkill.Train(6); // Knock down a very powerful enemy. if (tAction.Creature.IsDead) attackerSkill.Train(7); // Defeat a very powerful enemy. } return; } if (attackerSkill.Info.Rank >= SkillRank.RA && attackerSkill.Info.Rank <= SkillRank.R9) { if (rating == PowerRating.Normal) { if (tAction.Has(TargetOptions.KnockDown)) attackerSkill.Train(1); // Knock down a similar-ranked enemy. if (tAction.Creature.IsDead) attackerSkill.Train(2); // Defeat a similar-ranked enemy. } else if (rating == PowerRating.Strong) { if (tAction.Has(TargetOptions.KnockDown)) attackerSkill.Train(3); // Knock down a powerful enemy. if (tAction.Creature.IsDead) attackerSkill.Train(4); // Defeat a powerful enemy. } else if (rating == PowerRating.Awful) { if (tAction.Has(TargetOptions.KnockDown)) attackerSkill.Train(5); // Knock down a very powerful enemy. if (tAction.Creature.IsDead) attackerSkill.Train(6); // Defeat a very powerful enemy. } return; } if (attackerSkill.Info.Rank == SkillRank.R8) { if (rating == PowerRating.Normal) { if (tAction.Has(TargetOptions.KnockDown)) attackerSkill.Train(1); // Knock down a similar-ranked enemy. if (tAction.Creature.IsDead) attackerSkill.Train(2); // Defeat a similar-ranked enemy. } else if (rating == PowerRating.Strong) { if (tAction.Has(TargetOptions.KnockDown)) attackerSkill.Train(3); // Knock down a powerful enemy. if (tAction.Creature.IsDead) attackerSkill.Train(4); // Defeat a powerful enemy. } else if (rating == PowerRating.Awful) { if (tAction.Has(TargetOptions.KnockDown)) attackerSkill.Train(5); // Knock down a very powerful enemy. if (tAction.Creature.IsDead) attackerSkill.Train(6); // Defeat a very powerful enemy. } else if (rating == PowerRating.Boss) { if (tAction.Has(TargetOptions.KnockDown)) attackerSkill.Train(7); // Knock down a boss-level enemy. if (tAction.Creature.IsDead) attackerSkill.Train(8); // Defeat a boss-level enemy. } return; } if (attackerSkill.Info.Rank == SkillRank.R7) { if (rating == PowerRating.Normal) { if (tAction.Creature.IsDead) attackerSkill.Train(1); // Defeat a similar-ranked enemy. } else if (rating == PowerRating.Strong) { if (tAction.Has(TargetOptions.KnockDown)) attackerSkill.Train(2); // Knock down a powerful enemy. if (tAction.Creature.IsDead) attackerSkill.Train(3); // Defeat a powerful enemy. } else if (rating == PowerRating.Awful) { if (tAction.Has(TargetOptions.KnockDown)) attackerSkill.Train(4); // Knock down a very powerful enemy. if (tAction.Creature.IsDead) attackerSkill.Train(5); // Defeat a very powerful enemy. } else if (rating == PowerRating.Boss) { if (tAction.Has(TargetOptions.KnockDown)) attackerSkill.Train(6); // Knock down a boss-level enemy. if (tAction.Creature.IsDead) attackerSkill.Train(7); // Defeat a boss-level enemy. } return; } if (attackerSkill.Info.Rank >= SkillRank.R6 && attackerSkill.Info.Rank <= SkillRank.R1) { if (rating == PowerRating.Strong) { if (tAction.Has(TargetOptions.KnockDown)) attackerSkill.Train(1); // Knock down a powerful enemy. if (tAction.Creature.IsDead) attackerSkill.Train(2); // Defeat a powerful enemy. } else if (rating == PowerRating.Awful) { if (tAction.Has(TargetOptions.KnockDown)) attackerSkill.Train(3); // Knock down a very powerful enemy. if (tAction.Creature.IsDead) attackerSkill.Train(4); // Defeat a very powerful enemy. } else if (rating == PowerRating.Boss) { if (tAction.Has(TargetOptions.KnockDown)) attackerSkill.Train(5); // Knock down a boss-level enemy. if (tAction.Creature.IsDead) attackerSkill.Train(6); // Defeat a boss-level enemy. } return; } }
/// <summary> /// Training, called when someone attacks something. /// </summary> /// <param name="action"></param> public void OnCreatureAttackedByPlayer(TargetAction action) { // Check if skill used is LightningRod if (action.AttackerSkillId != SkillId.LightningRod) return; // Get skill var attackerSkill = action.Attacker.Skills.Get(SkillId.LightningRod); if (attackerSkill == null) return; // Should be impossible. // Learning by attacking switch (attackerSkill.Info.Rank) { case SkillRank.RF: case SkillRank.RE: attackerSkill.Train(2); // Attack an enemy break; case SkillRank.RD: case SkillRank.RC: attackerSkill.Train(2); // Attack an enemy if (action.Attacker.Temp.LightningRodFullCharge) attackerSkill.Train(3); // Attack an Enemy with a Max Charge break; case SkillRank.RB: case SkillRank.RA: case SkillRank.R9: case SkillRank.R8: case SkillRank.R7: case SkillRank.R6: case SkillRank.R5: case SkillRank.R4: case SkillRank.R3: case SkillRank.R2: case SkillRank.R1: if (action.Creature.IsDead) attackerSkill.Train(2); // Defeat an enemy if (action.Creature.IsDead && action.Attacker.Temp.LightningRodFullCharge) attackerSkill.Train(3); // Defeat an Enemy with a Max Charge break; } }
/// <summary> /// Handles training. /// </summary> /// <param name="tAction"></param> protected virtual void OnCreatureAttack(TargetAction tAction) { if (tAction.SkillId != this.SkillId) return; var attackerSkill = tAction.Attacker.Skills.Get(tAction.SkillId); if (attackerSkill == null) return; this.Train(tAction, attackerSkill); }
/// <summary> /// Bolt specific use code. /// </summary> /// <param name="attacker"></param> /// <param name="skill"></param> /// <param name="target"></param> protected virtual void UseSkillOnTarget(Creature attacker, Skill skill, Creature target) { target.StopMove(); // Create actions var aAction = new AttackerAction(CombatActionType.RangeHit, attacker, skill.Info.Id, target.EntityId); aAction.Set(AttackerOptions.Result); var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Info.Id); tAction.Set(TargetOptions.Result); tAction.Stun = TargetStun; var cap = new CombatActionPack(attacker, skill.Info.Id, aAction, tAction); // Damage var damage = this.GetDamage(attacker, skill); // Reduce damage if (this.Defendable) Defense.Handle(aAction, tAction, ref damage); SkillHelper.HandleMagicDefenseProtection(target, ref damage); ManaShield.Handle(target, ref damage, tAction); // Deal damage if (damage > 0) target.TakeDamage(tAction.Damage = damage, attacker); target.Aggro(attacker); // Death/Knockback this.HandleKnockBack(attacker, target, tAction); // Override stun set by defense aAction.Stun = AttackerStun; Send.Effect(attacker, Effect.UseMagic, EffectSkillName); Send.SkillUseStun(attacker, skill.Info.Id, aAction.Stun, 1); this.BeforeHandlingPack(attacker, skill); cap.Handle(); }
/// <summary> /// Handles using the skill. /// </summary> /// <param name="attacker"></param> /// <param name="skill"></param> /// <param name="targetAreaId"></param> /// <param name="unkInt1"></param> /// <param name="unkInt2"></param> public void Use(Creature attacker, Skill skill, long targetAreaId, int unkInt1, int unkInt2) { var range = this.GetRange(attacker, skill); var targets = attacker.GetTargetableCreaturesInRange(range, TargetableOptions.AddAttackRange); var rnd = RandomProvider.Get(); // Create actions var cap = new CombatActionPack(attacker, skill.Info.Id); var aAction = new AttackerAction(CombatActionType.Attacker, attacker, targetAreaId); aAction.Set(AttackerOptions.Result); aAction.Stun = AttackerStun; cap.Add(aAction); foreach (var target in targets) { // Check if hit var hitChance = this.GetHitChance(attacker, target, skill); if (rnd.Next(0, 100) > hitChance) continue; target.StopMove(); var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Info.Id); tAction.Set(TargetOptions.Result); tAction.Delay = 300; // Calculate damage var damage = this.GetDamage(attacker, skill); // Elementals damage *= attacker.CalculateElementalDamageMultiplier(target); // Handle skills and reductions CriticalHit.Handle(attacker, attacker.GetTotalCritChance(0), ref damage, tAction); SkillHelper.HandleDefenseProtection(target, ref damage); ManaShield.Handle(target, ref damage, tAction); HeavyStander.Handle(attacker, target, ref damage, tAction); // Clean Hit if not critical if (!tAction.Has(TargetOptions.Critical)) tAction.Set(TargetOptions.CleanHit); // Take damage if any is left if (damage > 0) { target.TakeDamage(tAction.Damage = damage, attacker); SkillHelper.HandleInjury(attacker, target, damage); } // Finish if dead, knock down if not defended if (target.IsDead) tAction.Set(TargetOptions.KnockDownFinish); else tAction.Set(TargetOptions.KnockDown); // Anger Management if (!target.IsDead) target.Aggro(attacker); // Stun & knock down tAction.Stun = CombatMastery.GetTargetStun(attacker.AverageKnockCount, attacker.AverageAttackSpeed, true); target.Stability = Creature.MinStability; // Add action cap.Add(tAction); } Send.UseMotion(attacker, 10, 1); cap.Handle(); Send.SkillUse(attacker, skill.Info.Id, targetAreaId, unkInt1, unkInt2); }
/// <summary> /// Handles Heavy Stander bonuses and auto-defense, reducing damage /// and setting the appropriate options on tAction. Returns whether /// or not Heavy Stander pinged. /// </summary> /// <remarks> /// All active and passive Heavy Standers are checked in sequence, /// followed by the equipment, with the passive damage reduction /// stacking. It's unknown whether this is official, and assumedly /// no monsters have multiple Heavy Stander skills. /// The ping reduction is only applied once, no matter where it /// came from. /// </remarks> /// <param name="attacker"></param> /// <param name="target"></param> /// <param name="damage"></param> /// <param name="tAction"></param> public static bool Handle(Creature attacker, Creature target, ref float damage, TargetAction tAction) { var pinged = false; var rank = DefaultMsgRank; var rnd = RandomProvider.Get(); // Check skills for (int i = 0; i < Skills.Length; ++i) { // Check if skill exists and it's either in use or passive var skill = target.Skills.Get(Skills[i]); if (skill != null && (skill.Info.Id == SkillId.HeavyStanderPassive || skill.Has(SkillFlags.InUse))) { var damageReduction = skill.RankData.Var1; var activationChance = skill.RankData.Var3; // Apply damage reduction if (damageReduction > 0) damage = Math.Max(1, damage - (damage / 100 * damageReduction)); // Apply auto defense if (!pinged && rnd.Next(100) < activationChance) { pinged = true; rank = skill.Info.Rank; } } } // Check equipment if (!pinged) { var equipment = target.Inventory.GetMainEquipment(); for (int i = 0; i < equipment.Length; ++i) { var activationChance = equipment[i].Data.AutoDefenseMelee; // Add upgrades activationChance += equipment[i].MetaData1.GetFloat("IM_MLE") * 100; if (activationChance > 0 && rnd.Next(100) < activationChance) { pinged = true; break; } } } // Notice, flag, and damage reduction if (pinged) { damage = Math.Max(1, damage / 2); tAction.EffectFlags |= EffectFlags.HeavyStander; var msg = ""; if (rank >= SkillRank.Novice && rank <= SkillRank.RA) msg = rnd.Rnd(Lv1Msgs); else if (rank >= SkillRank.R9 && rank <= SkillRank.R5) msg = rnd.Rnd(Lv2Msgs); else if (rank >= SkillRank.R4 && rank <= SkillRank.R1) msg = rnd.Rnd(Lv3Msgs); Send.Notice(attacker, msg); } return pinged; }