GetPosition() публичный Метод

Returns current position.
public GetPosition ( ) : Position
Результат Position
Пример #1
0
		/// <summary>
		/// Completes skill, dropping a cobweb.
		/// </summary>
		/// <param name="creature"></param>
		/// <param name="skill"></param>
		/// <param name="packet"></param>
		public void Complete(Creature creature, Skill skill, Packet packet)
		{
			var cobweb = new Item(ItemId);
			cobweb.Drop(creature.Region, creature.GetPosition(), 200, creature, true);

			Send.SkillComplete(creature, skill.Info.Id);
		}
Пример #2
0
		/// <summary>
		/// Bolt specific use code.
		/// </summary>
		/// <param name="attacker"></param>
		/// <param name="skill"></param>
		/// <param name="target"></param>
		protected override void UseSkillOnTarget(Creature attacker, Skill skill, Creature mainTarget)
		{
			// Create actions
			var aAction = new AttackerAction(CombatActionType.RangeHit, attacker, skill.Info.Id, mainTarget.EntityId);
			aAction.Set(AttackerOptions.Result);

			var cap = new CombatActionPack(attacker, skill.Info.Id, aAction);

			var targets = new List<Creature>();
			targets.Add(mainTarget);
			targets.AddRange(mainTarget.Region.GetCreaturesInRange(mainTarget.GetPosition(), SplashRange).Where(a => a != mainTarget && attacker.CanTarget(a) && attacker.CanAttack(a)));

			// Damage
			var damage = this.GetDamage(attacker, skill);

			var max = Math.Min(targets.Count, skill.Stacks);
			for (int i = 0; i < max; ++i)
			{
				var target = targets[i];
				var targetDamage = damage;

				target.StopMove();

				var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Info.Id);
				tAction.Set(TargetOptions.Result);
				tAction.Stun = TargetStun;

				// Full damage for the first target, -10% for every subsequent one.
				targetDamage -= (targetDamage * 0.1f) * i;

				// Reduce damage
				var maxDamage = damage; //Damage without Defense and Protection
				// Reduce damage
				Defense.Handle(aAction, tAction);
				SkillHelper.HandleMagicDefenseProtection(target, ref targetDamage);
				ManaShield.Handle(target, ref targetDamage, tAction, maxDamage, true);

				// Deal damage
				if (targetDamage > 0)
					target.TakeDamage(tAction.Damage = targetDamage, attacker);

				if (target == mainTarget)
					target.Aggro(attacker);

				// Death/Knockback
				this.HandleKnockBack(attacker, target, tAction);

				cap.Add(tAction);
			}

			// Override stun set by defense
			aAction.Stun = AttackerStun;

			Send.Effect(attacker, Effect.UseMagic, EffectSkillName);
			Send.SkillUseStun(attacker, skill.Info.Id, aAction.Stun, 1);

			this.BeforeHandlingPack(attacker, skill);

			cap.Handle();
		}
Пример #3
0
		protected override bool CheckProp(Creature creature, long propEntityId)
		{
			// Milling behaves like a skill that doesn't require a prop,
			// but as we know, it does, so we'll do a static check for
			// Tir's Windmill.

			propEntityId = 0xA000010009042B;

			// Check prop
			var prop = creature.Region.GetProp(propEntityId);
			if (prop == null)
			{
				Log.Error("Milling.CheckProp: Windmill not found ({0:X16}).", propEntityId);
				Send.ServerMessage(creature, Localization.Get("Error in prop check, please report."));
				return false;
			}

			// Check range
			if (!creature.GetPosition().InRange(prop.GetPosition(), 1500))
			{
				Send.Notice(creature, Localization.Get("You are too far away."));
				return false;
			}

			// Check state
			// Sanity check, client checks this.
			if (prop.State == "off")
			{
				Send.Notice(creature, Localization.Get("The Mill isn't working."));
				return false;
			}

			return true;
		}
Пример #4
0
		/// <summary>
		/// Completes skill, dropping a cobweb.
		/// </summary>
		/// <param name="creature"></param>
		/// <param name="skill"></param>
		/// <param name="packet"></param>
		public void Complete(Creature creature, Skill skill, Packet packet)
		{
			var cobweb = new Item(ItemId);
			cobweb.Drop(creature.Region, creature.GetPosition().GetRandomInRange(200, RandomProvider.Get()));

			Send.SkillComplete(creature, skill.Info.Id);
		}
Пример #5
0
		protected override bool CheckProp(Creature creature, long propEntityId)
		{
			// Check existence
			var prop = (propEntityId == 0 ? null : creature.Region.GetProp(propEntityId));
			if (prop == null || !prop.HasTag("/refine/"))
			{
				Log.Warning("Refining.Prepare: Creature '{0:X16}' tried to use production skill with invalid prop.", creature.EntityId);
				return false;
			}

			// Check distance
			if (!creature.GetPosition().InRange(prop.GetPosition(), 1000))
			{
				// Don't warn, could happen due to lag.
				Send.Notice(creature, Localization.Get("You are too far away."));
				return false;
			}

			// Check state
			// Sanity check, client should handle it.
			if (prop.State != "on")
			{
				Send.Notice(creature, Localization.Get("The Waterwheel isn't working,\nand that means the Furnace won't fire."));
				return false;
			}

			return true;
		}
