Representation of a location in the world.
Used to save locations, ie a location to warp back to.
예제 #1
0
		/// <summary>
		/// Uses LightningRod
		/// </summary>
		/// <param name="attacker"></param>
		/// <param name="skill"></param>
		/// <param name="packet"></param>
		public void Use(Creature attacker, Skill skill, Packet packet)
		{
			// Set full charge variable
			attacker.Temp.LightningRodFullCharge = (DateTime.Now >= attacker.Temp.LightningRodPrepareTime.AddMilliseconds(skill.RankData.Var3));

			// Get direction for target Area
			var direction = Mabi.MabiMath.ByteToRadian(attacker.Direction);

			var attackerPos = attacker.GetPosition();

			// Calculate polygon points
			var r = MabiMath.ByteToRadian(attacker.Direction);
			var poe = attackerPos.GetRelative(r, 800);
			var pivot = new Point(poe.X, poe.Y);
			var p1 = new Point(pivot.X - SkillLength / 2, pivot.Y - SkillWidth / 2);
			var p2 = new Point(pivot.X - SkillLength / 2, pivot.Y + SkillWidth / 2);
			var p3 = new Point(pivot.X + SkillLength / 2, pivot.Y + SkillWidth / 2);
			var p4 = new Point(pivot.X + SkillLength / 2, pivot.Y - SkillWidth / 2);
			p1 = this.RotatePoint(p1, pivot, r);
			p2 = this.RotatePoint(p2, pivot, r);
			p3 = this.RotatePoint(p3, pivot, r);
			p4 = this.RotatePoint(p4, pivot, r);

			// TargetProp
			var lProp = new Prop(280, attacker.RegionId, poe.X, poe.Y, MabiMath.ByteToRadian(attacker.Direction), 1f, 0f, "single");
			attacker.Region.AddProp(lProp);

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

			var targetAreaId = new Location(attacker.RegionId, poe).ToLocationId();

			var aAction = new AttackerAction(CombatActionType.SpecialHit, attacker, targetAreaId);
			aAction.Set(AttackerOptions.KnockBackHit1 | AttackerOptions.UseEffect);
			aAction.PropId = lProp.EntityId;
			cap.Add(aAction);

			// Get targets in Polygon - includes collission check
			var targets = attacker.Region.GetCreaturesInPolygon(p1, p2, p3, p4).Where(x => attacker.CanTarget(x) && !attacker.Region.Collisions.Any(attacker.GetPosition(), x.GetPosition())).ToList();

			var rnd = RandomProvider.Get();

			// Check crit
			var crit = false;
			var critSkill = attacker.Skills.Get(SkillId.CriticalHit);
			if (critSkill != null && critSkill.Info.Rank > SkillRank.Novice)
			{
				var critChance = Math2.Clamp(0, 30, attacker.GetTotalCritChance(0));
				if (rnd.NextDouble() * 100 < critChance)
					crit = true;
			}

			foreach (var target in targets)
			{
				var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, SkillId.CombatMastery);
				tAction.Set(TargetOptions.None);
				tAction.AttackerSkillId = skill.Info.Id;
				cap.Add(tAction);

				var damage = attacker.GetRndMagicDamage(skill, skill.RankData.Var1, skill.RankData.Var2);

				// Add damage if the skill is fully charged
				var dmgMultiplier = skill.RankData.Var4 / 100f;
				if (attacker.Temp.LightningRodFullCharge)
				{
					damage += (damage * dmgMultiplier);
				}

				// Critical Hit
				if (crit)
				{
					var bonus = critSkill.RankData.Var1 / 100f;
					damage = damage + (damage * bonus);

					tAction.Set(TargetOptions.Critical);
				}

				// MDef and MProt
				SkillHelper.HandleMagicDefenseProtection(target, ref damage);

				// Conditions
				SkillHelper.HandleConditions(attacker, target, ref damage);

				// Mana Deflector
				var delayReduction = ManaDeflector.Handle(attacker, target, ref damage, tAction);

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

				// Apply Damage
				target.TakeDamage(tAction.Damage = damage, attacker);

				// Stun Time
				tAction.Stun = TargetStun;

				// Death or Knockback
				if (target.IsDead)
				{
					tAction.Set(TargetOptions.FinishingKnockDown);
					attacker.Shove(target, KnockbackDistance);
				}
				else
				{
					// Always knock down
					if (target.Is(RaceStands.KnockDownable))
					{
						tAction.Set(TargetOptions.KnockDown);
						attacker.Shove(target, KnockbackDistance);
					}
				}
			}

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

			cap.Handle();

			Send.Effect(attacker, Effect.LightningRod, (int)LightningRodEffect.Attack, poe.X, poe.Y);

			Send.SkillUse(attacker, skill.Info.Id, targetAreaId, 0, 1);
			skill.Train(1); // Use the Skill

			attacker.Region.RemoveProp(lProp);
		}
