public bool Run(params object[] args)
        {
            NWPlaceable drill       = Object.OBJECT_SELF;
            string      structureID = drill.GetLocalString("PC_BASE_STRUCTURE_ID");

            if (string.IsNullOrWhiteSpace(structureID))
            {
                string areaName = drill.Area.Name;
                Console.WriteLine("There was an error retrieving the PC_BASE_STRUCTURE_ID variable on drill in area: " + areaName);
                return(false);
            }

            Guid            structureGUID = new Guid(structureID);
            PCBaseStructure pcStructure   = _data.Get <PCBaseStructure>(structureGUID);
            PCBase          pcBase        = _data.Get <PCBase>(pcStructure.PCBaseID);
            PCBaseStructure tower         = _base.GetBaseControlTower(pcBase.ID);

            // Check whether there's space in this tower.
            int capacity = _base.CalculateResourceCapacity(pcBase.ID);
            int count    = _data.Where <PCBaseStructureItem>(x => x.PCBaseStructureID == tower.ID).Count() + 1;

            if (count > capacity)
            {
                return(false);
            }

            BaseStructure baseStructure = _data.Get <BaseStructure>(pcStructure.BaseStructureID);
            DateTime      now           = DateTime.UtcNow;

            var outOfPowerEffect = drill.Effects.SingleOrDefault(x => _.GetEffectTag(x) == "CONTROL_TOWER_OUT_OF_POWER");

            if (now >= pcBase.DateFuelEnds)
            {
                if (outOfPowerEffect == null)
                {
                    outOfPowerEffect = _.EffectVisualEffect(VFX_DUR_AURA_RED);
                    outOfPowerEffect = _.TagEffect(outOfPowerEffect, "CONTROL_TOWER_OUT_OF_POWER");
                    _.ApplyEffectToObject(DURATION_TYPE_PERMANENT, outOfPowerEffect, drill);
                }

                return(true);
            }
            else if (now < pcBase.DateFuelEnds && outOfPowerEffect != null)
            {
                _.RemoveEffect(drill, outOfPowerEffect);
            }

            int minuteReduce    = 2 * pcStructure.StructureBonus;
            int increaseMinutes = 60 - minuteReduce;
            int retrievalRating = baseStructure.RetrievalRating;

            if (increaseMinutes <= 20)
            {
                increaseMinutes = 20;
            }
            if (pcStructure.DateNextActivity == null)
            {
                pcStructure.DateNextActivity = now.AddMinutes(increaseMinutes);
                _data.SubmitDataChange(pcStructure, DatabaseActionType.Update);
            }

            if (!(now >= pcStructure.DateNextActivity))
            {
                return(true);
            }

            // Time to spawn a new item and reset the timer.
            var    dbArea      = _data.Single <Area>(x => x.Resref == pcBase.AreaResref);
            string sector      = pcBase.Sector;
            int    lootTableID = 0;

            switch (sector)
            {
            case "NE": lootTableID = dbArea.NortheastLootTableID ?? 0; break;

            case "NW": lootTableID = dbArea.NorthwestLootTableID ?? 0; break;

            case "SE": lootTableID = dbArea.SoutheastLootTableID ?? 0; break;

            case "SW": lootTableID = dbArea.SouthwestLootTableID ?? 0; break;
            }

            if (lootTableID <= 0)
            {
                Console.WriteLine("WARNING: Loot table ID not defined for area " + dbArea.Name + ". Drills cannot retrieve items.");
                return(false);
            }

            pcStructure.DateNextActivity = now.AddMinutes(increaseMinutes);

            var controlTower = _base.GetBaseControlTower(pcStructure.PCBaseID);
            var itemDetails  = _loot.PickRandomItemFromLootTable(lootTableID);

            var    tempStorage = _.GetObjectByTag("TEMP_ITEM_STORAGE");
            NWItem item        = _.CreateItemOnObject(itemDetails.Resref, tempStorage, itemDetails.Quantity);

            // Guard against invalid resrefs and missing items.
            if (!item.IsValid)
            {
                Console.WriteLine("ERROR: Could not create base drill item with resref '" + itemDetails.Resref + "'. Is this item valid?");
                return(false);
            }

            if (!string.IsNullOrWhiteSpace(itemDetails.SpawnRule))
            {
                App.ResolveByInterface <ISpawnRule>("SpawnRule." + itemDetails.SpawnRule, action =>
                {
                    action.Run(item, retrievalRating);
                });
            }

            var dbItem = new PCBaseStructureItem
            {
                PCBaseStructureID = controlTower.ID,
                ItemGlobalID      = item.GlobalID.ToString(),
                ItemName          = item.Name,
                ItemResref        = item.Resref,
                ItemTag           = item.Tag,
                ItemObject        = _serialization.Serialize(item)
            };

            _data.SubmitDataChange(pcStructure, DatabaseActionType.Update);
            _data.SubmitDataChange(dbItem, DatabaseActionType.Insert);
            item.Destroy();
            return(true);
        }
