Beispiel #1
0
        public static void HandleQueueWeaponSkill(NWPlayer pc, Data.Entity.Perk entity, IPerkHandler ability, int spellFeatID)
        {
            int?   cooldownCategoryID = ability.CooldownCategoryID(pc, entity.CooldownCategoryID, spellFeatID);
            var    cooldownCategory   = DataService.Get <CooldownCategory>(cooldownCategoryID);
            string queueUUID          = Guid.NewGuid().ToString();

            pc.SetLocalInt("ACTIVE_WEAPON_SKILL", entity.ID);
            pc.SetLocalString("ACTIVE_WEAPON_SKILL_UUID", queueUUID);
            pc.SetLocalInt("ACTIVE_WEAPON_SKILL_FEAT_ID", spellFeatID);
            pc.SendMessage("Weapon skill '" + entity.Name + "' queued for next attack.");

            ApplyCooldown(pc, cooldownCategory, ability, spellFeatID);

            // Player must attack within 30 seconds after queueing or else it wears off.
            _.DelayCommand(30f, () =>
            {
                if (pc.GetLocalString("ACTIVE_WEAPON_SKILL_UUID") == queueUUID)
                {
                    pc.DeleteLocalInt("ACTIVE_WEAPON_SKILL");
                    pc.DeleteLocalString("ACTIVE_WEAPON_SKILL_UUID");
                    pc.DeleteLocalInt("ACTIVE_WEAPON_SKILL_FEAT_ID");
                    pc.SendMessage("Your weapon skill '" + entity.Name + "' is no longer queued.");
                }
            });
        }
Beispiel #2
0
        private static void OnHitCastSpell()
        {
            NWPlayer oPC = Object.OBJECT_SELF;

            if (!oPC.IsValid)
            {
                return;
            }

            NWObject oTarget = _.GetSpellTargetObject();
            NWItem   oItem   = _.GetSpellCastItem();

            // If this method was triggered by our own armor (from getting hit), return.
            if (oItem.BaseItemType == BASE_ITEM_ARMOR)
            {
                return;
            }

            // Flag this attack as physical so that the damage scripts treat it properly.
            LoggingService.Trace(TraceComponent.LastAttack, "Setting attack type from " + oPC.GlobalID + " against " + _.GetName(oTarget) + " to physical (" + ATTACK_PHYSICAL.ToString() + ")");
            oTarget.SetLocalInt(LAST_ATTACK + oPC.GlobalID, ATTACK_PHYSICAL);

            HandleGrenadeProficiency(oPC, oTarget);
            HandlePlasmaCellPerk(oPC, oTarget);
            int activeWeaponSkillID = oPC.GetLocalInt("ACTIVE_WEAPON_SKILL");

            if (activeWeaponSkillID <= 0)
            {
                return;
            }
            int activeWeaponSkillFeatID = oPC.GetLocalInt("ACTIVE_WEAPON_SKILL_FEAT_ID");

            if (activeWeaponSkillFeatID < 0)
            {
                activeWeaponSkillFeatID = -1;
            }

            PCPerk entity  = DataService.GetAll <PCPerk>().Single(x => x.PlayerID == oPC.GlobalID && x.PerkID == activeWeaponSkillID);
            var    perk    = DataService.Get <Data.Entity.Perk>(entity.PerkID);
            var    handler = PerkService.GetPerkHandler(activeWeaponSkillID);

            if (handler.CanCastSpell(oPC, oTarget))
            {
                handler.OnImpact(oPC, oTarget, entity.PerkLevel, activeWeaponSkillFeatID);

                if (oTarget.IsNPC)
                {
                    ApplyEnmity(oPC, oTarget.Object, perk);
                }
            }
            else
            {
                oPC.SendMessage(handler.CannotCastSpellMessage(oPC, oTarget) ?? "That ability cannot be used at this time.");
            }

            oPC.DeleteLocalString("ACTIVE_WEAPON_SKILL_UUID");
            oPC.DeleteLocalInt("ACTIVE_WEAPON_SKILL");
            oPC.DeleteLocalInt("ACTIVE_WEAPON_SKILL_FEAT_ID");
        }
        public void OnPlayerHeartbeat(NWPlayer oPC)
        {
            List <PCCustomEffect> effects = _db.PCCustomEffects.Where(x => x.PlayerID == oPC.GlobalID).ToList();
            string areaResref             = oPC.Area.Resref;

            foreach (PCCustomEffect effect in effects)
            {
                if (oPC.CurrentHP <= -11 || areaResref == "death_realm")
                {
                    RemovePCCustomEffect(oPC, effect.CustomEffectID);
                    return;
                }

                PCCustomEffect result = RunPCCustomEffectProcess(oPC, effect);
                if (result == null)
                {
                    string message       = effect.CustomEffect.WornOffMessage;
                    string scriptHandler = effect.CustomEffect.ScriptHandler;
                    oPC.SendMessage(message);
                    oPC.DeleteLocalInt("CUSTOM_EFFECT_ACTIVE_" + effect.CustomEffectID);
                    _db.PCCustomEffects.Remove(effect);
                    _db.SaveChanges();

                    ICustomEffect handler = App.ResolveByInterface <ICustomEffect>("CustomEffect." + scriptHandler);
                    handler?.WearOff(null, oPC);
                }
                else
                {
                    _db.SaveChanges();
                }
            }
        }
Beispiel #4
0
        private static void OnModuleUseFeat()
        {
            NWPlayer pc     = Object.OBJECT_SELF;
            int      featID = NWNXEvents.OnFeatUsed_GetFeatID();

            if (featID != (int)CustomFeatType.RenameCraftedItem)
            {
                return;
            }
            pc.ClearAllActions();

            bool   isSetting  = pc.GetLocalInt("CRAFT_RENAMING_ITEM") == TRUE;
            NWItem renameItem = NWNXEvents.OnFeatUsed_GetTarget().Object;

            if (isSetting)
            {
                pc.SendMessage("You are no longer naming an item.");
                pc.DeleteLocalInt("CRAFT_RENAMING_ITEM");
                pc.DeleteLocalObject("CRAFT_RENAMING_ITEM_OBJECT");
                return;
            }

            string crafterPlayerID = renameItem.GetLocalString("CRAFTER_PLAYER_ID");

            if (string.IsNullOrWhiteSpace(crafterPlayerID) || new Guid(crafterPlayerID) != pc.GlobalID)
            {
                pc.SendMessage("You may only rename items which you have personally crafted.");
                return;
            }

            pc.SetLocalInt("CRAFT_RENAMING_ITEM", TRUE);
            pc.SetLocalObject("CRAFT_RENAMING_ITEM_OBJECT", renameItem);
            pc.SendMessage("Please enter in a name for this item. Length should be between 3 and 64 characters. Use this feat again to cancel this procedure.");
        }
