예제 #1
0
        private static void HandleCreateItemRecipe(Player player, WorldObject source, WorldObject target, Recipe recipe)
        {
            ActionChain   craftChain     = new ActionChain();
            CreatureSkill skill          = null;
            bool          skillSuccess   = true; // assume success, unless there's a skill check
            double        percentSuccess = 1;

            UniversalMotion motion = new UniversalMotion(MotionStance.Standing, new MotionItem(MotionCommand.ClapHands));

            craftChain.AddAction(player, () => player.HandleActionMotion(motion));
            float craftAnimationLength = MotionTable.GetAnimationLength((uint)player.MotionTableId, MotionCommand.ClapHands);

            craftChain.AddDelaySeconds(craftAnimationLength);
            // craftChain.AddDelaySeconds(0.5);

            craftChain.AddAction(player, () =>
            {
                if (recipe.SkillId != null && recipe.SkillDifficulty != null)
                {
                    // there's a skill associated with this
                    Skill skillId = (Skill)recipe.SkillId.Value;

                    // this shouldn't happen, but sanity check for unexpected nulls
                    if (!player.Skills.ContainsKey(skillId))
                    {
                        log.Warn("Unexpectedly missing skill in Recipe usage");
                        player.SendUseDoneEvent();
                        return;
                    }

                    skill          = player.Skills[skillId];
                    percentSuccess = skill.GetPercentSuccess(recipe.SkillDifficulty.Value);
                }

                // straight skill check, if applciable
                if (skill != null)
                {
                    skillSuccess = _random.NextDouble() < percentSuccess;
                }

                if ((recipe.ResultFlags & (uint)RecipeResult.SourceItemDestroyed) > 0)
                {
                    player.DestroyInventoryItem(source);
                }

                if ((recipe.ResultFlags & (uint)RecipeResult.TargetItemDestroyed) > 0)
                {
                    player.DestroyInventoryItem(target);
                }

                if ((recipe.ResultFlags & (uint)RecipeResult.SourceItemUsesDecrement) > 0)
                {
                    if (source.Structure <= 1)
                    {
                        player.DestroyInventoryItem(source);
                    }
                    else
                    {
                        source.Structure--;
                        source.SendPartialUpdates(player.Session, _updateStructure);
                    }
                }

                if ((recipe.ResultFlags & (uint)RecipeResult.TargetItemUsesDecrement) > 0)
                {
                    if (target.Structure <= 1)
                    {
                        player.DestroyInventoryItem(target);
                    }
                    else
                    {
                        target.Structure--;
                        target.SendPartialUpdates(player.Session, _updateStructure);
                    }
                }

                if (skillSuccess)
                {
                    WorldObject newObject1 = null;
                    WorldObject newObject2 = null;

                    if ((recipe.ResultFlags & (uint)RecipeResult.SuccessItem1) > 0 && recipe.SuccessItem1Wcid != null)
                    {
                        newObject1 = player.AddNewItemToInventory(recipe.SuccessItem1Wcid.Value);
                    }

                    if ((recipe.ResultFlags & (uint)RecipeResult.SuccessItem2) > 0 && recipe.SuccessItem2Wcid != null)
                    {
                        newObject2 = player.AddNewItemToInventory(recipe.SuccessItem2Wcid.Value);
                    }

                    var text    = string.Format(recipe.SuccessMessage, source.Name, target.Name, newObject1?.Name, newObject2?.Name);
                    var message = new GameMessageSystemChat(text, ChatMessageType.Craft);
                    player.Session.Network.EnqueueSend(message);
                }
                else
                {
                    WorldObject newObject1 = null;
                    WorldObject newObject2 = null;

                    if ((recipe.ResultFlags & (uint)RecipeResult.FailureItem1) > 0 && recipe.FailureItem1Wcid != null)
                    {
                        newObject1 = player.AddNewItemToInventory(recipe.FailureItem1Wcid.Value);
                    }

                    if ((recipe.ResultFlags & (uint)RecipeResult.FailureItem2) > 0 && recipe.FailureItem2Wcid != null)
                    {
                        newObject2 = player.AddNewItemToInventory(recipe.FailureItem2Wcid.Value);
                    }

                    var text    = string.Format(recipe.FailMessage, source.Name, target.Name, newObject1?.Name, newObject2?.Name);
                    var message = new GameMessageSystemChat(text, ChatMessageType.Craft);
                    player.Session.Network.EnqueueSend(message);
                }

                player.SendUseDoneEvent();
            });

            craftChain.EnqueueChain();
        }