Пример #6
0
		/// <summary>
		/// Sends EnterDynamicRegion to creature's client.
		/// </summary>
		/// <param name="creature"></param>
		/// <param name="warpFromRegionId"></param>
		/// <param name="warpToRegion"></param>
		public static void EnterDynamicRegion(Creature creature, int warpFromRegionId, Region warpToRegion, int x, int y)
		{
			var warpTo = warpToRegion as DynamicRegion;
			if (warpTo == null)
				throw new ArgumentException("EnterDynamicRegion requires a dynamic region.");

			var pos = creature.GetPosition();

			var packet = new Packet(Op.EnterDynamicRegion, MabiId.Broadcast);
			packet.PutLong(creature.EntityId);
			packet.PutInt(warpFromRegionId); // creature's current region or 0?

			packet.PutInt(warpToRegion.Id);
			packet.PutString(warpToRegion.Name); // dynamic region name
			packet.PutUInt(0x80000000); // bitmask? (|1 = time difference?)
			packet.PutInt(warpTo.BaseId);
			packet.PutString(warpTo.BaseName);
			packet.PutInt(200); // 100|200 (100 changes the lighting?)
			packet.PutByte(0); // 1 = next is empty?
			packet.PutString("data/world/{0}/{1}", warpTo.BaseName, warpTo.Variation);

			packet.PutByte(0);
			//if (^ true)
			//{
			//	pp.PutByte(1);
			//	pp.PutInt(3100); // some region id?
			//}
			packet.PutInt(x); // target x pos
			packet.PutInt(y); // target y pos

			creature.Client.Send(packet);
		}
Пример #7
0
		/// <summary>
		/// Uses skill, the actual usage is in Complete.
		/// </summary>
		/// <param name="creature"></param>
		/// <param name="skill"></param>
		/// <param name="packet"></param>
		public void Use(Creature creature, Skill skill, Packet packet)
		{
			var location = packet.GetLong();
			var unkInt1 = packet.GetInt();
			var unkInt2 = packet.GetInt();

			var areaPosition = new Position(location);

			// Check range
			if (!creature.GetPosition().InRange(areaPosition, Range))
			{
				this.Cancel(creature, skill);
				Send.SkillUseSilentCancel(creature);
				Send.Notice(creature, Localization.Get("Out of range."));
				return;
			}

			// Reduce Dice
			if (creature.Inventory.RightHand != null)
				creature.Inventory.Decrement(creature.Inventory.RightHand);

			var number = (byte)(RandomProvider.Get().Next(6));

			Send.UseMotion(creature, 27, 2, false, false);
			Send.Effect(creature, Effect.Dice, 0, "process", location, number); // [200200, NA233 (2016-08-12)] New 0 int after effect id
			Send.SkillUse(creature, skill.Info.Id, location, unkInt1, unkInt2);

			skill.Stacks = 0;
		}
Пример #8
0
		/// <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;
		}
Пример #9
0
		/// <summary>
		/// Uses skill, the actual usage is in Complete.
		/// </summary>
		/// <param name="creature"></param>
		/// <param name="skill"></param>
		/// <param name="packet"></param>
		public void Use(Creature creature, Skill skill, Packet packet)
		{
			var location = packet.GetLong();
			var unkInt1 = packet.GetInt();
			var unkInt2 = packet.GetInt();

			var areaPosition = new Position(location);

			// Check range
			if (!creature.GetPosition().InRange(areaPosition, Range))
			{
				this.Cancel(creature, skill);
				Send.SkillUseSilentCancel(creature);
				Send.Notice(creature, Localization.Get("Out of range."));
				return;
			}

			// Reduce Dice
			if (creature.Inventory.RightHand != null)
				creature.Inventory.Decrement(creature.Inventory.RightHand);

			Send.UseMotion(creature, 27, 2, false, false);
			Send.Effect(creature, Effect.Dice, "process", location, (byte)3);
			Send.SkillUse(creature, skill.Info.Id, location, unkInt1, unkInt2);

			skill.Stacks = 0;
		}
Пример #10
0
		public bool Prepare(Creature creature, Skill skill, Packet packet)
		{
			var unkStr = packet.GetString();

			// Get all items on floor and remove those that are within skill range
			var items = creature.Region.GetAllItems();
			foreach (var item in items.Where(a => a.GetPosition().InRange(creature.GetPosition(), (int)skill.RankData.Var1)))
				creature.Region.RemoveItem(item);

			return false; // Silent cancel
		}
Пример #11
0
		/// <summary>
		/// Broadcasts HittingProp in range of creature.
		/// </summary>
		/// <param name="creature"></param>
		/// <param name="propEntityId"></param>
		/// <param name="stunTime"></param>
		public static void HittingProp(Creature creature, long propEntityId, int stunTime)
		{
			var pos = creature.GetPosition();

			var packet = new Packet(Op.HittingProp, creature.EntityId);
			packet.PutLong(propEntityId);
			packet.PutInt(stunTime);
			packet.PutFloat(pos.X);
			packet.PutFloat(pos.Y);

			creature.Region.Broadcast(packet, creature);
		}