Beispiel #5
0
        public void WearOff(NWCreature oCaster, NWObject oTarget, int effectiveLevel, string data)
        {
            NWPlayer player = oTarget.Object;

            player.IsBusy = false;
            player.DeleteLocalInt("MEDITATE_TICK");
        }
Beispiel #6
0
        private static void OnModuleNWNXChat()
        {
            NWPlayer pc      = NWNXChat.GetSender();
            string   newName = NWNXChat.GetMessage();

            if (!CanHandleChat(pc))
            {
                return;
            }

            NWNXChat.SkipMessage();
            NWItem renameItem = pc.GetLocalObject("CRAFT_RENAMING_ITEM_OBJECT");

            pc.DeleteLocalInt("CRAFT_RENAMING_ITEM");
            pc.DeleteLocalObject("CRAFT_RENAMING_ITEM_OBJECT");

            if (!renameItem.IsValid)
            {
                pc.SendMessage("Cannot find the item you were renaming.");
                return;
            }

            if (newName.Length < 3 || newName.Length > 64)
            {
                pc.SendMessage("Item names must be between 3 and 64 characters long.");
                return;
            }

            renameItem.Name = newName;

            pc.FloatingText("New name set!");
        }
        public bool Run(params object[] args)
        {
            NWPlayer player = GetEnteringPlayer();

            if (player.IsDM)
            {
                App.GetAppState().ConnectedDMs.Add(player);
            }

            player.DeleteLocalInt("IS_CUSTOMIZING_ITEM");
            _.ExecuteScript("dmfi_onclienter ", Object.OBJECT_SELF); // DMFI also calls "x3_mod_def_enter"
            _playerValidation.OnModuleEnter();
            _player.InitializePlayer(player);
            _data.CachePlayerData(player);
            _skill.OnModuleEnter();
            _player.LoadCharacter(player);
            _migration.OnModuleEnter();
            _player.ShowMOTD(player);
            ApplyGhostwalk();
            _quest.OnClientEnter();
            _activityLogging.OnModuleClientEnter();
            ApplyScriptEvents(player);
            _mapPin.OnModuleClientEnter();
            _objectVisibility.OnClientEnter();
            _customEffect.OnModuleEnter();
            _chatText.OnModuleEnter();
            _race.OnModuleEnter();

            player.SetLocalInt("LOGGED_IN_ONCE", TRUE);
            return(true);
        }
        public void ClearPlayerCraftingData(NWPlayer player)
        {
            var model = GetPlayerCraftingData(player);

            foreach (var item in model.MainComponents)
            {
                _.CopyItem(item.Object, player.Object, TRUE);
                item.Destroy();
            }
            foreach (var item in model.SecondaryComponents)
            {
                _.CopyItem(item.Object, player.Object, TRUE);
                item.Destroy();
            }
            foreach (var item in model.TertiaryComponents)
            {
                _.CopyItem(item.Object, player.Object, TRUE);
                item.Destroy();
            }
            foreach (var item in model.EnhancementComponents)
            {
                _.CopyItem(item.Object, player.Object, TRUE);
                item.Destroy();
            }

            player.Data.Remove("CRAFTING_MODEL");
            player.DeleteLocalInt("CRAFT_BLUEPRINT_ID");
        }
        public void OnHitCastSpell(NWPlayer oPC)
        {
            NWObject oTarget             = NWObject.Wrap(_.GetSpellTargetObject());
            int      activeWeaponSkillID = oPC.GetLocalInt("ACTIVE_WEAPON_SKILL");

            if (activeWeaponSkillID <= 0)
            {
                return;
            }

            Data.Entities.Perk entity = _db.Perks.Single(x => x.PerkID == activeWeaponSkillID);

            IPerk perk = App.ResolveByInterface <IPerk>("Perk." + entity.JavaScriptName);

            if (perk.CanCastSpell(oPC, oTarget))
            {
                perk.OnImpact(oPC, oTarget);

                if (oTarget.IsNPC)
                {
                    ApplyEnmity(oPC, NWCreature.Wrap(oTarget.Object), entity);
                }
            }
            else
            {
                oPC.SendMessage(perk.CannotCastSpellMessage(oPC, oTarget) ?? "That ability cannot be used at this time.");
            }

            oPC.DeleteLocalString("ACTIVE_WEAPON_SKILL_UUID");
            oPC.DeleteLocalInt("ACTIVE_WEAPON_SKILL");
        }
Beispiel #10
0
        private static void OnModuleUseFeat()
        {
            NWPlayer pc     = _.OBJECT_SELF;
            int      featID = Convert.ToInt32(NWNXEvents.GetEventData("FEAT_ID"));

            if (featID != (int)Feat.RenameCraftedItem)
            {
                return;
            }
            pc.ClearAllActions();

            bool   isSetting  = GetLocalBool(pc, "CRAFT_RENAMING_ITEM") == true;
            NWItem renameItem = NWNXObject.StringToObject(NWNXEvents.GetEventData("TARGET_OBJECT_ID"));

            if (isSetting)
            {
                pc.SendMessage("You are no longer naming an item.");
                pc.DeleteLocalInt("CRAFT_RENAMING_ITEM");
                pc.DeleteLocalObject("CRAFT_RENAMING_ITEM_OBJECT");
                return;
            }

            string crafterPlayerID = renameItem.GetLocalString("CRAFTER_PLAYER_ID");

            if (string.IsNullOrWhiteSpace(crafterPlayerID) || new Guid(crafterPlayerID) != pc.GlobalID)
            {
                pc.SendMessage("You may only rename items which you have personally crafted.");
                return;
            }

            SetLocalBool(pc, "CRAFT_RENAMING_ITEM", true);
            pc.SetLocalObject("CRAFT_RENAMING_ITEM_OBJECT", renameItem);
            pc.SendMessage("Please enter in a name for this item. Length should be between 3 and 64 characters. Use this feat again to cancel this procedure.");
        }
Beispiel #11
0
        public override void EndDialog()
        {
            NWPlayer player = GetPC();

            player.DeleteLocalObject("ITEM_BEING_RENAMED");
            player.DeleteLocalInt("ITEM_RENAMING_LISTENING");
            player.DeleteLocalString("RENAMED_ITEM_NEW_NAME");
        }
Beispiel #12
0
        private void ClearTempData()
        {
            NWPlayer player = GetPC();
            var      model  = GetDialogCustomData <Model>();

            model.IsConfirming = false;
            model.Title        = string.Empty;
            model.Message      = string.Empty;
            SetResponseText("PostDetailsPage", 1, "Remove Post");
            SetResponseText("CreatePostPage", 3, "Post Message");
            player.DeleteLocalInt("MESSAGE_BOARD_LISTENING");
            player.DeleteLocalString("MESSAGE_BOARD_TEXT");
        }
