public static void UseOpenRestMenuFeat()
        {
            var player = OBJECT_SELF;
            var feat   = (Feat)Convert.ToInt32(Events.GetEventData("FEAT_ID"));

            if (feat != Feat.ChatCommandTargeter)
            {
                return;
            }

            var target  = Object.StringToObject(Events.GetEventData("TARGET_OBJECT_ID"));
            var area    = Object.StringToObject(Events.GetEventData("AREA_OBJECT_ID"));
            var targetX = (float)Convert.ToDouble(Events.GetEventData("TARGET_POSITION_X"));
            var targetY = (float)Convert.ToDouble(Events.GetEventData("TARGET_POSITION_Y"));
            var targetZ = (float)Convert.ToDouble(Events.GetEventData("TARGET_POSITION_Z"));

            var targetLocation = Location(area, new Vector(targetX, targetY, targetZ), 0.0f);
            var command        = GetLocalString(player, "CHAT_COMMAND");
            var args           = GetLocalString(player, "CHAT_COMMAND_ARGS");

            if (string.IsNullOrWhiteSpace(command))
            {
                SendMessageToPC(player, "Please enter a chat command and then use this feat. Type /help to learn more about the available chat commands.");
                return;
            }

            ProcessChatCommand(command, player, target, targetLocation, args);

            DeleteLocalString(player, "CHAT_COMMAND");
            DeleteLocalString(player, "CHAT_COMMAND_ARGS");
        }
Exemple #2
0
        /// <summary>
        /// When an item is equipped, if any of a player's perks has an Equipped Trigger, run those actions now.
        /// </summary>
        private static void ApplyEquipTriggers()
        {
            var player = OBJECT_SELF;

            if (!GetIsPC(player) || GetIsDM(player))
            {
                return;
            }

            var playerId = GetObjectUUID(player);
            var dbPlayer = DB.Get <Player>(playerId);
            var item     = Object.StringToObject(Events.GetEventData("ITEM"));
            var slot     = (InventorySlot)Convert.ToInt32(Events.GetEventData("SLOT"));

            foreach (var(perkType, actionList) in Perk.GetAllEquipTriggers())
            {
                var playerPerkLevel = Perk.GetEffectivePerkLevel(player, perkType);
                if (playerPerkLevel <= 0)
                {
                    continue;
                }

                foreach (var action in actionList)
                {
                    action(player, item, slot, perkType, playerPerkLevel);
                }
            }
        }
Exemple #3
0
        private static uint CreateMerchantObject(string sellerPlayerId, PlayerStore dbPlayerStore)
        {
            const string StoreResref = "player_store";
            var          merchant    = CreateObject(ObjectType.Store, StoreResref, GetLocation(OBJECT_SELF));

            SetLocalString(merchant, "SELLER_PLAYER_ID", sellerPlayerId);

            foreach (var item in dbPlayerStore.ItemsForSale)
            {
                if (item.Value.Price <= 0)
                {
                    continue;
                }

                var deserialized = Object.Deserialize(item.Value.Data);
                Object.AcquireItem(merchant, deserialized);

                var originalBaseGPValue       = Core.NWNX.Item.GetBaseGoldPieceValue(deserialized);
                var originalAdditionalGPValue = Core.NWNX.Item.GetAddGoldPieceValue(deserialized);

                SetLocalInt(deserialized, "ORIGINAL_BASE_GP_VALUE", originalBaseGPValue);
                SetLocalInt(deserialized, "ORIGINAL_ADDITIONAL_GP_VALUE", originalAdditionalGPValue);

                Core.NWNX.Item.SetBaseGoldPieceValue(deserialized, item.Value.Price);
                Core.NWNX.Item.SetAddGoldPieceValue(deserialized, 0);
            }

            return(merchant);
        }