Пример #12
0
		/// <summary>
		/// Readies skill, activates fire effect.
		/// </summary>
		/// <param name="creature"></param>
		/// <param name="skill"></param>
		/// <param name="packet"></param>
		/// <returns></returns>
		public bool Ready(Creature creature, Skill skill, Packet packet)
		{
			creature.Temp.FireArrow = creature.Region.GetProps(a => a.Info.Id == 203 && a.GetPosition().InRange(creature.GetPosition(), 500)).Count > 0;
			if (creature.Temp.FireArrow)
				Send.Effect(creature, Effect.FireArrow, true);

			Send.SkillReady(creature, skill.Info.Id);

			creature.Lock(Locks.Run);

			return true;
		}
Пример #13
0
		/// <summary>
		/// Sends EnterRegion to creature's client.
		/// </summary>
		/// <param name="creature"></param>
		public static void EnterRegion(Creature creature, int regionId, int x, int y)
		{
			var pos = creature.GetPosition();

			var packet = new Packet(Op.EnterRegion, MabiId.Channel);
			packet.PutLong(creature.EntityId);
			packet.PutByte(true); // success?
			packet.PutInt(regionId);
			packet.PutInt(x);
			packet.PutInt(y);

			creature.Client.Send(packet);
		}
Пример #14
0
		/// <summary>
		/// Adds the referred creature's data to the referenced packet.
		/// </summary>
		/// <param name="creature"></param>
		/// <param name="packet"></param>
		public static void AddPartyMember(this Packet packet, Creature creature)
		{
			var loc = creature.GetPosition();

			packet.PutInt(creature.PartyPosition);
			packet.PutLong(creature.EntityId);
			packet.PutString(creature.Name);
			packet.PutByte(1);
			packet.PutInt(creature.Region.Id);
			packet.PutInt(loc.X);
			packet.PutInt(loc.Y);
			packet.PutByte(0);
			packet.PutInt((int)((creature.Life * 100) / creature.LifeMax));
			packet.PutInt((int)100);
		}
Пример #15
0
		/// <summary>
		/// Completes skill, teleporting behind target.
		/// </summary>
		/// <param name="creature"></param>
		/// <param name="skill"></param>
		/// <param name="packet"></param>
		public void Complete(Creature creature, Skill skill, Packet packet)
		{
			var target = creature.Target;
			if (target != null)
			{
				var pos = creature.GetPosition();
				var targetPos = target.GetPosition();
				var telePos = pos.GetRelative(targetPos, DistanceToTarget);

				Send.Effect(creature, Effect.SilentMoveTeleport, (byte)2, telePos.X, telePos.Y);
				creature.Warp(creature.RegionId, telePos);
			}

			Send.SkillComplete(creature, skill.Info.Id);
		}
Пример #16
0
		/// <summary>
		/// Broadcasts ForceRunTo in creature's range.
		/// </summary>
		/// <param name="creature"></param>
		/// <param name="to"></param>
		public static void ForceRunTo(Creature creature, Position to)
		{
			var pos = creature.GetPosition();

			var packet = new Packet(Op.ForceRunTo, creature.EntityId);

			// From
			packet.PutInt(pos.X);
			packet.PutInt(pos.Y);

			// To
			packet.PutInt(to.X);
			packet.PutInt(to.Y);

			packet.PutByte(1);
			packet.PutByte(0);

			creature.Region.Broadcast(packet, creature);
		}
Пример #17
0
		protected override bool CheckProp(Creature creature, long propEntityId)
		{
			// Check existence
			var prop = (propEntityId == 0 ? null : creature.Region.GetProp(propEntityId));
			if (prop == null || !prop.HasTag("/spin/|/loom/"))
			{
				Log.Warning("Weaving.Prepare: Creature '{0:X16}' tried to use production skill with invalid prop.", creature.EntityId);
				return false;
			}

			// Check distance
			if (!creature.GetPosition().InRange(prop.GetPosition(), 1000))
			{
				// Don't warn, could happen due to lag.
				Send.Notice(creature, Localization.Get("You can't reach a Spinning Wheel or Loom from here."));
				return false;
			}

			return true;
		}
Пример #18
0
		/// <summary>
		/// Starts rest skill.
		/// </summary>
		/// <param name="creature"></param>
		/// <param name="skill"></param>
		/// <param name="dict"></param>
		/// <returns></returns>
		public override StartStopResult Start(Creature creature, Skill skill, MabiDictionary dict)
		{
			creature.StopMove();

			creature.IsInBattleStance = false;
			creature.AttemptingAttack = false;

			var chairItemEntityId = dict.GetLong("ITEMID");

			if (chairItemEntityId != 0)
				this.SetUpChair(creature, chairItemEntityId);

			creature.Activate(CreatureStates.SitDown);
			if (skill.Info.Rank >= SkillRank.R9)
				creature.Activate(CreatureStatesEx.RestR9);

			Send.SitDown(creature);

			// Get bonuses if meditation isn't active.
			if (!creature.Conditions.Has(ConditionsE.Meditation))
			{
				ApplyRestBonus(creature, skill, chairItemEntityId);
			}
			else
			{
				RestCampfireBonus(creature, skill, chairItemEntityId);
			}

			// Add bonus from campfire
			// TODO: Check for disappearing of campfire? (OnDisappears+Recheck)
			var campfires = creature.Region.GetProps(a => a.Info.Id == 203 && a.GetPosition().InRange(creature.GetPosition(), 500));
			if (campfires.Count > 0)
			{
				Send.Notice(creature, Localization.Get("The fire feels very warm."));
			}

			if (skill.Info.Rank == SkillRank.Novice) skill.Train(1); // Use Rest.

			return StartStopResult.Okay;
		}
