/// <summary> /// Performs the skill by the player at the specified area. Additionally to the target area, a target object can be specified. /// </summary> /// <param name="player">The player.</param> /// <param name="extraTargetId">The extra target identifier.</param> /// <param name="skillId">The skill identifier.</param> /// <param name="targetAreaCenterX">The x coordinate of the center of the target area.</param> /// <param name="targetAreaCenterY">The y coordinate of the center of the target area.</param> /// <param name="rotation">The rotation in which the player is looking. It's not really relevant for the hitted objects yet, but for some directed skills in the future it might be.</param> public void Attack(Player player, ushort extraTargetId, ushort skillId, byte targetAreaCenterX, byte targetAreaCenterY, byte rotation) { SkillEntry skillEntry = player.SkillList.GetSkill(skillId); var skill = skillEntry.Skill; if (skill.SkillType == SkillType.PassiveBoost) { Logger.WarnFormat("AreaSkill is a passive boost"); return; } if (!player.TryConsumeForSkill(skill)) { Logger.WarnFormat("AreaSkill not enough resources"); return; } if (skill.SkillType == SkillType.AreaSkillAutomaticHits) { Logger.WarnFormat("AreaSkill perform automatic hits"); this.PerformAutomaticHits(player, extraTargetId, targetAreaCenterX, targetAreaCenterY, skillEntry, skill); } player.ForEachObservingPlayer(p => p.PlayerView.WorldView.ShowAreaSkillAnimation(player, skill, targetAreaCenterX, targetAreaCenterY, rotation), true); }
private void AddLearnedSkill(SkillEntry skill) { this.availableSkills.Add(skill.Skill.Number.ToUnsigned(), skill); this.learnedSkills.Add(skill); this.player.PlayerView.AddSkill(skill.Skill); }
/// <inheritdoc/> public void HandlePacket(Player player, Span <byte> packet) { if (packet.Length < 11) { return; } ushort skillId = NumberConversionExtensions.MakeWord(packet[4], packet[3]); if (!player.SkillList.ContainsSkill(skillId)) { return; } SkillEntry skillEntry = player.SkillList.GetSkill(skillId); ushort targetId = NumberConversionExtensions.MakeWord(packet[10], packet[9]); if (player.GetObject(targetId) is IAttackable target) { if (target is IObservable observable && observable.Observers.Contains(player)) { this.skillHitAction.AttackTarget(player, target, skillEntry); } else { // Client may be out of sync (or it's an hacker attempt), // so we tell him the object is out of scope - this should prevent further attempts to attack it. player.ViewPlugIns.GetPlugIn <IObjectsOutOfScopePlugIn>()?.ObjectsOutOfScope(target.GetAsEnumerable()); } }
/// <summary> /// Returns the base damage if the attacker, using a specific skill. /// </summary> /// <param name="attacker">The attacker.</param> /// <param name="skill">Skill which is used.</param> /// <param name="basemin">Minimum base damage.</param> /// <param name="basemax">Maximum base damage.</param> private static void GetBaseDmg(this IAttackable attacker, SkillEntry skill, out int basemin, out int basemax) { basemin = 0; basemax = 0; var attackerStats = attacker.Attributes; DamageType damageType = DamageType.Physical; if (skill != null) { damageType = skill.Skill.DamageType; var skillDamage = skill.Skill.AttackDamage.Where(d => d.Level == skill.Level).Select(d => d.Damage).FirstOrDefault(); basemin += skillDamage; basemax += skillDamage; } if (damageType == DamageType.Physical) { basemin = (int)attackerStats[Stats.MinimumPhysBaseDmg]; basemax = (int)attackerStats[Stats.MaximumPhysBaseDmg]; } else if (damageType == DamageType.Wizardry) { basemin = (int)attackerStats[Stats.MinimumWizBaseDmg]; basemax = (int)attackerStats[Stats.MaximumWizBaseDmg]; } else if (damageType == DamageType.Curse) { basemin = (int)attackerStats[Stats.MinimumCurseBaseDmg]; basemax = (int)attackerStats[Stats.MaximumCurseBaseDmg]; } }
public UseSkillButtonGump(SkillEntry skill) : base(skill.ID, 0) { while (UserInterface.GetControl <UseSkillButtonGump>(skill.ID) != null) { UserInterface.GetControl <UseSkillButtonGump>(skill.ID).Dispose(); } m_Skill = skill; m_World = Service.Get <WorldModel>(); IsMoveable = true; HandlesMouseInput = true; m_BG = new ResizePic[3]; m_BG[0] = (ResizePic)AddControl(new ResizePic(this, 0, 0, 0x24B8, 120, 40)); m_BG[1] = (ResizePic)AddControl(new ResizePic(this, 0, 0, 0x24EA, 120, 40)); m_BG[2] = (ResizePic)AddControl(new ResizePic(this, 0, 0, 0x251C, 120, 40)); m_Caption = (HtmlGumpling)AddControl(new HtmlGumpling(this, 0, 10, 120, 20, 0, 0, "<center>" + m_Skill.Name)); for (int i = 0; i < 3; i++) { m_BG[i].MouseDownEvent += EventMouseDown; m_BG[i].MouseUpEvent += EventMouseUp; m_BG[i].MouseClickEvent += EventMouseClick; } }
private void ApplySkill(Player player, IAttackable targetedTarget, SkillEntry skillEntry) { var skill = skillEntry.Skill; var targets = this.DetermineTargets(player, targetedTarget, skill); foreach (var target in targets) { if (skill.SkillType == SkillType.DirectHit || skill.SkillType == SkillType.CastleSiegeSkill) { target.AttackBy(player, skillEntry); target.ApplyElementalEffects(player, skillEntry); } else if (skill.MagicEffectDef != null) { if (skill.SkillType == SkillType.Buff) { target.ApplyMagicEffect(player, skillEntry); } else if (skill.SkillType == SkillType.Regeneration) { target.ApplyRegeneration(player, skill); } else { Log.Warn($"Skill.MagicEffectDef isn't null, but it's not a buff or regeneration skill. skill: {skill.Name} ({skill.Number}), skillType: {skill.SkillType}."); } } else { Log.Warn($"Skill.MagicEffectDef is null, skill: {skill.Name} ({skill.Number}), skillType: {skill.SkillType}."); } } }
/// <summary> /// Applies the regeneration of the players skill to the target. /// </summary> /// <param name="target">The target.</param> /// <param name="player">The player.</param> /// <param name="skillEntry">The skill entry.</param> public static void ApplyRegeneration(this IAttackable target, Player player, SkillEntry skillEntry) { if (player.Attributes is null) { return; } skillEntry.ThrowNotInitializedProperty(skillEntry.Skill is null, nameof(skillEntry.Skill)); var skill = skillEntry.Skill; var regeneration = Stats.IntervalRegenerationAttributes.FirstOrDefault(r => r.CurrentAttribute == skill.MagicEffectDef?.PowerUpDefinition?.TargetAttribute); if (regeneration != null) { var powerUpDefinition = skill.MagicEffectDef !.PowerUpDefinition !; var regenerationValue = player.Attributes.CreateElement(powerUpDefinition.Boost ?? throw Error.NotInitializedProperty(powerUpDefinition, nameof(powerUpDefinition.Boost))); var value = skillEntry.Level == 0 ? regenerationValue.Value : regenerationValue.Value + skillEntry.CalculateValue(); target.Attributes[regeneration.CurrentAttribute] = Math.Min( target.Attributes[regeneration.CurrentAttribute] + value, target.Attributes[regeneration.MaximumAttribute]); } else { player.Logger.LogWarning( $"Regeneration skill {skill.Name} is configured to regenerate a non-regeneration-able target attribute {skill.MagicEffectDef?.PowerUpDefinition?.TargetAttribute}."); } }
protected override void OnCreat() { SkillEntry entry = new SkillEntry(); var node = AddNode(entry, new Rect(Vector2.zero, new Vector2(80, 80))); node.Name = "Entry"; }
private GuildSkill TransformGuildSkill(Data.Repositories.Contracts.Classes.GuildSkill skill) { if (skill == null) { return(null); } var ret = new GuildSkill { Point = skill.Point }; using (var ms = new MemoryStream(skill.Skill)) { using (var br = new BinaryReader(ms)) { var l = new List <SkillEntry>(); for (var i = 0; i < ms.Length / 4; i++) { var se = new SkillEntry { SkillId = br.ReadInt16(), Level = br.ReadInt16() }; l.Add(se); } ret.Skills = l.ToArray(); } } return(ret); }
public void Render(SkillEntry skill) { var currentRank = GameWorld.Instance.Character.Allocations.GetPoints(AllocationType.Skill, skill.Name); _rankText.text = $"{currentRank}/{skill.MaxRank}"; _skillName = skill.Name; }
/// <inheritdoc /> public void AfterTargetGotAttacked(IAttackable attacker, IAttackable target, SkillEntry skillEntry, Point targetAreaCenter) { if (!target.Alive || !(target is IMovable movableTarget)) { return; } var startingPoint = attacker.Position; var currentTarget = target.Position; var direction = startingPoint.GetDirectionTo(currentTarget); if (direction == Direction.Undefined) { direction = (Direction)Rand.NextInt(1, 9); } var currentDistance = startingPoint.EuclideanDistanceTo(currentTarget); while (currentDistance < skillEntry.Skill.Range) { var nextTarget = currentTarget.CalculateTargetPoint(direction); if (!target.CurrentMap.Terrain.WalkMap[nextTarget.X, nextTarget.Y] || (target is NonPlayerCharacter && target.CurrentMap.Terrain.SafezoneMap[nextTarget.X, nextTarget.Y])) { // we don't want to push the target into a non-reachable area, through walls or monsters into the safe zone. break; } currentTarget = nextTarget; currentDistance = startingPoint.EuclideanDistanceTo(currentTarget); } movableTarget.Move(currentTarget); }
private void CreatePowerUpWrappers(SkillEntry skillEntry) { if (skillEntry.Skill.PassivePowerUps.TryGetValue(skillEntry.Level, out PowerUpDefinition powerUp)) { this.passiveSkillPowerUps.Add(skillEntry, PowerUpWrapper.CreateByPowerUpDefintion(powerUp, this.player.Attributes).ToList()); } }
private void ApplySkill(Player player, SkillEntry skillEntry, Skill skill, IAttackable target) { if (target.CheckSkillTargetRestrictions(player, skill)) { target.AttackBy(player, skillEntry); target.ApplyElementalEffects(player, skillEntry); } }
public static string SkillState(string name) { SkillManager manager = SkillManager.GetInstance(); SkillEntry s = manager.Items.FirstOrDefault(se => se.Skill.Name.ToLower().Contains(name.ToLower())); return(s?.LockStatus.ToString().ToLower() ?? "up"); }
public static double SkillCap(string name) { SkillManager manager = SkillManager.GetInstance(); SkillEntry s = manager.Items.FirstOrDefault(se => se.Skill.Name.ToLower().Contains(name.ToLower())); return(s?.Cap ?? 0); }
private void CreateBuffPowerUp(Player player, SkillEntry skillEntry) { var skill = skillEntry.Skill; var powerUpDef = skill.MagicEffectDef.PowerUpDefinition; skillEntry.BuffPowerUp = this.GetElement(player, powerUpDef.Boost); skillEntry.PowerUpDuration = this.GetElement(player, powerUpDef.Duration); }
/// <summary> /// Performs the skill. /// </summary> /// <param name="player">The player.</param> /// <param name="target">The target.</param> /// <param name="skillId">The skill identifier.</param> public void PerformSkill(Player player, IAttackable target, ushort skillId) { SkillEntry skillEntry = player.SkillList.GetSkill(skillId); var skill = skillEntry.Skill; if (skill.SkillType == SkillType.PassiveBoost) { Logger.WarnFormat("Skill is a passive boost"); return; } if (target == null) { Logger.WarnFormat("Skill has no target"); return; } if (!target.Alive) { Logger.WarnFormat("Skill target is already dead"); return; } var targetPlayer = target as Player; bool targetIsPlayer = targetPlayer != null; // is it a player? // enough mana, ag etc? if (!player.TryConsumeForSkill(skill)) { Logger.WarnFormat("Skill not enough resources"); return; } player.ForEachObservingPlayer(obs => obs.PlayerView.WorldView.ShowSkillAnimation(player, target, skill), true); if (!player.IsInRange(target.X, target.Y, skill.Range + 2)) { Logger.WarnFormat("Skill target is out of range"); return; } if (skill.SkillType == SkillType.DirectHit || skill.SkillType == SkillType.CastleSiegeSkill) { Logger.WarnFormat("Skill perform direct hit or castle siege skill"); target.AttackBy(player, skillEntry); } if (skill.SkillType == SkillType.Buff && skill.MagicEffectDef != null && targetIsPlayer) { // TODO: Summoned Monsters should be able to receive a buff too - add an interface ICanReceiveBuff which contains the MagicEffectList if (skillEntry.BuffPowerUp == null) { this.CreateBuffPowerUp(player, skillEntry); } var magicEffect = new MagicEffect(skillEntry.BuffPowerUp, skill.MagicEffectDef, new TimeSpan(0, 0, 0, 0, (int)skillEntry.PowerUpDuration.Value)); targetPlayer.MagicEffectList.AddEffect(magicEffect); } }
private void UpdateSkillPassivePowerUp(SkillEntry skillEntry) { if (this.passiveSkillPowerUps.TryGetValue(skillEntry, out IEnumerable <PowerUpWrapper> powerUps)) { this.passiveSkillPowerUps.Remove(skillEntry); powerUps.ForEach(p => p.Dispose()); this.CreatePowerUpWrappers(skillEntry); } }
private void AddItemSkill(Skill skill) { var skillEntry = new SkillEntry(); // Create by repository manager? Probably not, but I'm not sure... skillEntry.Skill = skill; skillEntry.Level = 0; this.itemSkills.Add(skillEntry); this.availableSkills.Add(skill.SkillID.ToUnsigned(), skillEntry); }
private void ApplySkill(Player player, SkillEntry skillEntry, IAttackable target, Point targetAreaCenter) { if (target.CheckSkillTargetRestrictions(player, skillEntry.Skill)) { target.AttackBy(player, skillEntry); target.ApplyElementalEffects(player, skillEntry); player.GameContext.PlugInManager.GetStrategy <short, IAreaSkillPlugIn>(skillEntry.Skill.Number)?.AfterTargetGotAttacked(player, target, skillEntry, targetAreaCenter); } }
public ChangeSkillLock(SkillEntry skill, LockStatus lockStatus) { _writer = new PacketWriter(6); _writer.Write((byte)0x3A); _writer.Write((short)6); _writer.Write((byte)0); _writer.Write((byte)skill.Skill.ID); _writer.Write((byte)lockStatus); }
/// <summary> /// Performs the skill. /// </summary> /// <param name="player">The player.</param> /// <param name="target">The target.</param> /// <param name="skillId">The skill identifier.</param> public void PerformSkill(Player player, IAttackable target, ushort skillId) { using var loggerScope = player.Logger.BeginScope(this.GetType()); SkillEntry skillEntry = player.SkillList.GetSkill(skillId); var skill = skillEntry.Skill; if (skill.SkillType == SkillType.PassiveBoost) { return; } if (target is null) { return; } if (!target.IsActive()) { return; } if (!target.CheckSkillTargetRestrictions(player, skill)) { return; } if (!player.IsInRange(target.Position, skill.Range + 2)) { // target position might be out of sync so we send the current coordinates to the client again. if (!(target is ISupportWalk walker && walker.IsWalking)) { player.ViewPlugIns.GetPlugIn <IObjectMovedPlugIn>()?.ObjectMoved(target, MoveType.Instant); } return; } // enough mana, ag etc? if (!player.TryConsumeForSkill(skill)) { return; } player.ForEachWorldObserver(obs => obs.ViewPlugIns.GetPlugIn <IShowSkillAnimationPlugIn>()?.ShowSkillAnimation(player, target, skill), true); if (skill.MovesToTarget) { player.Move(target.Position); } if (skill.MovesTarget) { target.MoveRandomly(); } this.ApplySkill(player, target, skillEntry); }
public static void Start() { ConsoleUtils.Write(ConsoleMsgType.Status, "Loading Skill Database...\n"); DB = new Dictionary <int, SkillEntry>(); Database db = new Database(Server.GameDbConString); MySqlDataReader reader = db.ReaderQuery( "SELECT `skill_id`, `name`, `max_level` " + "FROM `skill_db`", null, null ); while (reader.Read()) { SkillEntry skill = new SkillEntry(); int skillId = (int)reader["skill_id"]; skill.MaxLevel = (byte)reader["max_level"]; skill.RequiredJp = new int[skill.MaxLevel + 1]; skill.CooldownTime = 1000; Database db2 = new Database(Server.GameDbConString); MySqlDataReader reader2 = db2.ReaderQuery( "SELECT `skill_id`, `level`, `jp` " + "FROM `skill_jp_db` " + "WHERE `skill_id`=@sid", new string[] { "sid" }, new object[] { skillId } ); while (reader2.Read()) { byte lv = (byte)reader2["level"]; int jp = (int)reader2["jp"]; if (lv > skill.MaxLevel) { ConsoleUtils.Write( ConsoleMsgType.Warning, "Defined JP cost for skill {1} level {2}, that's higher than the max level ({3})\r\n", skillId, lv, skill.MaxLevel ); continue; } skill.RequiredJp[lv] = jp; } DB.Add(skillId, skill); } ConsoleUtils.Write(ConsoleMsgType.Status, "Skill Database Loaded.\n"); }
/// <inheritdoc /> public void AfterTargetGotAttacked(IAttacker attacker, IAttackable target, SkillEntry skillEntry, Point targetAreaCenter) { if (target is Player targetPlayer && Rand.NextRandomBool(25) && targetPlayer.Inventory.EquippedItems.SelectRandom() is Item randomItem) { randomItem.Durability /= 2; targetPlayer.ViewPlugIns.GetPlugIn <IItemDurabilityChangedPlugIn>()?.ItemDurabilityChanged(randomItem, false); } }
private void AddMasterPointToLearnedSkill(Player player, SkillEntry learnedSkill) { if (player.SelectedCharacter.MasterLevelUpPoints > 0 && learnedSkill.Level < MaximumSkillLevel) { learnedSkill.Level++; player.SelectedCharacter.MasterLevelUpPoints--; // TODO: Send response, see protocol documentation } }
private SkillEntry CreateSkillEntry(ushort skillId) { var skillEntry = new SkillEntry { Skill = new OpenMU.DataModel.Configuration.Skill { SkillID = skillId.ToSigned() } }; return(skillEntry); }
public static void ChangeSkillLock(SkillEntry skill, LockStatus lockStatus, bool requery = true) { Engine.SendPacketToServer(new ChangeSkillLock(skill, lockStatus)); if (requery) { Engine.SendPacketToServer( new MobileQuery(Engine.Player?.Serial ?? 0, MobileQueryType.SkillsRequest)); } }
private static int GetDamage(this SkillEntry skill) { var result = skill.Skill.AttackDamage; if (skill.Skill.MasterDefinition != null) { result += (int)skill.CalculateValue(); } return(result); }
/// <summary> /// Applies the magic effect of the players skill to the target. /// </summary> /// <param name="target">The target.</param> /// <param name="player">The player.</param> /// <param name="skillEntry">The skill entry.</param> public static void ApplyMagicEffect(this IAttackable target, Player player, SkillEntry skillEntry) { if (skillEntry.BuffPowerUp == null) { player.CreateMagicEffectPowerUp(skillEntry); } var magicEffect = new MagicEffect(skillEntry.BuffPowerUp, skillEntry.Skill.MagicEffectDef, TimeSpan.FromSeconds(skillEntry.PowerUpDuration.Value)); target.MagicEffectList.AddEffect(magicEffect); }
/// <summary> /// Attacks the target by the player with the specified skill. /// </summary> /// <param name="player">The player who is performing the skill.</param> /// <param name="target">The target.</param> /// <param name="skill">The skill.</param> public void AttackTarget(Player player, IAttackable target, SkillEntry skill) { if (skill.Skill.SkillType != SkillType.AreaSkillExplicitHits || target == null || !target.Alive) { return; } target.AttackBy(player, skill); }