예제 #2
0
        private static void HandleHealingRecipe(Player player, WorldObject source, WorldObject target, Recipe recipe)
        {
            ActionChain chain = new ActionChain();

            // skill will be null since the difficulty is calculated manually
            if (recipe.SkillId == null)
            {
                log.Warn($"healing recipe has null skill id (should almost certainly be healing, but who knows).  recipe id {recipe.RecipeId}.");
                player.SendUseDoneEvent();
                return;
            }

            if (!(target is Player))
            {
                var message = new GameMessageSystemChat($"The {source.Name} cannot be used on {target.Name}.", ChatMessageType.Craft);
                player.Session.Network.EnqueueSend(message);
                player.SendUseDoneEvent();
                return;
            }

            Player  targetPlayer = target as Player;
            Ability vital        = (Ability?)recipe.HealingAttribute ?? Ability.Health;

            // there's a skill associated with this
            Skill skillId = (Skill)recipe.SkillId.Value;

            // this shouldn't happen, but sanity check for unexpected nulls
            if (!player.Skills.ContainsKey(skillId))
            {
                log.Warn("Unexpectedly missing skill in Recipe usage");
                player.SendUseDoneEvent();
                return;
            }

            CreatureSkill skill = player.Skills[skillId];

            // at this point, we've validated that the target is a player, and the target is below max health

            if (target.Guid != player.Guid)
            {
                // TODO: validate range
            }

            MotionCommand cmd = MotionCommand.SkillHealSelf;

            if (target.Guid != player.Guid)
            {
                cmd = MotionCommand.Woah; // guess?  nothing else stood out
            }
            // everything pre-validatable is validated.  action will be attempted unless cancelled, so
            // queue up the animation and action
            UniversalMotion motion = new UniversalMotion(MotionStance.Standing, new MotionItem(cmd));

            chain.AddAction(player, () => player.HandleActionMotion(motion));
            chain.AddDelaySeconds(0.5);

            chain.AddAction(player, () =>
            {
                // TODO: revalidate range if other player (they could have moved)

                double difficulty = 2 * (targetPlayer.Vitals[vital].MaxValue - targetPlayer.Vitals[vital].Current);
                if (difficulty <= 0)
                {
                    // target is at max (or higher?) health, do nothing
                    var text = "You are already at full health.";

                    if (target.Guid != player.Guid)
                    {
                        text = $"{target.Name} is already at full health";
                    }

                    player.Session.Network.EnqueueSend(new GameMessageSystemChat(text, ChatMessageType.Craft));
                    player.SendUseDoneEvent();
                    return;
                }

                if (player.CombatMode != CombatMode.NonCombat && player.CombatMode != CombatMode.Undef)
                {
                    difficulty *= 1.1;
                }

                uint boost        = source.Boost ?? 0;
                double multiplier = source.HealkitMod ?? 1;

                double playerSkill = skill.ActiveValue + boost;
                if (skill.Status == SkillStatus.Trained)
                {
                    playerSkill *= 1.1;
                }
                else if (skill.Status == SkillStatus.Specialized)
                {
                    playerSkill *= 1.5;
                }

                // usage is inevitable at this point, consume the use
                if ((recipe.ResultFlags & (uint)RecipeResult.SourceItemUsesDecrement) > 0)
                {
                    if (source.Structure <= 1)
                    {
                        player.DestroyInventoryItem(source);
                    }
                    else
                    {
                        source.Structure--;
                        source.SendPartialUpdates(player.Session, _updateStructure);
                    }
                }

                double percentSuccess = CreatureSkill.GetPercentSuccess((uint)playerSkill, (uint)difficulty);

                if (_random.NextDouble() <= percentSuccess)
                {
                    string expertly = "";

                    if (_random.NextDouble() < 0.1d)
                    {
                        expertly    = "expertly ";
                        multiplier *= 1.2;
                    }

                    // calculate amount restored
                    uint maxRestore = targetPlayer.Vitals[vital].MaxValue - targetPlayer.Vitals[vital].Current;

                    // TODO: get actual forumula for healing.  this is COMPLETELY wrong.  this is 60 + random(1-60).
                    double amountRestored = 60d + _random.Next(1, 61);
                    amountRestored       *= multiplier;

                    uint actualRestored = (uint)Math.Min(maxRestore, amountRestored);
                    targetPlayer.Vitals[vital].Current += actualRestored;

                    var updateVital = new GameMessagePrivateUpdateAttribute2ndLevel(player.Session, vital.GetVital(), targetPlayer.Vitals[vital].Current);
                    player.Session.Network.EnqueueSend(updateVital);

                    if (targetPlayer.Guid != player.Guid)
                    {
                        // tell the other player they got healed
                        var updateVitalToTarget = new GameMessagePrivateUpdateAttribute2ndLevel(targetPlayer.Session, vital.GetVital(), targetPlayer.Vitals[vital].Current);
                        targetPlayer.Session.Network.EnqueueSend(updateVitalToTarget);
                    }

                    string name = "yourself";
                    if (targetPlayer.Guid != player.Guid)
                    {
                        name = targetPlayer.Name;
                    }

                    string vitalName = "Health";

                    if (vital == Ability.Stamina)
                    {
                        vitalName = "Stamina";
                    }
                    else if (vital == Ability.Mana)
                    {
                        vitalName = "Mana";
                    }

                    string uses = source.Structure == 1 ? "use" : "uses";

                    var text    = string.Format(recipe.SuccessMessage, expertly, name, actualRestored, vitalName, source.Name, source.Structure, uses);
                    var message = new GameMessageSystemChat(text, ChatMessageType.Craft);
                    player.Session.Network.EnqueueSend(message);

                    if (targetPlayer.Guid != player.Guid)
                    {
                        // send text to the other player too
                        text    = string.Format(recipe.AlternateMessage, player.Name, expertly, actualRestored, vitalName);
                        message = new GameMessageSystemChat(text, ChatMessageType.Craft);
                        targetPlayer.Session.Network.EnqueueSend(message);
                    }
                }

                player.SendUseDoneEvent();
            });

            chain.EnqueueChain();
        }