Пример #19
0
		public void Use(Creature creature, Skill skill, Packet packet)
		{
			var targetPos = new Position(packet.GetLong());

			// Check distance to target position
			if (!creature.GetPosition().InRange(targetPos, (int)skill.RankData.Var2 + DistanceBuffer))
			{
				Send.Notice(creature, Localization.Get("Out of range."));
				Send.SkillUse(creature, skill.Info.Id, 0);
				return;
			}

			// Stop creature's movement.
			creature.StopMove();

			// Teleport effect (does not actually teleport)
			Send.Effect(creature, Effect.SilentMoveTeleport, (byte)2, targetPos.X, targetPos.Y);

			// Teleport player to target position
			creature.SetPosition(targetPos.X, targetPos.Y);
			Send.SkillTeleport(creature, targetPos.X, targetPos.Y);

			Send.SkillUse(creature, skill.Info.Id, 1);
		}
Пример #20
0
		/// <summary>
		/// Sends CombatAttackR to creature's client.
		/// </summary>
		/// <remarks>
		/// Contains creature's and target's position, sent for out of range,
		/// so the client knows it has to adjust the creature's position.
		/// </remarks>
		/// <param name="creature"></param>
		/// <param name="target"></param>
		public static void CombatAttackR(Creature creature, Creature target)
		{
			var creaturePos = creature.GetPosition();
			var targetPos = target.GetPosition();

			var packet = new Packet(Op.CombatAttackR, creature.EntityId);
			packet.PutByte(100);
			packet.PutLong(target.EntityId);
			packet.PutByte(0);
			packet.PutByte(0);
			packet.PutInt(creaturePos.X);
			packet.PutInt(creaturePos.Y);
			packet.PutByte(0);
			packet.PutInt(targetPos.X);
			packet.PutInt(targetPos.Y);
			packet.PutString("");

			creature.Client.Send(packet);
		}
Пример #21
0
		/// <summary>
		/// Bolt specific use code.
		/// </summary>
		/// <param name="attacker"></param>
		/// <param name="skill"></param>
		/// <param name="target"></param>
		protected override void UseSkillOnTarget(Creature attacker, Skill skill, Creature mainTarget)
		{
			// Create actions
			var aAction = new AttackerAction(CombatActionType.RangeHit, attacker, mainTarget.EntityId);
			aAction.Set(AttackerOptions.Result);

			var cap = new CombatActionPack(attacker, skill.Info.Id, aAction);

			// Get targets
			// Add the main target as first target, so it gets the first hit,
			// and the full damage.
			var targets = new List<Creature>();
			targets.Add(mainTarget);

			var inSplashRange = attacker.GetTargetableCreaturesAround(mainTarget.GetPosition(), SplashRange);
			targets.AddRange(inSplashRange.Where(a => a != mainTarget));

			// Damage
			var damage = this.GetDamage(attacker, skill);

			var max = Math.Min(targets.Count, skill.Stacks);
			for (int i = 0; i < max; ++i)
			{
				var target = targets[i];
				var targetDamage = damage;

				target.StopMove();

				var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Info.Id);
				tAction.Set(TargetOptions.Result);
				tAction.Stun = TargetStun;

				// Full damage for the first target, -10% for every subsequent one.
				targetDamage -= (targetDamage * 0.1f) * i;

				// Critical Hit
				var critChance = attacker.GetTotalCritChance(target.Protection, true);
				CriticalHit.Handle(attacker, critChance, ref damage, tAction);

				// Reduce damage
				Defense.Handle(aAction, tAction, ref targetDamage);
				SkillHelper.HandleMagicDefenseProtection(target, ref targetDamage);
				SkillHelper.HandleConditions(attacker, target, ref damage);
				ManaShield.Handle(target, ref targetDamage, tAction);

				// Mana Deflector
				var mdResult = ManaDeflector.Handle(attacker, target, ref targetDamage, tAction);
				var delayReduction = mdResult.DelayReduction;
				var pinged = mdResult.Pinged;

				// Deal damage
				if (targetDamage > 0)
					target.TakeDamage(tAction.Damage = targetDamage, attacker);

				if (target == mainTarget)
					target.Aggro(attacker);

				// Reduce stun, based on ping
				if (pinged && delayReduction > 0)
					tAction.Stun = (short)Math.Max(0, tAction.Stun - (tAction.Stun / 100 * delayReduction));

				// Death/Knockback
				if (target.IsDead)
				{
					tAction.Set(TargetOptions.FinishingKnockDown);
				}
				else
				{
					// If knocked down, instant recovery,
					// if repeat hit, knock down,
					// otherwise potential knock back.
					if (target.IsKnockedDown)
					{
						tAction.Stun = 0;
					}
					else if (target.Stability < MinStability)
					{
						tAction.Set(TargetOptions.KnockDown);
					}
					else
					{
						// If number of stacks is greater than the number of
						// targets hit, the targets are knocked back, which is
						// done by reducing the stability to min here.
						// Targets with high enough Mana Deflector might
						// negate this knock back, by reducing the stability
						// reduction to 0.
						var stabilityReduction = (skill.Stacks > targets.Count ? OverchargeStabilityReduction : StabilityReduction);

						// Reduce reduction, based on ping
						// While the Wiki says that "the Knockdown Gauge [does not]
						// build up", tests show that it does. However, it's
						// reduced, assumedly based on the MD rank.
						if (delayReduction > 0)
							stabilityReduction = (short)Math.Max(0, stabilityReduction - (stabilityReduction / 100 * delayReduction));

						target.Stability -= stabilityReduction;

						if (target.IsUnstable)
						{
							tAction.Set(TargetOptions.KnockBack);
						}
					}
				}

				if (tAction.IsKnockBack)
					attacker.Shove(target, KnockbackDistance);

				cap.Add(tAction);
			}

			// Override stun set by defense
			aAction.Stun = AttackerStun;

			Send.Effect(attacker, Effect.UseMagic, EffectSkillName);
			Send.SkillUseStun(attacker, skill.Info.Id, aAction.Stun, 1);

			skill.Stacks = 0;

			// Update current weapon
			SkillHelper.UpdateWeapon(attacker, targets.FirstOrDefault(), ProficiencyGainType.Melee, attacker.RightHand);

			cap.Handle();
		}
