Esempio n. 1
0
        private void HandleAddItem()
        {
            NWPlayer oPC   = NWPlayer.Wrap(_.GetLastDisturbed());
            NWItem   oItem = NWItem.Wrap(_.GetInventoryDisturbItem());

            if (oItem.Resref == "cft_confirm")
            {
                return;
            }
            var         model   = _craft.GetPlayerCraftingData(oPC);
            NWPlaceable storage = NWPlaceable.Wrap(_.GetObjectByTag("craft_temp_store"));

            List <NWItem> list          = null;
            ComponentType allowedType   = ComponentType.None;
            bool          reachedCap    = false;
            string        componentName = string.Empty;

            switch (model.Access)
            {
            case CraftingAccessType.MainComponent:
                allowedType   = (ComponentType)model.Blueprint.MainComponentTypeID;
                reachedCap    = model.Blueprint.MainMinimum * 2 < model.MainComponents.Count + 1;
                list          = model.MainComponents;
                componentName = model.Blueprint.MainComponentType.Name;
                break;

            case CraftingAccessType.SecondaryComponent:
                allowedType   = (ComponentType)model.Blueprint.SecondaryComponentTypeID;
                reachedCap    = model.Blueprint.SecondaryMinimum * 2 < model.SecondaryComponents.Count + 1;
                list          = model.SecondaryComponents;
                componentName = model.Blueprint.SecondaryComponentType.Name;
                break;

            case CraftingAccessType.TertiaryComponent:
                allowedType   = (ComponentType)model.Blueprint.TertiaryComponentTypeID;
                reachedCap    = model.Blueprint.TertiaryMinimum * 2 < model.TertiaryComponents.Count + 1;
                list          = model.TertiaryComponents;
                componentName = model.Blueprint.TertiaryComponentType.Name;
                break;

            case CraftingAccessType.Enhancement:
                allowedType   = ComponentType.Enhancement;
                reachedCap    = model.Blueprint.EnhancementSlots < model.EnhancementComponents.Count + 1;
                list          = model.EnhancementComponents;
                componentName = "Enhancement";
                break;
            }

            if (list == null)
            {
                oPC.FloatingText("There was an issue getting the item data. Notify an admin.");
                _item.ReturnItem(oPC, oItem);
                return;
            }

            if (reachedCap)
            {
                _item.ReturnItem(oPC, oItem);
                oPC.FloatingText("You cannot add any more components of that type.");
                return;
            }

            foreach (var ip in oItem.ItemProperties)
            {
                if (_.GetItemPropertyType(ip) == (int)CustomItemPropertyType.ComponentType)
                {
                    int compType = _.GetItemPropertyCostTableValue(ip);
                    if (compType == (int)allowedType)
                    {
                        NWItem copy = NWItem.Wrap(_.CopyItem(oItem.Object, storage.Object, TRUE));
                        list.Add(copy);
                        return;
                    }
                }
            }

            oPC.FloatingText("Only " + componentName + " components may be used with this component type.");
            _item.ReturnItem(oPC, oItem);
        }
 protected NWPlayer GetPC()
 {
     return(NWPlayer.Wrap(_.GetPCSpeaker()));
 }
Esempio n. 3
0
        public void OnQuestTriggerEntered(NWObject oObject)
        {
            NWPlayer oPC = NWPlayer.Wrap(_.GetEnteringObject());

            HandleTriggerAndPlaceableQuestLogic(oPC, oObject);
        }
