Extending the Machinist Job to do more like become an animal farmer - JBurlison/Pandaros.API GitHub Wiki
You can Extend the roaming job to look like anything you want really! For this example we will use an animal farmer. The first step we need to do is create the job block. In settlers we have a base CSType that has all of a items virtual properties. We override the properties we are going to use in our item. Dont worry about registering the item or anything, settlers uses reflection to find all items by inheritance and will handle all the registering for you.
public class AnimalDudeJobType : CSType
{
public override string name => "AnimalDudeWorkbench";
public override string icon => "*YOUR ICON PATH HERE*/AnimalDudeWorkbench.png";
public override string onPlaceAudio => "stonePlace";
public override string onRemoveAudio => "stoneDelete";
public override string sideall => "stonebricks"; // texture of your block maybe add a mesh property if you have a custom mesh!
public override List<string> categories => new List<string>() { "job" }; // whatever you want really
}
Add the texture for your item!
public class AnimalDudeTexture : CSTextureMapping
{
public const string NAME = "AnimalDudeWorkbench";
public override string name => NAME;
public override string albedo => "*YOUR albedo PATH HERE*/AnimalDudeWorkbench.png";
public override string normal => "*YOUR normal PATH HERE*/AnimalDudeWorkbench.png";
public override string height => "*YOUR height PATH HERE*/AnimalDudeWorkbench.png";
}
Add a recipe! Like adding a item to the game, this is done by simply implementing the ICSRecipie interface. Hint: Settlers also has all of the items in settlers and colony survival in its ColonyBuiltIn and SettlersBuiltin classes
public class MachinistRecipe : ICSRecipe
{
public string name => "AnimalDudeWorkbench";
public List<RecipeItem> requires => new List<RecipeItem>()
{
{ new RecipeItem(ColonyBuiltIn.ItemTypes.BRONZEINGOT.Name, 2) },
{ new RecipeItem(ColonyBuiltIn.ItemTypes.IRONWROUGHT.Name, 2) },
{ new RecipeItem(ColonyBuiltIn.ItemTypes.COPPERTOOLS.Name, 1) },
{ new RecipeItem(ColonyBuiltIn.ItemTypes.STONEBRICKS.Name, 4) }
};
public List<RecipeItem> results => new List<RecipeItem>()
{
{ new RecipeItem("AnimalDudeWorkbench", 1) }
};
public CraftPriority defaultPriority => CraftPriority.Medium;
public bool isOptional => false;
public int defaultLimit => 2;
public string Job => "crafter";
}
Create the job settings:
public class AnimalGuySettings : IBlockJobSettings
{
static NPCType _Settings;
public virtual float NPCShopGameHourMinimum { get { return TimeCycle.Settings.SleepTimeEnd; } }
public virtual float NPCShopGameHourMaximum { get { return TimeCycle.Settings.SleepTimeStart; } }
static AnimalGuySettings()
{
NPCType.AddSettings(new NPCTypeStandardSettings
{
keyName = "MyDomain.AnimalDude",
printName = "AnimalDude",
maskColor1 = new Color32(242, 132, 29, 255),
type = NPCTypeID.GetNextID(),
inventoryCapacity = 1f
});
_Settings = NPCType.GetByKeyNameOrDefault("MyDomain.AnimalDude");
}
public virtual ItemTypes.ItemType[] BlockTypes => new[]
{
ItemTypes.GetType("AnimalDudesWorkbench") // the block type placed
};
public NPCType NPCType => _Settings;
public virtual InventoryItem RecruitmentItem => new InventoryItem("coppertools");
public virtual bool ToSleep => !TimeCycle.IsDay;
public Pipliz.Vector3Int GetJobLocation(BlockJobInstance instance)
{
if (instance is RoamingJob roamingJob)
return roamingJob.OriginalPosition;
return Pipliz.Vector3Int.invalidPos;
}
public void OnGoalChanged(BlockJobInstance instance, NPCBase.NPCGoal goalOld, NPCBase.NPCGoal goalNew)
{
}
public void OnNPCAtJob(BlockJobInstance instance, ref NPCBase.NPCState state)
{
instance.OnNPCAtJob(ref state);
}
public void OnNPCAtStockpile(BlockJobInstance instance, ref NPCBase.NPCState state)
{
}
}
Add your job!
public class AnimalDude: RoamingJob
{
public static string JOB_NAME = "AnimalDude";
public static string JOB_ITEM_KEY = "AnimalDudeWorkbench";
public static string JOB_RECIPE = "AnimalDudeWorkbench";
public AnimalDude(IBlockJobSettings settings, Pipliz.Vector3Int position, ItemTypes.ItemType type, ByteReader reader) :
base(settings, position, type, reader)
{
}
public AnimalDude(IBlockJobSettings settings, Pipliz.Vector3Int position, ItemTypes.ItemType type, Colony colony) :
base(settings, position, type, colony)
{
}
public override List<string> ObjectiveCategories => new List<string>() { "Animals" };
public override string JobItemKey => JOB_ITEM_KEY;
public override List<ItemId> OkStatus => new List<ItemId>
{
ItemId.GetItemId(NAMESPACE + ".Refuel"),
ItemId.GetItemId(NAMESPACE + ".Reload"),
ItemId.GetItemId(NAMESPACE + ".Repairing"),
ItemId.GetItemId(NAMESPACE + ".Waiting")
};
}
Side Note: Adding status'. A status can be added with a new item:
public class RepairingIcon : CSType
{
public override string name { get; set; } = NAMESPACE + "Repairing";
public override string icon { get; set; } = ICON_PATH + "Repairing.png";
}
Register the job with colony survivals entity manager
[ModLoader.ModCallback(ModLoader.EModCallbackType.AfterItemTypesDefined, NAMESPACE + ".AnimalDude")]
[ModLoader.ModCallbackProvidesFor("create_savemanager")]
public static void AfterDefiningNPCTypes()
{
ServerManager.BlockEntityCallbacks.RegisterEntityManager(
new BlockJobManager<AnimalDude>(
new AnimalGuySettings(),
(setting, pos, type, bytedata) => new AnimalDude(setting, pos, type, bytedata),
(setting, pos, type, colony) => new AnimalDude(setting, pos, type, colony)
)
);
Use the adding objectives page to create your farm and make sure you set your ObjectiveCategory types up properly so your farmer knows to go to them!