Пример #22
0
		/// <summary>
		/// Sets new position for target, based on attacker's position
		/// and the distance, takes collision into consideration.
		/// </summary>
		/// <param name="target">Entity to be knocked back</param>
		/// <param name="distance">Distance to knock back the target</param>
		/// <returns>New position</returns>
		public Position Shove(Creature target, int distance)
		{
			var attackerPosition = this.GetPosition();
			var targetPosition = target.GetPosition();

			var newPos = attackerPosition.GetRelative(targetPosition, distance);

			Position intersection;
			if (target.Region.Collisions.Find(targetPosition, newPos, out intersection))
				newPos = targetPosition.GetRelative(intersection, -50);

			target.SetPosition(newPos.X, newPos.Y);

			return newPos;
		}
Пример #23
0
		/// <summary>
		/// Called once ready to pull the fish out.
		/// </summary>
		/// <remarks>
		/// When you catch something just before running out of bait,
		/// and you send MotionCancel2 from Cancel, there's a
		/// visual bug on Aura, where the item keeps flying to you until
		/// you move. This does not happen on NA for unknown reason.
		/// The workaround: Check for cancellation in advance and only
		/// send the real in effect if the skill wasn't canceled.
		/// </remarks>
		/// <param name="creature"></param>
		/// <param name="method">Method used on this try</param>
		/// <param name="success">Success of manual try</param>
		public void OnResponse(Creature creature, FishingMethod method, bool success)
		{
			// Get skill
			var skill = creature.Skills.Get(SkillId.Fishing);
			if (skill == null)
			{
				Log.Error("Fishing.OnResponse: Missing skill.");
				return;
			}

			var rnd = RandomProvider.Get();

			// Update prop state
			creature.Temp.FishingProp.SetState("empty");

			// Get auto success
			if (method == FishingMethod.Auto)
				success = rnd.NextDouble() < skill.RankData.Var3 / 100f;

			// Perfect fishing
			if (ChannelServer.Instance.Conf.World.PerfectFishing)
				success = true;

			// Check fishing ground
			if (creature.Temp.FishingDrop == null)
			{
				Send.ServerMessage(creature, "Error: No items found.");
				Log.Error("Fishing.OnResponse: Failing, no drop found.");
				success = false;
			}

			// Check equipment
			if (!this.CheckEquipment(creature))
			{
				Send.ServerMessage(creature, "Error: Missing equipment.");
				Log.Error("Fishing.OnResponse: Failing, Missing equipment.");
				// TODO: Security violation once we're sure this can't happen
				//   without modding.
				success = false;
			}

			var cancel = false;

			// Reduce durability
			if (creature.RightHand != null)
			{
				creature.Inventory.ReduceDurability(creature.RightHand, 15);

				// Check rod durability
				if (creature.RightHand.Durability == 0)
					cancel = true;
			}

			// Remove bait
			if (creature.Magazine != null && !ChannelServer.Instance.Conf.World.InfiniteBait)
			{
				creature.Inventory.Decrement(creature.Magazine);

				// Check if bait was removed because it was empty
				if (creature.Magazine == null)
					cancel = true;
			}

			// Fail
			Item item = null;
			if (!success)
			{
				Send.Notice(creature, Localization.Get("I was hesistating for a bit, and it got away...")); // More responses?
				Send.Effect(creature, Effect.Fishing, (byte)FishingEffectType.Fall, true);
			}
			// Success
			else
			{
				var propName = "prop_caught_objbox_01";
				var propSize = 0;
				var size = 0;
				var dropData = creature.Temp.FishingDrop;

				// Create item
				if (dropData.QuestId != 0)
					item = Item.CreateQuestScroll(dropData.QuestId);
				else
					item = new Item(dropData);

				// Check fish
				var fish = AuraData.FishDb.Find(dropData.ItemId);
				if (fish != null)
				{
					propName = fish.PropName;
					propSize = fish.PropSize;

					// Random fish size, unofficial
					if (fish.SizeMin + fish.SizeMax != 0)
					{
						var min = fish.SizeMin;
						var max = fish.SizeMax;

						// Var1 bonus
						min += (int)skill.RankData.Var1;

						// Var4 bonus
						min += (int)Math.Max(0, (item.Data.BaseSize - fish.SizeMin) / 100f * skill.RankData.Var4);

						// Modify min and max, so the size falls into big or
						// small territory.
						var mid = (max - min) / 2;
						if (creature.Temp.CatchSize == CatchSize.BigOne)
							min += mid;
						else
							max -= mid;

						// Cap
						if (max < min) max = min;
						if (min > max) min = max;

						size = Math2.Clamp(fish.SizeMin, fish.SizeMax, rnd.Next(min, max + 1));
						var scale = (1f / item.Data.BaseSize * size);

						item.MetaData1.SetFloat("SCALE", scale);

						// Modify selling price based on scale.
						// The default selling price is 10% of the price.
						// If the scale is 2, double the base size (the
						// "usual" size so to speak), it fetches twice
						// the price. The formula is unofficial, but works.
						item.OptionInfo.SellingPrice = (int)(item.OptionInfo.SellingPrice * scale);
					}
				}

				// Set equipment durability to 0, does not apply to
				// unrepairable items, like Gargoyle Swords.
				// http://wiki.mabinogiworld.com/view/Fishing#Details
				if (item.HasTag("/equip/") && !item.HasTag("/not_repairable/"))
					item.Durability = 0;

				// Drop if inv add failed
				List<Item> changed;
				if (!creature.Inventory.Insert(item, false, out changed))
				{
					item.Drop(creature.Region, creature.GetPosition(), 100, creature, false);

					// Set protection limit to max, since fished items that
					// drop out of the player's overfilled bags should be
					// protected indefinitely.
					item.ProtectionLimit = DateTime.MaxValue;
				}

				var itemEntityId = (changed == null || changed.Count == 0 ? item.EntityId : changed.First().EntityId);

				// Show acquire using the item's entity id if it wasn't added
				// to a stack, or using the stack's id if it was.
				Send.AcquireInfo2(creature, "fishing", itemEntityId);

				// Holding up fish effect
				if (!cancel)
					Send.Effect(creature, Effect.Fishing, (byte)FishingEffectType.ReelIn, true, creature.Temp.FishingProp.EntityId, item.Info.Id, size, propName, propSize);
			}

			creature.Temp.FishingDrop = null;

			// Handle training
			this.Training(creature, skill, success, item);

			// Fishing event
			ChannelServer.Instance.Events.OnCreatureFished(creature, item);

			// Cancel
			if (cancel)
			{
				creature.Skills.CancelActiveSkill();
				return;
			}

			// Next round
			this.StartFishing(creature, 6000);
		}