Beispiel #2
0
        public bool Run(params object[] args)
        {
            NWPlaceable point = NWPlaceable.Wrap(Object.OBJECT_SELF);
            const int   baseChanceToFullyHarvest = 50;
            bool        alwaysDestroys           = point.GetLocalInt("FORAGE_POINT_ALWAYS_DESTROYS") == 1;

            NWPlayer oPC             = NWPlayer.Wrap(_.GetLastOpenedBy());
            bool     hasBeenSearched = point.GetLocalInt("FORAGE_POINT_FULLY_HARVESTED") == 1;

            if (hasBeenSearched)
            {
                oPC.SendMessage("There's nothing left to harvest here...");
                return(true);
            }

            // Not fully harvested but the timer hasn't counted down yet.
            int refillTick = point.GetLocalInt("FORAGE_POINT_REFILL_TICKS");

            if (refillTick > 0)
            {
                oPC.SendMessage("You couldn't find anything new here. Check back later...");
                return(true);
            }

            if (!oPC.IsPlayer && !oPC.IsDM)
            {
                return(false);
            }
            PCSkill pcSkill = _skill.GetPCSkill(oPC, SkillType.Forage);

            if (pcSkill == null)
            {
                return(false);
            }

            int lootTableID = point.GetLocalInt("FORAGE_POINT_LOOT_TABLE_ID");
            int level       = point.GetLocalInt("FORAGE_POINT_LEVEL");
            int rank        = pcSkill.Rank;
            int delta       = level - rank;

            if (delta > 8)
            {
                oPC.SendMessage("You aren't skilled enough to forage through this. (Required Level: " + (level - 8) + ")");
                oPC.AssignCommand(() => _.ActionInteractObject(point.Object));
                return(true);
            }

            int dc = 6 + delta;

            if (dc <= 4)
            {
                dc = 4;
            }
            int searchAttempts = 1 + CalculateSearchAttempts(oPC);

            int luck = _perk.GetPCPerkLevel(oPC, PerkType.Lucky) + oPC.EffectiveLuckBonus;

            if (_random.Random(100) + 1 <= luck / 2)
            {
                dc--;
            }

            oPC.AssignCommand(() => _.ActionPlayAnimation(ANIMATION_LOOPING_GET_LOW, 1.0f, 2.0f));

            for (int attempt = 1; attempt <= searchAttempts; attempt++)
            {
                int roll = _random.Random(20) + 1;
                if (roll >= dc)
                {
                    oPC.FloatingText(_color.SkillCheck("Search: *success*: (" + roll + " vs. DC: " + dc + ")"));
                    ItemVO spawnItem = _loot.PickRandomItemFromLootTable(lootTableID);

                    if (spawnItem == null)
                    {
                        return(false);
                    }

                    if (!string.IsNullOrWhiteSpace(spawnItem.Resref) && spawnItem.Quantity > 0)
                    {
                        _.CreateItemOnObject(spawnItem.Resref, point.Object, spawnItem.Quantity);
                    }

                    float xp = _skill.CalculateRegisteredSkillLevelAdjustedXP(50, level, rank);
                    _skill.GiveSkillXP(oPC, SkillType.Forage, (int)xp);
                }
                else
                {
                    oPC.FloatingText(_color.SkillCheck("Search: *failure*: (" + roll + " vs. DC: " + dc + ")"));

                    float xp = _skill.CalculateRegisteredSkillLevelAdjustedXP(10, level, rank);
                    _skill.GiveSkillXP(oPC, SkillType.Forage, (int)xp);
                }
                dc += _random.Random(3) + 1;
            }

            if (_random.Random(100) + 1 <= 3)
            {
                _food.DecreaseHungerLevel(oPC, 1);
            }


            // Chance to destroy the forage point.
            int chanceToFullyHarvest = baseChanceToFullyHarvest - (_perk.GetPCPerkLevel(oPC, PerkType.CarefulForager) * 5);
            int growingPlantID       = point.GetLocalInt("GROWING_PLANT_ID");

            if (growingPlantID > 0)
            {
                Data.Entities.GrowingPlant growingPlant = _farming.GetGrowingPlantByID(growingPlantID);
                chanceToFullyHarvest = chanceToFullyHarvest - (growingPlant.LongevityBonus);
            }

            if (chanceToFullyHarvest <= 5)
            {
                chanceToFullyHarvest = 5;
            }

            if (alwaysDestroys || _random.Random(100) + 1 <= chanceToFullyHarvest)
            {
                point.SetLocalInt("FORAGE_POINT_FULLY_HARVESTED", 1);
                oPC.SendMessage("This resource has been fully harvested...");
            }
            // Otherwise the forage point will be refilled in 10-20 minutes.
            else
            {
                point.SetLocalInt("FORAGE_POINT_REFILL_TICKS", 100 + _random.Random(100));
            }

            point.SetLocalInt("FORAGE_POINT_DESPAWN_TICKS", 30);

            return(true);
        }
