Aura.Channel.Skills.Life.Tailoring.Complete C# (CSharp) Метод

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

Completes skill, creating the items.
public Complete ( Creature creature, Skill skill, Packet packet ) : void
creature Aura.Channel.World.Entities.Creature
skill Skill
packet Packet
Результат void
		public void Complete(Creature creature, Skill skill, Packet packet)
		{
			var materials = new List<ProductionMaterial>();
			var stitches = new List<Point>();

			var stage = (Stage)packet.GetByte();
			var propEntityId = packet.GetLong();
			var unkInt1 = packet.GetInt();
			var existingItemEntityId = packet.GetLong();
			var finishId = packet.GetInt();

			if (stage == Stage.Progression)
			{
				// Materials
				if (!this.ReadMaterials(creature, packet, out materials))
					goto L_Fail;
			}
			else if (stage == Stage.Finish)
			{
				// Stitches
				if (!this.ReadStitches(creature, packet, out stitches))
					goto L_Fail;
			}
			else
			{
				Send.ServerMessage(creature, Localization.Get("Stage error, please report."));
				Log.Error("Tailoring: Unknown progress stage '{0}'.", stage);
				goto L_Fail;
			}

			// Check tools
			if (!CheckTools(creature))
				goto L_Fail;

			// Get manual
			var manualId = creature.Magazine.MetaData1.GetInt("FORMID");
			var manualData = AuraData.ManualDb.Find(ManualCategory.Tailoring, manualId);
			if (manualData == null)
			{
				Log.Error("Tailoring.Complete: Manual '{0}' not found.", manualId);
				Send.ServerMessage(creature, Localization.Get("Failed to look up pattern, please report."));
				goto L_Fail;
			}

			// Check existing item
			Item existingItem = null;
			if (existingItemEntityId != 0)
			{
				// Get item
				existingItem = creature.Inventory.GetItem(existingItemEntityId);
				if (existingItem == null)
				{
					Log.Warning("Tailoring.Complete: Creature '{0:X16}' tried to work on non-existing item.", creature.EntityId);
					goto L_Fail;
				}

				// Check id against manual
				if (existingItem.Info.Id != manualData.ItemId)
				{
					Log.Warning("Tailoring.Complete: Creature '{0:X16}' tried use an item with a different id than the manual.", creature.EntityId);
					goto L_Fail;
				}

				// Check progress
				if (!existingItem.MetaData1.Has(ProgressVar))
				{
					Log.Warning("Tailoring.Complete: Creature '{0:X16}' tried work on an item that is already finished.", creature.EntityId);
					goto L_Fail;
				}
			}

			var rnd = RandomProvider.Get();

			// Materials are only sent to Complete for progression,
			// finish materials are handled in Prepare.
			if (stage == Stage.Progression)
			{
				var requiredMaterials = manualData.GetMaterialList();

				// Get items to decrement
				List<ProductionMaterial> toDecrement;
				if (!this.GetItemsToDecrement(creature, Stage.Progression, manualData, requiredMaterials, materials, out toDecrement))
					goto L_Fail;

				// Decrement mats
				this.DecrementMaterialItems(creature, toDecrement, rnd);
			}

			// Reduce durability
			creature.Inventory.ReduceDurability(creature.RightHand, ToolDurabilityLoss);
			creature.Inventory.ReduceDurability(creature.Magazine, ManualDurabilityLoss);

			// Get to work
			var newItem = false;
			var success = false;
			var msg = "";

			// Create new item
			if (existingItem == null)
			{
				existingItem = new Item(manualData.ItemId);
				existingItem.OptionInfo.Flags |= ItemFlags.Incomplete;
				existingItem.MetaData1.SetFloat(ProgressVar, 0);
				existingItem.MetaData1.SetLong(StclmtVar, DateTime.Now);

				newItem = true;
			}

			// Finish item if progress is >= 1, otherwise increase progress.
			var progress = (newItem ? 0 : existingItem.MetaData1.GetFloat(ProgressVar));
			ProgressResult result;
			if (progress < 1)
			{
				// TODO: Random quality gain/loss?
				//   "The combination of tools and materials was quite good! (Quality +{0}%)"

				// Get success
				// Unofficial and mostly based on guessing. If process was
				// determined to be successful, a good result will happen,
				// if not, a bad one. Both are then split into very good
				// and very bad, based on another random number.
				var chance = this.GetSuccessChance(creature, skill, manualData.Rank);
				success = (rnd.NextDouble() * 100 < chance);
				var rngFailSuccess = rnd.NextDouble();

				// Calculate progress to add
				// Base line is between 50 and 100% of the max progress from
				// the db. For example, a Popo's skirt has 200%, which should
				// always put it on 100% instantly, as long as it's a success.
				var addProgress = rnd.Between(manualData.MaxProgress / 2, manualData.MaxProgress);
				var rankDiff = ((int)skill.Info.Rank - (int)manualData.Rank);

				// Apply RNG fail/success
				if (!success)
				{
					// 25% chance for very bad
					if (rngFailSuccess < 0.25f)
					{
						msg += Localization.Get("Catastrophic failure!");
						addProgress /= 2f;
						result = ProgressResult.VeryBad;
					}
					// 75% chance for bad
					else
					{
						msg += Localization.Get("That didn't go so well...");
						addProgress /= 1.5f;
						result = ProgressResult.Bad;
					}
				}
				else
				{
					// 25% chance for best, if manual is >= 2 ranks
					if (rngFailSuccess < 0.25f && rankDiff <= -2)
					{
						msg += Localization.Get("You created a masterpiece!");
						addProgress *= 2f;
						result = ProgressResult.VeryGood;
					}
					// 75% chance for good
					else
					{
						// Too easy if more than two ranks below, which counts
						// as a training fail, according to the Wiki.
						if (rankDiff >= 2)
						{
							msg += Localization.Get("You did it, but that was way too easy.");
							result = ProgressResult.Bad;
						}
						else
						{
							msg += Localization.Get("Success!");
							result = ProgressResult.Good;
						}
					}
				}

				// Weather bonus
				if (ChannelServer.Instance.Weather.GetWeatherType(creature.RegionId) == WeatherType.Rain)
					addProgress += manualData.RainBonus;

				progress = Math.Min(1, progress + addProgress);
				existingItem.MetaData1.SetFloat(ProgressVar, progress);

				if (progress == 1)
					msg += Localization.Get("\nFinal Stage remaining");
				else
					msg += string.Format(Localization.Get("\n{0}% completed."), (int)(progress * 100));

				this.OnProgress(creature, skill, result);
				Send.Notice(creature, msg);

				// Event
				ChannelServer.Instance.Events.OnCreatureFinishedProductionOrCollection(creature, success);
			}
			else
			{
				var quality = this.CalculateQuality(stitches, creature.Temp.TailoringMiniGameX, creature.Temp.TailoringMiniGameY);
				this.FinishItem(creature, skill, manualData, 0, existingItem, quality);
				this.OnProgress(creature, skill, ProgressResult.Finish);

				// Creation event
				ChannelServer.Instance.Events.OnCreatureCreatedItem(new CreationEventArgs(creature, CreationMethod.Tailoring, existingItem, manualData.Rank));

				result = ProgressResult.Finish;
				success = true;
			}

			// Add or update item
			if (!newItem)
				Send.ItemUpdate(creature, existingItem);
			else
				creature.Inventory.Add(existingItem, true);

			// Acquire info once it's finished and updated.
			if (result == ProgressResult.Finish)
				Send.AcquireInfo2(creature, "tailoring", existingItem.EntityId);

			// Success motion if it was a good result, otherwise keep
			// going to fail.
			if (success)
			{
				Send.UseMotion(creature, 14, 0); // Success motion
				Send.Echo(creature, packet);
				return;
			}

		L_Fail:
			Send.UseMotion(creature, 14, 3); // Fail motion
			Send.Echo(creature, packet);
		}