Esempio n. 4
0
        public void OnPlayerDeath()
        {
            NWPlayer oPC           = NWPlayer.Wrap(_.GetLastPlayerDied());
            string   corpseName    = oPC.Name + "'s Corpse";
            NWObject oHostileActor = NWObject.Wrap(_.GetLastHostileActor(oPC.Object));
            Location location      = oPC.Location;
            bool     hasItems      = false;

            var factionMember = _.GetFirstFactionMember(oHostileActor.Object, FALSE);

            while (_.GetIsObjectValid(factionMember) == TRUE)
            {
                _.ClearPersonalReputation(oPC.Object, factionMember);

                factionMember = _.GetNextFactionMember(oHostileActor.Object, FALSE);
            }

            _.PopUpDeathGUIPanel(oPC.Object, TRUE, TRUE, 0, RespawnMessage);

            NWPlaceable corpse = NWPlaceable.Wrap(_.CreateObject(OBJECT_TYPE_PLACEABLE, CorpsePlaceableResref, location));
            PCCorpse    entity = new PCCorpse
            {
                AreaTag     = _.GetTag(_.GetAreaFromLocation(location)),
                Name        = corpseName,
                Orientation = _.GetFacingFromLocation(location),
                PositionX   = _.GetPositionFromLocation(location).m_X,
                PositionY   = _.GetPositionFromLocation(location).m_Y,
                PositionZ   = _.GetPositionFromLocation(location).m_Z
            };

            if (oPC.Gold > 0)
            {
                corpse.AssignCommand(() =>
                {
                    _.TakeGoldFromCreature(oPC.Gold, oPC.Object);
                });

                hasItems = true;
            }

            foreach (NWItem item in oPC.InventoryItems)
            {
                if (!item.IsCursed)
                {
                    _.CopyItem(item.Object, corpse.Object, TRUE);
                    item.Destroy();
                    hasItems = true;
                }
            }

            if (!hasItems)
            {
                corpse.Destroy();
                return;
            }

            corpse.Name = corpseName;
            corpse.IdentifiedDescription = corpseName;

            foreach (NWItem corpseItem in corpse.InventoryItems)
            {
                PCCorpseItem corpseItemEntity = new PCCorpseItem
                {
                    GlobalID       = corpseItem.GlobalID,
                    NWItemObject   = _serialization.Serialize(corpseItem),
                    PCCorpseItemID = entity.PCCorpseID,
                    ItemName       = corpseItem.Name,
                    ItemTag        = corpseItem.Tag,
                    ItemResref     = corpseItem.Resref
                };
                entity.PCCorpseItems.Add(corpseItemEntity);
            }

            _db.PCCorpses.Add(entity);
            _db.SaveChanges();
            corpse.SetLocalInt("CORPSE_ID", (int)entity.PCCorpseID);
        }
Esempio n. 5
0
        public void OnCreatureDeath(NWCreature creature)
        {
            int npcGroupID = creature.GetLocalInt("NPC_GROUP");

            if (npcGroupID <= 0)
            {
                return;
            }

            NWObject oKiller = NWObject.Wrap(_.GetLastKiller());

            if (_.GetIsPC(oKiller.Object) == FALSE || _.GetIsDM(oKiller.Object) == TRUE)
            {
                return;
            }

            string areaResref = creature.Area.Resref;

            NWPlayer oPC = NWPlayer.Wrap(_.GetFirstFactionMember(oKiller.Object));

            while (oPC.IsValid)
            {
                if (areaResref != oPC.Area.Resref)
                {
                    continue;
                }
                if (_.GetDistanceBetween(creature.Object, oPC.Object) == 0.0f || _.GetDistanceBetween(creature.Object, oPC.Object) > 20.0f)
                {
                    continue;
                }

                List <PCQuestKillTargetProgress> killTargets = _db.PCQuestKillTargetProgresses.Where(x => x.PlayerID == oPC.GlobalID && x.NPCGroupID == npcGroupID).ToList();

                foreach (PCQuestKillTargetProgress kt in killTargets)
                {
                    kt.RemainingToKill--;
                    string targetGroupName = kt.NPCGroup.Name;
                    string questName       = kt.PcQuestStatus.Quest.Name;
                    string updateMessage   = "[" + questName + "] " + targetGroupName + " remaining: " + kt.RemainingToKill;

                    if (kt.RemainingToKill <= 0)
                    {
                        _db.PCQuestKillTargetProgresses.Remove(kt);
                        updateMessage += " " + _color.Green(" {COMPLETE}");

                        if (kt.PcQuestStatus.PCQuestKillTargetProgresses.Count - 1 <= 0)
                        {
                            AdvanceQuestState(oPC, kt.PcQuestStatus.QuestID);
                        }
                    }

                    _db.SaveChanges();
                    string finalMessage = updateMessage;
                    var    pc           = oPC;
                    oPC.DelayCommand(() =>
                    {
                        pc.SendMessage(finalMessage);
                    }, 1.0f);
                }

                oPC = NWPlayer.Wrap(_.GetNextFactionMember(oKiller.Object));
            }
        }