Пример #24
0
		/// <summary>
		/// Returns which creatures in the party are both in region, and a specified range.
		/// If no range is supplied, it returns all party creatures within visual(?) range.
		/// </summary>
		/// <remarks>3000 is a total guess as to the actual visible range.</remarks>
		/// <param name="creature"></param>
		/// <param name="range">Use 0 to get every member in the region.</param>
		/// <returns></returns>
		public List<Creature> GetMembersInRange(Creature creature, int range = -1)
		{
			var result = new List<Creature>();
			var pos = creature.GetPosition();

			if (range < 0)
				range = 3000;

			lock (_sync)
			{
				foreach (var member in _members.Where(a => a != creature && a.RegionId == this.Leader.RegionId))
				{
					if (range == 0 || pos.InRange(member.GetPosition(), range))
						result.Add(member);
				}
			}

			return result;
		}
Пример #25
0
		/// <summary>
		/// Broadcasts PlayDead in range of creature.
		/// </summary>
		/// <param name="creature"></param>
		public static void PlayDead(Creature creature)
		{
			var pos = creature.GetPosition();

			var packet = new Packet(Op.PlayDead, creature.EntityId);
			packet.PutByte(true); // ?
			packet.PutFloat(pos.X);
			packet.PutFloat(pos.Y);
			packet.PutInt(5000);

			creature.Region.Broadcast(packet, creature);
		}