Beispiel #13
0
        public bool Run(params object[] args)
        {
            NWPlayer     player = NWPlayer.Wrap(_.GetPCSpeaker());
            PlayerDialog dialog = _dialog.LoadPlayerDialog(player.GlobalID);

            IConversation convo = App.ResolveByInterface <IConversation>("Conversation." + dialog.ActiveDialogName);

            convo.EndDialog();
            _dialog.RemovePlayerDialog(player.GlobalID);
            player.DeleteLocalInt("DIALOG_SYSTEM_INITIALIZE_RAN");

            return(true);
        }
Beispiel #14
0
        public void RemovePCCustomEffect(NWPlayer oPC, long customEffectID)
        {
            PCCustomEffect effect = _db.PCCustomEffects.SingleOrDefault(x => x.PlayerID == oPC.GlobalID && x.CustomEffectID == customEffectID);

            oPC.DeleteLocalInt("CUSTOM_EFFECT_ACTIVE_" + customEffectID);

            if (effect == null)
            {
                return;
            }

            _db.PCCustomEffects.Remove(effect);
            oPC.SendMessage(effect.CustomEffect.WornOffMessage);
        }
Beispiel #15
0
        // ReSharper disable once UnusedMember.Local
        private static void Main()
        {
            // The order of the following procedures matters.
            NWPlayer player = _.GetEnteringObject();

            using (new Profiler(nameof(mod_on_enter) + ":AddDMToCache"))
            {
                if (player.IsDM)
                {
                    AppCache.ConnectedDMs.Add(player);
                }
            }

            using (new Profiler(nameof(mod_on_enter) + ":BiowareDefault"))
            {
                player.DeleteLocalInt("IS_CUSTOMIZING_ITEM");
                _.ExecuteScript("dmfi_onclienter ", NWGameObject.OBJECT_SELF); // DMFI also calls "x3_mod_def_enter"
            }

            using (new Profiler(nameof(mod_on_enter) + ":PlayerValidation"))
            {
                PlayerValidationService.OnModuleEnter();
            }

            using (new Profiler(nameof(mod_on_enter) + ":InitializePlayer"))
            {
                PlayerService.InitializePlayer(player);
            }

            using (new Profiler(nameof(mod_on_enter) + ":CachePlayerData"))
            {
                //DataService.CachePlayerData(player);
            }

            using (new Profiler(nameof(mod_on_enter) + ":SkillServiceEnter"))
            {
                SkillService.OnModuleEnter();
            }

            using (new Profiler(nameof(mod_on_enter) + ":PerkServiceEnter"))
            {
                PerkService.OnModuleEnter();
            }

            MessageHub.Instance.Publish(new OnModuleEnter());
            player.SetLocalInt("LOGGED_IN_ONCE", _.TRUE);
        }
Beispiel #16
0
        public static void OnDialogEnd()
        {
            using (new Profiler(nameof(DialogService) + "." + nameof(OnDialogEnd)))
            {
                NWPlayer player = (_.GetPCSpeaker());
                if (!HasPlayerDialog(player.GlobalID))
                {
                    return;
                }

                PlayerDialog dialog = LoadPlayerDialog(player.GlobalID);
                var          convo  = GetConversation(dialog.ActiveDialogName);
                convo.EndDialog();
                RemovePlayerDialog(player.GlobalID);
                player.DeleteLocalInt("DIALOG_SYSTEM_INITIALIZE_RAN");
            }
        }
Beispiel #17
0
        public static void ClearPlayerCraftingData(NWPlayer player, bool destroyComponents = false)
        {
            var model = GetPlayerCraftingData(player);

            foreach (var item in model.MainComponents)
            {
                if (!destroyComponents)
                {
                    _.CopyItem(item.Object, player.Object, true);
                }
                item.Destroy();
            }
            foreach (var item in model.SecondaryComponents)
            {
                if (!destroyComponents)
                {
                    _.CopyItem(item.Object, player.Object, true);
                }
                item.Destroy();
            }
            foreach (var item in model.TertiaryComponents)
            {
                if (!destroyComponents)
                {
                    _.CopyItem(item.Object, player.Object, true);
                }
                item.Destroy();
            }
            foreach (var item in model.EnhancementComponents)
            {
                if (!destroyComponents)
                {
                    _.CopyItem(item.Object, player.Object, true);
                }
                item.Destroy();
            }

            if (!string.IsNullOrWhiteSpace(model.SerializedSalvageItem))
            {
                SerializationService.DeserializeItem(model.SerializedSalvageItem, player);
            }

            player.Data.Remove("CRAFTING_MODEL");
            player.DeleteLocalInt("CRAFT_BLUEPRINT_ID");
        }
        public void RemovePCCustomEffect(NWPlayer oPC, int customEffectID)
        {
            PCCustomEffect effect = _data.SingleOrDefault <PCCustomEffect>(x => x.PlayerID == oPC.GlobalID && x.CustomEffectID == customEffectID);

            oPC.DeleteLocalInt("CUSTOM_EFFECT_ACTIVE_" + customEffectID);

            // Doesn't exist in DB or is already marked for removal
            if (effect == null ||
                _cache.PCEffectsForRemoval.Contains(effect.ID))
            {
                return;
            }
            var customEffect = _data.Get <Data.Entity.CustomEffect>(effect.CustomEffectID);

            oPC.SendMessage(customEffect.WornOffMessage);

            _cache.PCEffectsForRemoval.Add(effect.ID);
        }
Beispiel #19
0
        public static void RemovePCCustomEffect(NWPlayer oPC, int customEffectID)
        {
            PCCustomEffect effect = DataService.SingleOrDefault <PCCustomEffect>(x => x.PlayerID == oPC.GlobalID && x.CustomEffectID == customEffectID);

            oPC.DeleteLocalInt("CUSTOM_EFFECT_ACTIVE_" + customEffectID);

            // Doesn't exist in DB or is already marked for removal
            if (effect == null ||
                AppCache.PCEffectsForRemoval.Contains(effect.ID))
            {
                return;
            }
            var handler = GetCustomEffectHandler(customEffectID);

            oPC.SendMessage(handler.WornOffMessage);

            AppCache.PCEffectsForRemoval.Add(effect.ID);
        }