Esempio n. 6
0
        public void OnQuestPlaceableUsed(NWObject oObject)
        {
            NWPlayer oPC = NWPlayer.Wrap(_.GetLastUsedBy());

            HandleTriggerAndPlaceableQuestLogic(oPC, oObject);
        }
Esempio n. 7
0
        public bool Run(params object[] args)
        {
            int nodeType = (int)args[0];
            int nodeID   = (int)args[1];

            NWPlayer     player = NWPlayer.Wrap(_.GetPCSpeaker());
            PlayerDialog dialog = _dialog.LoadPlayerDialog(player.GlobalID);
            DialogPage   page   = dialog.CurrentPage;
            int          currentSelectionNumber = nodeID + 1;
            bool         displayNode            = false;
            string       newNodeText            = string.Empty;
            int          dialogOffset           = (_dialog.NumberOfResponsesPerPage + 1) * (dialog.DialogNumber - 1);

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

                if (displayCount > _dialog.NumberOfResponsesPerPage)
                {
                    displayNode = true;
                }
            }
            else if (currentSelectionNumber == _dialog.NumberOfResponsesPerPage + 2) // Previous Page
            {
                if (dialog.PageOffset > 0)
                {
                    displayNode = true;
                }
            }
            else if (nodeType == 2)
            {
                int responseID = (dialog.PageOffset * _dialog.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)
            {
                IConversation convo = App.ResolveByInterface <IConversation>("Conversation." + dialog.ActiveDialogName);
                if (player.GetLocalInt("DIALOG_SYSTEM_INITIALIZE_RAN") != 1)
                {
                    convo.Initialize();
                    player.SetLocalInt("DIALOG_SYSTEM_INITIALIZE_RAN", 1);
                }

                if (dialog.IsEnding)
                {
                    convo.EndDialog();
                    _dialog.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);
        }
Esempio n. 8
0
        public bool Run(params object[] args)
        {
            NWPlayer    oPC    = NWPlayer.Wrap(_.GetLastDisturbed());
            NWItem      oItem  = NWItem.Wrap(_.GetInventoryDisturbItem());
            NWPlaceable device = NWPlaceable.Wrap(Object.OBJECT_SELF);

            int            type        = _.GetInventoryDisturbType();
            string         resref      = oItem.Resref;
            string         tag         = oItem.Tag;
            int            blueprintID = device.GetLocalInt("CRAFT_BLUEPRINT_ID");
            NWItem         tools       = NWItem.Wrap(device.GetLocalObject("CRAFT_DEVICE_TOOLS"));
            CraftBlueprint blueprint   = _craft.GetBlueprintByID(blueprintID);

            if (type == INVENTORY_DISTURB_TYPE_REMOVED)
            {
                if (resref == "cft_choose_bp" || resref == "cft_craft_item")
                {
                    _item.ReturnItem(device, oItem);

                    if (tag == "CHOOSE_BLUEPRINT")
                    {
                        _dialog.StartConversation(oPC, device, "Crafting");
                    }
                    else if (tag == "CRAFT_ITEM")
                    {
                        HandleCraftItem(oPC, device);
                    }
                }
                else if (Equals(oItem, tools))
                {
                    device.DeleteLocalObject("CRAFT_DEVICE_TOOLS");
                }
            }
            else if (type == INVENTORY_DISTURB_TYPE_ADDED)
            {
                if (resref == "cft_choose_bp" || resref == "cft_craft_item")
                {
                    return(false);
                }

                if (blueprint == null)
                {
                    _item.ReturnItem(oPC, oItem);
                    oPC.SendMessage("Please select a blueprint before adding components.");
                }
                else if (oItem.CraftTierLevel > 0)
                {
                    if (blueprint.CraftTierLevel <= 0)
                    {
                        _item.ReturnItem(oPC, oItem);
                        oPC.SendMessage("Tools are not required to make this item.");
                    }
                    else if (blueprint.CraftTierLevel > oItem.CraftTierLevel || blueprint.SkillID != oItem.AssociatedSkillID)
                    {
                        _item.ReturnItem(oPC, oItem);
                        oPC.SendMessage("Those tools cannot be used with this blueprint. (Required Tool Level: " + blueprint.CraftTierLevel + ")");
                    }
                    else
                    {
                        if (tools.IsValid)
                        {
                            _item.ReturnItem(oPC, oItem);
                            oPC.SendMessage("You may only use one set of tools at a time.");
                        }
                        else
                        {
                            device.SetLocalObject("CRAFT_DEVICE_TOOLS", oItem.Object);
                        }
                    }
                }
            }
            return(true);
        }
Esempio n. 9
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);
            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.CalculateSkillAdjustedXP(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);
        }