Exemple #4
0
        public static void JoinParty()
        {
            var player    = OBJECT_SELF;
            var requester = Object.StringToObject(Events.GetEventData("INVITED_BY"));

            // This is a brand new party.
            // Add both the requester and the player to the cache.
            // Mark the requester as the party leader.
            if (!_playerToParty.ContainsKey(requester))
            {
                var partyId = Guid.NewGuid();
                _parties[partyId] = new List <uint>
                {
                    requester,
                    player
                };
                _partyLeaders[partyId]    = requester;
                _playerToParty[player]    = partyId;
                _playerToParty[requester] = partyId;
            }
            // This is an existing party.
            // Add the player to the party cache.
            else
            {
                var partyId = _playerToParty[requester];
                _parties[partyId].Add(player);
                _playerToParty[player] = partyId;
            }
        }
Exemple #5
0
        public static void TransferLeadership()
        {
            var player  = Object.StringToObject(Events.GetEventData("NEW_LEADER"));
            var partyId = _playerToParty[player];

            _partyLeaders[partyId] = player;
        }
Exemple #6
0
        public static void UseFeat()
        {
            var activator = OBJECT_SELF;
            var target    = Object.StringToObject(Events.GetEventData("TARGET_OBJECT_ID"));
            var feat      = (Feat)Convert.ToInt32(Events.GetEventData("FEAT_ID"));

            if (!Ability.IsFeatRegistered(feat))
            {
                return;
            }
            var ability = Ability.GetAbilityDetail(feat);

            // Creature cannot use the feat.
            var effectivePerkLevel = Perk.GetEffectivePerkLevel(activator, ability.EffectiveLevelPerkType);

            if (!CanUseAbility(activator, target, ability, effectivePerkLevel))
            {
                return;
            }

            Messaging.SendMessageNearbyToPlayers(activator, $"{GetName(activator)} readies {ability.Name}.");

            // Weapon abilties are queued for the next time the activator's attack lands on an enemy.
            if (ability.ActivationType == AbilityActivationType.Weapon)
            {
                QueueWeaponAbility(activator, ability, feat, effectivePerkLevel);
            }
            // All other abilities are funneled through the same process.
            else
            {
                ActivateAbility(activator, target, ability, effectivePerkLevel);
            }
        }
        public static void SetBarteringFlag()
        {
            var player1 = OBJECT_SELF;
            var player2 = Object.StringToObject(Events.GetEventData("BARTER_TARGET"));

            SetLocalBool(player1, "IS_BARTERING", true);
            SetLocalBool(player2, "IS_BARTERING", true);
        }
        public static void RemoveBarteringFlag()
        {
            var player1 = OBJECT_SELF;
            var player2 = Object.StringToObject(Events.GetEventData("BARTER_TARGET"));

            DeleteLocalBool(player1, "IS_BARTERING");
            DeleteLocalBool(player2, "IS_BARTERING");
        }
Exemple #9
0
        public static void ValidateItemUse()
        {
            var creature = OBJECT_SELF;
            var item     = Object.StringToObject(Events.GetEventData("ITEM_OBJECT_ID"));

            Events.SetEventResult(string.IsNullOrWhiteSpace(CanItemBeUsed(creature, item)) ? "1" : "0");
            Events.SkipEvent();
        }
Exemple #10
0
        public static void ValidateDualWield()
        {
            var creature = OBJECT_SELF;
            var item     = Object.StringToObject(Events.GetEventData("ITEM"));
            var slot     = (InventorySlot)Convert.ToInt32(Events.GetEventData("SLOT"));

            // Not equipping to the left hand, or there's nothing equipped in the right hand.
            if (slot != InventorySlot.LeftHand)
            {
                return;
            }
            if (!GetIsObjectValid(GetItemInSlot(InventorySlot.RightHand, creature)))
            {
                return;
            }

            var baseItem         = GetBaseItemType(item);
            var dualWieldWeapons = new[]
            {
                BaseItem.ShortSword,
                BaseItem.Longsword,
                BaseItem.BattleAxe,
                BaseItem.BastardSword,
                BaseItem.LightFlail,
                BaseItem.LightMace,
                BaseItem.Dagger,
                BaseItem.Club,
                BaseItem.HandAxe,
                BaseItem.Kama,
                BaseItem.Katana,
                BaseItem.Kukri,
                BaseItem.Rapier,
                BaseItem.Scimitar,
                BaseItem.Sickle
            };

            if (!dualWieldWeapons.Contains(baseItem))
            {
                return;
            }

            var dualWieldLevel = Perk.GetEffectivePerkLevel(creature, PerkType.DualWield);

            if (dualWieldLevel <= 0)
            {
                SendMessageToPC(creature, ColorToken.Red("Equipping two weapons requires the Dual Wield perk."));
                Events.SkipEvent();
            }
        }