Пример #26
0
		/// <summary>
		/// Uses the skill.
		/// </summary>
		/// <param name="attacker"></param>
		/// <param name="skill"></param>
		/// <param name="targetEntityId"></param>
		/// <returns></returns>
		public CombatSkillResult Use(Creature attacker, Skill skill, long targetEntityId)
		{
			// Get target
			var target = attacker.Region.GetCreature(targetEntityId);
			if (target == null)
				return CombatSkillResult.InvalidTarget;

			if (target.IsNotReadyToBeHit)
				return CombatSkillResult.Okay;

			var targetPos = target.GetPosition();
			var attackerPos = attacker.GetPosition();

			// Check range
			//if (!attackerPos.InRange(targetPos, attacker.RightHand.OptionInfo.EffectiveRange + 100))
			//	return CombatSkillResult.OutOfRange;

			// Actions
			var cap = new CombatActionPack(attacker, skill.Info.Id);

			var aAction = new AttackerAction(CombatActionType.RangeHit, attacker, skill.Info.Id, targetEntityId);
			aAction.Set(AttackerOptions.Result);
			aAction.Stun = AttackerStun;
			cap.Add(aAction);

			// Hit by chance
			var chance = attacker.AimMeter.GetAimChance(target);
			var rnd = RandomProvider.Get();
			if (rnd.NextDouble() * 100 < chance)
			{
				var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Info.Id);
				tAction.Set(TargetOptions.Result);
				tAction.Stun = TargetStun;
				cap.Add(tAction);

				// Damage
				var damage = attacker.GetRndRangedDamage();

				// More damage with fire arrow
				if (attacker.Temp.FireArrow)
					damage *= FireBonus;

				// Critical Hit
				var critShieldReduction = (target.LeftHand != null ? target.LeftHand.Data.DefenseBonusCrit : 0);
				var critChance = attacker.GetRightCritChance(target.Protection + critShieldReduction);
				CriticalHit.Handle(attacker, critChance, ref damage, tAction);

				var maxDamage = damage; //Damage without Defense and Protection
				// Subtract target def/prot
				SkillHelper.HandleDefenseProtection(target, ref damage);

				// Defense
				Defense.Handle(aAction, tAction, ref damage, true);

				// Mana Shield
				ManaShield.Handle(target, ref damage, tAction, maxDamage);

				// Deal with it!
				if (damage > 0)
					target.TakeDamage(tAction.Damage = damage, attacker);

				// Aggro
				target.Aggro(attacker);

				// Death/Knockback
				if (target.IsDead)
				{
					tAction.Set(TargetOptions.FinishingKnockDown);
					attacker.Shove(target, KnockBackDistance);
				}
				else
				{
					// Insta-recover in knock down
					// TODO: Tied to stability?
					if (target.IsKnockedDown)
					{
						tAction.Stun = 0;
					}
					// Knock down if hit repeatedly
					else if (target.Stability < 30)
					{
						tAction.Set(TargetOptions.KnockDown);
					}
					// Normal stability reduction
					else
					{
						target.Stability -= StabilityReduction;
						if (target.IsUnstable)
						{
							tAction.Set(TargetOptions.KnockBack);
							attacker.Shove(target, KnockBackDistance);
						}
					}
				}
			}

			// Skill training
			if (skill.Info.Rank == SkillRank.Novice || skill.Info.Rank == SkillRank.RF)
				skill.Train(1); // Try ranged attack.

			// Reduce arrows
			if (attacker.Magazine != null && !ChannelServer.Instance.Conf.World.InfiniteArrows)
				attacker.Inventory.Decrement(attacker.Magazine);

			// Disable fire arrow effect
			if (attacker.Temp.FireArrow)
				Send.Effect(attacker, Effect.FireArrow, false);

			// "Cancels" the skill
			// 800 = old load time? == aAction.Stun? Varies? Doesn't seem to be a stun.
			Send.SkillUse(attacker, skill.Info.Id, 800, 1);

			cap.Handle();

			return CombatSkillResult.Okay;
		}
Пример #27
0
		/// <summary>
		/// Uses skill on target.
		/// </summary>
		/// <param name="creature"></param>
		/// <param name="skill"></param>
		/// <param name="packet"></param>
		public void Use(Creature creature, Skill skill, Packet packet)
		{
			var entityId = packet.GetLong();
			var unkInt1 = packet.GetInt();
			var unkInt2 = packet.GetInt();

			// Get creature
			var target = creature.Region.GetCreature(entityId);
			if (target == null)
				goto L_End;

			// Check range
			if (!creature.GetPosition().InRange(target.GetPosition(), Range))
			{
				Send.Notice(creature, Localization.Get("Not in range.")); // Unofficial
				goto L_End;
			}

			// TODO: Check target validity once we have skill target support

			// Calculate heal amount
			var rnd = RandomProvider.Get();
			var healAmount = rnd.Next((int)skill.RankData.Var1, (int)skill.RankData.Var3 + 1);

			// Add magic attack bonus
			healAmount += (int)(creature.MagicAttack / 10);

			// Add wand bonus
			if (creature.RightHand != null && creature.RightHand.HasTag("/healing_wand/"))
				healAmount += 5;

			// Reduce user's stamina if target is the user
			if (target == creature && target.Life < target.LifeInjured)
			{
				creature.Stamina -= healAmount;
				Send.StatUpdate(creature, StatUpdateType.Private, Stat.Stamina, Stat.Hunger, Stat.StaminaMax);
			}

			// Skill training
			// Call before heal to calculate if in distress
			this.OnUseSkillOnTarget(creature, target);
			ChannelServer.Instance.Events.OnPlayerHealsCreature(creature, target, skill);

			// Heal target
			target.Life += healAmount;
			Send.StatUpdateDefault(target);
			Send.Effect(target, Effect.HealLife, healAmount);

			// Reduce stacks
			skill.Stacks--;

		L_End:
			Send.Effect(creature, Effect.StackUpdate, "healing_stack", (byte)skill.Stacks, (byte)0);
			Send.Effect(creature, Effect.UseMagic, "healing", entityId);
			Send.SkillUse(creature, skill.Info.Id, entityId, unkInt1, unkInt2);
		}