Esempio n. 10
0
        public void OnModuleClientLeave()
        {
            NWPlayer oPC = NWPlayer.Wrap(_.GetExitingObject());

            RemovePlayerFromRegistrations(oPC);
        }
Esempio n. 11
0
        public void OnAreaExit()
        {
            NWPlayer oPC = NWPlayer.Wrap(_.GetExitingObject());

            RemovePlayerFromRegistrations(oPC);
        }
Esempio n. 12
0
        public void OnModuleActivatedItem()
        {
            NWPlayer oPC            = NWPlayer.Wrap(_.GetItemActivator());
            NWItem   oItem          = NWItem.Wrap(_.GetItemActivated());
            NWObject oTarget        = NWObject.Wrap(_.GetItemActivatedTarget());
            Location targetLocation = _.GetItemActivatedTargetLocation();

            string className = oItem.GetLocalString("JAVA_SCRIPT");

            if (string.IsNullOrWhiteSpace(className))
            {
                className = oItem.GetLocalString("ACTIVATE_JAVA_SCRIPT");
            }
            if (string.IsNullOrWhiteSpace(className))
            {
                className = oItem.GetLocalString("JAVA_ACTION_SCRIPT");
            }
            if (string.IsNullOrWhiteSpace(className))
            {
                className = oItem.GetLocalString("SCRIPT");
            }
            if (string.IsNullOrWhiteSpace(className))
            {
                return;
            }

            oPC.ClearAllActions();

            // Remove "Item." prefix if it exists.
            if (className.StartsWith("Item."))
            {
                className = className.Substring(5);
            }

            IActionItem item = App.ResolveByInterface <IActionItem>("Item." + className);

            if (oPC.IsBusy)
            {
                oPC.SendMessage("You are busy.");
                return;
            }

            string invalidTargetMessage = item.IsValidTarget(oPC, oItem, oTarget, targetLocation);

            if (!string.IsNullOrWhiteSpace(invalidTargetMessage))
            {
                oPC.SendMessage(invalidTargetMessage);
                return;
            }

            if (item.MaxDistance() > 0.0f)
            {
                if (_.GetDistanceBetween(oPC.Object, oTarget.Object) > item.MaxDistance() ||
                    oPC.Area.Resref != oTarget.Area.Resref)
                {
                    oPC.SendMessage("Your target is too far away.");
                    return;
                }
            }

            CustomData customData   = item.StartUseItem(oPC, oItem, oTarget, targetLocation);
            float      delay        = item.Seconds(oPC, oItem, oTarget, targetLocation, customData);
            int        animationID  = item.AnimationID();
            bool       faceTarget   = item.FaceTarget();
            Vector     userPosition = oPC.Position;

            oPC.AssignCommand(() =>
            {
                oPC.IsBusy = true;
                if (faceTarget)
                {
                    _.SetFacingPoint(oTarget.Position);
                }
                if (animationID > 0)
                {
                    _.ActionPlayAnimation(animationID, 1.0f, delay);
                }
            });

            _nwnxPlayer.StartGuiTimingBar(oPC, delay, string.Empty);
            oPC.DelayCommand(() =>
            {
                FinishActionItem(item, oPC, oItem, oTarget, targetLocation, userPosition, customData);
            }, delay);
        }