Beispiel #20
0
        public void OnHitCastSpell(NWPlayer oPC)
        {
            NWObject oTarget             = NWObject.Wrap(_.GetSpellTargetObject());
            int      activeWeaponSkillID = oPC.GetLocalInt("ACTIVE_WEAPON_SKILL");

            if (activeWeaponSkillID <= 0)
            {
                return;
            }

            Data.Entities.Perk entity = _db.Perks.Single(x => x.PerkID == activeWeaponSkillID);

            IPerk perk = App.ResolveByInterface <IPerk>("Perk." + entity.JavaScriptName);

            perk?.OnImpact(oPC, oTarget);

            oPC.DeleteLocalString("ACTIVE_WEAPON_SKILL_UUID");
            oPC.DeleteLocalInt("ACTIVE_WEAPON_SKILL");
        }
Beispiel #21
0
        private void HandleQueueWeaponSkill(NWPlayer pc, Data.Entities.Perk entity, IPerk ability)
        {
            string queueUUID = Guid.NewGuid().ToString();

            pc.SetLocalInt("ACTIVE_WEAPON_SKILL", entity.PerkID);
            pc.SetLocalString("ACTIVE_WEAPON_SKILL_UUID", queueUUID);
            pc.SendMessage("Weapon skill '" + entity.Name + "' queued for next attack.");

            ApplyCooldown(pc, entity.CooldownCategory, ability);

            // Player must attack within 30 seconds after queueing or else it wears off.
            pc.DelayCommand(() =>
            {
                if (pc.GetLocalString("ACTIVE_WEAPON_SKILL_UUID") == queueUUID)
                {
                    pc.DeleteLocalInt("ACTIVE_WEAPON_SKILL");
                    pc.DeleteLocalString("ACTIVE_WEAPON_SKILL_UUID");
                    pc.SendMessage("Your weapon skill '" + entity.Name + "' is no longer queued.");
                }
            }, 30.0f);
        }
Beispiel #22
0
        public void DoAction(NWPlayer user, NWObject target, NWLocation targetLocation, params string[] args)
        {
            if (!user.IsPlayer)
            {
                return;
            }

            //Checks if the player has Plasma Cell
            if (!_.GetHasFeat(Feat.PlasmaCell, user))
            {
                user.SendMessage(ColorTokenService.Red("You do not have the perk: Plasma Cell."));
                return;
            }

            //Checks if the player has toggled plasma cell off
            if (user.GetLocalBool("PLASMA_CELL_TOGGLE_OFF") == false)
            {
                user.SetLocalInt("PLASMA_CELL_TOGGLE_OFF", 1);
                user.SendMessage(ColorTokenService.Red("Plasma Cell is now toggled off."));
                return;
            }

            //Checks if plasma cell has been toggled off
            else if (user.GetLocalInt("PLASMA_CELL_TOGGLE_OFF") > 0)
            {
                user.DeleteLocalInt("PLASMA_CELL_TOGGLE_OFF");
                user.SendMessage(ColorTokenService.Green("Plasma Cell is now toggled on!"));
                return;
            }

            //If the above aren't working, this should appear and debugging required
            else
            {
                user.SendMessage(ColorTokenService.Red("Something's wrong, contact a code contributor!"));
                return;
            }
        }
Beispiel #23
0
        public void OnHitCastSpell(NWPlayer oPC)
        {
            NWObject oTarget = _.GetSpellTargetObject();

            HandleGrenadeProficiency(oPC, oTarget);
            HandlePlasmaCellPerk(oPC, oTarget);
            int activeWeaponSkillID = oPC.GetLocalInt("ACTIVE_WEAPON_SKILL");

            if (activeWeaponSkillID <= 0)
            {
                return;
            }

            PCPerk entity = _data.GetAll <PCPerk>().Single(x => x.PlayerID == oPC.GlobalID && x.PerkID == activeWeaponSkillID);
            var    perk   = _data.Get <Data.Entity.Perk>(entity.PerkID);

            App.ResolveByInterface <IPerk>("Perk." + perk.ScriptName, (script) =>
            {
                if (script.CanCastSpell(oPC, oTarget))
                {
                    script.OnImpact(oPC, oTarget, entity.PerkLevel);

                    if (oTarget.IsNPC)
                    {
                        ApplyEnmity(oPC, oTarget.Object, perk);
                    }
                }
                else
                {
                    oPC.SendMessage(script.CannotCastSpellMessage(oPC, oTarget) ?? "That ability cannot be used at this time.");
                }

                oPC.DeleteLocalString("ACTIVE_WEAPON_SKILL_UUID");
                oPC.DeleteLocalInt("ACTIVE_WEAPON_SKILL");
            });
        }
