public void EnqueueBroadcastUpdateObject() { if (CurrentLandblock != null) { GameMessage msg = new GameMessageUpdateObject(this); CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, msg); } }
public static void UseObjectOnTarget(Player player, WorldObject source, WorldObject target) { if (player.IsBusy) { player.SendUseDoneEvent(WeenieError.YoureTooBusy); return; } if (source == target) { var message = new GameMessageSystemChat($"The {source.Name} cannot be combined with itself.", ChatMessageType.Craft); player.Session.Network.EnqueueSend(message); player.SendUseDoneEvent(); return; } var recipe = DatabaseManager.World.GetCachedCookbook(source.WeenieClassId, target.WeenieClassId); if (recipe == null) { var message = new GameMessageSystemChat($"The {source.Name} cannot be used on the {target.Name}.", ChatMessageType.Craft); player.Session.Network.EnqueueSend(message); player.SendUseDoneEvent(); return; } // verify requirements if (!VerifyRequirements(recipe.Recipe, player, source, target)) { player.SendUseDoneEvent(WeenieError.YouDoNotPassCraftingRequirements); return; } if (source.ItemType == ItemType.TinkeringMaterial) { HandleTinkering(player, source, target); return; } ActionChain craftChain = new ActionChain(); CreatureSkill skill = null; bool success = true; // assume success, unless there's a skill check double percentSuccess = 1; player.IsBusy = true; if (player.CombatMode != CombatMode.NonCombat) { var stanceTime = player.SetCombatMode(CombatMode.NonCombat); craftChain.AddDelaySeconds(stanceTime); } var motion = new Motion(MotionStance.NonCombat, MotionCommand.ClapHands); craftChain.AddAction(player, () => player.EnqueueBroadcastMotion(motion)); var motionTable = DatManager.PortalDat.ReadFromDat <MotionTable>(player.MotionTableId); var craftAnimationLength = motionTable.GetAnimationLength(MotionCommand.ClapHands); craftChain.AddDelaySeconds(craftAnimationLength); craftChain.AddAction(player, () => { if (recipe.Recipe.Skill > 0 && recipe.Recipe.Difficulty > 0) { // there's a skill associated with this Skill skillId = (Skill)recipe.Recipe.Skill; // this shouldn't happen, but sanity check for unexpected nulls skill = player.GetCreatureSkill(skillId); if (skill == null) { log.Warn("Unexpectedly missing skill in Recipe usage"); player.SendUseDoneEvent(); player.IsBusy = false; return; } //Console.WriteLine("Skill difficulty: " + recipe.Recipe.Difficulty); percentSuccess = skill.GetPercentSuccess(recipe.Recipe.Difficulty); //FIXME: Pretty certain this is broken } if (skill != null) { // check for pre-MoA skill // convert into appropriate post-MoA skill // pre-MoA melee weapons: get highest melee weapons skill var newSkill = player.ConvertToMoASkill(skill.Skill); skill = player.GetCreatureSkill(newSkill); //Console.WriteLine("Required skill: " + skill.Skill); if (skill.AdvancementClass <= SkillAdvancementClass.Untrained) { var message = new GameEventWeenieError(player.Session, WeenieError.YouAreNotTrainedInThatTradeSkill); player.Session.Network.EnqueueSend(message); player.SendUseDoneEvent(WeenieError.YouAreNotTrainedInThatTradeSkill); player.IsBusy = false; return; } } // perform skill check, if applicable if (skill != null) { success = ThreadSafeRandom.Next(0.0f, 1.0f) <= percentSuccess; } CreateDestroyItems(player, recipe.Recipe, source, target, success); // this code was intended for dyes, but UpdateObj seems to remove crafting components // from shortcut bar, if they are hotkeyed // more specifity for this, only if relevant properties are modified? var shortcuts = player.GetShortcuts(); if (!shortcuts.Select(i => i.ObjectId).Contains(target.Guid.Full)) { var updateObj = new GameMessageUpdateObject(target); var updateDesc = new GameMessageObjDescEvent(player); if (target.CurrentWieldedLocation != null) { player.EnqueueBroadcast(updateObj, updateDesc); } else { player.Session.Network.EnqueueSend(updateObj); } } player.SendUseDoneEvent(); player.IsBusy = false; }); craftChain.EnqueueChain(); }