Exemple #11
0
        public static void ValidateItemEquip()
        {
            var creature = OBJECT_SELF;
            var item     = Object.StringToObject(Events.GetEventData("ITEM"));

            var error = CanItemBeUsed(creature, item);

            if (string.IsNullOrWhiteSpace(error))
            {
                ApplyEquipTriggers();
                return;
            }

            SendMessageToPC(creature, ColorToken.Red(error));
            Events.SkipEvent();
        }
        public static void OnUseItem()
        {
            var creature = OBJECT_SELF;
            var item     = Object.StringToObject(Events.GetEventData("ITEM_OBJECT_ID"));
            var script   = GetLocalString(item, "SCRIPT");

            // No script associated. Let it run the normal execution process.
            if (string.IsNullOrWhiteSpace(script))
            {
                return;
            }

            Events.SkipEvent();
            Events.SetEventResult("0"); // Prevents the "You cannot use that item" error message from being sent.
            ExecuteScript(script, creature);
        }
Exemple #13
0
        public static void AddItemToBankStorage()
        {
            var container = OBJECT_SELF;

            if (GetResRef(container) != "bank_chest" || GetLocalBool(container, "IS_DESERIALIZING"))
            {
                return;
            }

            var item      = Object.StringToObject(Events.GetEventData("ITEM"));
            var player    = GetItemPossessor(item);
            var playerId  = GetObjectUUID(player);
            var storageId = GetStorageID();
            var key       = $"{storageId}:{playerId}";

            AddItem(key, "Bank");
        }
        private void MovePageInit(DialogPage page)
        {
            var player = GetPC();
            var model  = GetDataModel <Model>();

            void Move(float x, float y, float z)
            {
                var position = GetPosition(model.Placeable);

                position.X += x;
                position.Y += y;
                position.Z += z;

                if (position.Z > 10f)
                {
                    position.Z = 10f;
                }
                else if (position.Z < -10f)
                {
                    position.Z = -10f;
                }

                Object.SetPosition(model.Placeable, position);

                var furnitureId = GetLocalString(model.Placeable, "HOUSING_FURNITURE_ID");
                var dbHouse     = DB.Get <PlayerHouse>(model.OwnerUUID);

                dbHouse.Furnitures[furnitureId].X = position.X;
                dbHouse.Furnitures[furnitureId].Y = position.Y;
                dbHouse.Furnitures[furnitureId].Z = position.Z;

                DB.Set(model.OwnerUUID, dbHouse);
            }

            page.Header = ColorToken.Green("Move Furniture") + "\n\n";

            page.AddResponse("Move North", () => Move(0f, 0.2f, 0f));
            page.AddResponse("Move South", () => Move(0f, -0.2f, 0f));
            page.AddResponse("Move East", () => Move(0.2f, 0f, 0f));
            page.AddResponse("Move West", () => Move(-0.2f, 0f, 0f));
            page.AddResponse("Move Up", () => Move(0f, 0f, 0.1f));
            page.AddResponse("Move Down", () => Move(0f, 0f, -0.1f));
        }