Beispiel #24
0
        public static void SetIsInCall(NWPlayer sender, NWPlayer receiver, bool value = true)
        {
            if (value) // START CALL
            {
                SetLocalBool(sender, "HOLOCOM_CALL_CONNECTED", true);
                SetLocalBool(receiver, "HOLOCOM_CALL_CONNECTED", true);

                sender.SetLocalObject("HOLOCOM_CALL_CONNECTED_WITH", receiver);
                receiver.SetLocalObject("HOLOCOM_CALL_CONNECTED_WITH", sender);

                string message = "Call Connected. (Use the HoloCom or the chat command /endcall to terminate the call)";
                SendMessageToPC(sender, message);
                SendMessageToPC(receiver, message);
                var effectImmobilized = EffectCutsceneImmobilize();
                TagEffect(effectImmobilized, "HOLOCOM_CALL_IMMOBILIZE");
                ApplyEffectToObject(DurationType.Permanent, effectImmobilized, sender);
                ApplyEffectToObject(DurationType.Permanent, effectImmobilized, receiver);

                var holosender   = CopyObject(sender, VectorService.MoveLocation(receiver.Location, GetFacing(receiver), 2.0f, 180));
                var holoreceiver = CopyObject(receiver, VectorService.MoveLocation(sender.Location, GetFacing(sender), 2.0f, 180));

                ApplyEffectToObject(DurationType.Permanent, EffectVisualEffect(VisualEffect.Vfx_Dur_Ghostly_Visage_No_Sound, false), holosender);
                ApplyEffectToObject(DurationType.Permanent, EffectVisualEffect(VisualEffect.Vfx_Dur_Ghostly_Visage_No_Sound, false), holoreceiver);
                SetPlotFlag(holoreceiver, true);
                SetPlotFlag(holosender, true);
                sender.SetLocalObject("HOLOCOM_HOLOGRAM", holosender);
                receiver.SetLocalObject("HOLOCOM_HOLOGRAM", holoreceiver);

                SetLocalObject(holosender, "HOLOGRAM_OWNER", sender);
                SetLocalObject(holoreceiver, "HOLOGRAM_OWNER", receiver);

                sender.AssignCommand(() =>
                {
                    PlaySound("hologram_on");
                });
                receiver.AssignCommand(() =>
                {
                    PlaySound("hologram_on");
                });

                /*
                 * Console.WriteLine("SENDERS PERSPECTIVE:");
                 * Console.WriteLine("Sender Name:            " + HoloComService.GetCallSender(sender).Name);
                 * Console.WriteLine("Receiver Name:          " + HoloComService.GetCallReceiver(sender).Name);
                 * Console.WriteLine("Sender Call Attempts:   " + HoloComService.GetCallAttempt(sender));
                 * Console.WriteLine("Sender Connected With:  " + HoloComService.GetTargetForActiveCall(sender));
                 * Console.WriteLine("RECEIVERS PERSPECTIVE:");
                 * Console.WriteLine("Sender Name:            " + HoloComService.GetCallSender(receiver).Name);
                 * Console.WriteLine("Receiver Name:          " + HoloComService.GetCallReceiver(receiver).Name);
                 * Console.WriteLine("Sender Call Attempts:   " + HoloComService.GetCallAttempt(GetCallSender(receiver)));
                 * Console.WriteLine("Receiver Connected With:" + HoloComService.GetTargetForActiveCall(receiver));
                 */
            }
            else // END CALL
            {
                foreach (var effect in sender.Effects)
                {
                    if (_.GetIsEffectValid(effect) == true)
                    {
                        var effectType = GetEffectType(effect);
                        if (effectType == EffectTypeScript.CutsceneImmobilize)
                        {
                            RemoveEffect(sender.Object, effect);
                        }
                    }
                }

                foreach (var effect in receiver.Effects)
                {
                    if (_.GetIsEffectValid(effect) == true)
                    {
                        var effectType = GetEffectType(effect);
                        if (effectType == EffectTypeScript.CutsceneImmobilize)
                        {
                            RemoveEffect(receiver.Object, effect);
                        }
                    }
                }

                sender.AssignCommand(() =>
                {
                    PlaySound("hologram_off");
                });
                receiver.AssignCommand(() =>
                {
                    PlaySound("hologram_off");
                });

                DestroyObject(GetHoloGram(sender));
                DestroyObject(GetHoloGram(receiver));

                sender.DeleteLocalInt("HOLOCOM_CALL_CONNECTED");
                receiver.DeleteLocalInt("HOLOCOM_CALL_CONNECTED");

                sender.DeleteLocalInt("HOLOCOM_CALL_SENDER");
                receiver.DeleteLocalInt("HOLOCOM_CALL_SENDER");

                sender.DeleteLocalInt("HOLOCOM_CALL_RECEIVER");
                receiver.DeleteLocalInt("HOLOCOM_CALL_RECEIVER");

                sender.DeleteLocalObject("HOLOCOM_CALL_CONNECTED_WITH");
                receiver.DeleteLocalObject("HOLOCOM_CALL_CONNECTED_WITH");

                sender.DeleteLocalObject("HOLOCOM_HOLOGRAM");
                receiver.DeleteLocalObject("HOLOCOM_HOLOGRAM");

                sender.DeleteLocalInt("HOLOCOM_CALL_ATTEMPT");
                receiver.DeleteLocalInt("HOLOCOM_CALL_ATTEMPT");

                sender.DeleteLocalObject("HOLOCOM_CALL_RECEIVER_OBJECT");
                receiver.DeleteLocalObject("HOLOCOM_CALL_RECEIVER_OBJECT");

                sender.DeleteLocalObject("HOLOCOM_CALL_SENDER_OBJECT");
                receiver.DeleteLocalObject("HOLOCOM_CALL_SENDER_OBJECT");
            }
        }
Beispiel #25
0
        private static void OnHitCastSpell()
        {
            NWPlayer oPC = _.OBJECT_SELF;

            if (!oPC.IsValid)
            {
                return;
            }

            NWObject oTarget = _.GetSpellTargetObject();
            NWItem   oItem   = _.GetSpellCastItem();

            // If this method was triggered by our own armor (from getting hit), return.
            if (oItem.BaseItemType == BaseItem.Armor)
            {
                return;
            }

            // Flag this attack as physical so that the damage scripts treat it properly.
            LoggingService.Trace(TraceComponent.LastAttack, "Setting attack type from " + oPC.GlobalID + " against " + _.GetName(oTarget) + " to physical (" + ATTACK_PHYSICAL.ToString() + ")");
            oTarget.SetLocalInt(LAST_ATTACK + oPC.GlobalID, ATTACK_PHYSICAL);

            HandleGrenadeProficiency(oPC, oTarget);
            HandlePlasmaCellPerk(oPC, oTarget);
            int activeWeaponSkillID = oPC.GetLocalInt("ACTIVE_WEAPON_SKILL");

            if (activeWeaponSkillID <= 0)
            {
                return;
            }
            int activeWeaponSkillFeatID = oPC.GetLocalInt("ACTIVE_WEAPON_SKILL_FEAT_ID");

            if (activeWeaponSkillFeatID < 0)
            {
                activeWeaponSkillFeatID = -1;
            }

            PCPerk entity   = DataService.PCPerk.GetByPlayerAndPerkID(oPC.GlobalID, activeWeaponSkillID);
            var    perk     = DataService.Perk.GetByID(entity.PerkID);
            var    perkFeat = DataService.PerkFeat.GetByFeatID(activeWeaponSkillFeatID);
            var    handler  = PerkService.GetPerkHandler(activeWeaponSkillID);

            string canCast = handler.CanCastSpell(oPC, oTarget, perkFeat.PerkLevelUnlocked);

            if (string.IsNullOrWhiteSpace(canCast))
            {
                handler.OnImpact(oPC, oTarget, entity.PerkLevel, perkFeat.PerkLevelUnlocked);

                if (oTarget.IsNPC)
                {
                    ApplyEnmity(oPC, oTarget.Object, perk);
                }
            }
            else
            {
                oPC.SendMessage(canCast);
            }

            oPC.DeleteLocalString("ACTIVE_WEAPON_SKILL_UUID");
            oPC.DeleteLocalInt("ACTIVE_WEAPON_SKILL");
            oPC.DeleteLocalInt("ACTIVE_WEAPON_SKILL_FEAT_ID");
        }
