public virtual void CalculateSubPosition(IAreaJob job, ref Vector3Int positionSub) { if (stages == null || stages.Length < 2) { return; } bool hasSeeds = job.NPC.Colony.UsedStockpile.Contains(stages[0]); bool reversed = false; Vector3Int firstPlanting = Vector3Int.invalidPos; Vector3Int min = job.Minimum; Vector3Int max = job.Maximum; for (int x = min.x; x <= max.x; x++) { int z = reversed ? max.z : min.z; while (reversed ? (z >= min.z) : (z <= max.z)) { ushort type; Vector3Int possiblePositionSub = new Vector3Int(x, min.y, z); if (!World.TryGetTypeAt(possiblePositionSub, out type)) { return; } if (type == 0) { if (!hasSeeds && !firstPlanting.IsValid) { firstPlanting = possiblePositionSub; } if (hasSeeds) { positionSub = possiblePositionSub; return; } } if (type == stages[stages.Length - 1]) { positionSub = possiblePositionSub; return; } z = reversed ? z - 1 : z + 1; } reversed = !reversed; } if (firstPlanting.IsValid) { positionSub = firstPlanting; return; } int xRandom = Random.Next(min.x, max.x + 1); int zRandom = Random.Next(min.z, max.z + 1); positionSub = new Vector3Int(xRandom, min.y, zRandom); }
public override void CalculateSubPosition(IAreaJob rawJob, ref Vector3Int positionSub) { BerryFarmerJob job = (BerryFarmerJob)rawJob; Vector3Int min = job.Minimum; Vector3Int max = job.Maximum; if (job.checkMissingBushes && job.NPC.Colony.UsedStockpile.Contains(BuiltinBlocks.BerryBush)) { // remove legacy positions for (int x = min.x + 1; x <= max.x; x += 2) { for (int z = min.z; z <= max.z; z += 2) { ushort type; Vector3Int possiblePositionSub = new Vector3Int(x, min.y, z); if (!World.TryGetTypeAt(possiblePositionSub, out type)) { return; } if (type == BuiltinBlocks.BerryBush) { job.removingOldBush = true; job.bushLocation = possiblePositionSub; positionSub = Server.AI.AIManager.ClosestPosition(job.bushLocation, job.NPC.Position); return; } } } // place new positions for (int x = min.x; x <= max.x; x += 2) { for (int z = min.z; z <= max.z; z += 2) { ushort type; Vector3Int possiblePositionSub = new Vector3Int(x, min.y, z); if (!World.TryGetTypeAt(possiblePositionSub, out type)) { return; } if (type == 0) { job.placingMissingBush = true; job.bushLocation = possiblePositionSub; positionSub = Server.AI.AIManager.ClosestPositionNotAt(job.bushLocation, job.NPC.Position); return; } } } job.checkMissingBushes = false; } positionSub = min; positionSub.x += Random.Next(0, (max.x - min.x) / 2 + 1) * 2; positionSub.z += Random.Next(0, (max.z - min.z) / 2 + 1) * 2; }
public override void CalculateSubPosition(IAreaJob job, ref Vector3Int positionSub) { bool hasSeeds = job.UsedNPC.Colony.UsedStockpile.Contains(BuiltinBlocks.Sapling); Vector3Int firstPlanting = Vector3Int.invalidPos; Vector3Int min = job.Minimum; Vector3Int max = job.Maximum; for (int x = min.x + 1; x < max.x; x += 3) { for (int z = min.z + 1; z < max.z; z += 3) { ushort type; Vector3Int possiblePositionSub = new Vector3Int(x, min.y, z); if (!World.TryGetTypeAt(possiblePositionSub, out type)) { positionSub = min; return; } if (type == 0) { if (hasSeeds) { positionSub = possiblePositionSub; // can plant here return; } else if (!firstPlanting.IsValid) { firstPlanting = possiblePositionSub; // no seeds but should plant here. If no location found, go here } } else if (type == BuiltinBlocks.LogTemperate) { positionSub = possiblePositionSub; // should cut here return; } } } if (firstPlanting.IsValid) { positionSub = firstPlanting; return; } int xOffset = max.x - min.x; int zOffset = max.z - min.z; int xRandom = Random.Next(0, xOffset / 3) * 3 + min.x; int zRandom = Random.Next(0, zOffset / 3) * 3 + min.z; positionSub = new Vector3Int(xRandom, min.y, zRandom); }
private static bool MoveNext(IIterationType iterationType, IAreaJob areaJob, ConstructionJobInstance job, ArchitectIterator bpi, int prvX, int prvY, int prvZ) { if (bpi.PreviousPosition != Pipliz.Vector3Int.invalidPos && prvX <= bpi.BuilderSchematic.XMax && prvY <= bpi.BuilderSchematic.YMax && prvZ <= bpi.BuilderSchematic.ZMax && !bpi.BuilderSchematic.Blocks[prvX, prvY, prvZ].BlockID.Contains("bedend")) { ServerManager.TryChangeBlock(bpi.PreviousPosition, ItemId.GetItemId(bpi.BuilderSchematic.Blocks[prvX, prvY, prvZ].BlockID).Id, new BlockChangeRequestOrigin(job.Owner), ESetBlockFlags.DefaultAudio); } if (!bpi.MoveNext()) { CleanupJob(iterationType, areaJob, job, bpi, prvX, prvY, prvZ); return(false); } return(true); }
private static void CleanupJob(IIterationType iterationType, IAreaJob areaJob, ConstructionJobInstance job, ArchitectIterator bpi, int prvX, int prvY, int prvZ) { if (_needsChunkLoaded.Contains(bpi)) { _needsChunkLoaded.Remove(bpi); } if (bpi.PreviousPosition != Pipliz.Vector3Int.invalidPos && prvX <= bpi.BuilderSchematic.XMax && prvY <= bpi.BuilderSchematic.YMax && prvZ <= bpi.BuilderSchematic.ZMax && !bpi.BuilderSchematic.Blocks[prvX, prvY, prvZ].BlockID.Contains("bedend")) { ServerManager.TryChangeBlock(bpi.PreviousPosition, ItemId.GetItemId(bpi.BuilderSchematic.Blocks[prvX, prvY, prvZ].BlockID).Id, new BlockChangeRequestOrigin(job.Owner), ESetBlockFlags.DefaultAudio); } SchematicReader.SaveSchematic(areaJob.Owner, bpi.BuilderSchematic); AreaJobTracker.RemoveJob(areaJob); }
public void DoJob( IIterationType iterationType, IAreaJob areaJob, ConstructionJobInstance job, ref NPCBase.NPCState state) { if (iterationType == null) { AreaJobTracker.RemoveJob(areaJob); } else { Stockpile stockpile = areaJob.Owner.Stockpile; int num = 4096; while (num-- > 0) { Vector3Int currentPosition = iterationType.CurrentPosition; if (!currentPosition.IsValid) { state.SetIndicator(new IndicatorState(5f, BuiltinBlocks.Indices.erroridle, false, true), true); AreaJobTracker.RemoveJob(areaJob); return; } ushort val; if (World.TryGetTypeAt(currentPosition, out val)) { if (val == (ushort)0) { iterationType.MoveNext(); continue; } ItemTypes.ItemType type = ItemTypes.GetType(val); if (!type.IsDestructible) { iterationType.MoveNext(); continue; } if (type != this.digType) { bool flag = false; for (ItemTypes.ItemType parentItemType = type.ParentItemType; parentItemType != (ItemTypes.ItemType)null; parentItemType = parentItemType.ParentItemType) { if (parentItemType == this.digType) { flag = true; break; } } if (!flag) { iterationType.MoveNext(); continue; } } if (!stockpile.Contains(this.buildType.ItemIndex, 1)) { float num2 = Random.NextFloat(5f, 8f); job.Owner.Stats.RecordNPCIdleSeconds(job.NPCType, num2); state.SetIndicator(new IndicatorState(num2, this.buildType.ItemIndex, true, false), true); return; } if (ServerManager.TryChangeBlock(currentPosition, this.buildType, (BlockChangeRequestOrigin)areaJob.Owner, ESetBlockFlags.DefaultAudio) == EServerChangeBlockResult.Success) { stockpile.TryRemove(this.buildType.ItemIndex, 1, true); float cooldown = ReplacerSpecial.GetCooldown((float)type.DestructionTime * (1f / 1000f)); ReplacerSpecial.GatherResults.Clear(); List <ItemTypes.ItemTypeDrops> onRemoveItems = type.OnRemoveItems; for (int index = 0; index < onRemoveItems.Count; ++index) { ReplacerSpecial.GatherResults.Add(onRemoveItems[index]); } ModLoader.Callbacks.OnNPCGathered.Invoke((IJob)job, currentPosition, ReplacerSpecial.GatherResults); InventoryItem weightedRandom = ItemTypes.ItemTypeDrops.GetWeightedRandom(ReplacerSpecial.GatherResults); if (weightedRandom.Amount > 0) { state.SetIndicator(new IndicatorState(cooldown, weightedRandom.Type, false, true), true); } else { state.SetCooldown((double)cooldown); } state.Inventory.Add((IList <ItemTypes.ItemTypeDrops>)ReplacerSpecial.GatherResults); ++job.StoredItemCount; iterationType.MoveNext(); if (job.StoredItemCount < this.MaxGatheredPerRun) { return; } job.ShouldTakeItems = true; state.JobIsDone = true; return; } state.SetIndicator(new IndicatorState(5f, BuiltinBlocks.Indices.missingerror, true, false), true); return; } else { state.SetIndicator(new IndicatorState(5f, BuiltinBlocks.Indices.missingerror, true, false), true); return; } } state.SetCooldown(0.8, 1.2); } }
public void DoJob(IIterationType iterationType, IAreaJob job, ref NPC.NPCBase.NPCState state) { if (iterationType == null) { AreaJobTracker.RemoveJob(job); return; } while (true) { Vector3Int jobPosition = iterationType.CurrentPosition; ushort foundTypeIndex; if (World.TryGetTypeAt(jobPosition, out foundTypeIndex)) { if (!iterationType.MoveNext()) { // failed to find next position to do job at, self-destruct state.SetIndicator(new Shared.IndicatorState(5f, BuiltinBlocks.ErrorIdle)); AreaJobTracker.RemoveJob(job); return; } if (foundTypeIndex != 0) { ItemTypes.ItemType foundType = ItemTypes.GetType(foundTypeIndex); if (!foundType.IsDestructible) { continue; // skip this block, retry } if (ServerManager.TryChangeBlock(jobPosition, 0, job.Owner, ServerManager.SetBlockFlags.DefaultAudio)) { InventoryItem typeDropped = InventoryItem.Empty; var onRemoveItems = ItemTypes.GetType(foundTypeIndex).OnRemoveItems; for (int i = 0; i < onRemoveItems.Count; i++) { if (Random.NextDouble() <= onRemoveItems[i].chance) { typeDropped = onRemoveItems[i].item; state.Inventory.Add(typeDropped); } } float blockDestructionTime = GetCooldown(foundType.DestructionTime * 0.001f); if (typeDropped.Amount > 0) { state.SetIndicator(new Shared.IndicatorState(blockDestructionTime, typeDropped.Type)); } else { state.SetCooldown(blockDestructionTime); } } else { state.SetIndicator(new Shared.IndicatorState(5f, BuiltinBlocks.ErrorMissing, true, false)); } return; // either changed a block or set indicator, job done } else { continue; // found air, try next loop } // unreachable } else { state.SetIndicator(new Shared.IndicatorState(5f, BuiltinBlocks.ErrorMissing, true, false)); return; // end loop, wait for world to load } // unreachable } // unreachable }
public virtual void OnRemove(IAreaJob job) { }
public virtual void OnNPCAtJob(IAreaJob job, ref Vector3Int positionSub, ref NPCBase.NPCState state, ref bool shouldDumpInventory) { if (stages == null || stages.Length < 2) { state.SetCooldown(1.0); return; } state.JobIsDone = true; if (positionSub.IsValid) { ushort type; if (World.TryGetTypeAt(positionSub, out type)) { ushort typeSeeds = stages[0]; ushort typeFinal = stages[stages.Length - 1]; if (type == 0) { if (state.Inventory.TryGetOneItem(typeSeeds) || job.NPC.Colony.UsedStockpile.TryRemove(typeSeeds)) { ushort typeBelow; if (World.TryGetTypeAt(positionSub.Add(0, -1, 0), out typeBelow)) { // check for fertile below if (ItemTypes.GetType(typeBelow).IsFertile) { ServerManager.TryChangeBlock(positionSub, typeSeeds, job.Owner, ServerManager.SetBlockFlags.DefaultAudio); state.SetCooldown(1.0); shouldDumpInventory = false; } else { // not fertile below AreaJobTracker.RemoveJob(job); state.SetCooldown(2.0); } } else { // didn't load this part of the world state.SetCooldown(Random.NextFloat(3f, 6f)); } } else { state.SetIndicator(new Shared.IndicatorState(2f, typeSeeds, true, false)); shouldDumpInventory = state.Inventory.UsedCapacity > 0f; } } else if (type == typeFinal) { if (ServerManager.TryChangeBlock(positionSub, 0, job.Owner, ServerManager.SetBlockFlags.DefaultAudio)) { GatherResults.Clear(); var results = ItemTypes.GetType(typeFinal).OnRemoveItems; for (int i = 0; i < results.Count; i++) { GatherResults.Add(results[i]); } ModLoader.TriggerCallbacks(ModLoader.EModCallbackType.OnNPCGathered, job as IJob, positionSub, GatherResults); job.NPC.Inventory.Add(GatherResults); } state.SetCooldown(1.0); shouldDumpInventory = false; } else { shouldDumpInventory = state.Inventory.UsedCapacity > 0f; Server.GrowableBlocks.IGrowableBlock block; if (Server.GrowableBlocks.GrowableBlockManager.TryGetGrowableBlock(positionSub, out block)) { state.SetCooldown(5.0); } else { bool found = false; for (int i = 0; i < stages.Length; i++) { if (stages[i] == type) { ItemTypesServer.OnChange(positionSub, 0, type, null); state.SetIndicator(new Shared.IndicatorState(2f, type)); state.SetCooldown(0.2); found = true; break; } } if (!found) { state.SetCooldown(5.0); } } } } else { state.SetCooldown(Random.NextFloat(3f, 6f)); } positionSub = Vector3Int.invalidPos; } else { state.SetCooldown(10.0); } }
public void DoJob(IIterationType iterationType, IAreaJob areaJob, ConstructionJob job, ref NPC.NPCBase.NPCState state) { if (iterationType == null || buildType == null || buildType.ItemIndex == 0) { AreaJobTracker.RemoveJob(areaJob); return; } int iMax = 4096; while (iMax-- > 0) { Vector3Int jobPosition = iterationType.CurrentPosition; ushort foundTypeIndex; if (World.TryGetTypeAt(jobPosition, out foundTypeIndex)) { if (foundTypeIndex == 0 || foundTypeIndex == BuiltinBlocks.Water) { Stockpile ownerStockPile = Stockpile.GetStockPile(areaJob.Owner); if (ownerStockPile.Contains(buildType.ItemIndex)) { if (ServerManager.TryChangeBlock(jobPosition, buildType.ItemIndex, areaJob.Owner, ServerManager.SetBlockFlags.DefaultAudio)) { if (--job.storedItems == 0) { state.JobIsDone = true; } ownerStockPile.TryRemove(buildType.ItemIndex); if (iterationType.MoveNext()) { state.SetIndicator(new Shared.IndicatorState(GetCooldown(), buildType.ItemIndex)); } else { // failed to find next position to do job at, self-destruct state.SetIndicator(new Shared.IndicatorState(5f, BuiltinBlocks.ErrorIdle)); AreaJobTracker.RemoveJob(areaJob); } return; } else { // shouldn't really happen, world not loaded (just checked) state.SetIndicator(new Shared.IndicatorState(5f, BuiltinBlocks.ErrorMissing, true, false)); } } else { // missing building item state.SetIndicator(new Shared.IndicatorState(Random.NextFloat(5f, 8f), buildType.ItemIndex, true, false)); } return; // either changed a block or set indicator, job done } else { // move iterator, not placing at non-air blocks if (iterationType.MoveNext()) { continue; // found non-air, try next loop } else { // failed to find next position to do job at, self-destruct state.SetIndicator(new Shared.IndicatorState(5f, BuiltinBlocks.ErrorIdle)); AreaJobTracker.RemoveJob(areaJob); return; } } // unreachable } else { state.SetIndicator(new Shared.IndicatorState(5f, BuiltinBlocks.ErrorMissing, true, false)); return; // end loop, wait for world to load } // unreachable } // reached loop count limit Assert.IsTrue(iMax <= 0); state.SetCooldown(1.0); }
public override void OnNPCAtJob(IAreaJob job, ref Vector3Int positionSub, ref NPCBase.NPCState state, ref bool shouldDumpInventory) { state.JobIsDone = true; Vector3Int min = job.Minimum; Vector3Int max = job.Maximum; if (positionSub.x == min.x || positionSub.x == max.x || positionSub.z == min.z || positionSub.z == max.z || (positionSub.x - (min.x + 1)) % 3 != 0 || (positionSub.z - (min.z + 1)) % 3 != 0) { ushort type; if (World.TryGetTypeAt(positionSub.Add(1, 0, 1), out type)) { if (type == saplingIndex) { Server.GrowableBlocks.IGrowableBlock block; if (Server.GrowableBlocks.GrowableBlockManager.TryGetGrowableBlock(positionSub.Add(1, 0, 1), out block)) { state.SetCooldown(5.0); } else { ItemTypesServer.OnChange(positionSub.Add(1, 0, 1), 0, saplingIndex, null); state.SetIndicator(new Shared.IndicatorState(2f, saplingIndex)); state.SetCooldown(0.2); } } } } else if (positionSub.IsValid) { ushort type; if (World.TryGetTypeAt(positionSub, out type)) { if (type == 0) { if (job.NPC.Inventory.TryGetOneItem(saplingIndex) || job.NPC.Colony.UsedStockpile.TryRemove(saplingIndex)) { ServerManager.TryChangeBlock(positionSub, saplingIndex, job.Owner, ServerManager.SetBlockFlags.DefaultAudio); state.SetCooldown(2.0); } else { state.SetIndicator(new Shared.IndicatorState(2f, saplingIndex)); } } else if (type == logIndex) { if (ChopTree(positionSub, job.Owner)) { state.SetIndicator(new Shared.IndicatorState(10f, logIndex)); ServerManager.SendAudio(positionSub.Vector, "woodDeleteHeavy"); GatherResults.Clear(); GatherResults.Add(new ItemTypes.ItemTypeDrops(logIndex, 3, 1.0)); GatherResults.Add(new ItemTypes.ItemTypeDrops(leaveIndex, 9, 1.0)); GatherResults.Add(new ItemTypes.ItemTypeDrops(saplingIndex, 1, 1.0)); GatherResults.Add(new ItemTypes.ItemTypeDrops(saplingIndex, 1, 0.25)); GatherResults.Add(new ItemTypes.ItemTypeDrops(fruitIndex, 2, 0.5)); ModLoader.TriggerCallbacks(ModLoader.EModCallbackType.OnNPCGathered, job as IJob, positionSub, GatherResults); job.NPC.Inventory.Add(GatherResults); } else { state.SetCooldown(Random.NextFloat(3f, 6f)); } } else { state.SetCooldown(Random.NextFloat(8f, 16f)); } } else { state.SetCooldown(Random.NextFloat(3f, 6f)); } } else { state.SetCooldown(10.0); } positionSub = Vector3Int.invalidPos; }
public virtual void OnNPCAtJob(IAreaJob job, ref Vector3Int positionSub, ref NPCBase.NPCState state, ref bool shouldDumpInventory) { if (stages == null || stages.Length < 2) { state.SetCooldown(1.0); return; } state.JobIsDone = true; if (positionSub.IsValid) { ushort type; if (World.TryGetTypeAt(positionSub, out type)) { ushort typeSeeds = stages[0]; ushort typeFinal = stages[stages.Length - 1]; if (type == 0) { if (state.Inventory.TryGetOneItem(typeSeeds) || job.UsedNPC.Colony.UsedStockpile.TryRemove(typeSeeds)) { ServerManager.TryChangeBlock(positionSub, typeSeeds, job.Owner, ServerManager.SetBlockFlags.DefaultAudio); state.SetCooldown(1.0); shouldDumpInventory = false; } else { state.SetIndicator(new Shared.IndicatorState(2f, typeSeeds, true, false)); shouldDumpInventory = state.Inventory.UsedCapacity > 0f; } } else if (type == typeFinal) { if (ServerManager.TryChangeBlock(positionSub, 0, job.Owner, ServerManager.SetBlockFlags.DefaultAudio)) { job.UsedNPC.Inventory.Add(ItemTypes.GetType(typeFinal).OnRemoveItems); } state.SetCooldown(1.0); shouldDumpInventory = false; } else { shouldDumpInventory = state.Inventory.UsedCapacity > 0f; Server.GrowableBlocks.IGrowableBlock block; if (Server.GrowableBlocks.GrowableBlockManager.TryGetGrowableBlock(positionSub, out block)) { state.SetCooldown(5.0); } else { bool found = false; for (int i = 0; i < stages.Length; i++) { if (stages[i] == type) { ItemTypesServer.OnChange(positionSub, 0, type, null); state.SetIndicator(new Shared.IndicatorState(2f, type)); state.SetCooldown(0.2); found = true; break; } } if (!found) { state.SetCooldown(5.0); } } } } else { state.SetCooldown(Random.NextFloat(3f, 6f)); } positionSub = Vector3Int.invalidPos; } else { state.SetCooldown(10.0); } }
public override void OnNPCAtJob(IAreaJob job, ref Vector3Int positionSub, ref NPCBase.NPCState state, ref bool shouldDumpInventory) { state.JobIsDone = true; Vector3Int min = job.Minimum; Vector3Int max = job.Maximum; if (positionSub.x == min.x || positionSub.x == max.x || positionSub.z == min.z || positionSub.z == max.z || (positionSub.x - (min.x + 1)) % 3 != 0 || (positionSub.z - (min.z + 1)) % 3 != 0) { ushort type; if (World.TryGetTypeAt(positionSub.Add(1, 0, 1), out type)) { if (type == BuiltinBlocks.Sapling) { Server.GrowableBlocks.IGrowableBlock block; if (Server.GrowableBlocks.GrowableBlockManager.TryGetGrowableBlock(positionSub.Add(1, 0, 1), out block)) { state.SetCooldown(5.0); } else { ItemTypesServer.OnChange(positionSub.Add(1, 0, 1), 0, BuiltinBlocks.Sapling, null); state.SetIndicator(NPCIndicatorType.Crafted, 2f, BuiltinBlocks.Sapling); state.SetCooldown(0.2); } } } } else if (positionSub.IsValid) { ushort type; if (World.TryGetTypeAt(positionSub, out type)) { if (type == 0) { if (job.UsedNPC.Inventory.TryGetOneItem(BuiltinBlocks.Sapling) || job.UsedNPC.Colony.UsedStockpile.TryRemove(BuiltinBlocks.Sapling)) { ServerManager.TryChangeBlock(positionSub, BuiltinBlocks.Sapling, ServerManager.SetBlockFlags.DefaultAudio); state.SetCooldown(2.0); } else { state.SetIndicator(NPCIndicatorType.MissingItem, 2f, BuiltinBlocks.Sapling); } } else if (type == BuiltinBlocks.LogTemperate) { if (ChopTree(positionSub)) { state.SetIndicator(NPCIndicatorType.Crafted, 10f, BuiltinBlocks.LogTemperate); ServerManager.SendAudio(positionSub.Vector, "woodDeleteHeavy"); AddResults(job.UsedNPC.Inventory); } else { state.SetCooldown(Random.NextFloat(3f, 6f)); } } else { state.SetCooldown(Random.NextFloat(8f, 16f)); } } else { state.SetCooldown(Random.NextFloat(3f, 6f)); } } else { state.SetCooldown(10.0); } positionSub = Vector3Int.invalidPos; }
public override void OnRemove(IAreaJob job) { SetLayer(job.Minimum, job.Maximum, BuiltinBlocks.GrassTemperate, -1); }
public override void CalculateSubPosition(IAreaJob rawJob, ref Vector3Int positionSub) { if (rawJob != null) { AppleFarmerJob job = (AppleFarmerJob)rawJob; Vector3Int min = job.Minimum; Vector3Int max = job.Maximum; Logger.Log("Min/Max {0}/{1}", job.Minimum, job.Maximum); Logger.Log("Saplings available {0}", job.NPC.Colony.UsedStockpile.Contains(saplingIndex)); if (job.checkMissingBushes && job.NPC.Colony.UsedStockpile.Contains(saplingIndex)) { // remove legacy positions for (int x = min.x + 1; x <= max.x; x += 3) { for (int z = min.z; z <= max.z; z += 3) { ushort type; Vector3Int possiblePositionSub = new Vector3Int(x, min.y, z); if (!World.TryGetTypeAt(possiblePositionSub, out type)) { return; } if (type == leaveIndex) { job.removingOldBush = true; job.bushLocation = possiblePositionSub; positionSub = Server.AI.AIManager.ClosestPosition(job.bushLocation, job.NPC.Position); return; } } } // place new positions for (int x = min.x; x <= max.x; x += 3) { for (int z = min.z; z <= max.z; z += 3) { ushort type; Vector3Int possiblePositionSub = new Vector3Int(x, min.y, z); if (!World.TryGetTypeAt(possiblePositionSub, out type)) { return; } if (type == 0) { job.placingMissingBush = true; job.bushLocation = possiblePositionSub; positionSub = Server.AI.AIManager.ClosestPositionNotAt(job.bushLocation, job.NPC.Position); return; } } } job.checkMissingBushes = false; } positionSub = min; positionSub.x += Random.Next(0, (max.x - min.x) / 3 + 1) * 3; positionSub.z += Random.Next(0, (max.z - min.z) / 3 + 1) * 3; } else { Logger.Log("rawJob equals null"); } }
public override void OnNPCAtJob(IAreaJob rawJob, ref Vector3Int positionSub, ref NPCBase.NPCState state, ref bool shouldDumpInventory) { AppleFarmerJob job = (AppleFarmerJob)rawJob; state.JobIsDone = true; if (positionSub.IsValid) { ushort type; if (job.placingMissingBush) { if (job.NPC.Colony.UsedStockpile.TryRemove(saplingIndex)) { job.placingMissingBush = false; ServerManager.TryChangeBlock(job.bushLocation, saplingIndex, rawJob.Owner, ServerManager.SetBlockFlags.DefaultAudio); state.SetCooldown(2.0); } else { state.SetIndicator(new Shared.IndicatorState(Random.NextFloat(8f, 14f), saplingIndex, true, false)); } } else if (job.removingOldBush) { if (ServerManager.TryChangeBlock(job.bushLocation, 0, rawJob.Owner, ServerManager.SetBlockFlags.DefaultAudio)) { job.NPC.Colony.UsedStockpile.Add(saplingIndex); job.removingOldBush = false; } state.SetCooldown(2.0); } else if (World.TryGetTypeAt(positionSub, out type)) { if (type == 0) { job.checkMissingBushes = true; state.SetCooldown(1.0, 4.0); } else if (World.TryGetTypeAt(positionSub.Add(0, 3, 0), out type) && type == leaveIndex) { GatherResults.Clear(); GatherResults.Add(new ItemTypes.ItemTypeDrops(fruitIndex, 1, 1.0)); GatherResults.Add(new ItemTypes.ItemTypeDrops(saplingIndex, 1, 0.1)); ModLoader.TriggerCallbacks(ModLoader.EModCallbackType.OnNPCGathered, rawJob as IJob, positionSub, GatherResults); InventoryItem toShow = ItemTypes.ItemTypeDrops.GetWeightedRandom(GatherResults); if (toShow.Amount > 0) { state.SetIndicator(new Shared.IndicatorState(8.5f, toShow.Type)); } else { state.SetCooldown(8.5); } job.NPC.Inventory.Add(GatherResults); } else { state.SetIndicator(new Shared.IndicatorState(Random.NextFloat(8f, 14f), BuiltinBlocks.ErrorMissing)); } } else { state.SetCooldown(Random.NextFloat(3f, 6f)); } positionSub = Vector3Int.invalidPos; } else { state.SetCooldown(10.0); } }
public void DoJob(IIterationType iterationType, IAreaJob areaJob, ConstructionJobInstance job, ref NPCBase.NPCState state) { int i = 0; var bpi = iterationType as SchematicIterator; if (bpi == null) { SettlersLogger.Log(ChatColor.yellow, "iterationType must be of type SchematicIterator for the SchematicBuilder."); state.SetIndicator(new Shared.IndicatorState(5f, ColonyBuiltIn.ItemTypes.ERRORIDLE.Name)); AreaJobTracker.RemoveJob(areaJob); return; } while (true) // This is to move past air. { if (i > 4000) { break; } var adjX = iterationType.CurrentPosition.x - bpi.BuilderSchematic.StartPos.x; var adjY = iterationType.CurrentPosition.y - bpi.BuilderSchematic.StartPos.y; var adjZ = iterationType.CurrentPosition.z - bpi.BuilderSchematic.StartPos.z; var block = bpi.BuilderSchematic.GetBlock(adjX, adjY, adjZ); var mapped = block.MappedBlock; var buildType = ItemTypes.GetType(mapped.CSIndex); if (buildType == null) { state.SetIndicator(new Shared.IndicatorState(5f, ColonyBuiltIn.ItemTypes.ERRORIDLE.Name)); AreaJobTracker.RemoveJob(areaJob); return; } if (World.TryGetTypeAt(iterationType.CurrentPosition, out ushort foundTypeIndex)) { i++; var founditemId = ItemId.GetItemId(foundTypeIndex); if (foundTypeIndex == buildType.ItemIndex || buildType.Name.Contains("bedend") || (founditemId.Name.Contains("bedend") && buildType.ItemIndex == ColonyBuiltIn.ItemTypes.AIR)) // check if the blocks are the same, if they are, move past. Most of the time this will be air. { if (iterationType.MoveNext()) { continue; } else { if (_needsChunkLoaded.Contains(bpi)) { _needsChunkLoaded.Remove(bpi); } state.SetIndicator(new Shared.IndicatorState(5f, ColonyBuiltIn.ItemTypes.ERRORIDLE.Name)); AreaJobTracker.RemoveJob(areaJob); return; } } Stockpile ownerStockPile = areaJob.Owner.Stockpile; bool stockpileContainsBuildItem = buildType.ItemIndex == ColonyBuiltIn.ItemTypes.AIR.Id; if (!stockpileContainsBuildItem && ownerStockPile.Contains(buildType.ItemIndex)) { stockpileContainsBuildItem = true; } if (!stockpileContainsBuildItem && buildType.Name.Contains("bed") && ownerStockPile.Contains(ItemId.GetItemId("bed"))) { stockpileContainsBuildItem = true; } if (!stockpileContainsBuildItem && !string.IsNullOrWhiteSpace(buildType.ParentType) && ownerStockPile.Contains(buildType.ParentItemType.ItemIndex)) { stockpileContainsBuildItem = true; } if (stockpileContainsBuildItem) { if (foundTypeIndex != ColonyBuiltIn.ItemTypes.AIR.Id && foundTypeIndex != ColonyBuiltIn.ItemTypes.WATER.Id) { var foundItem = ItemTypes.GetType(foundTypeIndex); if (foundItem != null && foundItem.ItemIndex != ColonyBuiltIn.ItemTypes.AIR.Id && foundItem.OnRemoveItems != null && foundItem.OnRemoveItems.Count > 0) { ownerStockPile.Add(foundItem.OnRemoveItems.Select(itm => itm.item).ToList()); } } var changeResult = ServerManager.TryChangeBlock(iterationType.CurrentPosition, buildType.ItemIndex, new BlockChangeRequestOrigin(job.Owner), ESetBlockFlags.DefaultAudio); if (changeResult == EServerChangeBlockResult.Success) { if (buildType.ItemIndex != ColonyBuiltIn.ItemTypes.AIR.Id) { if (--job.StoredItemCount <= 0) { job.ShouldTakeItems = true; state.JobIsDone = true; } ownerStockPile.TryRemove(buildType.ItemIndex); if (buildType.Name.Contains("bed")) { ownerStockPile.TryRemove(ItemId.GetItemId("bed")); } } } else if (changeResult != EServerChangeBlockResult.CancelledByCallback) { if (!_needsChunkLoaded.Contains(bpi)) { _needsChunkLoaded.Add(bpi); } state.SetIndicator(new Shared.IndicatorState(5f, buildType.Name)); ChunkQueue.QueuePlayerSurrounding(iterationType.CurrentPosition.ToChunk()); return; } } else { state.SetIndicator(new Shared.IndicatorState(5f, buildType.Name, true, false)); return; } } else { if (!_needsChunkLoaded.Contains(bpi)) { _needsChunkLoaded.Add(bpi); } ChunkQueue.QueuePlayerSurrounding(iterationType.CurrentPosition.ToChunk()); state.SetIndicator(new Shared.IndicatorState(5f, ColonyBuiltIn.ItemTypes.ERRORIDLE.Name)); return; } if (iterationType.MoveNext()) { if (buildType.ItemIndex != ColonyBuiltIn.ItemTypes.AIR.Id) { state.SetIndicator(new Shared.IndicatorState(GetCooldown(), buildType.ItemIndex)); } else { state.SetIndicator(new Shared.IndicatorState(GetCooldown(), foundTypeIndex)); } return; } else { if (_needsChunkLoaded.Contains(bpi)) { _needsChunkLoaded.Remove(bpi); } // failed to find next position to do job at, self-destruct state.SetIndicator(new Shared.IndicatorState(5f, ColonyBuiltIn.ItemTypes.ERRORIDLE.Name)); AreaJobTracker.RemoveJob(areaJob); return; } } if (iterationType.MoveNext()) { state.SetIndicator(new Shared.IndicatorState(5f, ColonyBuiltIn.ItemTypes.ERRORIDLE.Name)); return; } else { if (_needsChunkLoaded.Contains(bpi)) { _needsChunkLoaded.Remove(bpi); } // failed to find next position to do job at, self-destruct state.SetIndicator(new Shared.IndicatorState(5f, ColonyBuiltIn.ItemTypes.ERRORIDLE.Name)); AreaJobTracker.RemoveJob(areaJob); SettlersLogger.Log(ChatColor.yellow, "Failed to MoveNext after while. Iterator position: {0}.", iterationType.CurrentPosition); return; } }
public void DoJob(IIterationType iterationType, IAreaJob areaJob, ConstructionJobInstance job, ref NPC.NPCBase.NPCState state) { if (iterationType == null) { AreaJobTracker.RemoveJob(areaJob); return; } int iMax = 4096; while (iMax-- > 0) { Vector3Int jobPosition = iterationType.CurrentPosition; if (!jobPosition.IsValid) { // failed to find next position to do job at, self-destruct state.SetIndicator(new Shared.IndicatorState(5f, BuiltinBlocks.Indices.erroridle)); AreaJobTracker.RemoveJob(areaJob); return; } ushort foundTypeIndex; if (World.TryGetTypeAt(jobPosition, out foundTypeIndex)) { iterationType.MoveNext(); if (foundTypeIndex != 0) { ItemTypes.ItemType foundType = ItemTypes.GetType(foundTypeIndex); if (!foundType.IsDestructible) { continue; // skip this block, retry } if (ServerManager.TryChangeBlock(jobPosition, foundTypeIndex, 0, areaJob.Owner, ESetBlockFlags.DefaultAudio) == EServerChangeBlockResult.Success) { float blockDestructionTime = GetCooldown(foundType.DestructionTime * 0.001f); GatherResults.Clear(); var itemList = foundType.OnRemoveItems; for (int i = 0; i < itemList.Count; i++) { GatherResults.Add(itemList[i]); } ModLoader.Callbacks.OnNPCGathered.Invoke(job, jobPosition, GatherResults); InventoryItem toShow = ItemTypes.ItemTypeDrops.GetWeightedRandom(GatherResults); if (toShow.Amount > 0) { state.SetIndicator(new Shared.IndicatorState(blockDestructionTime, toShow.Type)); } else { state.SetCooldown(blockDestructionTime); } state.Inventory.Add(GatherResults); job.StoredItemCount++; if (job.StoredItemCount >= MaxGatheredPerRun) { job.ShouldTakeItems = true; state.JobIsDone = true; } } else { state.SetIndicator(new Shared.IndicatorState(5f, BuiltinBlocks.Indices.missingerror, true, false)); } return; // either changed a block or set indicator, job done } else { continue; // found air, try next loop } // unreachable } else { state.SetIndicator(new Shared.IndicatorState(5f, BuiltinBlocks.Indices.missingerror, true, false)); return; // end loop, wait for world to load } // unreachable } // reached loop count limit Assert.IsTrue(iMax <= 0); state.SetCooldown(1.0); }
public override void OnNPCAtJob(IAreaJob rawJob, ref Vector3Int positionSub, ref NPCBase.NPCState state, ref bool shouldDumpInventory) { BerryFarmerJob job = (BerryFarmerJob)rawJob; state.JobIsDone = true; if (positionSub.IsValid) { ushort type; if (job.placingMissingBush) { if (job.UsedNPC.Colony.UsedStockpile.TryRemove(BuiltinBlocks.BerryBush)) { job.placingMissingBush = false; ServerManager.TryChangeBlock(job.bushLocation, BuiltinBlocks.BerryBush, rawJob.Owner, ServerManager.SetBlockFlags.DefaultAudio); state.SetCooldown(2.0); } else { state.SetIndicator(new Shared.IndicatorState(Random.NextFloat(8f, 14f), BuiltinBlocks.BerryBush, true, false)); } } else if (job.removingOldBush) { if (ServerManager.TryChangeBlock(job.bushLocation, 0, rawJob.Owner, ServerManager.SetBlockFlags.DefaultAudio)) { job.UsedNPC.Colony.UsedStockpile.Add(BuiltinBlocks.BerryBush); job.removingOldBush = false; } state.SetCooldown(2.0); } else if (World.TryGetTypeAt(positionSub, out type)) { if (type == 0) { job.checkMissingBushes = true; state.SetCooldown(1.0, 4.0); } else if (type == BuiltinBlocks.BerryBush) { state.SetIndicator(new Shared.IndicatorState(8.5f, BuiltinBlocks.Berry)); NPCInventory inv = job.UsedNPC.Inventory; inv.Add(BuiltinBlocks.Berry); if (Random.Next(0, 10) >= 9) { inv.Add(BuiltinBlocks.BerryBush); } } else { state.SetIndicator(new Shared.IndicatorState(Random.NextFloat(8f, 14f), BuiltinBlocks.ErrorMissing)); } } else { state.SetCooldown(Random.NextFloat(3f, 6f)); } positionSub = Vector3Int.invalidPos; } else { state.SetCooldown(10.0); } }
public void DoJob(IIterationType iterationType, IAreaJob areaJob, ConstructionJobInstance job, ref NPCBase.NPCState state) { int i = 0; var bpi = iterationType as ArchitectIterator; if (bpi == null) { SettlersLogger.Log(ChatColor.yellow, "iterationType must be of type ArchitectIterator for the ArchitectBuilder."); state.SetIndicator(new Shared.IndicatorState(5f, ColonyBuiltIn.ItemTypes.ERRORIDLE.Name)); AreaJobTracker.RemoveJob(areaJob); return; } while (true) // move past air { if (i > 4000) { break; } i++; var adjX = iterationType.CurrentPosition.x - bpi.BuilderSchematic.StartPos.x; var adjY = iterationType.CurrentPosition.y - bpi.BuilderSchematic.StartPos.y; var adjZ = iterationType.CurrentPosition.z - bpi.BuilderSchematic.StartPos.z; var prvX = bpi.PreviousPosition.x - bpi.BuilderSchematic.StartPos.x; var prvY = bpi.PreviousPosition.y - bpi.BuilderSchematic.StartPos.y; var prvZ = bpi.PreviousPosition.z - bpi.BuilderSchematic.StartPos.z; if (World.TryGetTypeAt(iterationType.CurrentPosition, out ItemTypes.ItemType foundType)) { state.SetCooldown(2); state.SetIndicator(new Shared.IndicatorState(2, foundType.Name)); if (foundType.ItemIndex == ColonyBuiltIn.ItemTypes.AIR || foundType.Name == ColonyBuiltIn.ItemTypes.BANNER) { if (!MoveNext(iterationType, areaJob, job, bpi, prvX, prvY, prvZ)) { return; } continue; } try { bpi.BuilderSchematic.Blocks[adjX, adjY, adjZ].BlockID = foundType.Name; } catch (IndexOutOfRangeException) { SettlersLogger.Log(ChatColor.red, $"Index out of range on ArchitectBuilder {adjX}, {adjY}, {adjZ} to a max of {bpi.BuilderSchematic.Blocks.GetLength(0)}, {bpi.BuilderSchematic.Blocks.GetLength(1)}, {bpi.BuilderSchematic.Blocks.GetLength(2)}."); CleanupJob(iterationType, areaJob, job, bpi, prvX, prvY, prvZ); break; } if (!foundType.Name.Contains("bedend")) { ServerManager.TryChangeBlock(iterationType.CurrentPosition, SettlersBuiltIn.ItemTypes.SELECTOR.Id, new BlockChangeRequestOrigin(job.Owner), ESetBlockFlags.DefaultAudio); } MoveNext(iterationType, areaJob, job, bpi, prvX, prvY, prvZ); } else { if (!_needsChunkLoaded.Contains(bpi)) { _needsChunkLoaded.Add(bpi); } ChunkQueue.QueuePlayerSurrounding(iterationType.CurrentPosition.ToChunk()); state.SetIndicator(new Shared.IndicatorState(5f, ColonyBuiltIn.ItemTypes.ERRORIDLE.Name)); } break; } }
public virtual void CalculateSubPosition(IAreaJob job, ref Vector3Int positionSub) { }
public virtual void OnNPCAtJob(IAreaJob job, ref Vector3Int positionSub, ref NPCBase.NPCState state, ref bool shouldDumpInventory) { }
public override void OnNPCAtJob(IAreaJob job, ref Vector3Int positionSub, ref NPCBase.NPCState state, ref bool shouldDumpInventory) { state.JobIsDone = true; Vector3Int min = job.Minimum; Vector3Int max = job.Maximum; if (positionSub.x == min.x || positionSub.x == max.x || positionSub.z == min.z || positionSub.z == max.z || (positionSub.x - (min.x + 1)) % 3 != 0 || (positionSub.z - (min.z + 1)) % 3 != 0) { ushort type; if (World.TryGetTypeAt(positionSub.Add(1, 0, 1), out type)) { if (type == BuiltinBlocks.Sapling) { Server.GrowableBlocks.IGrowableBlock block; if (Server.GrowableBlocks.GrowableBlockManager.TryGetGrowableBlock(positionSub.Add(1, 0, 1), out block)) { state.SetCooldown(5.0); } else { ItemTypesServer.OnChange(positionSub.Add(1, 0, 1), 0, BuiltinBlocks.Sapling, null); state.SetIndicator(new Shared.IndicatorState(2f, BuiltinBlocks.Sapling)); state.SetCooldown(0.2); } } else { state.SetCooldown(1.0); // no sapling at sapling spot (shouldn't occur a lot, something changed between calculate sub position and this } } else { state.SetCooldown(4.0); // walked to sapling spot, not loaded } } else if (positionSub.IsValid) { ushort type; if (World.TryGetTypeAt(positionSub, out type)) { if (type == 0) { if (job.NPC.Inventory.TryGetOneItem(BuiltinBlocks.Sapling) || job.NPC.Colony.UsedStockpile.TryRemove(BuiltinBlocks.Sapling)) { ServerManager.TryChangeBlock(positionSub, BuiltinBlocks.Sapling, job.Owner, ServerManager.SetBlockFlags.DefaultAudio); state.SetCooldown(2.0); } else { state.SetIndicator(new Shared.IndicatorState(2f, BuiltinBlocks.Sapling)); } } else if (type == BuiltinBlocks.LogTemperate) { if (ChopTree(positionSub, job.Owner)) { state.SetIndicator(new Shared.IndicatorState(10f, BuiltinBlocks.LogTemperate)); ServerManager.SendAudio(positionSub.Vector, "woodDeleteHeavy"); GatherResults.Clear(); GatherResults.Add(new ItemTypes.ItemTypeDrops(BuiltinBlocks.LogTemperate, 3, 1.0)); GatherResults.Add(new ItemTypes.ItemTypeDrops(BuiltinBlocks.LeavesTemperate, 9, 1.0)); GatherResults.Add(new ItemTypes.ItemTypeDrops(BuiltinBlocks.Sapling, 1, 1.0)); GatherResults.Add(new ItemTypes.ItemTypeDrops(BuiltinBlocks.Sapling, 1, 0.25)); ModLoader.TriggerCallbacks(ModLoader.EModCallbackType.OnNPCGathered, job as IJob, positionSub, GatherResults); job.NPC.Inventory.Add(GatherResults); } else { state.SetCooldown(Random.NextFloat(3f, 6f)); } } else { state.SetCooldown(Random.NextFloat(8f, 16f)); } } else { state.SetCooldown(Random.NextFloat(3f, 6f)); } } else { state.SetCooldown(10.0); } positionSub = Vector3Int.invalidPos; }
static void Postfix(BuilderBasic __instance, IIterationType iterationType, IAreaJob areaJob, ConstructionJobInstance job, ref NPCBase.NPCState state) { // Log.WriteWarning("BuilderBasicHookDoJob::Postfix"); npc = null; }
static void Postfix(BuilderBasic __instance, IIterationType iterationType, IAreaJob areaJob, ConstructionJobInstance job, ref NPCBase.NPCState state) { DebugLog.Write(MethodBase.GetCurrentMethod().DeclaringType + "::" + MethodBase.GetCurrentMethod().Name); npc = null; }