예제 #3
0
        public static void UseObjectOnTarget(Player player, WorldObject source, WorldObject target)
        {
            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;
            }

            ActionChain   craftChain     = new ActionChain();
            CreatureSkill skill          = null;
            bool          skillSuccess   = true; // assume success, unless there's a skill check
            double        percentSuccess = 1;

            UniversalMotion motion = new UniversalMotion(MotionStance.Standing, new MotionItem(MotionCommand.ClapHands));

            craftChain.AddAction(player, () => player.HandleActionMotion(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();
                        return;
                    }

                    percentSuccess = skill.GetPercentSuccess(recipe.Recipe.Difficulty); //FIXME: Pretty certain this is broken
                }

                if (skill != null)
                {
                    if (skill.Status == SkillStatus.Untrained)
                    {
                        var message = new GameEventWeenieError(player.Session, WeenieError.YouAreNotTrainedInThatTradeSkill);
                        player.Session.Network.EnqueueSend(message);
                        player.SendUseDoneEvent(WeenieError.YouAreNotTrainedInThatTradeSkill);
                        return;
                    }
                }

                // straight skill check, if applicable
                if (skill != null)
                {
                    skillSuccess = _random.NextDouble() < percentSuccess;
                }


                var components = recipe.Recipe.RecipeComponent.ToList();

                if (skillSuccess)
                {
                    var targetSuccess = components[0];
                    var sourceSuccess = components[1];

                    bool destroyTarget = _random.NextDouble() < targetSuccess.DestroyChance;
                    bool destroySource = _random.NextDouble() < sourceSuccess.DestroyChance;

                    if (destroyTarget)
                    {
                        if (target.OwnerId == player.Guid.Full)
                        {
                            player.TryRemoveItemFromInventoryWithNetworking(target, (ushort)targetSuccess.DestroyAmount);
                        }
                        else
                        {
                            target.Destroy();
                        }

                        if (targetSuccess.DestroyMessage != "")
                        {
                            var destroyMessage = new GameMessageSystemChat(targetSuccess.DestroyMessage, ChatMessageType.Craft);
                            player.Session.Network.EnqueueSend(destroyMessage);
                        }
                    }

                    if (destroySource)
                    {
                        if (source.OwnerId == player.Guid.Full)
                        {
                            player.TryRemoveItemFromInventoryWithNetworking(source, (ushort)sourceSuccess.DestroyAmount);
                        }
                        else
                        {
                            source.Destroy();
                        }

                        if (sourceSuccess.DestroyMessage != "")
                        {
                            var destroyMessage = new GameMessageSystemChat(sourceSuccess.DestroyMessage, ChatMessageType.Craft);
                            player.Session.Network.EnqueueSend(destroyMessage);
                        }
                    }

                    if (recipe.Recipe.SuccessWCID > 0)
                    {
                        var wo = WorldObjectFactory.CreateNewWorldObject(recipe.Recipe.SuccessWCID);

                        if (wo != null)
                        {
                            if (recipe.Recipe.SuccessAmount > 1)
                            {
                                wo.StackSize = (ushort)recipe.Recipe.SuccessAmount;
                            }

                            player.TryCreateInInventoryWithNetworking(wo);
                        }
                    }

                    var message = new GameMessageSystemChat(recipe.Recipe.SuccessMessage, ChatMessageType.Craft);
                    player.Session.Network.EnqueueSend(message);
                }
                else
                {
                    var targetFail = components[2];
                    var sourceFail = components[3];

                    bool destroyTarget = _random.NextDouble() < targetFail.DestroyChance;
                    bool destroySource = _random.NextDouble() < sourceFail.DestroyChance;

                    if (destroyTarget)
                    {
                        if (target.OwnerId == player.Guid.Full)
                        {
                            player.TryRemoveItemFromInventoryWithNetworking(target, (ushort)targetFail.DestroyAmount);
                        }
                        else
                        {
                            target.Destroy();
                        }

                        if (targetFail.DestroyMessage != "")
                        {
                            var destroyMessage = new GameMessageSystemChat(targetFail.DestroyMessage, ChatMessageType.Craft);
                            player.Session.Network.EnqueueSend(destroyMessage);
                        }
                    }

                    if (destroySource)
                    {
                        if (source.OwnerId == player.Guid.Full)
                        {
                            player.TryRemoveItemFromInventoryWithNetworking(source, (ushort)sourceFail.DestroyAmount);
                        }
                        else
                        {
                            source.Destroy();
                        }

                        if (sourceFail.DestroyMessage != "")
                        {
                            var destroyMessage = new GameMessageSystemChat(sourceFail.DestroyMessage, ChatMessageType.Craft);
                            player.Session.Network.EnqueueSend(destroyMessage);
                        }
                    }

                    if (recipe.Recipe.FailWCID > 0)
                    {
                        var wo = WorldObjectFactory.CreateNewWorldObject(recipe.Recipe.FailWCID);

                        if (wo != null)
                        {
                            if (recipe.Recipe.FailAmount > 1)
                            {
                                wo.StackSize = (ushort)recipe.Recipe.FailAmount;
                            }

                            player.TryCreateInInventoryWithNetworking(wo);
                        }
                    }

                    var message = new GameMessageSystemChat(recipe.Recipe.FailMessage, ChatMessageType.Craft);
                    player.Session.Network.EnqueueSend(message);
                }

                player.SendUseDoneEvent();
            });

            craftChain.EnqueueChain();
        }