Beispiel #26
0
        private void CastSpell(NWPlayer pc,
                               NWObject target,
                               Data.Entities.Perk entity,
                               IPerk perk,
                               CooldownCategory cooldown)
        {
            string spellUUID       = Guid.NewGuid().ToString();
            int    itemBonus       = pc.CastingSpeed;
            float  baseCastingTime = perk.CastingTime(pc, (float)entity.BaseCastingTime);
            float  castingTime     = baseCastingTime;

            // Casting Bonus % - Shorten casting time.
            if (itemBonus < 0)
            {
                float castingPercentageBonus = Math.Abs(itemBonus) * 0.01f;
                castingTime = castingTime - (castingTime * castingPercentageBonus);
            }
            // Casting Penalty % - Increase casting time.
            else if (itemBonus > 0)
            {
                float castingPercentageBonus = Math.Abs(itemBonus) * 0.01f;
                castingTime = castingTime + (castingTime * castingPercentageBonus);
            }

            if (castingTime < 0.5f)
            {
                castingTime = 0.5f;
            }

            // Heavy armor increases casting time by 2x the base casting time
            if (pc.Chest.CustomItemType == CustomItemType.HeavyArmor)
            {
                castingTime = baseCastingTime * 2;
            }

            if (_.GetActionMode(pc.Object, ACTION_MODE_STEALTH) == 1)
            {
                _.SetActionMode(pc.Object, ACTION_MODE_STEALTH, 0);
            }

            _.ClearAllActions();
            _biowarePosition.TurnToFaceObject(target, pc);
            _.ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
                                  _.EffectVisualEffect(VFX_DUR_ELEMENTAL_SHIELD),
                                  pc.Object,
                                  castingTime + 0.2f);

            float animationTime = castingTime;

            pc.AssignCommand(() => _.ActionPlayAnimation(ANIMATION_LOOPING_CONJURE1, 1.0f, animationTime - 0.1f));

            pc.IsBusy = true;
            CheckForSpellInterruption(pc, spellUUID, pc.Position);
            pc.SetLocalInt(spellUUID, SPELL_STATUS_STARTED);

            _nwnxPlayer.StartGuiTimingBar(pc, (int)castingTime, "");

            pc.DelayCommand(() =>
            {
                if (pc.GetLocalInt(spellUUID) == SPELL_STATUS_INTERRUPTED || // Moved during casting
                    pc.CurrentHP < 0 || pc.IsDead)                           // Or is dead/dying
                {
                    pc.DeleteLocalInt(spellUUID);
                    pc.SendMessage("Your spell has been interrupted.");
                    return;
                }

                pc.DeleteLocalInt(spellUUID);

                if ((PerkExecutionType)entity.ExecutionTypeID == PerkExecutionType.Spell ||
                    (PerkExecutionType)entity.ExecutionTypeID == PerkExecutionType.CombatAbility)
                {
                    perk.OnImpact(pc, target);
                }
                else
                {
                    HandleQueueWeaponSkill(pc, entity, perk);
                }


                // Adjust mana only if spell cost > 0
                PlayerCharacter pcEntity = _db.PlayerCharacters.Single(x => x.PlayerID == pc.GlobalID);
                if (perk.ManaCost(pc, entity.BaseManaCost) > 0)
                {
                    pcEntity.CurrentMana = pcEntity.CurrentMana - perk.ManaCost(pc, entity.BaseManaCost);
                    _db.SaveChanges();
                    pc.SendMessage(_color.Custom("Mana: " + pcEntity.CurrentMana + " / " + pcEntity.MaxMana, 32, 223, 219));
                }

                if (_random.Random(100) + 1 <= 3)
                {
                    _food.DecreaseHungerLevel(pc, 1);
                }
                // Mark cooldown on category
                ApplyCooldown(pc, cooldown, perk);
                pc.IsBusy = false;
            }, castingTime + 0.5f);
        }
        public bool Run(params object[] args)
        {
            using (new Profiler(nameof(FinishAbilityUse)))
            {
                NWPlayer pc          = (NWPlayer)args[0];
                string   spellUUID   = Convert.ToString(args[1]);
                int      perkID      = (int)args[2];
                NWObject target      = (NWObject)args[3];
                int      pcPerkLevel = (int)args[4];
                int      featID      = (int)args[5];

                Data.Entity.Perk  entity        = DataService.Single <Data.Entity.Perk>(x => x.ID == perkID);
                PerkExecutionType executionType = (PerkExecutionType)entity.ExecutionTypeID;
                IPerkHandler      perk          = PerkService.GetPerkHandler(perkID);

                int?cooldownID            = perk.CooldownCategoryID(pc, entity.CooldownCategoryID, featID);
                CooldownCategory cooldown = cooldownID == null ? null : DataService.SingleOrDefault <CooldownCategory>(x => x.ID == cooldownID);

                if (pc.GetLocalInt(spellUUID) == (int)SpellStatusType.Interrupted || // Moved during casting
                    pc.CurrentHP < 0 || pc.IsDead)                                   // Or is dead/dying
                {
                    pc.DeleteLocalInt(spellUUID);
                    return(false);
                }

                pc.DeleteLocalInt(spellUUID);

                if (executionType == PerkExecutionType.ForceAbility ||
                    executionType == PerkExecutionType.CombatAbility ||
                    executionType == PerkExecutionType.Stance)
                {
                    perk.OnImpact(pc, target, pcPerkLevel, featID);

                    if (entity.CastAnimationID != null && entity.CastAnimationID > 0)
                    {
                        pc.AssignCommand(() => { _.ActionPlayAnimation((int)entity.CastAnimationID, 1f, 1f); });
                    }

                    if (target.IsNPC)
                    {
                        AbilityService.ApplyEnmity(pc, (target.Object), entity);
                    }
                }
                else if (executionType == PerkExecutionType.QueuedWeaponSkill)
                {
                    AbilityService.HandleQueueWeaponSkill(pc, entity, perk, featID);
                }


                // Adjust FP only if spell cost > 0
                Data.Entity.Player pcEntity = DataService.Single <Data.Entity.Player>(x => x.ID == pc.GlobalID);
                int fpCost = perk.FPCost(pc, entity.BaseFPCost, featID);

                if (fpCost > 0)
                {
                    pcEntity.CurrentFP = pcEntity.CurrentFP - fpCost;
                    DataService.SubmitDataChange(pcEntity, DatabaseActionType.Update);
                    pc.SendMessage(ColorTokenService.Custom("FP: " + pcEntity.CurrentFP + " / " + pcEntity.MaxFP, 32, 223, 219));
                }

                bool hasChainspell = CustomEffectService.DoesPCHaveCustomEffect(pc, CustomEffectType.Chainspell) &&
                                     executionType == PerkExecutionType.ForceAbility;

                if (!hasChainspell && cooldown != null)
                {
                    // Mark cooldown on category
                    AbilityService.ApplyCooldown(pc, cooldown, perk, featID);
                }

                pc.IsBusy = false;
                pc.SetLocalInt(spellUUID, (int)SpellStatusType.Completed);

                return(true);
            }
        }
