/// <summary> /// Prepares skill, skips right to used. /// </summary> /// <remarks> /// Doesn't check anything, like what you can gather with what, /// because at this point there's no chance for abuse. /// </remarks> /// <param name="creature"></param> /// <param name="skill"></param> /// <param name="packet"></param> /// <returns></returns> public bool Prepare(Creature creature, Skill skill, Packet packet) { var entityId = packet.GetLong(); var collectId = packet.GetInt(); // You shall stop creature.StopMove(); var creaturePosition = creature.GetPosition(); // Get target (either prop or creature) var targetEntity = this.GetTargetEntity(creature.Region, entityId); if (targetEntity != null) creature.Temp.GatheringTargetPosition = targetEntity.GetPosition(); // Check distance if (!creaturePosition.InRange(creature.Temp.GatheringTargetPosition, MaxDistance)) { Send.Notice(creature, Localization.Get("Your arms are too short to reach that from here.")); return false; } // ? (sets creatures position on the client side) Send.CollectAnimation(creature, entityId, collectId, creaturePosition); // Use Send.SkillUse(creature, skill.Info.Id, entityId, collectId); skill.State = SkillState.Used; return true; }
/// <summary> /// Handles usage of the skill, called once a part was selected. /// </summary> /// <param name="creature"></param> /// <param name="skill"></param> /// <param name="packet"></param> public void Use(Creature creature, Skill skill, Packet packet) { var part = packet.GetInt(); if (packet.Peek() == PacketElementType.Short) this.UseRegular(creature, skill, packet, part); else if (packet.Peek() == PacketElementType.Byte) this.UseFixed(creature, skill, packet, part); }
/// <summary> /// Handles usage of the skill, called once a part was selected. /// </summary> /// <param name="creature"></param> /// <param name="skill"></param> /// <param name="packet"></param> public void Use(Creature creature, Skill skill, Packet packet) { var part = packet.GetInt(); switch (packet.Peek()) { case PacketElementType.Short: this.UseRegular(creature, skill, packet, part); break; case PacketElementType.Byte: this.UseFixed(creature, skill, packet, part); break; } }
public void Complete(Creature creature, Skill skill, Packet packet) { var part = packet.GetInt(); if (creature.Skills.ActiveSkill != skill) return; if (creature.Temp.SkillItem1 == null || creature.Temp.SkillItem2 == null) return; creature.Skills.ActiveSkill = null; if (packet.Peek() == PacketElementType.Short) this.CompleteRegular(creature, packet, skill, part); else if (packet.Peek() == PacketElementType.Byte) this.CompleteFixed(creature, packet, skill, part); }
/// <summary> /// Completes skill, handling the whole item gathering process. /// </summary> /// <param name="creature"></param> /// <param name="skill"></param> /// <param name="packet"></param> public void Complete(Creature creature, Skill skill, Packet packet) { var entityId = packet.GetLong(); var collectId = packet.GetInt(); var rnd = RandomProvider.Get(); // Check data var collectData = AuraData.CollectingDb.Find(collectId); if (collectData == null) { Log.Warning("Gathering.Complete: Unknown collect id '{0}'", collectId); this.DoComplete(creature, entityId, collectId, false, 1); return; } // Check tools if (!this.CheckHand(collectData.RightHand, creature.RightHand) || !this.CheckHand(collectData.LeftHand, creature.LeftHand)) { Log.Warning("Gathering.Complete: Collecting using invalid tool.", collectId); this.DoComplete(creature, entityId, collectId, false, 1); return; } // Reduce tool's durability if (creature.RightHand != null && collectData.DurabilityLoss > 0) { var reduce = collectData.DurabilityLoss; // Half dura loss if blessed if (creature.RightHand.IsBlessed) reduce = Math.Max(1, reduce / 2); creature.RightHand.Durability -= reduce; Send.ItemDurabilityUpdate(creature, creature.RightHand); Send.ItemExpUpdate(creature, creature.RightHand); } // Get target (either prop or creature) var targetEntity = this.GetTargetEntity(creature.Region, entityId); // Check target if (targetEntity == null || !targetEntity.HasTag(collectData.Target)) { Log.Warning("Gathering.Complete: Collecting from invalid entity '{0:X16}'", entityId); this.DoComplete(creature, entityId, collectId, false, 1); return; } // Check position var creaturePosition = creature.GetPosition(); var targetPosition = targetEntity.GetPosition(); if (!creaturePosition.InRange(targetPosition, MaxDistance)) { Send.Notice(creature, Localization.Get("Your arms are too short to reach that from here.")); this.DoComplete(creature, entityId, collectId, false, 1); return; } // Check if moved if (creature.Temp.GatheringTargetPosition.GetDistance(targetPosition) > MaxMoveDistance) { this.DoComplete(creature, entityId, collectId, false, 3); return; } // Determine success var successChance = this.GetSuccessChance(creature, collectData); var collectSuccess = rnd.NextDouble() * 100 < successChance; // Get reduction var reduction = collectData.ResourceReduction; if (ChannelServer.Instance.Weather.GetWeatherType(creature.RegionId) == WeatherType.Rain) reduction += collectData.ResourceReductionRainBonus; // Check resource if (targetEntity is Prop) { var targetProp = (Prop)targetEntity; // Check if prop was emptied if (targetProp.State == "empty") { this.DoComplete(creature, entityId, collectId, false, 2); return; } // Regenerate resources targetProp.Resource += (float)((DateTime.Now - targetProp.LastCollect).TotalMinutes * collectData.ResourceRecovering); // Fail if currently no resources available if (targetProp.Resource < reduction) { this.DoComplete(creature, entityId, collectId, false, 2); return; } // Reduce resources on success if (collectSuccess) { if (!ChannelServer.Instance.Conf.World.InfiniteResources) targetProp.Resource -= reduction; targetProp.LastCollect = DateTime.Now; } // Set prop's state to "empty" if it was emptied and is not // regenerating resources. if (collectData.ResourceRecovering == 0 && targetProp.Resource < reduction) targetProp.SetState("empty"); } else { var targetCreature = (Creature)targetEntity; // Fail if creature doesn't have enough mana if (targetCreature.Mana < reduction) { this.DoComplete(creature, entityId, collectId, false, 2); return; } if (collectSuccess && !ChannelServer.Instance.Conf.World.InfiniteResources) targetCreature.Mana -= reduction; } // Drop var receiveItemId = 0; if (collectSuccess) { // Product var itemId = receiveItemId = collectData.GetRndProduct(rnd); if (itemId != 0) { var item = new Item(itemId); if (collectData.Source == 0) { // Try to drop item in the middle, between creature // and target. If there already is an item on that // position, find another random one. var pos = targetPosition.GetRelative(creaturePosition, -FeetDropDistance); for (int i = 0; creature.Region.GetItem(a => a.GetPosition() == pos) != null && i < 10; ++i) pos = creaturePosition.GetRandomInRange(DropRange, rnd); item.Drop(creature.Region, pos, 0, creature, false); } else { creature.Inventory.Remove(creature.RightHand); creature.Inventory.Add(item, creature.Inventory.RightHandPocket); } } // Product2 itemId = collectData.GetRndProduct2(rnd); if (itemId != 0) { var item = new Item(itemId); item.Drop(creature.Region, creaturePosition, DropRange, creature, false); } } // TODO: Figure out how fail products work. //else //{ // // FailProduct // var itemId = receiveItemId = collectData.GetRndFailProduct(rnd); // if (itemId != 0) // { // var item = new Item(itemId); // if (collectData.Source == 0) // item.Drop(creature.Region, creaturePosition, DropRange); // else // { // creature.Inventory.Remove(creature.RightHand); // creature.Inventory.Add(item, creature.Inventory.RightHandPocket); // } // } // // FailProduct2 // itemId = collectData.GetRndFailProduct2(rnd); // if (itemId != 0) // { // var item = new Item(itemId); // item.Drop(creature.Region, creaturePosition.GetRandomInRange(DropRange, rnd)); // } //} // Events ChannelServer.Instance.Events.OnCreatureGathered(new CollectEventArgs(creature, collectData, collectSuccess, receiveItemId)); // Complete this.DoComplete(creature, entityId, collectId, collectSuccess, 0); }
/// <summary> /// Uses WM, attacking targets. /// </summary> /// <param name="attacker"></param> /// <param name="skill"></param> /// <param name="packet"></param> public void Use(Creature attacker, Skill skill, Packet packet) { var targetAreaId = packet.GetLong(); // There exists a seemingly rare case where these parameters // aren't sent. var unkInt1 = (packet.Peek() != PacketElementType.None ? packet.GetInt() : 0); var unkInt2 = (packet.Peek() != PacketElementType.None ? packet.GetInt() : 0); this.Use(attacker, skill, targetAreaId, unkInt1, unkInt2); }
/// <summary> /// Completes skill usage, called once the dyeing is completed. /// </summary> /// <param name="creature"></param> /// <param name="skill"></param> /// <param name="packet"></param> public void Complete(Creature creature, Skill skill, Packet packet) { var part = packet.GetInt(); if (creature.Skills.ActiveSkill != skill) return; if (creature.Temp.SkillItem1 == null || creature.Temp.SkillItem2 == null) return; switch (packet.Peek()) { case PacketElementType.Short: this.CompleteRegular(creature, packet, skill, part); break; case PacketElementType.Byte: this.CompleteFixed(creature, packet, skill, part); break; } }
/// <summary> /// Handles skill usage. /// </summary> /// <param name="creature"></param> /// <param name="skill"></param> /// <param name="packet"></param> public void Use(Creature creature, Skill skill, Packet packet) { var targetEntityId = packet.GetLong(); // Similar to WM there is a case where these aren't sent. // Apparently this can happen if you activate the skill while // targetting an enemy. var unk1 = (packet.Peek() != PacketElementType.None ? packet.GetInt() : 0); var unk2 = (packet.Peek() != PacketElementType.None ? packet.GetInt() : 0); if (_cm == null) _cm = ChannelServer.Instance.SkillManager.GetHandler<CombatMastery>(SkillId.CombatMastery); // TODO: Check duration var attackResult = false; var target = creature.Region.GetCreature(targetEntityId); if (target != null && !creature.IsStunned && creature.CanTarget(target)) { var pos = creature.GetPosition(); var targetPos = target.GetPosition(); var inRange = pos.InRange(targetPos, creature.AttackRangeFor(target)); if (!inRange) { var telePos = pos.GetRelative(targetPos, -creature.AttackRangeFor(target) + 100); // Check teleport distance if (pos.GetDistance(telePos) > skill.RankData.Var3 + 100) { Send.Notice(creature, "Out of range"); } else { Send.Effect(creature, Effect.SilentMoveTeleport, targetEntityId, (byte)0); creature.SetPosition(telePos.X, telePos.Y); Send.SkillTeleport(creature, telePos.X, telePos.Y); inRange = true; } } if (inRange) attackResult = (_cm.Use(creature, skill, targetEntityId) == CombatSkillResult.Okay); } Send.CombatAttackR(creature, attackResult); Send.SkillUse(creature, skill.Info.Id, targetEntityId, unk1, unk2); }
/// <summary> /// Handles skill usage. /// </summary> /// <param name="creature"></param> /// <param name="skill"></param> /// <param name="packet"></param> public void Use(Creature creature, Skill skill, Packet packet) { var targetEntityId = packet.GetLong(); var unk1 = packet.GetInt(); var unk2 = packet.GetInt(); Use(creature, skill, targetEntityId, unk1, unk2); }