/// <summary> /// New Skill. /// </summary> /// <param name="creature"></param> /// <param name="id"></param> /// <param name="rank"></param> /// <param name="race"></param> public Skill(Creature creature, SkillId id, SkillRank rank, int race) { _creature = creature; _race = race; this.Info.Id = id; this.Info.Rank = rank; this.Info.MaxRank = rank; this.Info.Flag = SkillFlags.Shown; // The conditions are set to the max and are reduced afterwards, // making them "Complete" once they reach 0. Initializing to 1 // in case of problems. this.Info.ConditionCount1 = 1; this.Info.ConditionCount2 = 1; this.Info.ConditionCount3 = 1; this.Info.ConditionCount4 = 1; this.Info.ConditionCount5 = 1; this.Info.ConditionCount6 = 1; this.Info.ConditionCount7 = 1; this.Info.ConditionCount8 = 1; this.Info.ConditionCount9 = 1; this.LoadRankData(); }
/// <summary> /// Sends SkillComplete to creature's client. /// </summary> /// <param name="creature"></param> /// <param name="skillId"></param> public static void SkillComplete(Creature creature, SkillId skillId) { var packet = new Packet(Op.SkillComplete, creature.EntityId); packet.PutUShort((ushort)skillId); creature.Client.Send(packet); }
public AttackerAction(CombatActionType type, Creature creature, SkillId skillId, long targetId) { this.Type = type; this.Creature = creature; this.SkillId = skillId; this.TargetId = targetId; }
/// <summary> /// Sends SkillStartSilentCancel to creature's client. /// </summary> /// <param name="creature"></param> /// <param name="skillId"></param> public static void SkillStartSilentCancel(Creature creature, SkillId skillId) { var packet = new Packet(Op.SkillStartSilentCancel, creature.EntityId); packet.PutUShort((ushort)skillId); creature.Client.Send(packet); }
public void SetCooldown(SkillId skillId, DateTime endTime) { if (this._cooldownDictionary.ContainsKey(skillId)) this._cooldownDictionary[skillId] = endTime; else this._cooldownDictionary.Add(skillId, endTime); }
/// <summary> /// Creates new attacker action. /// </summary> /// <param name="type"></param> /// <param name="creature"></param> /// <param name="targetId"></param> /// <param name="skillId"></param> public AttackerAction(CombatActionType type, Creature creature, long targetId, SkillId skillId) { this.Flags = type; this.Creature = creature; this.TargetId = targetId; this.WeaponParameterType = 1; this.SkillId = skillId; }
ISkill ISkillCollection.this[SkillId skillId] { get { Contract.Ensures(Contract.Result<ISkill>() != null); throw new NotImplementedException(); } }
/// <summary> /// Broadcasts RankUp in range of creature. /// </summary> /// <remarks> /// The second parameter is the rank, but doesn't seem to be necessary. /// </remarks> /// <param name="creature"></param> /// <param name="skillId">Excluded if 0</param> public static void RankUp(Creature creature, SkillId skillId = 0) { var packet = new Packet(Op.RankUp, creature.EntityId); if (skillId > 0) packet.PutUShort((ushort)skillId); packet.PutShort(1); // Rank creature.Region.Broadcast(packet, creature); }
public GenericWeapon(InventorySlotTypeMask slot, DamageInfo[] damages, SkillId skill, float minRange, float maxRange, int attackTime) { InventorySlotMask = slot; Damages = damages; Skill = skill; MinRange = minRange; MaxRange = maxRange; AttackTime = attackTime; }
public GenericWeapon(bool isRanged, DamageInfo[] damages, SkillId skill, float minRange, float maxRange, int attackTime) { IsRanged = isRanged; IsMelee = !isRanged; Damages = damages; Skill = skill; MinRange = minRange; MaxRange = maxRange; AttackTime = attackTime; }
private void OnSkillUsed(SkillId skillId, int hotbarIndex, float cooldown) { var hotbarElement = _hotbarElements[hotbarIndex]; hotbarElement.OnSkillUsed(cooldown); }
public static int GetSkillLevel(this GameObject obj, SkillId skill) { return(GetSkillLevel(obj, null, skill)); }
/// <summary> /// Trains condition in skill. /// </summary> /// <param name="skillId"></param> /// <param name="condition">Condition nr (1-9)</param> /// <param name="amount"></param> public void Train(SkillId skillId, int condition, int amount = 1) { var skill = this.Get(skillId); if (skill == null) return; skill.Train(condition, amount); }
/// <summary> /// Returns true if creature has skill and its rank is equal /// or greater than the given rank. /// </summary> /// <param name="id"></param> /// <param name="rank"></param> /// <returns></returns> public bool Has(SkillId id, SkillRank rank = SkillRank.Novice) { var skill = this.Get(id); return (skill != null && skill.Info.Rank >= rank); }
/// <summary> /// Runs and resets callback (it one was set) /// </summary> /// <param name="skillId"></param> public void Callback(SkillId skillId) { lock (_callbacks) { Action callback; _callbacks.TryGetValue(skillId, out callback); if (callback == null) return; callback(); _callbacks[skillId] = null; } }
/// <summary> /// Adds callback /// </summary> /// <param name="skillId"></param> /// <param name="action"></param> public void Callback(SkillId skillId, Action action) { lock (_callbacks) _callbacks[skillId] = action; }
/// <summary> /// Returns true if rank of skill is equal. /// </summary> /// <param name="id"></param> /// <param name="rank"></param> /// <returns></returns> public bool Is(SkillId id, SkillRank rank) { var skill = this.Get(id); return(skill != null && skill.Info.Rank == rank); }
/// <summary> /// Returns true if creature has skill and its rank is equal /// or greater than the given rank. /// </summary> /// <param name="id"></param> /// <param name="rank"></param> /// <returns></returns> public bool Has(SkillId id, SkillRank rank = SkillRank.Novice) { var skill = this.Get(id); return(skill != null && skill.Info.Rank >= rank); }
/// <summary> /// Tries to learn the given tier for the given skill (if allowed) /// </summary> /// <returns>Whether it succeeded</returns> public bool TryLearn(SkillId id) { return(TryLearn(id, SkillTierId.Apprentice)); }
/// <summary> /// Add a new Skill to this SkillCollection if its not a profession or the character still has professions left /// </summary> public Skill Add(SkillId skill, uint value, uint max, bool ignoreRestrictions) { return(Add(SkillHandler.Get(skill), value, max, ignoreRestrictions)); }
/// <summary>Adds and returns a skill with max values</summary> public void LearnMax(SkillId id) { LearnMax(SkillHandler.Get(id)); }
/// <summary> /// Returns whether the given skill is known to the player /// </summary> public bool Contains(SkillId skill) { return(m_skills.ContainsKey(skill)); }
/// <summary> /// Adds skill silently. Returns false if the skill already exists, /// with a rank that's equal or higher. /// </summary> /// <param name="skillId"></param> /// <param name="skillRank"></param> /// <param name="raceId"></param> public bool Add(SkillId skillId, SkillRank skillRank, int raceId) { if (!AuraData.SkillDb.Exists((int)skillId)) { Log.Warning("CreatureSkills.Add: Skill '{0}' not found in data.", skillId); return false; } return this.Add(new Skill(_creature, skillId, skillRank, raceId)); }
/// <summary> /// Returns true if the specified skill is active (somewhere /// between Prepare and Complete/Cancel). /// </summary> /// <param name="skillId"></param> /// <returns></returns> public bool IsActive(SkillId skillId) { return(this.ActiveSkill != null && this.ActiveSkill.Info.Id == skillId); }
public Skill GetSafe(SkillId id) { var r = this.Get(id); if (r == null) throw new ModerateViolation("Tried to get nonexistant skill {0}.", id); return r; }
/// <summary> /// Returns true if the specified skill is active and on state "Ready". /// </summary> /// <param name="skillId"></param> /// <returns></returns> public bool IsReady(SkillId skillId) { return(this.IsActive(skillId) && this.ActiveSkill.State == SkillState.Ready); }
/// <summary> /// Returns true if the specified skill is active (somewhere /// between Prepare and Complete/Cancel). /// </summary> /// <param name="skillId"></param> /// <returns></returns> public bool IsActive(SkillId skillId) { return (this.ActiveSkill != null && this.ActiveSkill.Info.Id == skillId); }
/// <summary> /// Cancels given skill if it's active after the given time span. /// </summary> /// <param name="skillId"></param> /// <param name="timeSpan"></param> public void CancleAfter(SkillId skillId, TimeSpan timeSpan) { _autoCancel = skillId; _autoCancelTime = DateTime.Now.Add(timeSpan); }
/// <summary> /// For all things that depend on info of all spells from first Init-round and other things /// </summary> internal void Init2() { if (inited) { return; } inited = true; IsChanneled = AttributesEx.HasAnyFlag(SpellAttributesEx.Channeled_1 | SpellAttributesEx.Channeled_2) || // don't use Enum.HasFlag! ChannelInterruptFlags > 0; IsPassive = (!IsChanneled && Attributes.HasFlag(SpellAttributes.Passive)) || // tracking spells are also passive HasEffectWith(effect => effect.AuraType == AuraType.TrackCreatures) || HasEffectWith(effect => effect.AuraType == AuraType.TrackResources) || HasEffectWith(effect => effect.AuraType == AuraType.TrackStealthed); foreach (var effect in Effects) { effect.Init2(); if (effect.IsHealEffect) { IsHealSpell = true; } if (effect.EffectType == SpellEffectType.NormalizedWeaponDamagePlus) { IsDualWieldAbility = true; } } InitAura(); if (IsChanneled) { if (Durations.Min == 0) { Durations.Min = Durations.Max = 1000; } foreach (var effect in Effects) { if (effect.IsPeriodic) { ChannelAmplitude = effect.Amplitude; break; } } } IsOnNextStrike = Attributes.HasAnyFlag(SpellAttributes.OnNextMelee | SpellAttributes.OnNextMelee_2); // don't use Enum.HasFlag! IsRangedAbility = !IsTriggeredSpell && (Attributes.HasAnyFlag(SpellAttributes.Ranged) || AttributesExC.HasFlag(SpellAttributesExC.ShootRangedWeapon)); IsStrikeSpell = HasEffectWith(effect => effect.IsStrikeEffect); IsWeaponAbility = IsRangedAbility || IsOnNextStrike || IsStrikeSpell; DamageIncreasedByAP = DamageIncreasedByAP || (PowerType == PowerType.Rage && SchoolMask == DamageSchoolMask.Physical); IsFinishingMove = AttributesEx.HasAnyFlag(SpellAttributesEx.FinishingMove) || HasEffectWith(effect => effect.PointsPerComboPoint > 0 && effect.EffectType != SpellEffectType.Dummy); TotemEffect = GetFirstEffectWith(effect => effect.HasTarget( ImplicitTargetType.TotemAir, ImplicitTargetType.TotemEarth, ImplicitTargetType.TotemFire, ImplicitTargetType.TotemWater)); // Required Item slot for weapon abilities if (RequiredItemClass == ItemClass.Armor && RequiredItemSubClassMask == ItemSubClassMask.Shield) { EquipmentSlot = EquipmentSlot.OffHand; } else { EquipmentSlot = (IsRangedAbility || AttributesExC.HasFlag(SpellAttributesExC.RequiresWand)) ? EquipmentSlot.ExtraWeapon : (AttributesExC.HasFlag(SpellAttributesExC.RequiresOffHandWeapon) ? EquipmentSlot.OffHand : (AttributesExC.HasFlag(SpellAttributesExC.RequiresMainHandWeapon) ? EquipmentSlot.MainHand : EquipmentSlot.End)); } HasIndividualCooldown = CooldownTime > 0 || (IsWeaponAbility && !IsOnNextStrike && EquipmentSlot != EquipmentSlot.End); //IsAoe = HasEffectWith((effect) => { // if (effect.ImplicitTargetA == ImplicitTargetType.) // effect.ImplicitTargetA = ImplicitTargetType.None; // if (effect.ImplicitTargetB == ImplicitTargetType.Unused_EnemiesInAreaChanneledWithExceptions) // effect.ImplicitTargetB = ImplicitTargetType.None; // return false; //}); var profEffect = GetEffect(SpellEffectType.SkillStep); if (profEffect != null) { TeachesApprenticeAbility = profEffect.BasePoints == 0; } IsProfession = !IsRangedAbility && Ability != null && Ability.Skill.Category == SkillCategory.Profession; IsEnhancer = SpellClassSet != 0 && !SpellClassMask.Contains(val => val != 0) && HasEffectWith(effect => effect.AffectMask.Contains(val => val != 0)); IsFishing = HasEffectWith(effect => effect.HasTarget(ImplicitTargetType.SelfFishing)); IsSkinning = HasEffectWith(effect => effect.EffectType == SpellEffectType.Skinning); IsTameEffect = HasEffectWith(effect => effect.EffectType == SpellEffectType.TameCreature); if (Id == 18425) { ToString(); } if (IsPreventionDebuff || Mechanic.IsNegative()) { HasHarmfulEffects = true; HasBeneficialEffects = false; HarmType = HarmType.Harmful; } else { HasHarmfulEffects = HasEffectWith(effect => effect.HarmType == HarmType.Harmful); HasBeneficialEffects = HasEffectWith(effect => effect.HarmType == HarmType.Beneficial); if (HasHarmfulEffects != HasBeneficialEffects && !HasEffectWith(effect => effect.HarmType == HarmType.Neutral)) { HarmType = HasHarmfulEffects ? HarmType.Harmful : HarmType.Beneficial; } else { HarmType = HarmType.Neutral; } } ReqDeadTarget = TargetFlags.HasAnyFlag(SpellTargetFlags.Corpse | SpellTargetFlags.PvPCorpse | SpellTargetFlags.UnitCorpse); CostsMana = PowerCost > 0 || PowerCostPercentage > 0; HasTargets = !HasEffectWith(effect => effect.HasTargets); CasterIsTarget = HasTargets && HasEffectWith(effect => effect.HasTarget(ImplicitTargetType.Self)); //HasSingleNotSelfTarget = IsAreaSpell = HasEffectWith(effect => effect.IsAreaEffect); IsDamageSpell = HasHarmfulEffects && !HasBeneficialEffects && HasEffectWith(effect => effect.EffectType == SpellEffectType.Attack || effect.EffectType == SpellEffectType.EnvironmentalDamage || effect.EffectType == SpellEffectType.InstantKill || effect.EffectType == SpellEffectType.SchoolDamage || effect.IsStrikeEffect); if (DamageMultipliers[0] <= 0) { DamageMultipliers[0] = 1; } IsHearthStoneSpell = HasEffectWith(effect => effect.HasTarget(ImplicitTargetType.HeartstoneLocation)); ForeachEffect(effect => { if (effect.EffectType == SpellEffectType.Skill) { SkillId = (SkillId)effect.MiscValue; } }); Schools = Utility.GetSetIndices<DamageSchool>((uint)SchoolMask); if (Schools.Length == 0) { Schools = new[] { DamageSchool.Physical }; } RequiresCasterOutOfCombat = !HasHarmfulEffects && CastDelay > 0 && (Attributes.HasFlag(SpellAttributes.CannotBeCastInCombat) || AttributesEx.HasFlag(SpellAttributesEx.RemainOutOfCombat) || AuraInterruptFlags.HasFlag(AuraInterruptFlags.OnStartAttack)); if (RequiresCasterOutOfCombat) { // We fail if being attacked (among others) InterruptFlags |= InterruptFlags.OnTakeDamage; } IsThrow = AttributesExC.HasFlag(SpellAttributesExC.ShootRangedWeapon) && Attributes.HasFlag(SpellAttributes.Ranged) && Ability != null && Ability.Skill.Id == SkillId.Thrown; HasModifierEffects = HasEffectWith(effect => effect.AuraType == AuraType.AddModifierFlat || effect.AuraType == AuraType.AddModifierPercent); ForeachEffect(effect => { for (var i = 0; i < 3; i++) { AllAffectingMasks[i] |= effect.AffectMask[i]; } }); if (Range.MaxDist == 0) { Range.MaxDist = 5; } if (RequiredToolIds == null) { RequiredToolIds = new uint[0]; } else { if (RequiredToolIds.Length > 0 && (RequiredToolIds[0] > 0 || RequiredToolIds[1] > 0)) { SpellHandler.SpellsRequiringTools.Add(this); } ArrayUtil.PruneVals(ref RequiredToolIds); } ArrayUtil.PruneVals(ref RequiredTotemCategories); ForeachEffect(effect => { if (effect.SpellEffectHandlerCreator != null) { EffectHandlerCount++; } }); //IsHealSpell = HasEffectWith((effect) => effect.IsHealEffect); }
public CombatSkillResult UseWithoutRangeCheck(Creature attacker, Skill skill, long targetEntityId, Creature mainTarget, SkillId interceptingSkillId = SkillId.None) { //Against Smash Skill smash = mainTarget.Skills.Get(SkillId.Smash); if (interceptingSkillId == SkillId.None && smash != null && mainTarget.Skills.IsReady(SkillId.Smash)) { interceptingSkillId = SkillId.Smash; } var rightWeapon = attacker.Inventory.RightHand; var leftWeapon = attacker.Inventory.LeftHand; var dualWield = (rightWeapon != null && leftWeapon != null && leftWeapon.Data.WeaponType != 0 && (leftWeapon.HasTag("/weapon/edged/") || leftWeapon.HasTag("/weapon/blunt/"))); // Against Combat Mastery Skill combatMastery = mainTarget.Skills.Get(SkillId.CombatMastery); var simultaneousAttackStun = 0; if (interceptingSkillId == SkillId.None) { if (combatMastery != null && (mainTarget.Skills.ActiveSkill == null || mainTarget.Skills.ActiveSkill == combatMastery || mainTarget.Skills.IsReady(SkillId.FinalHit)) && mainTarget.IsInBattleStance && mainTarget.Target == attacker && mainTarget.AttemptingAttack && (!mainTarget.IsStunned || mainTarget.IsKnockedDown)) { var attackerStunTime = CombatMastery.GetAttackerStun(attacker, attacker.RightHand, false); var mainTargetStunTime = CombatMastery.GetAttackerStun(mainTarget, mainTarget.Inventory.RightHand, false); var slowestStun = CombatMastery.GetAttackerStun(1, AttackSpeed.VerySlow, false); var additionalStun = slowestStun + (CombatMastery.GetAttackerStun(5, AttackSpeed.VeryFast, false) / 2); //Fastest stun divided by two so that the fastest stun doesn't always beat out the slowest stun. The addition is so that the subtration (Ex. additionalStun - attackerStunTime) ends in the desired range. var formulaMultiplier = 320; //Multiplier to keep the result reasonable, found through trial and error? var formulaEqualizer = 50; //Balances the subtraction to keep the result in a reasonable range and balanced out no matter the order. double chances = ((((additionalStun - attackerStunTime) / slowestStun) * formulaMultiplier) - (((additionalStun - mainTargetStunTime) / slowestStun) * formulaMultiplier)) + formulaEqualizer; //Probability in percentage that you will not lose. chances = Math2.Clamp(0.0, 99.0, chances); //Cap the stun, just in case. if (((mainTarget.LastKnockedBackBy == attacker && mainTarget.KnockDownTime > attacker.KnockDownTime && mainTarget.KnockDownTime.AddMilliseconds(mainTargetStunTime) > DateTime.Now || /*attackerStunTime > initialTargetStunTime && */ !Math2.Probability(chances) && !(attacker.LastKnockedBackBy == mainTarget && attacker.KnockDownTime > mainTarget.KnockDownTime && attacker.KnockDownTime.AddMilliseconds(attackerStunTime) > DateTime.Now)))) { if (!Math2.Probability(chances)) //Probability in percentage that it will be an interception instead of a double hit. Always in favor of the faster attacker. { if (mainTarget.CanTarget(attacker) && mainTarget.Can(Locks.Attack)) //TODO: Add Hit lock when available. { var skillHandler = ChannelServer.Instance.SkillManager.GetHandler <ICombatSkill>(combatMastery.Info.Id); if (skillHandler == null) { Log.Error("CombatMastery.Use: Target's skill handler not found for '{0}'.", combatMastery.Info.Id); return(CombatSkillResult.Okay); } ((CombatMastery)skillHandler).UseWithoutRangeCheck(mainTarget, combatMastery, attacker.EntityId, attacker, SkillId.CombatMastery); return(CombatSkillResult.Okay); } } else { interceptingSkillId = SkillId.CombatMastery; if (mainTarget.CanTarget(attacker) && mainTarget.Can(Locks.Attack)) //TODO: Add Hit lock when available. { var skillHandler = ChannelServer.Instance.SkillManager.GetHandler <ICombatSkill>(combatMastery.Info.Id); if (skillHandler == null) { Log.Error("CombatMastery.Use: Target's skill handler not found for '{0}'.", combatMastery.Info.Id); } else { ((CombatMastery)skillHandler).UseWithoutRangeCheck(mainTarget, combatMastery, attacker.EntityId, attacker, SkillId.CombatMastery); simultaneousAttackStun = attacker.Stun; attacker.Stun = 0; } } } } else { if (Math2.Probability(chances)) //Probability in percentage that it will be an interception instead of a double hit. Always in favor of the faster attacker. { interceptingSkillId = SkillId.CombatMastery; } else { interceptingSkillId = SkillId.CombatMastery; if (mainTarget.CanTarget(attacker) && mainTarget.Can(Locks.Attack)) //TODO: Add Hit lock when available. { var skillHandler = ChannelServer.Instance.SkillManager.GetHandler <ICombatSkill>(combatMastery.Info.Id); if (skillHandler == null) { Log.Error("CombatMastery.Use: Target's skill handler not found for '{0}'.", combatMastery.Info.Id); } else { ((CombatMastery)skillHandler).UseWithoutRangeCheck(mainTarget, combatMastery, attacker.EntityId, attacker, SkillId.CombatMastery); simultaneousAttackStun = attacker.Stun; attacker.Stun = 0; } } } } } } attacker.StopMove(); mainTarget.StopMove(); // Get targets, incl. splash. var targets = new HashSet <Creature>() { mainTarget }; targets.UnionWith(attacker.GetTargetableCreaturesInCone(mainTarget.GetPosition(), attacker.GetTotalSplashRadius(), attacker.GetTotalSplashAngle())); // Counter if (Counterattack.Handle(targets, attacker)) { return(CombatSkillResult.Okay); } var magazine = attacker.Inventory.Magazine; var maxHits = (byte)(attacker.IsDualWielding ? 2 : 1); int prevId = 0; var knockedBackTargets = new HashSet <long>(); for (byte i = 1; i <= maxHits; ++i) { var weapon = (i == 1 ? rightWeapon : leftWeapon); var weaponIsKnuckle = (weapon != null && weapon.Data.HasTag("/knuckle/")); AttackerAction aAction; if (interceptingSkillId == SkillId.Smash) { aAction = new AttackerAction(CombatActionType.SimultaneousHit, attacker, targetEntityId); } else if (interceptingSkillId == SkillId.CombatMastery) { aAction = new AttackerAction(CombatActionType.SimultaneousHit, attacker, targetEntityId); } else { aAction = new AttackerAction(CombatActionType.Attacker, attacker, targetEntityId); } aAction.Set(AttackerOptions.Result); if (attacker.IsDualWielding) { aAction.Set(AttackerOptions.DualWield); aAction.WeaponParameterType = (byte)(i == 1 ? 2 : 1); } var cap = new CombatActionPack(attacker, skill.Info.Id); if (interceptingSkillId != SkillId.Smash) { cap.Add(aAction); } cap.Hit = i; cap.Type = (attacker.IsDualWielding ? CombatActionPackType.TwinSwordAttack : CombatActionPackType.NormalAttack); cap.PrevId = prevId; prevId = cap.Id; var mainDamage = (i == 1 ? attacker.GetRndRightHandDamage() : attacker.GetRndLeftHandDamage()); foreach (var target in targets) { // Skip targets that were knocked back, as they aren't in // range anymore. if (knockedBackTargets.Contains(target.EntityId)) { continue; } target.StopMove(); TargetAction tAction; if (target == mainTarget) { if (interceptingSkillId == SkillId.Smash) { tAction = new TargetAction(CombatActionType.CounteredHit, target, attacker, SkillId.Smash); } else if (interceptingSkillId == SkillId.CombatMastery) { tAction = new TargetAction(CombatActionType.CounteredHit, target, attacker, target.Skills.IsReady(SkillId.FinalHit) ? SkillId.FinalHit : SkillId.CombatMastery); } else { tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, target.Skills.IsReady(SkillId.FinalHit) ? SkillId.FinalHit : SkillId.CombatMastery); } } else { tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, target.Skills.IsReady(SkillId.FinalHit) ? SkillId.FinalHit : SkillId.CombatMastery); } tAction.Set(TargetOptions.Result); cap.Add(tAction); if (target == mainTarget && interceptingSkillId == SkillId.Smash) { cap.Add(aAction); } // Base damage var damage = mainDamage; // Elementals damage *= attacker.CalculateElementalDamageMultiplier(target); // Splash modifier if (target != mainTarget) { damage *= attacker.GetSplashDamage(weapon); } // Critical Hit var critChance = (i == 1 ? attacker.GetRightCritChance(target.Protection) : attacker.GetLeftCritChance(target.Protection)); CriticalHit.Handle(attacker, critChance, ref damage, tAction); // Subtract target def/prot SkillHelper.HandleDefenseProtection(target, ref damage); // Conditions SkillHelper.HandleConditions(attacker, target, ref damage); // Defense Defense.Handle(aAction, tAction, ref damage); // Mana Shield ManaShield.Handle(target, ref damage, tAction); // Heavy Stander // Can only happen on the first hit var pinged = (cap.Hit == 1 && HeavyStander.Handle(attacker, target, ref damage, tAction)); // Deal with it! if (damage > 0) { target.TakeDamage(tAction.Damage = damage, attacker); SkillHelper.HandleInjury(attacker, target, damage); } // Knock down on deadly if (target.Conditions.Has(ConditionsA.Deadly)) { tAction.Set(TargetOptions.KnockDown); tAction.Stun = GetTargetStun(attacker, weapon, tAction.IsKnockBack); } // Aggro if (target == mainTarget) { target.Aggro(attacker); } // Evaluate caused damage if (!target.IsDead) { if (tAction.SkillId != SkillId.Defense) { target.Stability -= this.GetStabilityReduction(attacker, weapon) / maxHits; // React normal for CombatMastery, knock down if // FH and not dual wield, don't knock at all if dual. if (skill.Info.Id != SkillId.FinalHit) { // Originally we thought you knock enemies back, unless it's a critical // hit, but apparently you knock *down* under normal circumstances. // More research to be done. if (target.IsUnstable && target.Is(RaceStands.KnockBackable)) { //tAction.Set(tAction.Has(TargetOptions.Critical) ? TargetOptions.KnockDown : TargetOptions.KnockBack); tAction.Set(TargetOptions.KnockDown); } } else if (!attacker.IsDualWielding && !weaponIsKnuckle && target.Is(RaceStands.KnockBackable)) { target.Stability = Creature.MinStability; tAction.Set(TargetOptions.KnockDown); } } } else { tAction.Set(TargetOptions.FinishingKnockDown); } // React to knock back if (tAction.IsKnockBack) { attacker.Shove(target, KnockBackDistance); if (target == mainTarget) { aAction.Set(AttackerOptions.KnockBackHit2); } knockedBackTargets.Add(target.EntityId); } // Set stun time if not defended, Defense handles the stun // in case the target used it. if (tAction.SkillId != SkillId.Defense) { if (target == mainTarget) { aAction.Stun = GetAttackerStun(attacker, weapon, tAction.IsKnockBack && skill.Info.Id != SkillId.FinalHit); } tAction.Stun = GetTargetStun(attacker, weapon, tAction.IsKnockBack); } if (target == mainTarget) { // Set increased stun if target pinged if (pinged) { aAction.Stun = GetAttackerStun(attacker, weapon, true); } // Second hit doubles stun time for normal hits if (cap.Hit == 2 && !tAction.IsKnockBack && !pinged) { aAction.Stun *= 2; } // Update current weapon SkillHelper.UpdateWeapon(attacker, target, ProficiencyGainType.Melee, weapon); // Consume stamina for weapon var staminaUsage = (rightWeapon != null && rightWeapon.Data.StaminaUsage != 0 ? rightWeapon.Data.StaminaUsage : 0.7f) + (dualWield ? leftWeapon.Data.StaminaUsage : 0f); if (attacker.Stamina < staminaUsage) { Send.Notice(attacker, Localization.Get("Your stamina is too low to fight properly!")); } attacker.Stamina -= staminaUsage; // No second hit if defended, pinged, or knocked back if (tAction.IsKnockBack || tAction.SkillId == SkillId.Defense || pinged) { // Set to 1 to prevent second run maxHits = 1; // Remove dual wield option if last hit doesn't come from // the second weapon. If this isn't done, the client shows // the second hit. if (cap.Hit != 2) { aAction.Options &= ~AttackerOptions.DualWield; } } // Reduce attacker's knockback stun in new combat, to allow // movement after sooner. // It's unknown when exactly this was added, but older EU logs // don't have this packet, so we'll assume it was part of the the // new combat, which's purpose was to be faster. // Sending the packet appears to reset the movement lock, and // officials seem to send this about 1s after the attack, for // an effective 1s movement lock after an attack. // If it's send for non-knockback hits, it can add a delay, // maybe increasing the time of the lock, like for dual-wielding. if (AuraData.FeaturesDb.IsEnabled("CombatSystemRenewal")) { if (tAction.IsKnockBack) { Task.Delay(1000).ContinueWith(_ => Send.CharacterLockUpdate(attacker, 18, 1500)); } } } } // Handle cap.Handle(); } attacker.AttemptingAttack = false; return(CombatSkillResult.Okay); }
/// <summary> /// Removes stat mod. /// </summary> /// <param name="stat"></param> /// <param name="source"></param> /// <param name="ident"></param> public void Remove(Stat stat, StatModSource source, SkillId ident) { this.Remove(stat, source, (long)ident); }
// ^ Skill check ^ /// <summary> /// Initializes upgrade effect, setting required default values. /// You should generally use this constructor! /// </summary> /// <param name="type"></param> public UpgradeEffect(UpgradeType type) { Type = type; Unk1 = 0; Unk2 = 0; Stat = 0; ValueType = 0; Value = 0; SkillId = 0; SkillVar = 0; Unk4 = 0x0A; Unk5 = 0; CheckType = UpgradeCheckType.None; CheckStat = 0; CheckRace = 0; CheckPtj = 0; CheckMonth = 0; CheckBroken = false; CheckTitleId = 0; CheckCondition = 0; CheckValueType = 0; CheckValue = 0; CheckSkillId = 0; CheckSkillRank = 0; }
/// <summary> /// Changes effect to check for a skill rank. /// </summary> /// <param name="skillId"></param> /// <param name="checkType">SkillRankEqual, SkillRankGreaterThan, or SkillRankLowerThan</param> /// <param name="rank"></param> public void SetSkillCheck(SkillId skillId, UpgradeCheckType checkType, SkillRank rank) { if (checkType < UpgradeCheckType.SkillRankEqual || checkType > UpgradeCheckType.SkillRankLowerThan) throw new ArgumentException(checkType + " is not a skill check."); CheckType = checkType; CheckSkillId = skillId; CheckValue = 0; CheckSkillRank = rank; }
/// <summary> /// Returns success chance, based on skill, option set, and powder /// used. /// <remarks> /// Unofficial. It kinda matches the debug output of the client, /// but it is a little off. /// </remarks> /// </summary> /// <param name="creature"></param> /// <param name="rightHand"></param> /// <param name="skill"></param> /// <param name="optionSetData"></param> /// <returns></returns> public static float GetChance(Creature creature, Item rightHand, SkillId skillId, OptionSetData optionSetData) { // Check right hand, only use it if it's powder if (rightHand != null && !rightHand.HasTag("/enchant/powder/")) { rightHand = null; } // Get base chance, based on skill and powder var baseChance = _baseChanceB00; // (Blessed) Magic Powder/None if (skillId == SkillId.Enchant && rightHand != null) { if (rightHand.HasTag("/powder02/")) // Elite Magic Powder { baseChance = _baseChanceB05; } else if (rightHand.HasTag("/powder03/")) // Elven Magic Powder { baseChance = _baseChanceB10; } else if (rightHand.HasTag("/powder01/")) // Ancient Magic Powder { baseChance = _baseChanceB50; } else if (rightHand.HasTag("/powder04/") && rightHand.Info.Id == 85865) // Notorious Magic Powder { baseChance = _baseChanceB60; } } // Get chance var rank = Math2.Clamp(0, _baseChanceB00.Length - 1, (int)optionSetData.Rank - 1); var chance = baseChance[rank]; var intBonus = 1f; var thursdayBonus = 0f; // Int bonus if using powder if (skillId == SkillId.Enchant && rightHand != null) { intBonus = 1f + ((creature.Int - 35f) / 350f); } // Thursday bonus if (ErinnTime.Now.Month == 4) { thursdayBonus = Math.Max(0, (15 - rank) / 2f); } // Result var result = Math2.Clamp(0, 90, chance * intBonus + thursdayBonus); // Debug if (creature.Titles.SelectedTitle == TitleId.devCAT) { Send.ServerMessage(creature, "Debug: Enchant success chance: {0:0} (base: {1:0}, int: {2:0}, thu: {3:0})", result, chance, (chance / 1f * (intBonus - 1f)), thursdayBonus); } return(result); }
public QuestRewardSkill(SkillId id, SkillRank rank) { this.SkillId = id; this.Rank = rank; }
public static int GetSkillLevel(this GameObject obj, GameObject against, SkillId skill) { return(obj.dispatch1ESkillLevel(skill, against, SkillCheckFlags.UnderDuress)); }
private void Update() { if (Input.GetMouseButton(0) && m_move && m_skillId != SkillId.NONE) { Ray _ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit _hit; int _layerMask = 1 << 8; if (Physics.Raycast(_ray, out _hit, 100, _layerMask)) { if (_hit.collider.gameObject.tag.Equals("Plane")) { MapData _data = _hit.transform.GetComponent <MapData>(); if (CheckCanMove(_data.Pos.m_row, _data.Pos.m_col, _data.Data)) { if (GameManager.SceneConfigId == 0) { RookieModule _rookieModule = (RookieModule)GameManager.GameManagerObj.GetComponent <GameManager>().GetModuleByName("RookieModule"); _rookieModule.RefreshMap(); } else { SceneModule _sceneModule = (SceneModule)GameManager.GameManagerObj.GetComponent <GameManager>().GetModuleByName("SceneModule"); _sceneModule.RefreshMap(); } IntEventArgs args = new IntEventArgs((int)m_skillId); EventManager.SendEvent(HLEventId.PLAYER_START_MOVE, args); m_state = State.Move; float _targetPosX = _data.Pos.m_row * DiffX; float _targetPosZ = _data.Pos.m_col * DiffZ; if (m_skillId == SkillId.JU) { Sequence _sequence = DOTween.Sequence(); _sequence.Append(transform.DOMove(new Vector3(_targetPosX, this.transform.position.y, _targetPosZ), 0.4f).SetEase(m_juCurve)); _sequence.AppendCallback(MoveEnd); _sequence.SetAutoKill(true); } else if (m_skillId == SkillId.MA || m_skillId == SkillId.PAO) { float _targetPosY = 0f; if (_data.Data == MapDataType.GAOTAI) { _targetPosY = 1.0f; } float _midTargetPosX = 0.0f; float _midTargetPosZ = 0.0f; if (_data.Pos.m_row == m_playerPos.m_row + 2) { _midTargetPosX = (m_playerPos.m_row + 1) * DiffX; _midTargetPosZ = this.transform.position.z; } else if (_data.Pos.m_row == m_playerPos.m_row - 2) { _midTargetPosX = (m_playerPos.m_row - 1) * DiffX; _midTargetPosZ = this.transform.position.z; } else if (_data.Pos.m_col == m_playerPos.m_col + 2) { _midTargetPosX = this.transform.position.x; _midTargetPosZ = (m_playerPos.m_col + 1) * DiffZ; } else if (_data.Pos.m_col == m_playerPos.m_col - 2) { _midTargetPosX = this.transform.position.x; _midTargetPosZ = (m_playerPos.m_col - 1) * DiffZ; } Sequence _sequence = DOTween.Sequence(); _sequence.Append(transform.DOMove(new Vector3(_midTargetPosX, this.transform.position.y, _midTargetPosZ), 0.3f).SetEase(m_maCurve1)); _sequence.Append(transform.DOJump(new Vector3(_targetPosX, _targetPosY, _targetPosZ), 0.4f, 1, 0.3f).SetEase(m_maCurve2)); _sequence.AppendCallback(MoveEnd); _sequence.SetAutoKill(true); } else if (m_skillId == SkillId.XIANG) { float _targetPosY = 0f; if (_data.Data == MapDataType.GAOTAI) { _targetPosY = 1.0f; } Sequence _sequence = DOTween.Sequence(); _sequence.Append(transform.DOJump(new Vector3(_targetPosX, _targetPosY, _targetPosZ), 0.4f, 1, 0.5f).SetEase(m_xiangCurve)); _sequence.AppendCallback(MoveEnd); _sequence.SetAutoKill(true); } m_skillId = SkillId.NONE; m_playerPos.m_row = _data.Pos.m_row; m_playerPos.m_col = _data.Pos.m_col; } } } } }
/// <summary> /// Makes creature prepare given skill. /// </summary> /// <param name="skillId"></param> /// <returns></returns> protected IEnumerable PrepareSkill(SkillId skillId) { // Get skill var skill = this.Creature.Skills.Get(skillId); if (skill == null) { Log.Warning("AI.PrepareSkill: AI '{0}' tried to preapre skill that its creature '{1}' doesn't have.", this.GetType().Name, this.Creature.Race); yield break; } // Cancel previous skill if (this.Creature.Skills.ActiveSkill != null) { this.ExecuteOnce(this.CancelSkill()); } // Explicit handling if (skillId == SkillId.WebSpinning) { var skillHandler = ChannelServer.Instance.SkillManager.GetHandler <WebSpinning>(skillId); skillHandler.Prepare(this.Creature, skill, 0, null); skillHandler.Complete(this.Creature, skill, null); } // Try to handle implicitly else { // Get preparable handler var skillHandler = ChannelServer.Instance.SkillManager.GetHandler <IPreparable>(skillId); if (skillHandler == null) { Log.Unimplemented("AI.PrepareSkill: Missing handler or IPreparable for '{0}'.", skillId); yield break; } // Get readyable handler. // TODO: There are skills that don't have ready, but go right to // use from Prepare. Handle somehow. var readyHandler = skillHandler as IReadyable; if (readyHandler == null) { Log.Unimplemented("AI.PrepareSkill: Missing IReadyable for '{0}'.", skillId); yield break; } this.SharpMind(skillId, SharpMindStatus.Loading); // Prepare skill try { skillHandler.Prepare(this.Creature, skill, skill.RankData.LoadTime, null); this.Creature.Skills.SkillInProgress = true; // Probably not needed for AIs? } catch (NullReferenceException) { Log.Warning("AI.PrepareSkill: Null ref exception while preparing '{0}', skill might have parameters.", skillId); } catch (NotImplementedException) { Log.Unimplemented("AI.PrepareSkill: Skill prepare method for '{0}'.", skillId); } // Wait for loading to be done foreach (var action in this.Wait(skill.RankData.LoadTime)) { yield return(action); } // Call ready, in case it sets something important readyHandler.Ready(this.Creature, skill, null); this.SharpMind(skillId, SharpMindStatus.Loaded); } }
/// <summary> /// Changes effect to give a skill bonus. /// </summary> /// <param name="skillId"></param> /// <param name="skillVar"></param> /// <param name="value"></param> public void SetSkillEffect(SkillId skillId, short skillVar, short value, UpgradeValueType valueType) { Unk2 = 0x1B; Stat = UpgradeStat.Skill; ValueType = valueType; Value = value; SkillId = skillId; SkillVar = skillVar; }
public LanguageDescription(ChatLanguage lang, SpellId spell, SkillId skill) { Language = lang; SpellId = spell; SkillId = skill; }
public bool IsOnCooldown(SkillId skillId) { if (this._cooldownDictionary.ContainsKey(skillId)) return (DateTime.Now < this._cooldownDictionary[skillId]); return false; }
protected QuestPrerequisite ReachedRank(SkillId skillId, SkillRank rank) { return(new QuestPrerequisiteReachedRank(skillId, rank)); }
public QuestPrerequisiteNotSkill(SkillId skillId, SkillRank rank = SkillRank.Novice) { this.Id = skillId; this.Rank = rank; }
protected QuestPrerequisite NotSkill(SkillId skillId, SkillRank rank = SkillRank.Novice) { return(new QuestPrerequisiteNotSkill(skillId, rank)); }
public QuestRewardSkill(SkillId id, SkillRank rank, int training = 0) { this.SkillId = id; this.Rank = rank; this.Training = training; }
protected QuestObjective ReachRank(SkillId skillId, SkillRank rank) { return(new QuestObjectiveReachRank(skillId, rank)); }
protected QuestObjective UseSkill(SkillId skillId) { return(new QuestObjectiveUseSkill(skillId)); }
/// <summary> /// Returns skill by id, or null. /// </summary> /// <param name="id"></param> /// <returns></returns> public Skill Get(SkillId id) { Skill result; lock (_skills) _skills.TryGetValue(id, out result); return result; }
protected QuestReward Skill(SkillId skillId, SkillRank rank) { return(new QuestRewardSkill(skillId, rank, 0)); }
/// <summary> /// Adds skill at rank, or updates it. /// Sends appropriate packets. /// </summary> /// <param name="id"></param> /// <param name="rank"></param> public void Give(SkillId id, SkillRank rank) { var skill = this.Get(id); if (skill == null) { this.Add(skill = new Skill(_creature, id, rank, _creature.RaceId)); Send.SkillInfo(_creature, skill); if (_creature.Region != Region.Limbo) Send.RankUp(_creature); ChannelServer.Instance.Events.OnSkillRankChanged(_creature, skill); } else { this.RemoveBonuses(skill); skill.ChangeRank(rank); Send.SkillRankUp(_creature, skill); if (_creature.Region != Region.Limbo) Send.RankUp(_creature, skill.Info.Id); this.AddBonuses(skill); } Send.StatUpdate(_creature, StatUpdateType.Private, Stat.Str, Stat.Int, Stat.Dex, Stat.Will, Stat.Luck, Stat.Life, Stat.LifeInjured, Stat.LifeMaxMod, Stat.LifeMax, Stat.Mana, Stat.ManaMaxMod, Stat.ManaMax, Stat.Stamina, Stat.Hunger, Stat.StaminaMaxMod, Stat.StaminaMax ); Send.StatUpdate(_creature, StatUpdateType.Public, Stat.Life, Stat.LifeInjured, Stat.LifeMaxMod, Stat.LifeMax); this.RankChanged.Raise(_creature, skill); }
protected QuestReward Skill(SkillId skillId, SkillRank rank, int training) { return(new QuestRewardSkill(skillId, rank, training)); }
/// <summary> /// Returns true if rank of skill is equal. /// </summary> /// <param name="id"></param> /// <param name="rank"></param> /// <returns></returns> public bool Is(SkillId id, SkillRank rank) { var skill = this.Get(id); return (skill != null && skill.Info.Rank == rank); }
private void LoadXml(string fileName) { XmlDocument doc = new XmlDocument(); doc.Load(fileName); int nextId = 0; CustomMonsterTemplate newTemplate; foreach (XmlNode monsterNode in doc.DocumentElement.ChildNodes) { if (!monsterNode.Name.Equals("monster")) { continue; } newTemplate = new CustomMonsterTemplate(); if (monsterNode.Attributes != null) { foreach (XmlAttribute attr in monsterNode.Attributes) { if (attr.Name == "name") { newTemplate.TemplateName = attr.Value; } } } foreach (XmlNode mainParam in monsterNode.ChildNodes) { switch (mainParam.Name) { case "name": newTemplate.TemplateName = mainParam.InnerText; break; case "visibleName": newTemplate.Name = mainParam.InnerText; break; case "target_rotation_speed": newTemplate.TargetRotationSpeed = int.Parse(mainParam.InnerText); break; case "check_visibility": newTemplate.CheckVisibility = bool.Parse(mainParam.InnerText); break; case "attack_closest": newTemplate.AttackClosest = bool.Parse(mainParam.InnerText); break; case "sprite": newTemplate.Sprite = mainParam.InnerText; break; case "animation": newTemplate.Animation = mainParam.InnerText; break; case "size": newTemplate.SpriteSize = float.Parse(mainParam.InnerText); break; case "mass": newTemplate.Mass = float.Parse(mainParam.InnerText); break; case "template": MonsterId id = (MonsterId)Enum.Parse(typeof(MonsterId), mainParam.InnerText); MonsterTemplate oldTemplate = GetType(id); newTemplate.SetDefaultTemplate(oldTemplate); break; case "stats": foreach (XmlNode statNode in mainParam.ChildNodes) { switch (statNode.Name) { case "MaxHp": newTemplate.MaxHp = Int32.Parse(statNode.InnerText); break; case "MaxHp_scale": newTemplate.HpLevelScale = Int32.Parse(statNode.InnerText); break; case "MaxSpeed": newTemplate.MaxSpeed = Int32.Parse(statNode.InnerText); break; case "RotationSpeed": newTemplate.RotationSpeed = Int32.Parse(statNode.InnerText); break; case "IsAggressive": newTemplate.IsAggressive = statNode.InnerText.ToLower() == "true"; break; case "AggressionRange": newTemplate.AggressionRange = Int32.Parse(statNode.InnerText); break; case "RambleAround": newTemplate.RambleAround = statNode.InnerText.ToLower() == "true"; break; case "RambleAroundMaxDist": newTemplate.RambleAroundMaxDist = Int32.Parse(statNode.InnerText); break; case "AlertsAllies": newTemplate.AlertsAllies = statNode.InnerText.ToLower() == "true"; break; case "XpReward": newTemplate.XpReward = Int32.Parse(statNode.InnerText); break; } } break; case "spawn_on_die": foreach (XmlNode mNode in mainParam.ChildNodes) { string name = mNode.Name; newTemplate.AddOnSpawnOnDie(name); } break; case "attached_cells": foreach (XmlNode mNode in mainParam.ChildNodes) { string name = mNode.Name; newTemplate.AddAttachedCell(name); } break; case "ai": string aiType = "Blank"; if (mainParam.Attributes != null) { foreach (XmlAttribute attr in mainParam.Attributes) { if (attr.Name == "type") { aiType = attr.Value; } } } if (aiType == null) { continue; } newTemplate.AiType = aiType + "MonsterAI"; foreach (XmlNode statNode in mainParam.ChildNodes) { if (statNode.Name == "set") { string idString = null; string module = null; string param = null; string value = null; if (statNode.Attributes != null) { foreach (XmlAttribute attrib in statNode.Attributes) { switch (attrib.Name) { case "id_module": idString = attrib.Value; break; case "module": module = attrib.Value; break; case "param": param = attrib.Value; break; case "value": value = attrib.Value; break; } } } if ((module != null || idString != null) && param != null && value != null) { int idVal = -1; if (idString != null) { idVal = Int32.Parse(idString); } newTemplate.AddAiParam(idVal, module, param, value); } } else if (statNode.Name == "add") { string idString = null; string module = null; string param = null; string value = null; string priority = "low"; if (statNode.Attributes != null) { foreach (XmlAttribute attrib in statNode.Attributes) { switch (attrib.Name) { case "id_module": idString = attrib.Value; break; case "priority": // "low", "high" priority = attrib.Value; break; case "module": module = attrib.Value; break; case "param": param = attrib.Value; break; case "value": value = attrib.Value; break; } } } if (module != null) { int idNumber = -1; if (idString != null) { idNumber = Int32.Parse(idString); } newTemplate.AddAIModule(idNumber, module, priority, param, value); } } } break; case "add_skills": foreach (XmlNode skillNode in mainParam.ChildNodes) { string skillName = skillNode.Name; SkillId skillId = (SkillId)Enum.Parse(typeof(SkillId), skillName); newTemplate.NewSkills.Add(skillId); foreach (XmlNode skillParamNode in skillNode.ChildNodes) { if (skillParamNode.Name == "add_effect") { string effectName = null; Dictionary <string, string> parameters = new Dictionary <string, string>(); foreach (XmlAttribute attr in skillParamNode.Attributes) { if (attr.Name == "name") { effectName = attr.Value; } else { parameters.Add(attr.Name, attr.Value); } } newTemplate.AddAdditionalSkillEffects(skillId, effectName, parameters); } else if (skillParamNode.Name == "remove_effects") { newTemplate.DisableSkillEffects(skillId); } else { string paramName = skillParamNode.Name; string val = skillParamNode.InnerText; newTemplate.AddSkillModifyInfo(skillId, paramName, val); } } } break; case "modify_skills": foreach (XmlNode skillNode in mainParam.ChildNodes) { string skillName = skillNode.Name; SkillId skillId = (SkillId)Enum.Parse(typeof(SkillId), skillName); foreach (XmlNode skillParamNode in skillNode.ChildNodes) { if (skillParamNode.Name == "add_effect") { string effectName = null; Dictionary <string, string> parameters = new Dictionary <string, string>(); foreach (XmlAttribute attr in skillParamNode.Attributes) { if (attr.Name == "name") { effectName = attr.Value; } else { parameters.Add(attr.Name, attr.Value); } } newTemplate.AddAdditionalSkillEffects(skillId, effectName, parameters); } else if (skillParamNode.Name == "remove_effects") { newTemplate.DisableSkillEffects(skillId); } else { string paramName = skillParamNode.Name; string val = skillParamNode.InnerText; newTemplate.AddSkillModifyInfo(skillId, paramName, val); } } } break; case "remove_skills": foreach (XmlNode skillNode in mainParam.ChildNodes) { string skillName = skillNode.Name; SkillId skillId = (SkillId)Enum.Parse(typeof(SkillId), skillName); newTemplate.SkillsToRemove.Add(skillId); } break; case "add_autoattack": foreach (XmlNode skillNode in mainParam.ChildNodes) { string skillName = skillNode.Name; SkillId skillId = (SkillId)Enum.Parse(typeof(SkillId), skillName); newTemplate.NewAutoattack = skillId; foreach (XmlNode skillParamNode in skillNode.ChildNodes) { if (skillParamNode.Name == "add_effect") { string effectName = null; Dictionary <string, string> parameters = new Dictionary <string, string>(); foreach (XmlAttribute attr in skillParamNode.Attributes) { if (attr.Name == "name") { effectName = attr.Value; } else { parameters.Add(attr.Name, attr.Value); } } newTemplate.AddMeleeSkillEffects(skillId, effectName, parameters); } else if (skillParamNode.Name == "remove_effects") { newTemplate.DisableMeleeEffects(); } else { string paramName = skillParamNode.Name; string val = skillParamNode.InnerText; newTemplate.AddAutoattackModifyInfo(skillId, paramName, val); } } break; } break; case "remove_autoattack": newTemplate.NewAutoattack = SkillId.CustomRemove; break; } } newTemplate.InitCustomSkillsOnTemplate(); customTypes.Add(newTemplate); } }
/// <summary> /// Returns true if the specified skill is active and on state "Ready". /// </summary> /// <param name="skillId"></param> /// <returns></returns> public bool IsReady(SkillId skillId) { return (this.IsActive(skillId) && this.ActiveSkill.State == SkillState.Ready); }
public override int GetHashCode() { return(SkillId != null?SkillId.GetHashCode() : 0); }
/// <summary> /// Trains condition in skill if it has the given rank. /// </summary> /// <param name="skillId"></param> /// <param name="rank">Rank to which the training is limited.</param> /// <param name="condition">Condition nr (1-9)</param> /// <param name="amount"></param> public void Train(SkillId skillId, SkillRank rank, int condition, int amount = 1) { var skill = this.Get(skillId); if (skill == null || skill.Info.Rank != rank) return; skill.Train(condition, amount); }
public void ChangeMap(SkillId id) { SceneModule _sceneModule = (SceneModule)GameManager.GameManagerObj.GetComponent <GameManager>().GetModuleByName("SceneModule"); if (id == SkillId.MA && m_matList.Count == 0) { Transform _tsf1 = _sceneModule.GetTsfMapData(3, 2); Material _material1 = _tsf1.GetComponent <MeshRenderer>().material; m_originColorList.Add(_material1.GetColor("_Color")); _material1.SetColor("_Color", Color.red); m_matList.Add(_material1); Transform _tsf2 = _sceneModule.GetTsfMapData(3, 4); Material _material2 = _tsf2.GetComponent <MeshRenderer>().material; m_originColorList.Add(_material2.GetColor("_Color")); _material2.SetColor("_Color", Color.red); m_matList.Add(_material2); } if (id == SkillId.JU && m_matList.Count == 0) { // Transform _tsf1 = _sceneModule.GetTsfMapData(0, 4); Material _material1 = _tsf1.GetComponent <MeshRenderer>().material; m_originColorList.Add(_material1.GetColor("_Color")); _material1.SetColor("_Color", Color.red); m_matList.Add(_material1); // Transform _tsf2 = _sceneModule.GetTsfMapData(1, 4); Material _material2 = _tsf2.GetComponent <MeshRenderer>().material; m_originColorList.Add(_material2.GetColor("_Color")); _material2.SetColor("_Color", Color.red); m_matList.Add(_material2); // Transform _tsf3 = _sceneModule.GetTsfMapData(2, 4); Material _material3 = _tsf3.GetComponent <MeshRenderer>().material; m_originColorList.Add(_material3.GetColor("_Color")); _material3.SetColor("_Color", Color.red); m_matList.Add(_material3); // Transform _tsf4 = _sceneModule.GetTsfMapData(4, 4); Material _material4 = _tsf4.GetComponent <MeshRenderer>().material; m_originColorList.Add(_material4.GetColor("_Color")); _material4.SetColor("_Color", Color.red); m_matList.Add(_material4); // Transform _tsf5 = _sceneModule.GetTsfMapData(5, 4); Material _material5 = _tsf5.GetComponent <MeshRenderer>().material; m_originColorList.Add(_material5.GetColor("_Color")); _material5.SetColor("_Color", Color.red); m_matList.Add(_material5); } if (id == SkillId.XIANG && m_matList.Count == 0) { if (m_step == 2) { // Transform _tsf1 = _sceneModule.GetTsfMapData(3, 2); Material _material1 = _tsf1.GetComponent <MeshRenderer>().material; m_originColorList.Add(_material1.GetColor("_Color")); _material1.SetColor("_Color", Color.red); m_matList.Add(_material1); // Transform _tsf2 = _sceneModule.GetTsfMapData(3, 6); Material _material2 = _tsf2.GetComponent <MeshRenderer>().material; m_originColorList.Add(_material2.GetColor("_Color")); _material2.SetColor("_Color", Color.red); m_matList.Add(_material2); // Transform _tsf3 = _sceneModule.GetTsfMapData(7, 2); Material _material3 = _tsf3.GetComponent <MeshRenderer>().material; m_originColorList.Add(_material3.GetColor("_Color")); _material3.SetColor("_Color", Color.red); m_matList.Add(_material3); // Transform _tsf4 = _sceneModule.GetTsfMapData(7, 6); Material _material4 = _tsf4.GetComponent <MeshRenderer>().material; m_originColorList.Add(_material4.GetColor("_Color")); _material4.SetColor("_Color", Color.red); m_matList.Add(_material4); } //else if(m_step == 3) //{ // // // Transform _tsf1 = _sceneModule.GetTsfMapData(5, 0); // Material _material1 = _tsf1.GetComponent<MeshRenderer>().material; // m_originColorList.Add(_material1.GetColor("_Color")); // _material1.SetColor("_Color", Color.red); // m_matList.Add(_material1); // // // Transform _tsf2 = _sceneModule.GetTsfMapData(5, 4); // _tsf2.GetComponent<MapData>().Data = MapDataType.NEWMODE; // _sceneModule.Data[5][4] = MapDataType.NEWMODE; // Material _material2 = _tsf2.GetComponent<MeshRenderer>().material; // m_originColorList.Add(_material2.GetColor("_Color")); // _material2.SetColor("_Color", Color.red); // m_matList.Add(_material2); // // // Transform _tsf3 = _sceneModule.GetTsfMapData(9, 0); // Material _material3 = _tsf3.GetComponent<MeshRenderer>().material; // m_originColorList.Add(_material3.GetColor("_Color")); // _material3.SetColor("_Color", Color.red); // m_matList.Add(_material3); // // // Transform _tsf4 = _sceneModule.GetTsfMapData(9, 4); // Material _material4 = _tsf4.GetComponent<MeshRenderer>().material; // m_originColorList.Add(_material4.GetColor("_Color")); // _material4.SetColor("_Color", Color.red); // m_matList.Add(_material4); //} } }
/// <summary> /// Sends CombatUsedSkill to creature's client. /// </summary> /// <param name="creature"></param> /// <param name="skillId"></param> public static void CombatUsedSkill(Creature creature, SkillId skillId) { var packet = new Packet(Op.CombatUsedSkill, creature.EntityId); packet.PutUShort((ushort)skillId); creature.Client.Send(packet); }
/// <summary> /// Adds stat mod. /// </summary> /// <param name="stat">Stat to change</param> /// <param name="value">Amount</param> /// <param name="source">What is changing the stat?</param> /// <param name="ident">Identificator for the source, eg skill or title id.</param> public void Add(Stat stat, float value, StatModSource source, SkillId ident) { this.Add(stat, value, source, (long)ident); }