Esempio n. 13
0
        public bool Run(params object[] args)
        {
            NWPlaceable container = NWPlaceable.Wrap(Object.OBJECT_SELF);
            NWPlayer    oPC       = NWPlayer.Wrap(_.GetLastDisturbed());
            int         type      = _.GetInventoryDisturbType();
            NWItem      item      = NWItem.Wrap(_.GetInventoryDisturbItem());

            if (type != INVENTORY_DISTURB_TYPE_ADDED)
            {
                return(false);
            }

            int plantID = item.GetLocalInt("PLANT_ID");

            if (plantID <= 0)
            {
                _item.ReturnItem(oPC, item);
                oPC.SendMessage("You cannot plant that item.");
                return(true);
            }

            Plant plant = _farming.GetPlantByID(plantID);

            if (plant == null)
            {
                _item.ReturnItem(oPC, item);
                oPC.SendMessage("You cannot plant that item.");
                return(true);
            }

            PCSkill pcSkill = _skill.GetPCSkill(oPC, SkillType.Farming);
            int     rank    = 0;

            if (pcSkill != null)
            {
                rank = pcSkill.Rank;
            }

            if (rank + 2 < plant.Level)
            {
                _item.ReturnItem(oPC, item);
                oPC.SendMessage("You do not have enough Farming skill to plant that seed. (Required: " + (plant.Level - 2) + ")");
                return(true);
            }

            item.Destroy();

            string   areaTag       = container.Area.Tag;
            Location plantLocation = container.Location;
            int      perkBonus     = _perk.GetPCPerkLevel(oPC, PerkType.FarmingEfficiency) * 2;
            int      ticks         = (int)(plant.BaseTicks - ((_perk.GetPCPerkLevel(oPC, PerkType.ExpertFarmer) * 0.05f)) * plant.BaseTicks);

            Data.Entities.GrowingPlant growingPlant = new Data.Entities.GrowingPlant();
            growingPlant.PlantID             = plant.PlantID;
            growingPlant.RemainingTicks      = ticks;
            growingPlant.LocationAreaTag     = areaTag;
            growingPlant.LocationOrientation = _.GetFacingFromLocation(plantLocation);
            growingPlant.LocationX           = _.GetPositionFromLocation(plantLocation).m_X;
            growingPlant.LocationY           = _.GetPositionFromLocation(plantLocation).m_Y;
            growingPlant.LocationZ           = _.GetPositionFromLocation(plantLocation).m_Z;
            growingPlant.IsActive            = true;
            growingPlant.DateCreated         = DateTime.UtcNow;
            growingPlant.LongevityBonus      = perkBonus;

            _db.GrowingPlants.Add(growingPlant);
            _db.SaveChanges();

            NWPlaceable hole     = NWPlaceable.Wrap(container.GetLocalObject("FARM_SMALL_HOLE"));
            NWPlaceable plantPlc = NWPlaceable.Wrap(_.CreateObject(OBJECT_TYPE_PLACEABLE, "growing_plant", hole.Location));

            plantPlc.SetLocalInt("GROWING_PLANT_ID", growingPlant.GrowingPlantID);
            plantPlc.Name = "Growing Plant (" + plant.Name + ")";

            container.Destroy();
            hole.Destroy();

            int xp = (int)_skill.CalculateSkillAdjustedXP(200, plant.Level, rank);

            if (_random.Random(100) + 1 <= _perk.GetPCPerkLevel(oPC, PerkType.Lucky))
            {
                xp *= 2;
            }

            _skill.GiveSkillXP(oPC, SkillType.Farming, xp);
            return(true);
        }