Exemple #15
0
        /// <summary>
        /// Creates a new spawn object into its spawn area.
        /// Hand-placed objects are deserialized and added to the area.
        /// Spawn tables run their own logic to determine which object to spawn.
        /// </summary>
        /// <param name="spawnId">The ID of the spawn</param>
        /// <param name="detail">The details of the spawn</param>
        private static uint SpawnObject(Guid spawnId, SpawnDetail detail)
        {
            // Hand-placed spawns are stored as a serialized string.
            // Deserialize and add it to the area.
            if (!string.IsNullOrWhiteSpace(detail.SerializedObject))
            {
                var deserialized = Object.Deserialize(detail.SerializedObject);
                var position     = new Vector(detail.X, detail.Y, detail.Z);
                Object.AddToArea(deserialized, detail.Area, position);

                AssignCommand(deserialized, () => SetFacing(detail.Facing));
                SetLocalString(deserialized, "SPAWN_ID", spawnId.ToString());

                return(deserialized);
            }
            // Spawn tables have their own logic which must be run to determine the spawn to use.
            // Create the object at the stored location.
            else if (detail.SpawnTableId > 0)
            {
                var spawnTable = _spawnTables[detail.SpawnTableId];
                var(objectType, resref) = spawnTable.GetNextSpawnResref();

                // It's possible that the rules of the spawn table don't have a spawn ready to be created.
                // In this case, exit early.
                if (string.IsNullOrWhiteSpace(resref))
                {
                    return(OBJECT_INVALID);
                }

                var position = new Vector(detail.X, detail.Y, detail.Z);
                var location = Location(detail.Area, position, detail.Facing);

                var spawn = CreateObject(objectType, resref, location);
                SetLocalString(spawn, "SPAWN_ID", spawnId.ToString());

                return(spawn);
            }

            return(OBJECT_INVALID);
        }
Exemple #16
0
        public static void MarketTerminalDisturbed()
        {
            if (GetInventoryDisturbType() != DisturbType.Added)
            {
                return;
            }

            var player        = GetLastDisturbed();
            var playerId      = GetObjectUUID(player);
            var dbPlayer      = DB.Get <Player>(playerId);
            var dbPlayerStore = DB.Get <PlayerStore>(playerId);
            var item          = GetInventoryDisturbItem();
            var itemId        = GetObjectUUID(item);
            var serialized    = Object.Serialize(item);
            var listingLimit  = 5 + dbPlayer.SeedProgress.Rank * 5;

            if (dbPlayerStore.ItemsForSale.Count >= listingLimit || // Listing limit reached.
                GetBaseItemType(item) == BaseItem.Gold ||           // Gold can't be listed.
                string.IsNullOrWhiteSpace(GetResRef(item)) ||       // Items without resrefs can't be listed.
                GetHasInventory(item))                              // Bags and other containers can't be listed.
            {
                Item.ReturnItem(player, item);
                SendMessageToPC(player, "This item cannot be listed.");
                return;
            }

            dbPlayerStore.ItemsForSale.Add(itemId, new PlayerStoreItem
            {
                Data      = serialized,
                Name      = GetName(item),
                Price     = 0,
                StackSize = GetItemStackSize(item)
            });

            DB.Set(playerId, dbPlayerStore);
            DestroyObject(item);

            SendMessageToPC(player, $"Listing limit: {dbPlayerStore.ItemsForSale.Count} / {5 + dbPlayer.SeedProgress.Rank * 5}");
        }
Exemple #17
0
        public static void UsePerkRefundTome()
        {
            var player = OBJECT_SELF;

            if (!GetIsPC(player) || GetIsDM(player))
            {
                return;
            }
            var item = Object.StringToObject(Events.GetEventData("ITEM_OBJECT_ID"));

            if (GetResRef(item) != "refund_tome")
            {
                return;
            }

            SetLocalObject(player, "PERK_REFUND_OBJECT", item);
            AssignCommand(player, () => ClearAllActions());
            Dialog.StartConversation(player, player, "PerkRefundDialog");

            // Don't display the "You cannot use this item" message. Skip the event.
            Events.SetEventResult("1");
            Events.SkipEvent();
        }