Пример #28
0
		/// <summary>
		/// Handles skill usage.
		/// </summary>
		/// <param name="attacker"></param>
		/// <param name="skill"></param>
		/// <param name="targetEntityId"></param>
		/// <returns></returns>
		public virtual CombatSkillResult Use(Creature attacker, Skill skill, long targetEntityId)
		{
			// Check target
			var target = attacker.Region.GetCreature(targetEntityId);
			if (target == null)
				return CombatSkillResult.InvalidTarget;

			// Check distance
			var targetPosition = target.GetPosition();
			var attackerPosition = attacker.GetPosition();

			if (!attackerPosition.InRange(targetPosition, this.GetRange(attacker, skill)))
				return CombatSkillResult.OutOfRange;

			// Use
			this.UseSkillOnTarget(attacker, skill, target);

			return CombatSkillResult.Okay;
		}
Пример #29
0
		/// <summary>
		/// Completes skill, healing the target.
		/// </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 unkInt1 = packet.GetInt();
			var unkInt2 = packet.GetInt();

			// Get target
			var target = ChannelServer.Instance.World.GetCreature(entityId);
			if (target == null)
			{
				Send.Notice(creature, Localization.Get("Invalid target."));
				goto L_End;
			}

			// Check range
			if (!creature.GetPosition().InRange(target.GetPosition(), Range))
			{
				Send.Notice(creature, Localization.Get("Out of range."));
				goto L_End;
			}

			// Check bandage, make sure he still has the item and that
			// it wasn't switched with something else somehow.
			if (creature.Temp.SkillItem1 == null || !creature.Temp.SkillItem1.HasTag("/bandage/") || !creature.Inventory.Has(creature.Temp.SkillItem1))
			{
				Log.Warning("FirstAid.Complete: Creature '{0:X16}' apparently switched the skill item somehow, between Ready and Complete.", creature.EntityId);
				Send.Notice(creature, Localization.Get("Invalid bandage."));
				goto L_End;
			}

			// Remove bandage
			if (!creature.Inventory.Decrement(creature.Temp.SkillItem1))
			{
				Log.Error("FirstAid.Complete: Decrementing the skill item failed somehow.");
				Send.Notice(creature, Localization.Get("Unknown error."));
				goto L_End;
			}

			// Fails if target is moving.
			if (target.IsMoving)
			{
				// Unofficial
				Send.Notice(creature, Localization.Get("Failed because target was moving."));
				// Fail motion?
				goto L_End;
			}

			// Heal injuries
			var rnd = RandomProvider.Get();
			var heal = rnd.Next((int)skill.RankData.Var1, (int)skill.RankData.Var2 + 1);

			// Add bonus from higher grade bandages
			if (creature.Temp.SkillItem1.HasTag("/common_grade/"))
				heal += 3;
			else if (creature.Temp.SkillItem1.HasTag("/high_grade/"))
				heal += 6;
			else if (creature.Temp.SkillItem1.HasTag("/highest_grade/"))
				heal += 10;

			// 50% efficiency if target isn't resting
			if (!target.Has(CreatureStates.SitDown))
				heal /= 2;

			target.Injuries -= heal;
			Send.StatUpdateDefault(target);

			// Skill training
			if (skill.Info.Rank == SkillRank.Novice)
				skill.Train(1); // Use First Aid.

			// First Aid animation
			Send.Effect(creature, Effect.UseMagic, "healing_firstaid", entityId);

		L_End:
			Send.SkillComplete(creature, skill.Info.Id, entityId, unkInt1, unkInt2);
		}
Пример #30
0
        /// <summary>
        /// Checks if creature is able to enter a dungeon with the given item,
        /// at his current position, if so, a dungeon is created and the
        /// party is moved inside.
        /// </summary>
        /// <param name="creature"></param>
        /// <param name="item"></param>
        /// <returns></returns>
        public bool CheckDrop(Creature creature, Item item)
        {
            var currentRegionId = creature.RegionId;
            if (!_entryRegionIds.Contains(currentRegionId))
                return false;

            var pos = creature.GetPosition();

            var clientEvent = creature.Region.GetClientEvent(a => a.Data.IsAltar);
            if (clientEvent == null)
            {
                Log.Warning("DungeonManager.CheckDrop: No altar found.");
                return false;
            }

            if (!clientEvent.IsInside(pos.X, pos.Y))
            {
                // Tell player to step on altar?
                return false;
            }

            var parameter = clientEvent.Data.Parameters.FirstOrDefault(a => a.EventType == EventType.Altar);
            if (parameter == null || parameter.XML == null || parameter.XML.Attribute("dungeonname") == null)
            {
                Log.Warning("DungeonManager.CheckDrop: No dungeon name found in altar event '{0:X16}'.", clientEvent.EntityId);
                return false;
            }

            var dungeonName = parameter.XML.Attribute("dungeonname").Value.ToLower();

            // Check script
            var dungeonScript = ChannelServer.Instance.ScriptManager.DungeonScripts.Get(dungeonName);
            if (dungeonScript == null)
            {
                Send.ServerMessage(creature, "This dungeon hasn't been added yet.");
                Log.Warning("DungeonManager.CheckDrop: No routing dungeon script found for '{0}'.", dungeonName);
                return false;
            }

            // Check route
            if (!dungeonScript.Route(creature, item, ref dungeonName))
            {
                // The response in case of a fail is handled by the router.
                return false;
            }

            // Check party
            if (creature.IsInParty && creature.Party.Leader != creature)
            {
                // Unofficial
                Send.Notice(creature, Localization.Get("Only the leader may create the dungeon."));
                return false;
            }

            return this.CreateDungeonAndWarp(dungeonName, item.Info.Id, creature);
        }