예제 #2
0
		/// <summary>
		/// Saves characters, despawns and disposes them, etc.
		/// </summary>
		public override void CleanUp()
		{
			// Moved here to always be called when a client is being killed off.
			if (this.Controlling != null)
				ChannelServer.Instance.Events.OnPlayerDisconnect(this.Controlling);

			// Dispose creatures, to remove subscriptions and stuff.
			// Do this before unspawning, the creature might need the region.
			foreach (var creature in this.Creatures.Values)
				creature.Dispose();

			foreach (var creature in this.Creatures.Values.Where(a => a.Region != Region.Limbo))
			{
				// Close NPC sessions
				if (creature.Client.NpcSession.Script != null)
					creature.Client.NpcSession.Clear();

				var newLocation = new Location();

				// Use fallback location if creature is in a temp region.
				if (creature.Region is DynamicRegion)
					newLocation = creature.FallbackLocation;

				// Use dungeon exit as fallback location if in a dungeon.
				var dungeonRegion = creature.Region as DungeonRegion;
				if (dungeonRegion != null)
				{
					try
					{
						newLocation = new Location(dungeonRegion.Dungeon.Data.Exit);
					}
					catch (Exception ex)
					{
						Log.Exception(ex, "Failed to fallback warp character in dungeon.");
						newLocation = new Location(1, 12800, 38100); // Tir square
					}

					if (dungeonRegion.Dungeon.Script != null)
						dungeonRegion.Dungeon.Script.OnLeftEarly(dungeonRegion.Dungeon, creature);
				}

				// Unspawn creature
				creature.Region.RemoveCreature(creature);

				// Set new location (if applicable) after everyting else is done,
				// in case on of the previous calls needs the creature's
				// original position.
				if (newLocation.RegionId != 0)
					creature.SetLocation(newLocation);
			}

			// Save everything after we're done cleaning up
			if (this.Account != null)
				ChannelServer.Instance.Database.SaveAccount(this.Account);

			this.Creatures.Clear();
			this.Account = null;
		}
예제 #3
0
		protected void ShootFirework(Location location, FireworkType type, string message)
		{
			var region = ChannelServer.Instance.World.GetRegion(location.RegionId);
			if (region == null)
			{
				Log.Warning(this.GetType().Name + ".ShootFirework: Unknown region.");
				return;
			}

			if (message == null)
				message = "";

			var delay = 500;
			var rnd = RandomProvider.Get();
			var height = rnd.Between(750, 2000);
			var heightf = height / 100f;

			var prop = new Prop(208, location.RegionId, location.X, location.Y, 0);
			prop.DisappearTime = DateTime.Now.AddMilliseconds(20000 + delay);
			region.AddProp(prop);

			Task.Delay(delay).ContinueWith(__ =>
			{
				prop.Xml.SetAttributeValue("height", height);
				prop.Xml.SetAttributeValue("message", message + " (" + heightf.ToString("0.##") + "m)");
				prop.Xml.SetAttributeValue("type", (int)type);
				prop.Xml.SetAttributeValue("seed", Interlocked.Increment(ref _fireworkSeed));
				Send.PropUpdate(prop);
			});
		}
예제 #4
0
		/// <summary>
		/// Warps creature, based on the item's properties.
		/// </summary>
		/// <param name="creature"></param>
		/// <param name="item"></param>
		/// <returns>Whether a warp happened or not.</returns>
		public static bool Warp(Creature creature, Item item)
		{
			if (creature == null)
				throw new ArgumentNullException("creature");

			if (item == null)
				throw new ArgumentNullException("item");

			// Check meta data
			if (!item.MetaData1.Has("TARGET"))
			{
				Send.ServerMessage(creature, Localization.Get("No target found."));
				return false;
			}

			// Get target
			var target = item.MetaData1.GetString("TARGET");

			// Get location based on target
			Location loc;
			if (target.StartsWith("pos")) // pos@regionId,x,y
			{
				var match = Regex.Match(target, @"pos@(?<regionId>[0-9]+),(?<x>[0-9]+),(?<y>[0-9]+)");
				if (!match.Success)
				{
					Log.Warning("HiddenTownBack: Invalid position target: {0}", target);
					Send.ServerMessage(creature, Localization.Get("Invalid target."));
					return false;
				}

				loc.RegionId = Convert.ToInt32(match.Groups["regionId"].Value);
				loc.X = Convert.ToInt32(match.Groups["x"].Value);
				loc.Y = Convert.ToInt32(match.Groups["y"].Value);
			}
			else if (target.StartsWith("portal")) // portal@name
			{
				// Remove "portal@" prefix
				target = target.Substring(7).Trim();

				// Get portal data
				var portalData = AuraData.PortalDb.Find(target);
				if (portalData == null)
				{
					Log.Warning("HiddenTownBack: Unknown target: {0}", target);
					Send.ServerMessage(creature, Localization.Get("Unknown target."));
					return false;
				}

				// Get location
				try
				{
					loc = new Location(portalData.Location);
				}
				catch
				{
					Log.Warning("HiddenTownBack: Invalid portal location: {0}", target);
					Send.ServerMessage(creature, Localization.Get("Invalid portal location."));
					return false;
				}
			}
			else if (target == "last_town")
			{
				loc = new Location(creature.LastTown);
			}
			else
			{
				Log.Warning("HiddenTownBack: Unknown target type: {0}", target);
				Send.ServerMessage(creature, Localization.Get("Unknown target type."));
				return false;
			}

			// Warp
			creature.Warp(loc);

			return true;
		}