Exemple #18
0
        public static void LearnRecipes()
        {
            var user = OBJECT_SELF;

            if (!GetIsPC(user) || GetIsDM(user))
            {
                SendMessageToPC(user, "Only players may use this item.");
                return;
            }

            var item           = Object.StringToObject(Events.GetEventData("ITEM_OBJECT_ID"));
            var playerId       = GetObjectUUID(user);
            var dbPlayer       = DB.Get <Player>(playerId);
            var recipeList     = GetLocalString(item, "RECIPES");
            var recipeIds      = recipeList.Split(',');
            var recipesLearned = 0;

            foreach (var recipeId in recipeIds)
            {
                // If it fails to parse, exit early.
                if (!int.TryParse(recipeId, out var convertedId))
                {
                    SendMessageToPC(user, "This recipe book has a configuration problem. Please inform a DM.");
                    return;
                }

                // Id number is zero or negative. Skip as those aren't valid.
                if (convertedId <= 0)
                {
                    SendMessageToPC(user, "This recipe book has a configuration problem. Please inform a DM.");
                    return;
                }

                var recipeType = (RecipeType)convertedId;

                // Ensure this type of recipe has been registered.
                if (!Craft.RecipeExists(recipeType))
                {
                    SendMessageToPC(user, "This recipe has not been registered. Please inform a DM.");
                    return;
                }

                // Player already knows this recipe. Move to the next one.
                if (dbPlayer.UnlockedRecipes.ContainsKey(recipeType))
                {
                    continue;
                }

                recipesLearned++;
                dbPlayer.UnlockedRecipes[recipeType] = DateTime.UtcNow;

                var recipeDetail = Craft.GetRecipe(recipeType);
                var skillDetail  = Skill.GetSkillDetails(recipeDetail.Skill);
                SendMessageToPC(user, $"You learn the {skillDetail.Name} recipe: {recipeDetail.Name}.");
            }

            // Player didn't learn any recipes. Let them know but don't destroy the item.
            if (recipesLearned <= 0)
            {
                SendMessageToPC(user, "You have already learned all of the recipes contained in this book.");
                return;
            }

            DestroyObject(item);
        }
Exemple #19
0
        private void ListingInit(DialogPage page)
        {
            var player        = GetPC();
            var playerId      = GetObjectUUID(player);
            var dbPlayerStore = DB.Get <PlayerStore>(playerId);
            var model         = GetDataModel <Model>();
            var item          = dbPlayerStore.ItemsForSale[model.SelectedItemId];

            void AdjustPrice(int amount)
            {
                item.Price += amount;

                if (item.Price <= 0)
                {
                    item.Price = 1;
                }
                else if (item.Price > 999999)
                {
                    item.Price = 999999;
                }

                DB.Set(playerId, dbPlayerStore);
                PlayerMarket.UpdateCacheEntry(playerId, dbPlayerStore);
            }

            page.Header = ColorToken.Green("Item: ") + item.StackSize + "x " + item.Name + "\n" +
                          ColorToken.Green("Price: ") + item.Price + "\n\n" +
                          "Please select an option.";

            if (model.IsConfirmingRemoveItem)
            {
                page.AddResponse(ColorToken.Red("CONFIRM REMOVE ITEM"), () =>
                {
                    var inWorldItem = Object.Deserialize(item.Data);
                    Object.AcquireItem(player, inWorldItem);
                    dbPlayerStore.ItemsForSale.Remove(model.SelectedItemId);

                    DB.Set(playerId, dbPlayerStore);
                    PlayerMarket.UpdateCacheEntry(playerId, dbPlayerStore);

                    ChangePage(EditItemListPageId, false);
                    model.IsConfirmingRemoveItem = false;
                });
            }
            else
            {
                page.AddResponse(ColorToken.Red("Remove Item"), () =>
                {
                    model.IsConfirmingRemoveItem = true;
                });
            }

            page.AddResponse("Increase by 10,000 gil", () =>
            {
                AdjustPrice(10000);
            });
            page.AddResponse("Increase by 1,000 gil", () =>
            {
                AdjustPrice(1000);
            });
            page.AddResponse("Increase by 100 gil", () =>
            {
                AdjustPrice(100);
            });
            page.AddResponse("Increase by 10 gil", () =>
            {
                AdjustPrice(10);
            });
            page.AddResponse("Increase by 1 gil", () =>
            {
                AdjustPrice(1);
            });

            page.AddResponse("Decrease by 10,000 gil", () =>
            {
                AdjustPrice(-10000);
            });
            page.AddResponse("Decrease by 1,000 gil", () =>
            {
                AdjustPrice(-1000);
            });
            page.AddResponse("Decrease by 100 gil", () =>
            {
                AdjustPrice(-100);
            });
            page.AddResponse("Decrease by 10 gil", () =>
            {
                AdjustPrice(-10);
            });
            page.AddResponse("Decrease by 1 gil", () =>
            {
                AdjustPrice(-1);
            });
        }
