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