public override void OnDie(ActorExt killedBy) { { if (client.Character.Tasks.TryGetValue("ActorCatch", out Task removed)) { removed.Deactivate(); } } if (!client.Character.Status.Dying) { client.Character.Status.Dying = true; DieTask task = new DieTask(client); client.Character.Tasks["DieTask"] = task; task.Activate(); } else { if (client.Character.Tasks.TryRemove("DieTask", out Task removed)) { removed.Deactivate(); } if (client.Character.Tasks.TryRemove("RecoverTask", out removed)) { removed.Deactivate(); } client.Character.Status.Dying = false; client.Character.Status.Recovering = false; } }
private int CalcDamage(SkillArg arg, ActorExt target, out int bonusCount, out int bonusDamage, out uint bonusAdditionID) { int dmgMin = (int)(arg.Caster.Status.AtkMin * arg.Skill.BaseData.MinAtk); int dmgMax = (int)(arg.Caster.Status.AtkMax * arg.Skill.BaseData.MaxAtk); int dmg = Global.Random.Next(dmgMin, dmgMax); float rate = arg.Skill.BaseData.ActivationTimes.Count > 0 ? 1f / arg.Skill.BaseData.ActivationTimes.Count : 1f; dmg = (int)(dmg * rate); bonusCount = 0; bonusDamage = 0; bonusAdditionID = 0; if (!string.IsNullOrEmpty(arg.Skill.BaseData.BonusAddition)) { if (target.Tasks.TryGetValue(arg.Skill.BaseData.BonusAddition, out Task task)) { if (task is SkillHandlers.Common.Additions.BonusAddition addition) { bonusCount = addition.AccumulateCount; bonusDamage = (int)(dmg * (arg.Skill.BaseData.BonusRate * bonusCount)); bonusAdditionID = addition.BonusAdditionID; } task.Deactivate(); } } return(dmg); }
private ActorExt GetCurrentTarget() { ulong[] actors = hateTable.Keys.ToArray(); Map.Map map = MapManager.Instance.GetMap(npc.MapInstanceID); if (map == null) { Deactivate(); return(null); } int hate = int.MinValue; ActorExt found = null; foreach (ulong i in actors) { int val = hateTable[i]; if (val > hate) { found = map.GetActor(i) as ActorExt; if (found == null || found.Status.Stealth) { found = null; continue; } if (found == null || i == npc.ActorID || FactionRelationFactory.Instance[npc.Faction][found.Faction] == Relations.Friendly) { hateTable.TryRemove(i, out val); continue; } hate = val; } } return(found); }
private void ApplyDamage(ActorExt sActor, ActorExt dActor, int damage) { Interlocked.Add(ref dActor.HP, -damage); if (dActor.HP < 0) { Interlocked.Exchange(ref dActor.HP, 0); } }
public Attack(AI ai, ActorNPC self, ActorExt target) { this.ai = ai; this.self = self; this.target = target; map = Map.MapManager.Instance.GetMap(self.MapInstanceID); ai.Period = 400; Init(); }
public List <Skill> GetPossibleSkills(ActorExt target, bool includingSelf = true) { var query = from skill in npc.BaseData.Skill.Values where Skills.SkillManager.Instance.CheckSkillCast(npc, target, npc.Dir, skill) && (includingSelf || skill.BaseData.SkillType == SkillType.Single) orderby skill.BaseData.SkillType == SkillType.Single ? skill.BaseData.CastRangeMax : 55 descending select skill; return(query.ToList()); }
public Frost(SkillArg arg, ActorExt target) : base(target, "Frost", 6400) { this.arg = arg; this.target = target; OnAdditionStart += new StartEventHandler(Frost_OnAdditionStart); OnAdditionEnd += new EndEventHandler(Frost_OnAdditionEnd); }
public ActorFrosen(SkillArg arg, ActorExt target, uint additionID, int damage = 0, int duration = 5000) : base(target, "ActorFrosen", duration) { this.arg = arg; this.target = target; this.additionID = additionID; this.damage = damage; OnAdditionStart += new StartEventHandler(ActorFrosen_OnAdditionStart); OnAdditionEnd += new EndEventHandler(ActorFrosen_OnAdditionEnd); }
private SkillAttackResult CalcAttackResult(ActorExt sActor, ActorExt dActor, bool ignoreRange, int maxRange) { if (dActor.Status.Invincible) { return(SkillAttackResult.Miss); } if (sActor.DistanceToActor(dActor) > maxRange && !ignoreRange) { return(SkillAttackResult.Miss); } int angDif = Math.Abs(sActor.Dir - dActor.Dir); if (dActor.Status.Blocking && angDif >= 90) { return(SkillAttackResult.TotalParry); } if (dActor.Status.Counter && angDif >= 90) { return(SkillAttackResult.Counter); } if (dActor.Status.Dummy) { return(SkillAttackResult.Counter); } if (Global.Random.Next(0, 99) <= 95 || dActor.Status.Down) { int random = Global.Random.Next(0, 99); if (random <= 15) { return(SkillAttackResult.Critical); } else if (random <= 18 && !dActor.Status.Down) { return(SkillAttackResult.Avoid); } else if (random <= 20 && !dActor.Status.Down) { return(SkillAttackResult.Parry); } else { return(SkillAttackResult.Normal); } } else { return(SkillAttackResult.Miss); } }
protected override void OnDeactivate() { currentTarget = null; if (currentCommand?.Type == CommandTypes.Attack) { ((Attack)currentCommand).Target = null; } currentCommand = null; hateTable.Clear(); }
public int GetCurrentCastRange(ActorExt target) { int res = 40; List <Skill> possible = GetPossibleSkills(target, false); if (possible.Count > 0) { res = (int)(possible[0].BaseData.CastRangeMax / 1.5f); } return(res); }
public Chase(AI ai, ActorNPC self, ActorExt target) { this.ai = ai; this.self = self; this.target = target; map = Map.MapManager.Instance.GetMap(self.MapInstanceID); ai.Period = (int)(1000 / ((float)self.Speed / 100)); ai.Period = SmartEngine.Network.Global.Random.Next(ai.Period - ai.Period / 20, ai.Period + ai.Period / 20); if (self.BaseData.NoMove) { status = CommandStatus.Finished; } }
public Suicide(SkillArg arg, ActorExt target, uint additionID) : base(target, "Suicide", 1000) { this.arg = arg; this.target = target; this.additionID = additionID; if (target.Tasks.TryGetValue("Suicide", out Task task)) { task.Deactivate(); } target.Tasks["Suicide"] = this; OnAdditionEnd += new EndEventHandler(ActorFrosen_OnAdditionEnd); }
public ActorItemPickDropTask(ActorPC pc, ActorExt item, ActionTypes action) : base(pc, "ActorItemPickDropTask", 400) { this.pc = pc; this.item = item; this.action = action; OnAdditionStart += new StartEventHandler(ActorItemPickDropTask_OnAdditionStart); OnAdditionEnd += new EndEventHandler(ActorItemPickDropTask_OnAdditionEnd); if (pc.Tasks.TryRemove("ActorItemPickDropTask", out Task removed)) { removed.Deactivate(); } }
public Stun(SkillArg arg, ActorExt target, int lifeTime) : base(target, "Stun", lifeTime) { this.arg = arg; this.target = target; if (target.Tasks.TryGetValue("Stun", out Task task)) { task.Deactivate(); } target.Tasks["Stun"] = this; OnAdditionStart += new StartEventHandler(ActorDown_OnAdditionStart); OnAdditionEnd += new EndEventHandler(ActorDown_OnAdditionEnd); }
public static void ChangeStance(this ActorExt actor, Stances stance, byte skillSession, uint additionID, int stance2 = -1) { if (actor.Status.Stance != stance) { actor.Status.Stance = stance; UpdateEvent evt = UpdateEvent.NewActorAdditionEvent(actor, actor, skillSession, 0, additionID, UpdateEvent.ExtraUpdateModes.None); //evt.AddActorPara(PacketParameter.Stance, (int)stance); if (stance2 >= 0) { //evt.AddActorPara(PacketParameter.Stance2, stance2); MapManager.Instance.GetMap(actor.MapInstanceID).SendEventToAllActorsWhoCanSeeActor(MapEvents.EVENT_BROADCAST, evt, actor, true); } } }
public static UpdateEvent NewActorAdditionExtEvent(ActorExt src, byte session, ushort additionSession, uint additionID, int restTime, ExtraUpdateModes mode) { UpdateEvent evt = new UpdateEvent() { Actor = src, AdditionSession = additionSession, AdditionID = additionID, RestTime = restTime, SkillSession = session, ExtraActivateMode = mode, UpdateType = UpdateTypes.ActorExtension }; return(evt); }
public static UpdateEvent NewActorAdditionEvent(ActorExt src, ActorExt target, byte session, ushort additionSession, uint additionID, ExtraUpdateModes mode) { UpdateEvent evt = new UpdateEvent() { Actor = src, Target = target, SkillSession = session, AdditionID = additionID, AdditionSession = additionSession, ExtraActivateMode = mode, UpdateType = UpdateTypes.Actor }; return(evt); }
public Poisen(SkillArg arg, ActorExt target, uint additionID, int damage = 0, int duration = 5000) : base(target, "Poisen", duration, 2000) { this.arg = arg; this.target = target; this.additionID = additionID; this.damage = damage; if (target.Tasks.TryGetValue("Poisen", out Task task)) { task.Deactivate(); } target.Tasks["Poisen"] = this; OnAdditionStart += new StartEventHandler(ActorFrosen_OnAdditionStart); OnAdditionEnd += new EndEventHandler(ActorFrosen_OnAdditionEnd); OnUpdate += new UpdateEventHandler(Poisen_OnUpdate); }
private Skill ChooseSkill(ActorExt target) { List <Skill> possibleSkills = ai.GetPossibleSkills(target); List <Skill> comboSkills = (from skill in possibleSkills where skill.BaseData.PreviousSkills.Count > 0 || skill.BaseData.RequiredCasterStance != SkillCastStances.None || skill.BaseData.RequiredTargetStance != SkillCastStances.None select skill).ToList(); List <Skill> skills = comboSkills.Count > 0 ? comboSkills : possibleSkills; int idx = Global.Random.Next(1, skills.Count) - 1; if (idx >= skills.Count) { return(null); } return(skills[idx]); }
private bool CheckMana(ActorExt sActor, Skill skill) { if (sActor is ActorPC pc) { if (pc.MP >= skill.BaseData.ManaCost) { return(true); } else { return(false); } } else { return(true); } }
public Fire(SkillArg arg, ActorExt target) : base(target, "Fire", 10000) { this.arg = arg; BonusAdditionID = 12000036; if (target.Tasks.TryGetValue("Fire", out Task task)) { task.Deactivate(); AccumulateCount = ((Fire)task).AccumulateCount; } AccumulateCount++; if (AccumulateCount > 5) { AccumulateCount = 5; } target.Tasks["Fire"] = this; OnAdditionStart += new StartEventHandler(Fire_OnAdditionStart); OnAdditionEnd += new EndEventHandler(Fire_OnAdditionEnd); }
public Frosen(SkillArg arg, ActorExt target) : base(target, "Frosen", 6000) { this.arg = arg; this.target = target; BonusAdditionID = 12000057; if (target.Tasks.TryGetValue("Frosen", out Task task)) { task.Deactivate(); AccumulateCount = ((Frosen)task).AccumulateCount; } AccumulateCount++; if (AccumulateCount > 3) { AccumulateCount = 3; } target.Tasks["Frosen"] = this; OnAdditionStart += new StartEventHandler(Frosen_OnAdditionStart); OnAdditionEnd += new EndEventHandler(Frosen_OnAdditionEnd); }
public PoisenCharge(SkillArg arg, ActorExt target) : base(target, "PoisenCharge", 5000) { this.arg = arg; BonusAdditionID = 15000017; if (target.Tasks.TryGetValue("PoisenCharge", out Task task)) { task.Deactivate(); AccumulateCount = ((PoisenCharge)task).AccumulateCount; } AccumulateCount++; if (AccumulateCount > 5) { if (arg.Caster.Tasks.TryGetValue("Poisening", out task)) { task.Deactivate(); } AccumulateCount = 5; } target.Tasks["PoisenCharge"] = this; OnAdditionStart += new StartEventHandler(Poisening_OnAdditionStart); OnAdditionEnd += new EndEventHandler(Poisening_OnAdditionEnd); }
public void OnQuestUpdateRequest(CM_QUEST_UPDATE_REQUEST p) { if (p.NpcActorID != 0) { Quest q = null; if (chara.Quests.ContainsKey(p.QuestID)) { q = chara.Quests[p.QuestID]; } ActorExt actor = map.GetActor(p.NpcActorID) as ActorExt; if (actor is ActorCorpse corpse) { corpse.QuestID = p.QuestID; corpse.Step = p.Step; if (chara.Quests.TryGetValue(corpse.QuestID, out q)) { QuestManager.Instance.ProcessQuest(chara, corpse.QuestID, corpse.Step, q, corpse.NPC, true); } for (int i = 0; i < corpse.NPC.BaseData.QuestIDs.Count; i++) { if (corpse.NPC.BaseData.QuestIDs[i] == p.QuestID) { UpdateEvent evt = new UpdateEvent() { Actor = corpse, UpdateType = UpdateTypes.CorpseDoQuest, UserData = currentCorpse.NPC.BaseData.QuestSteps[i] }; map.SendEventToAllActorsWhoCanSeeActor(MapEvents.EVENT_BROADCAST, evt, corpse, false); } } } else { if (actor is ActorNPC npc) { if (account.GMLevel > 0) { Logger.Log.Warn(string.Format("Player:{0}({1}) requests to update quest:{2} to step:{3} at NPC:{4}", chara.Name, account.UserName, p.QuestID, p.Step, npc.NpcID)); } if (Scripting.ScriptManager.Instance.NpcScripts.ContainsKey(npc.NpcID)) { ((Scripting.NPCScriptHandler)npc.EventHandler).OnQuest(chara, q.QuestID, q.NextStep > 0 ? q.NextStep : (byte)1, q); } QuestManager.Instance.ProcessQuest(chara, q.QuestID, q.NextStep > 0 ? q.NextStep : (byte)1, q, npc, false, false, p.RewardSelection); } else { if (account.GMLevel > 0) { Logger.Log.Warn(string.Format("Player:{0}({1}) requests to update quest:{2} to step:{3} at NPC:{4}", chara.Name, account.UserName, p.QuestID, p.Step, p.NpcActorID)); } ProcessQuest(p.QuestID, p.Step); } } } else { ProcessQuest(p.QuestID, p.Step); } }
public bool SkillCast(SkillArg arg) { ActorExt sActor = arg.Caster; ActorExt dActor = arg.Target; Skill skill = arg.Skill; ushort dir = arg.Dir; DateTime now = DateTime.Now; if (skill.BaseData.Effect != 0) { skill.BaseData.Duration = (int)Effect.EffectManager.Instance[skill.BaseData.Effect].Duration; } if (!sActor.Status.CastingSkill || arg.CastFinished) { if (arg.CastFinished || CheckSkillCast(sActor, dActor, dir, skill)) { if (arg.Skill.BaseData.ManaCost > 0 && !arg.CastFinished && arg.Caster.ActorType == SmartEngine.Network.Map.ActorType.PC) { System.Threading.Interlocked.Add(ref arg.Caster.MP, -arg.Skill.BaseData.ManaCost); ((ActorPC)arg.Caster).Client().SendPlayerMP(); } if (arg.Caster.Tasks.TryGetValue("SwordBlocking", out Task duration)) { duration.Deactivate(); } if (arg.Caster.Tasks.TryGetValue("Teleport", out duration)) { duration.Deactivate(); } if (arg.Caster.Tasks.TryGetValue("FoodRecovery", out duration)) { duration.Deactivate(); } if (arg.Caster.Tasks.TryGetValue("Stealth", out duration)) { duration.Deactivate(); } if (skill.BaseData.CastTime == 0 || (skill.BaseData.ShouldApproach && arg.CastFinished) || (skill.BaseData.ActionTime != 0 && skill.BaseData.CastTime == 0) || arg.CastFinished) { sActor.Status.CastingSkill = true; if (skill.BaseData.ShouldApproach || skill.BaseData.ActionTime != 0) { int castTime = 0; if (skill.BaseData.ShouldApproach) { castTime = 500; if (arg.Target != null && arg.Target != arg.Caster) { castTime = arg.Caster.DistanceToActor(arg.Target) * arg.Skill.BaseData.ApproachTimeRate; } arg.ApproachTime = castTime; BroadcastSkillCast(arg, SkillMode.CastActionDelay); } else if (skill.BaseData.ActionTime > 0) { castTime = skill.BaseData.ActionTime; arg.ApproachTime = castTime; BroadcastSkillCast(arg, SkillMode.CastActionDelay); } if ((arg.Caster is ActorPC pc) && arg.Skill.BaseData.MovementLockOnCasting > 0) { SkillHandlers.Common.Additions.MovementLock mLock = new SkillHandlers.Common.Additions.MovementLock(pc.Client(), arg.Skill.BaseData.MovementLockOnCasting); mLock.Activate(); } HandleSkillCasting(arg); SkillCastTask task = new SkillCastTask(castTime, sActor, arg); sActor.Tasks["SkillCast"] = task; task.Activate(); } else { SkillActivate(arg); } } else { sActor.Status.CastingSkill = true; int castTime = 0; BroadcastSkillCast(arg, SkillMode.Cast); castTime = skill.BaseData.CastTime; if ((arg.Caster is ActorPC pc) && arg.Skill.BaseData.MovementLockOnCasting > 0) { SkillHandlers.Common.Additions.MovementLock mLock = new SkillHandlers.Common.Additions.MovementLock(pc.Client(), arg.Skill.BaseData.MovementLockOnCasting); mLock.Activate(); } HandleSkillCasting(arg); SkillCastTask task = new SkillCastTask(castTime, sActor, arg); sActor.Tasks["SkillCast"] = task; task.Activate(); } return(true); } return(false); } else { return(false); } }
public bool CheckSkillCast(ActorExt sActor, ActorExt dActor, ushort dir, Skill skill) { DateTime now = DateTime.Now; if (now < sActor.Status.SkillCooldownEnd || now < skill.CoolDownEndTime) { return(false); } if (skill.BaseData.PreviousSkills.Count > 0 && !skill.BaseData.PreviousSkills.Contains(sActor.Status.LastSkillID)) { return(false); } switch (skill.BaseData.RequiredCasterStance) { case SkillCastStances.None: if (sActor.Status.Dead || sActor.Status.Down || sActor.Status.TakeDown) { return(false); } break; case SkillCastStances.TakeDown: if (!sActor.Status.TakeDown) { return(false); } break; default: return(false); } if (dActor != null) { if (NPC.FactionRelationFactory.Instance[sActor.Faction][dActor.Faction] == Relations.Friendly && sActor != dActor) { return(false); } switch (skill.BaseData.RequiredTargetStance) { case SkillCastStances.Down: if (!dActor.Status.Down || sActor.Status.TakeDown) { return(false); } break; case SkillCastStances.NoMove: if (!dActor.Status.Down && !dActor.Status.Frosen && !dActor.Status.Stun) { return(false); } break; } } switch (skill.BaseData.SkillType) { case SkillType.Single: { int dist = sActor.DistanceToActor(dActor); if (dist >= skill.BaseData.CastRangeMin && dist <= skill.BaseData.CastRangeMax) { return(CheckMana(sActor, skill)); } else { return(false); } } case SkillType.Self: if (sActor == dActor) { return(CheckMana(sActor, skill)); } else { return(true); } case SkillType.Direction: case SkillType.NoTarget: return(CheckMana(sActor, skill)); default: return(false); } }
public override void OnDie(ActorExt killedBy) { }
public unsafe void HandleSkillActivate(SkillArg arg) { if (arg.Caster.Tasks.ContainsKey("FoodRecovery")) { Buff buff = arg.Caster.Tasks["FoodRecovery"] as Buff; buff.Deactivate(); } Map.Map map = MapManager.Instance.GetMap(arg.Caster.MapInstanceID); Buff add = new Buff(arg.Caster, "FoodRecovery", arg.Skill.BaseData.Duration, 2000); add.OnAdditionStart += (actor, addition) => { UpdateEvent evt = new UpdateEvent() { Actor = actor, Target = actor, Skill = arg.Skill, SkillSession = arg.SkillSession, AdditionID = arg.Skill.BaseData.Effect, AdditionSession = 20481, ExtraActivateMode = UpdateEvent.ExtraUpdateModes.Activate, UpdateType = UpdateTypes.Actor }; map.SendEventToAllActorsWhoCanSeeActor(MapEvents.EVENT_BROADCAST, evt, actor, true); evt = new UpdateEvent() { Actor = actor, Target = actor, Skill = arg.Skill, AdditionSession = 20481, AdditionID = arg.Skill.BaseData.Effect, RestTime = arg.Skill.BaseData.Duration, SkillSession = arg.SkillSession, UpdateType = UpdateTypes.ActorExtension }; map.SendEventToAllActorsWhoCanSeeActor(MapEvents.EVENT_BROADCAST, evt, actor, true); }; add.OnUpdate += (actor, addition) => { ActorExt act = (ActorExt)actor; if (act.HP < act.MaxHP) { Interlocked.Add(ref act.HP, recovery); if (act.HP > act.MaxHP) { Interlocked.Exchange(ref act.HP, act.MaxHP); } UpdateEvent evt = new UpdateEvent() { Actor = actor, Target = actor, UpdateType = UpdateTypes.Actor }; evt.AddActorPara(SagaBNS.Common.Packets.GameServer.PacketParameter.HP, act.HP); evt.SkillSession = arg.SkillSession; evt.AdditionID = arg.Skill.BaseData.Effect; evt.AdditionSession = 20481; evt.ExtraActivateMode = UpdateEvent.ExtraUpdateModes.Update; byte[] buf = new byte[9]; fixed(byte *res = buf) { res[0] = 8; *(int *)&res[1] = recovery; } evt.UserData = buf; map.SendEventToAllActorsWhoCanSeeActor(MapEvents.EVENT_BROADCAST, evt, actor, true); } }; add.OnAdditionEnd += (actor, addition, cancel) => { ((ActorExt)actor).Tasks.TryRemove("FoodRecovery", out Task removed); UpdateEvent evt = new UpdateEvent() { Actor = actor, Target = actor, Skill = arg.Skill, AdditionID = arg.Skill.BaseData.Effect, AdditionSession = 20481, ExtraActivateMode = UpdateEvent.ExtraUpdateModes.Cancel, SkillSession = arg.SkillSession, UpdateType = UpdateTypes.Actor, UserData = new byte[] { 9, 1, 0 } }; map.SendEventToAllActorsWhoCanSeeActor(MapEvents.EVENT_BROADCAST, evt, actor, true); evt = new UpdateEvent() { Actor = actor, Target = actor, Skill = arg.Skill, AdditionSession = 20481, AdditionID = arg.Skill.BaseData.Effect, ExtraActivateMode = UpdateEvent.ExtraUpdateModes.Cancel, SkillSession = arg.SkillSession, UpdateType = UpdateTypes.ActorExtension }; map.SendEventToAllActorsWhoCanSeeActor(MapEvents.EVENT_BROADCAST, evt, actor, true); SkillManager.Instance.BroadcastSkillCast(arg, SkillMode.End); }; arg.Caster.Tasks["FoodRecovery"] = add; add.Activate(); }
public SkillCastTask(int castTime, ActorExt actor, SkillArg skill) : base(castTime, castTime, "SkillCast") { this.actor = actor; this.skill = skill; }