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); }
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); }
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); }