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

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

Completes skill, increasting item's progress or finishing it.
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 rnd = RandomProvider.Get();
			var materials = new List<ProductionMaterial>();
			var hits = new List<HammerHit>();

			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)
			{
				// Hits
				if (!this.ReadHits(creature, packet, out hits))
					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 (!this.CheckTools(creature))
				goto L_Fail;

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

			// 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);

			var success = true;
			var isNewItem = false;
			Item item = null;

			// Get item to work on
			if (existingItemEntityId == 0)
			{
				// Create new item
				item = new Item(manualData.ItemId);
				item.OptionInfo.Flags |= ItemFlags.Incomplete;
				item.MetaData1.SetFloat(ProgressVar, 0);

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

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

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

			// Finish item if progress is >= 1, otherwise increase progress.
			var progress = item.MetaData1.GetFloat(ProgressVar);
			if (progress < 1)
			{
				// 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);

				var msg = "";
				ProgressResult result;

				// Apply RNG fail/success
				if (!success)
				{
					// 25% chance for very bad
					if (rngFailSuccess < 0.25f)
					{
						msg += Localization.Get("Yikes. That was terrible. Are you feeling okay?");
						addProgress /= 2f;
						result = ProgressResult.VeryBad;
					}
					// 75% chance for bad
					else
					{
						msg += Localization.Get("Failed...");
						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("A smashing success!!!");
						addProgress *= 2f;
						result = ProgressResult.VeryGood;
					}
					// 85% 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("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
				progress = Math.Min(1, progress + addProgress);
				item.MetaData1.SetFloat(ProgressVar, progress);

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

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

				// Event
				ChannelServer.Instance.Events.OnCreatureFinishedProductionOrCollection(creature, result >= ProgressResult.Good);
			}
			else
			{
				var quality = this.CalculateQuality(hits, creature.Temp.BlacksmithingMiniGameDots);
				this.FinishItem(creature, skill, manualData, creature.Temp.CreationFinishId, item, quality);
				this.OnProgress(creature, skill, item, ProgressResult.Finish);

				// Creation event
				ChannelServer.Instance.Events.OnCreatureCreatedItem(new CreationEventArgs(creature, CreationMethod.Blacksmithing, item, manualData.Rank));
			}

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

			// 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);
		}