Beispiel #28
0
        public static bool OnAppearsWhen(int nodeType, int nodeID)
        {
            NWPlayer player    = (_.GetPCSpeaker());
            bool     hasDialog = HasPlayerDialog(player.GlobalID);

            if (!hasDialog)
            {
                return(false);
            }
            PlayerDialog dialog = LoadPlayerDialog(player.GlobalID);

            using (new Profiler(nameof(DialogService) + "." + nameof(OnAppearsWhen) + "." + dialog.ActiveDialogName))
            {
                DialogPage page  = dialog.CurrentPage;
                var        convo = GetConversation(dialog.ActiveDialogName);
                int        currentSelectionNumber = nodeID + 1;
                bool       displayNode            = false;
                string     newNodeText            = string.Empty;
                int        dialogOffset           = (NumberOfResponsesPerPage + 1) * (dialog.DialogNumber - 1);

                if (currentSelectionNumber == NumberOfResponsesPerPage + 1) // Next page
                {
                    int displayCount = page.NumberOfResponses - (NumberOfResponsesPerPage * dialog.PageOffset);

                    if (displayCount > NumberOfResponsesPerPage)
                    {
                        displayNode = true;
                    }
                }
                else if (currentSelectionNumber == NumberOfResponsesPerPage + 2) // Previous Page
                {
                    if (dialog.PageOffset > 0)
                    {
                        displayNode = true;
                    }
                }
                else if (currentSelectionNumber == NumberOfResponsesPerPage + 3) // Back
                {
                    if (dialog.NavigationStack.Count > 0 && dialog.EnableBackButton)
                    {
                        displayNode = true;
                    }
                }
                else if (nodeType == 2)
                {
                    int responseID = (dialog.PageOffset * NumberOfResponsesPerPage) + nodeID;
                    if (responseID + 1 <= page.NumberOfResponses)
                    {
                        DialogResponse response = page.Responses[responseID];

                        if (response != null)
                        {
                            newNodeText = response.Text;
                            displayNode = response.IsActive;
                        }
                    }
                }
                else if (nodeType == 1)
                {
                    if (player.GetLocalInt("DIALOG_SYSTEM_INITIALIZE_RAN") != 1)
                    {
                        convo.Initialize();
                        player.SetLocalInt("DIALOG_SYSTEM_INITIALIZE_RAN", 1);
                    }

                    if (dialog.IsEnding)
                    {
                        convo.EndDialog();
                        RemovePlayerDialog(player.GlobalID);
                        player.DeleteLocalInt("DIALOG_SYSTEM_INITIALIZE_RAN");
                        return(false);
                    }

                    page        = dialog.CurrentPage;
                    newNodeText = page.Header;

                    _.SetCustomToken(90000 + dialogOffset, newNodeText);
                    return(true);
                }

                _.SetCustomToken(90001 + nodeID + dialogOffset, newNodeText);
                return(displayNode);
            }
        }
Beispiel #29
0
        public bool Run(params object[] args)
        {
            NWPlayer pc          = (NWPlayer)args[0];
            string   spellUUID   = Convert.ToString(args[1]);
            int      perkID      = (int)args[2];
            NWObject target      = (NWObject)args[3];
            int      pcPerkLevel = (int)args[4];

            Data.Entity.Perk  entity        = _data.Single <Data.Entity.Perk>(x => x.ID == perkID);
            CooldownCategory  cooldown      = _data.SingleOrDefault <CooldownCategory>(x => x.ID == entity.CooldownCategoryID);
            PerkExecutionType executionType = (PerkExecutionType)entity.ExecutionTypeID;

            return(App.ResolveByInterface <IPerk, bool>("Perk." + entity.ScriptName, perk =>
            {
                if (pc.GetLocalInt(spellUUID) == (int)SpellStatusType.Interrupted || // Moved during casting
                    pc.CurrentHP < 0 || pc.IsDead)                                   // Or is dead/dying
                {
                    pc.DeleteLocalInt(spellUUID);
                    return false;
                }

                pc.DeleteLocalInt(spellUUID);

                if (executionType == PerkExecutionType.ForceAbility ||
                    executionType == PerkExecutionType.CombatAbility ||
                    executionType == PerkExecutionType.Stance)
                {
                    perk.OnImpact(pc, target, pcPerkLevel);

                    if (entity.CastAnimationID != null && entity.CastAnimationID > 0)
                    {
                        pc.AssignCommand(() =>
                        {
                            _.ActionPlayAnimation((int)entity.CastAnimationID, 1f, 1f);
                        });
                    }

                    if (target.IsNPC)
                    {
                        _ability.ApplyEnmity(pc, (target.Object), entity);
                    }
                }
                else if (executionType == PerkExecutionType.QueuedWeaponSkill)
                {
                    _ability.HandleQueueWeaponSkill(pc, entity, perk);
                }


                // Adjust FP only if spell cost > 0
                Data.Entity.Player pcEntity = _data.Single <Data.Entity.Player>(x => x.ID == pc.GlobalID);
                if (perk.FPCost(pc, entity.BaseFPCost) > 0)
                {
                    pcEntity.CurrentFP = pcEntity.CurrentFP - perk.FPCost(pc, entity.BaseFPCost);
                    _data.SubmitDataChange(pcEntity, DatabaseActionType.Update);
                    pc.SendMessage(_color.Custom("FP: " + pcEntity.CurrentFP + " / " + pcEntity.MaxFP, 32, 223, 219));
                }

                bool hasChainspell = _customEffect.DoesPCHaveCustomEffect(pc, CustomEffectType.Chainspell) &&
                                     executionType == PerkExecutionType.ForceAbility;

                if (!hasChainspell)
                {
                    // Mark cooldown on category
                    _ability.ApplyCooldown(pc, cooldown, perk);
                }
                pc.IsBusy = false;
                pc.SetLocalInt(spellUUID, (int)SpellStatusType.Completed);

                return true;
            }));
        }