Beispiel #3
0
        public bool Run(params object[] args)
        {
            NWPlaceable     drill         = Object.OBJECT_SELF;
            int             structureID   = drill.GetLocalInt("PC_BASE_STRUCTURE_ID");
            PCBaseStructure structure     = _data.Get <PCBaseStructure>(structureID);
            PCBase          pcBase        = _data.Get <PCBase>(structure.PCBaseID);
            BaseStructure   baseStructure = _data.Get <BaseStructure>(structure.BaseStructureID);
            DateTime        now           = DateTime.UtcNow;

            if (now >= pcBase.DateFuelEnds)
            {
                var outOfPowerEffect = drill.Effects.SingleOrDefault(x => _.GetEffectTag(x) == "CONTROL_TOWER_OUT_OF_POWER");
                if (outOfPowerEffect == null)
                {
                    outOfPowerEffect = _.EffectVisualEffect(VFX_DUR_AURA_RED);
                    outOfPowerEffect = _.TagEffect(outOfPowerEffect, "CONTROL_TOWER_OUT_OF_POWER");
                    _.ApplyEffectToObject(DURATION_TYPE_PERMANENT, outOfPowerEffect, drill);
                }

                return(true);
            }

            int minuteReduce    = 2 * structure.StructureBonus;
            int increaseMinutes = 60 - minuteReduce;
            int retrievalRating = baseStructure.RetrievalRating;

            if (increaseMinutes <= 20)
            {
                increaseMinutes = 20;
            }
            if (structure.DateNextActivity == null)
            {
                structure.DateNextActivity = now.AddMinutes(increaseMinutes);
                _data.SubmitDataChange(structure, DatabaseActionType.Update);
            }

            if (!(now >= structure.DateNextActivity))
            {
                return(true);
            }

            // Time to spawn a new item and reset the timer.
            var    dbArea      = _data.Single <Area>(x => x.Resref == pcBase.AreaResref);
            string sector      = pcBase.Sector;
            int    lootTableID = 0;

            switch (sector)
            {
            case "NE": lootTableID = dbArea.NortheastLootTableID ?? 0; break;

            case "NW": lootTableID = dbArea.NorthwestLootTableID ?? 0; break;

            case "SE": lootTableID = dbArea.SoutheastLootTableID ?? 0; break;

            case "SW": lootTableID = dbArea.SouthwestLootTableID ?? 0; break;
            }

            if (lootTableID <= 0)
            {
                Console.WriteLine("WARNING: Loot table ID not defined for area " + dbArea.Name + ". Drills cannot retrieve items.");
                return(false);
            }

            structure.DateNextActivity = now.AddMinutes(increaseMinutes);

            var controlTower = _base.GetBaseControlTower(structure.PCBaseID);
            var itemDetails  = _loot.PickRandomItemFromLootTable(lootTableID);

            var    tempStorage = _.GetObjectByTag("TEMP_ITEM_STORAGE");
            NWItem item        = _.CreateItemOnObject(itemDetails.Resref, tempStorage, itemDetails.Quantity);

            if (!string.IsNullOrWhiteSpace(itemDetails.SpawnRule))
            {
                App.ResolveByInterface <ISpawnRule>("SpawnRule." + itemDetails.SpawnRule, action =>
                {
                    action.Run(item, retrievalRating);
                });
            }

            var dbItem = new PCBaseStructureItem
            {
                PCBaseStructureID = controlTower.ID,
                ItemGlobalID      = item.GlobalID.ToString(),
                ItemName          = item.Name,
                ItemResref        = item.Resref,
                ItemTag           = item.Tag,
                ItemObject        = _serialization.Serialize(item)
            };

            _data.SubmitDataChange(structure, DatabaseActionType.Update);
            _data.SubmitDataChange(dbItem, DatabaseActionType.Insert);
            item.Destroy();
            return(true);
        }