예제 #4
0
        public static void UseObjectOnTarget(Player player, WorldObject source, WorldObject target)
        {
            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;
            }

            ActionChain   craftChain     = new ActionChain();
            CreatureSkill skill          = null;
            bool          skillSuccess   = true; // assume success, unless there's a skill check
            double        percentSuccess = 1;

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

                // straight skill check, if applicable
                if (skill != null)
                {
                    skillSuccess = _random.NextDouble() < percentSuccess;
                }


                if (skillSuccess)
                {
                    bool destroyTarget = _random.NextDouble() < recipe.Recipe.SuccessDestroyTargetChance;
                    bool destroySource = _random.NextDouble() < recipe.Recipe.SuccessDestroySourceChance;

                    if (destroyTarget)
                    {
                        if (target.OwnerId == player.Guid.Full || player.GetInventoryItem(target.Guid) != null)
                        {
                            player.TryRemoveItemFromInventoryWithNetworkingWithDestroy(target, (ushort)recipe.Recipe.SuccessDestroyTargetAmount);
                        }
                        else if (target.WielderId == player.Guid.Full)
                        {
                            if (!player.TryRemoveItemWithNetworking(target))
                            {
                                throw new Exception($"Failed to remove {target.Name} from player inventory.");
                            }
                        }
                        else
                        {
                            target.Destroy();
                        }

                        if (!String.IsNullOrEmpty(recipe.Recipe.SuccessDestroyTargetMessage))
                        {
                            var destroyMessage = new GameMessageSystemChat(recipe.Recipe.SuccessDestroyTargetMessage, ChatMessageType.Craft);
                            player.Session.Network.EnqueueSend(destroyMessage);
                        }
                    }

                    if (destroySource)
                    {
                        if (source.OwnerId == player.Guid.Full || player.GetInventoryItem(target.Guid) != null)
                        {
                            player.TryRemoveItemFromInventoryWithNetworkingWithDestroy(source, (ushort)recipe.Recipe.SuccessDestroySourceAmount);
                        }
                        else if (source.WielderId == player.Guid.Full)
                        {
                            if (!player.TryRemoveItemWithNetworking(source))
                            {
                                throw new Exception($"Failed to remove {source.Name} from player inventory.");
                            }
                        }
                        else
                        {
                            source.Destroy();
                        }

                        if (!String.IsNullOrEmpty(recipe.Recipe.SuccessDestroySourceMessage))
                        {
                            var destroyMessage = new GameMessageSystemChat(recipe.Recipe.SuccessDestroySourceMessage, ChatMessageType.Craft);
                            player.Session.Network.EnqueueSend(destroyMessage);
                        }
                    }

                    if (recipe.Recipe.SuccessWCID > 0)
                    {
                        var wo = WorldObjectFactory.CreateNewWorldObject(recipe.Recipe.SuccessWCID);

                        if (wo != null)
                        {
                            if (recipe.Recipe.SuccessAmount > 1)
                            {
                                wo.StackSize = (ushort)recipe.Recipe.SuccessAmount;
                            }

                            player.TryCreateInInventoryWithNetworking(wo);
                        }
                    }

                    var message = new GameMessageSystemChat(recipe.Recipe.SuccessMessage, ChatMessageType.Craft);
                    player.Session.Network.EnqueueSend(message);
                }
                else
                {
                    bool destroyTarget = _random.NextDouble() < recipe.Recipe.FailDestroyTargetChance;
                    bool destroySource = _random.NextDouble() < recipe.Recipe.FailDestroySourceChance;

                    if (destroyTarget)
                    {
                        if (target.OwnerId == player.Guid.Full || player.GetInventoryItem(target.Guid) != null)
                        {
                            player.TryRemoveItemFromInventoryWithNetworkingWithDestroy(target, (ushort)recipe.Recipe.FailDestroyTargetAmount);
                        }
                        else if (target.WielderId == player.Guid.Full)
                        {
                            if (!player.TryRemoveItemWithNetworking(target))
                            {
                                throw new Exception($"Failed to remove {target.Name} from player inventory.");
                            }
                        }
                        else
                        {
                            target.Destroy();
                        }

                        if (!String.IsNullOrEmpty(recipe.Recipe.FailDestroyTargetMessage))
                        {
                            var destroyMessage = new GameMessageSystemChat(recipe.Recipe.FailDestroyTargetMessage, ChatMessageType.Craft);
                            player.Session.Network.EnqueueSend(destroyMessage);
                        }
                    }

                    if (destroySource)
                    {
                        if (source.OwnerId == player.Guid.Full || player.GetInventoryItem(target.Guid) != null)
                        {
                            player.TryRemoveItemFromInventoryWithNetworkingWithDestroy(source, (ushort)recipe.Recipe.FailDestroySourceAmount);
                        }
                        else if (source.WielderId == player.Guid.Full)
                        {
                            if (!player.TryRemoveItemWithNetworking(source))
                            {
                                throw new Exception($"Failed to remove {source.Name} from player inventory.");
                            }
                        }
                        else
                        {
                            source.Destroy();
                        }

                        if (!String.IsNullOrEmpty(recipe.Recipe.FailDestroySourceMessage))
                        {
                            var destroyMessage = new GameMessageSystemChat(recipe.Recipe.FailDestroySourceMessage, ChatMessageType.Craft);
                            player.Session.Network.EnqueueSend(destroyMessage);
                        }
                    }

                    if (recipe.Recipe.FailWCID > 0)
                    {
                        var wo = WorldObjectFactory.CreateNewWorldObject(recipe.Recipe.FailWCID);

                        if (wo != null)
                        {
                            if (recipe.Recipe.FailAmount > 1)
                            {
                                wo.StackSize = (ushort)recipe.Recipe.FailAmount;
                            }

                            player.TryCreateInInventoryWithNetworking(wo);
                        }
                    }

                    var message = new GameMessageSystemChat(recipe.Recipe.FailMessage, ChatMessageType.Craft);
                    player.Session.Network.EnqueueSend(message);
                }

                player.SendUseDoneEvent();
            });

            craftChain.EnqueueChain();
        }
예제 #5
0
        public void FiftyFiftyIsAccurate()
        {
            var result = CreatureSkill.GetPercentSuccess(100, 100);

            Assert.AreEqual(0.5d, result);
        }
예제 #6
0
        public static void UseObjectOnTarget(Player player, WorldObject source, WorldObject target)
        {
            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;

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

                // perform skill check, if applicable
                if (skill != null)
                {
                    success = ThreadSafeRandom.Next(0.0f, 1.0f) <= percentSuccess;
                }

                CreateDestroyItems(player, recipe.Recipe, source, target, success);

                player.SendUseDoneEvent();
            });

            craftChain.EnqueueChain();
        }