Beispiel #30
0
        public bool Run(params object[] args)
        {
            NWPlaceable resource = NWPlaceable.Wrap(Object.OBJECT_SELF);
            NWPlayer    oPC      = NWPlayer.Wrap(_.GetLastDamager(resource.Object));

            if (oPC.GetLocalInt("NOT_USING_CORRECT_WEAPON") == 1)
            {
                oPC.DeleteLocalInt("NOT_USING_CORRECT_WEAPON");
                return(true);
            }

            PlayerCharacter pcEntity = _db.PlayerCharacters.Single(x => x.PlayerID == oPC.GlobalID);

            NWItem    oWeapon            = NWItem.Wrap(_.GetLastWeaponUsed(oPC.Object));
            Location  location           = oPC.Location;
            string    resourceItemResref = resource.GetLocalString("RESOURCE_RESREF");
            int       activityID         = resource.GetLocalInt("RESOURCE_ACTIVITY");
            string    resourceName       = resource.GetLocalString("RESOURCE_NAME");
            int       resourceCount      = resource.GetLocalInt("RESOURCE_COUNT");
            int       difficultyRating   = resource.GetLocalInt("RESOURCE_DIFFICULTY_RATING");
            int       weaponChanceBonus;
            SkillType skillType;
            int       perkChanceBonus;
            int       secondResourceChance;
            int       durabilityChanceReduction = 0;
            int       hasteChance;
            int       lucky = _perk.GetPCPerkLevel(oPC, PerkType.Lucky) + oPC.EffectiveLuckBonus;
            bool      hasBaggerPerk;

            if (activityID == 1) // 1 = Logging
            {
                weaponChanceBonus = oWeapon.LoggingBonus;
                if (weaponChanceBonus > 0)
                {
                    weaponChanceBonus        += _perk.GetPCPerkLevel(oPC, PerkType.LoggingAxeExpert) * 5;
                    durabilityChanceReduction = _perk.GetPCPerkLevel(oPC, PerkType.LoggingAxeExpert) * 10 + lucky;
                }

                skillType            = SkillType.Logging;
                perkChanceBonus      = _perk.GetPCPerkLevel(oPC, PerkType.Lumberjack) * 5 + lucky;
                secondResourceChance = _perk.GetPCPerkLevel(oPC, PerkType.PrecisionLogging) * 10;
                hasteChance          = _perk.GetPCPerkLevel(oPC, PerkType.SpeedyLogger) * 10 + lucky;

                if (pcEntity.BackgroundID == (int)BackgroundType.Lumberjack)
                {
                    hasteChance += 10;
                }

                hasBaggerPerk = _perk.GetPCPerkLevel(oPC, PerkType.WoodBagger) > 0;
            }
            else if (activityID == 2) // Mining
            {
                weaponChanceBonus = oWeapon.MiningBonus;
                if (weaponChanceBonus > 0)
                {
                    weaponChanceBonus        += _perk.GetPCPerkLevel(oPC, PerkType.PickaxeExpert) * 5;
                    durabilityChanceReduction = _perk.GetPCPerkLevel(oPC, PerkType.PickaxeExpert) * 10 + lucky;
                }
                skillType            = SkillType.Mining;
                perkChanceBonus      = _perk.GetPCPerkLevel(oPC, PerkType.Miner) * 5 + lucky;
                secondResourceChance = _perk.GetPCPerkLevel(oPC, PerkType.PrecisionMining) * 10;
                hasteChance          = _perk.GetPCPerkLevel(oPC, PerkType.SpeedyMiner) * 10 + lucky;

                if (pcEntity.BackgroundID == (int)BackgroundType.Miner)
                {
                    hasteChance += 10;
                }

                hasBaggerPerk = _perk.GetPCPerkLevel(oPC, PerkType.OreBagger) > 0;
            }
            else
            {
                return(false);
            }
            PCSkill skill = _skill.GetPCSkillByID(oPC.GlobalID, (int)skillType);
            int     durabilityLossChance = 100 - durabilityChanceReduction;

            if (_random.Random(100) <= durabilityLossChance)
            {
                _durability.RunItemDecay(oPC, oWeapon);
            }

            int baseChance = 10;
            int chance     = baseChance + weaponChanceBonus;

            chance += CalculateSuccessChanceDeltaModifier(difficultyRating, skill.Rank);
            chance += perkChanceBonus;

            bool givePityItem = false;

            if (chance > 0)
            {
                if (_random.Random(100) + 1 <= hasteChance)
                {
                    _.ApplyEffectToObject(DURATION_TYPE_TEMPORARY, _.EffectHaste(), oPC.Object, 8.0f);
                }

                // Give an item if the player hasn't gotten anything after 6-8 attempts.
                int      attemptFailureCount = oPC.GetLocalInt("RESOURCE_ATTEMPT_FAILURE_COUNT") + 1;
                NWObject failureResource     = NWObject.Wrap(oPC.GetLocalObject("RESOURCE_ATTEMPT_FAILURE_OBJECT"));

                if (!failureResource.IsValid || !Equals(failureResource, resource))
                {
                    failureResource     = resource;
                    attemptFailureCount = 1;
                }

                int pityItemChance = 0;
                if (attemptFailureCount == 6)
                {
                    pityItemChance = 60;
                }
                else if (attemptFailureCount == 7)
                {
                    pityItemChance = 80;
                }
                else if (attemptFailureCount >= 8)
                {
                    pityItemChance = 100;
                }

                if (_random.Random(100) + 1 <= pityItemChance)
                {
                    givePityItem        = true;
                    attemptFailureCount = 0;
                }

                oPC.SetLocalInt("RESOURCE_ATTEMPT_FAILURE_COUNT", attemptFailureCount);
                oPC.SetLocalObject("RESOURCE_ATTEMPT_FAILURE_OBJECT", failureResource.Object);
            }

            if (chance <= 0)
            {
                oPC.FloatingText("You do not have enough skill to harvest this resource...");
            }
            else if (_random.Random(100) <= chance || givePityItem)
            {
                if (hasBaggerPerk)
                {
                    _.CreateItemOnObject(resourceItemResref, oPC.Object);
                }
                else
                {
                    _.CreateObject(OBJECT_TYPE_ITEM, resourceItemResref, location);
                }


                oPC.FloatingText("You break off some " + resourceName + ".");
                resource.SetLocalInt("RESOURCE_COUNT", --resourceCount);
                _.ApplyEffectToObject(DURATION_TYPE_INSTANT, _.EffectHeal(10000), resource.Object);

                if (_random.Random(100) + 1 <= secondResourceChance)
                {
                    oPC.FloatingText("You break off a second piece.");

                    if (hasBaggerPerk)
                    {
                        _.CreateItemOnObject(resourceItemResref, oPC.Object);
                    }
                    else
                    {
                        _.CreateObject(OBJECT_TYPE_ITEM, resourceItemResref, location);
                    }
                }

                float deltaModifier = CalculateXPDeltaModifier(difficultyRating, skill.Rank);
                float baseXP        = (100 + _random.Random(20)) * deltaModifier;
                int   xp            = (int)_skill.CalculateRegisteredSkillLevelAdjustedXP(baseXP, oWeapon.RecommendedLevel, skill.Rank);
                _skill.GiveSkillXP(oPC, skillType, xp);

                oPC.DeleteLocalInt("RESOURCE_ATTEMPT_FAILURE_COUNT");
                oPC.DeleteLocalObject("RESOURCE_ATTEMPT_FAILURE_OBJECT");
            }

            if (resourceCount <= 0)
            {
                SpawnSeed(resource, oPC);

                NWObject prop = NWObject.Wrap(resource.GetLocalObject("RESOURCE_PROP_OBJ"));
                if (prop.IsValid)
                {
                    prop.Destroy();
                }
                resource.Destroy();
            }
            return(true);
        }