protected void Regenerate() { if (UsedCampfire != null) { CreatureLogic.StaminaChanged(Player, Player.LifeStats.PlusStamina(UsedCampfire.Type == 4 ? 2 : 1)); } if (Player.LifeStats.Hp < Player.MaxHp) { CreatureLogic.HpChanged(Player, Player.LifeStats.PlusHp(UsedCampfire != null ? Player.MaxHp / 100 : Player.MaxHp / 200)); } switch (Player.PlayerData.Class) { case PlayerClass.Slayer: case PlayerClass.Berserker: if (LastBattleUts + 5000 < RandomUtilities.GetCurrentMilliseconds() && Player.LifeStats.Mp > 0) { CreatureLogic.MpChanged(Player, Player.LifeStats.MinusMp(Player.MaxHp / 90)); } break; default: if (Player.LifeStats.Mp < Player.MaxMp) { CreatureLogic.MpChanged(Player, Player.LifeStats.PlusMp(UsedCampfire != null ? Player.MaxMp * Player.GameStats.NaturalMpRegen / 350 : Player.MaxMp * Player.GameStats.NaturalMpRegen / 700)); } break; } }
protected void Regenerate() { switch (Player.PlayerData.Class) { default: int regenRate = 100; switch (Player.PlayerMode) { case PlayerMode.Relax: regenRate = 10; break; case PlayerMode.Normal: regenRate = 80; break; case PlayerMode.Armored: regenRate = 140; break; } if (Player.LifeStats.Hp < Player.MaxHp) { CreatureLogic.HpChanged(Player, Player.LifeStats.PlusHp(Player.MaxHp / regenRate)); } if (Player.LifeStats.Mp < Player.MaxMp) { CreatureLogic.MpChanged(Player, Player.LifeStats.PlusMp(Player.MaxMp * Player.GameStats.NaturalMpRegen / regenRate)); } break; } }
public override void Tick() { switch (Effect.Method) { case 2: CreatureLogic.MpChanged(Creature, Creature.LifeStats.PlusMp((int)Effect.Value), Creature); break; case 3: //Percent CreatureLogic.MpChanged(Creature, Creature.LifeStats.PlusMp((int)(Creature.MaxMp * Effect.Value)), Creature); break; default: Player player = Creature as Player; if (player != null) { new SpChatMessage("Unknown method " + Effect.Method + " for RegenMp effect.", ChatType.System).Send(player); } break; } }
private async void ProcessArea(Creature creature, Skill skill, Targeting targeting, TargetingArea area, Projectile projectile = null) { try { bool isProjectileSkill = skill.Type == SkillType.Projectile || skill.Type == SkillType.Userslug; int skillId = creature.Attack.Args.SkillId; if (isProjectileSkill) { skillId += 20; } if (targeting.Time > 0) { await Task.Delay((int)(targeting.Time / skill.TimeRate)); } int elapsed = targeting.Time; Player player = creature as Player; do { try { if (creature.LifeStats.IsDead()) { return; } if (area.DropItem != null) { creature.Instance.AddDrop(new Item { Owner = player, ItemId = (int)area.DropItem, Count = 1, Position = Geom.ForwardPosition(creature.Position, 40), Instance = player.Instance, }); } Point3D center = projectile != null ? projectile.Position.ToPoint3D() : Geom.GetNormal(creature.Position.Heading) .Multiple(area.OffsetDistance) .Add(creature.Position); int count = 0; List <Creature> targets = creature.Attack.Args.Targets.Count > 0 ? creature.Attack.Args.Targets : VisibleService.FindTargets(creature, center, projectile != null ? projectile.AttackDistance : area.MaxRadius, area.Type); foreach (Creature target in targets) { if (target != creature && //Ignore checks for self-target !isProjectileSkill && !creature.Attack.Args.IsItemSkill) { if (center.DistanceTo(target.Position) < area.MinRadius - 40) { continue; } if (center.DistanceTo(target.Position) > area.MaxRadius) { continue; } short diff = Geom.GetAngleDiff(creature.Attack.Args.StartPosition.Heading, Geom.GetHeading(center, target.Position)); //diff from 0 to 180 //area.RangeAngel from 0 to 360 if (diff * 2 > (creature.Attack.Args.IsTargetAttack ? 90 : Math.Abs(area.RangeAngle) + 10)) { continue; } } if (skill.TotalAtk > 0) { int damage = SeUtils.CalculateDamage(creature, target, skill.TotalAtk * area.Effect.Atk); AttackResult result = new AttackResult { AttackType = AttackType.Normal, AttackUid = creature.Attack.UID, Damage = damage, Target = target, }; result.AngleDif = Geom.GetAngleDiff(creature.Attack.Args.StartPosition.Heading, result.Target.Position.Heading); SeUtils.UpdateAttackResult(creature, result); if (result.AttackType == AttackType.Block) { VisibleService.Send(target, new SpAttackShowBlock(target, skillId)); } VisibleService.Send(target, new SpAttackResult(creature, skillId, result)); AiLogic.OnAttack(creature, target); AiLogic.OnAttacked(target, creature, result.Damage); if (target is Player && ((Player)target).Duel != null && player != null && ((Player)target).Duel.Equals(player.Duel) && target.LifeStats.GetHpDiffResult(damage) < 1) { DuelService.FinishDuel(player); } else { CreatureLogic.HpChanged(target, target.LifeStats.MinusHp(result.Damage)); } } if (area.Effect.HpDiff > 0) { AttackResult result = new AttackResult { HpDiff = area.Effect.HpDiff, Target = target }; PassivityProcessor.OnHeal(player, result); if (target is Player) { PassivityProcessor.OnHealed((Player)target, result); } CreatureLogic.HpChanged(target, target.LifeStats.PlusHp(result.HpDiff), creature); } if (area.Effect.MpDiff > 0) { CreatureLogic.MpChanged(target, target.LifeStats.PlusMp(area.Effect.MpDiff), creature); } if (area.Effect.AbnormalityOnCommon != null) { for (int i = 0; i < area.Effect.AbnormalityOnCommon.Count; i++) { AbnormalityProcessor.AddAbnormality(target, area.Effect.AbnormalityOnCommon[i], creature); } } if (player != null) { DuelService.ProcessDamage(player); //MP regen on combo skill if (skill.Id / 10000 == 1 && player.GameStats.CombatMpRegen > 0) { CreatureLogic.MpChanged(player, player.LifeStats.PlusMp( player.MaxMp * player.GameStats.CombatMpRegen / 200)); } } if (++count == area.MaxCount) { break; } } } catch (Exception ex) { Logger.WriteLine(LogState.Exception, "SkillEngine: ProcessAreaExc: " + ex); } if (targeting.Interval > 0) { await Task.Delay((int)(targeting.Interval / skill.TimeRate)); elapsed += targeting.Interval; } } while (targeting.Interval > 0 && elapsed < targeting.Until); } catch (Exception ex) { Logger.WriteLine(LogState.Exception, "SkillEngine: ProcessArea: " + ex); } }
public void UseSkill(IConnection connection, UseSkillArgs args) { Player player = connection.Player; Skill skill = args.GetSkill(player); if (skill == null) { return; } if (skill.ChargingStageList != null) { args.IsChargeSkill = true; } if (skill.Type == SkillType.Mount) { MountService.ProcessMount(player, skill.Id); new SpSkillCooldown(skill.Id, skill.Precondition.CoolTime).Send(player.Connection); return; } if (player.Attack != null && !player.Attack.IsFinished) { if (player.Attack.Args.IsDelaySkill) { int stage = player.Attack.Stage; if (player.Attack.Args.IsChargeSkill) { skill = player.Attack.Args.GetSkill(player); if (skill.ChargingStageList != null && skill.ChargingStageList.ChargeStageList.Count > stage) { int useHp = (int)(skill.ChargingStageList.CostTotalHp * skill.ChargingStageList.ChargeStageList[stage].CostHpRate); int useMp = (int)(skill.ChargingStageList.CostTotalMp * skill.ChargingStageList.ChargeStageList[stage].CostMpRate); if (player.LifeStats.Hp <= useHp) { SystemMessages.YouCannotUseThatSkillAtTheMoment.Send(player.Connection); stage = -1; } else if (player.LifeStats.Mp < useMp) { SystemMessages.NotEnoughMp.Send(player.Connection); stage = -1; } else { if (useHp > 0) { CreatureLogic.HpChanged(player, player.LifeStats.MinusHp(useHp)); } if (useMp > 0) { CreatureLogic.MpChanged(player, player.LifeStats.MinusMp(useMp)); } args = new UseSkillArgs { SkillId = player.Attack.Args.SkillId + 10 + stage, StartPosition = player.Position.Clone(), TargetPosition = player.Attack.Args.TargetPosition, }; } } else { stage = -1; } } player.Attack.Finish(); if (skill.BaseId == 20100 && (player.PlayerData.Class == PlayerClass.Berserker || player.PlayerData.Class == PlayerClass.Lancer)) { player.EffectsImpact.ResetChanges(player); //Set IsBlockFrontAttacks } if (player.Attack.Args.IsChargeSkill && stage != -1) { UseSkill(connection, args); } return; } if (args.SkillId / 10000 == player.Attack.Args.SkillId / 10000) { player.Attack.Finish(); if (player.Attack.Args.Targets.Count == 0) { return; } args.Targets = new List <Creature>(player.Attack.Args.Targets); ProcessSkill(player, args, skill); } return; } if (!CheckRequirements(player, skill)) { return; } args.StartPosition.CopyTo(player.Position); ProcessSkill(player, args, skill); }
private void ProcessSkill(Creature creature, UseSkillArgs args, Skill skill, Projectile projectile = null) { bool isProjectileSkill = skill.Type == SkillType.Projectile || skill.Type == SkillType.Userslug; if (!isProjectileSkill) { if (skill.ChargingStageList == null || skill.ChargingStageList.ChargeStageList.Count == 0) { if (skill.Precondition.Cost.Hp > 0) { CreatureLogic.HpChanged(creature, creature.LifeStats.MinusHp(skill.Precondition.Cost.Hp)); } if (skill.Precondition.Cost.Mp > 0) { CreatureLogic.MpChanged(creature, creature.LifeStats.MinusMp(skill.Precondition.Cost.Mp)); } } if (!args.IsDelaySkill || args.IsDelayStart) { if (args.TargetPosition.IsNull()) { double angle = args.StartPosition.Heading * Math.PI / 32768; args.StartPosition.CopyTo(args.TargetPosition); args.TargetPosition.X += 100 * (float)Math.Cos(angle); args.TargetPosition.Y += 100 * (float)Math.Sin(angle); } // ReSharper disable ImplicitlyCapturedClosure creature.Attack = new Attack(creature, args, () => GlobalLogic.AttackStageEnd(creature), () => GlobalLogic.AttackFinished(creature)); // ReSharper restore ImplicitlyCapturedClosure VisibleService.Send(creature, new SpAttack(creature, creature.Attack)); VisibleService.Send(creature, new SpAttackDestination(creature, creature.Attack)); if (!args.IsDelaySkill) { ProcessStages(creature, skill); } else { Player player = creature as Player; if (player != null && skill.BaseId == 20100 && (player.PlayerData.Class == PlayerClass.Berserker || player.PlayerData.Class == PlayerClass.Lancer)) { player.EffectsImpact.ResetChanges(player); //Set IsBlockFrontAttacks } } ProcessMove(creature, skill); } } else { creature.Attack.Args.IsTargetAttack = args.IsTargetAttack; creature.Attack.Args.Targets = args.Targets; ProcessProjectileTargets(creature, skill, projectile); } AiLogic.OnUseSkill(creature, skill); if (skill.ChargingStageList != null) { if (args.IsDelayStart) { int uid = creature.Attack.UID; ThreadPool.QueueUserWorkItem( o => { Thread.Sleep(750); for (int i = 1; i < skill.ChargingStageList.ChargeStageList.Count; i++) { if (creature.Attack.UID != uid) { return; } creature.Attack.NextStage(); if (i != 3) { Thread.Sleep(750); } } }); } } else { ProcessTargets(creature, skill); } }