Exemple #20
0
        public static void LeaveParty()
        {
            var player = Object.StringToObject(Events.GetEventData("LEAVING"));

            RemovePlayerFromParty(player);
        }
Exemple #21
0
        /// <summary>
        /// When the module loads, spawns are located in all areas. Details about those spawns are stored
        /// into the cached data.
        /// </summary>
        public static void StoreSpawns()
        {
            for (var area = GetFirstArea(); GetIsObjectValid(area); area = GetNextArea())
            {
                for (var obj = GetFirstObjectInArea(area); GetIsObjectValid(obj); obj = GetNextObjectInArea(area))
                {
                    var type     = GetObjectType(obj);
                    var position = GetPosition(obj);
                    var facing   = GetFacing(obj);
                    var id       = Guid.NewGuid();

                    // Hand-placed creature information is stored and the actual NPC is destroyed so it can be spawned by the system.
                    if (type == ObjectType.Creature)
                    {
                        _spawns.Add(id, new SpawnDetail
                        {
                            SerializedObject = Object.Serialize(obj),
                            X      = position.X,
                            Y      = position.Y,
                            Z      = position.Z,
                            Facing = facing,
                            Area   = area,
                            RespawnDelayMinutes = 5
                        });

                        // Add this entry to the spawns by area cache.
                        if (!_allSpawnsByArea.ContainsKey(area))
                        {
                            _allSpawnsByArea[area] = new List <Guid>();
                        }

                        _allSpawnsByArea[area].Add(id);

                        DestroyObject(obj);
                    }
                    // Waypoints with a spawn table ID
                    else if (type == ObjectType.Waypoint)
                    {
                        var spawnTableId = GetLocalInt(obj, "SPAWN_TABLE_ID");
                        if (spawnTableId > 0)
                        {
                            if (!_spawnTables.ContainsKey(spawnTableId))
                            {
                                Log.Write(LogGroup.Error, $"Waypoint has an invalid spawn table Id. ({spawnTableId}) is not defined. Do you have the right spawn table Id?");
                                continue;
                            }

                            var spawnTable = _spawnTables[spawnTableId];
                            _spawns.Add(id, new SpawnDetail
                            {
                                SpawnTableId        = spawnTableId,
                                X                   = position.X,
                                Y                   = position.Y,
                                Z                   = position.Z,
                                Facing              = facing,
                                Area                = area,
                                RespawnDelayMinutes = spawnTable.RespawnDelayMinutes
                            });

                            // Add this entry to the spawns by area cache.
                            if (!_allSpawnsByArea.ContainsKey(area))
                            {
                                _allSpawnsByArea[area] = new List <Guid>();
                            }

                            _allSpawnsByArea[area].Add(id);
                        }
                    }
                }
            }
        }