Beispiel #1
0
        private static void HandleCreateItemRecipe(Player player, WorldObject source, WorldObject target, AceRecipe 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));
            var motionTable          = DatManager.PortalDat.ReadFromDat <MotionTable>((uint)player.MotionTableId);
            var craftAnimationLength = motionTable.GetAnimationLength(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
                    skill = player.GetCreatureSkill(skillId);

                    if (skill == null)
                    {
                        log.Warn("Unexpectedly missing skill in Recipe usage");
                        player.SendUseDoneEvent();
                        return;
                    }

                    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();
        }
Beispiel #2
0
        private static void HandleHealingRecipe(Player player, WorldObject source, WorldObject target, AceRecipe 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.RecipeGuid}.");
                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 = (Player)target;
            //Ability vital = (Ability?)recipe.HealingAttribute ?? Ability.Health;

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

            var skill = player.GetCreatureSkill(skillId);

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

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

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

            //    double playerSkill = skill.Current + 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();
        }