Template_Livestock
Server/NPC/Roles/_Core/Templates/Template_Livestock.json, 79.4 KB
Fields
| Field | Type |
|---|---|
Type | string |
StartState | string |
Parameters | object |
IsMemory | object |
MemoriesCategory | object |
MemoriesNameOverride | object |
DropList | object |
FlockSpawnTypes | object |
FlockSpawnTypesRandom | boolean |
DisableDamageGroups | array[1] |
Appearance | object |
DefaultPlayerAttitude | object |
DefaultNPCAttitude | string |
AttitudeGroup | object |
ApplySeparation | boolean |
SeparationDistance | object |
SeparationWeight | number |
SeparationDistanceTarget | object |
SeparationNearRadiusTarget | number |
SeparationFarRadiusTarget | number |
BreathesInWater | object |
KnockbackScale | number |
DeathParticles | object |
DropDeathItemsInstantly | object |
DeathAnimationTime | object |
MotionControllerList | array[1] |
StateTransitions | array[5] |
MaxHealth | object |
InteractionVars | object |
Instructions | array[6] |
InteractionInstruction | object |
NameTranslationKey | object |
Source
{
"Type": "Abstract",
"StartState": "Idle",
"Parameters": {
"Appearance": {
"Value": "Deer_Stag",
"Description": "The NPC's model."
},
"ParticleOffset": {
"Value": [ 0, 1, 0 ],
"Description": "The offset of any spawned particle systems."
},
"SeparationDistance": {
"Value": 1,
"Description": "The separation distance between this and other NPCs."
},
"WanderRadius": {
"Value": 7,
"Description": "The wander radius of the NPC."
},
"ViewRange": {
"Value": 16,
"Description": "The view distance of the NPC, in blocks."
},
"ViewSector": {
"Value": 180,
"Description": "The view sector of the NPC, in degrees."
},
"HearingRange": {
"Value": 8,
"Description": "The hearing distance of the NPC, in blocks."
},
"SmellingRange": {
"Value": 4,
"Description": "The smelling distance of the NPC, in blocks. Used to detect when an attractive item is being held nearby."
},
"AbsoluteDetectionRange": {
"Value": 4,
"Description": "The range at which a target is guaranteed to be detected, in blocks. If set to zero, absolute detection will be disabled. The interval [ AbsoluteDetectionRange, AlertedActionRange ] defines the distance range within which an NPC can be befriended."
},
"AlertedRange": {
"Value": 18,
"Description": "The range within which the target can be seen/sensed when the NPC is alerted to their presence, in blocks. Should be higher than sense ranges."
},
"AlertedActionRange": {
"Value": 6,
"Description": "The range at which an NPC will react to other NPCs and players, depending on the attitude towards them, in blocks. Should be higher than AbsoluteDetectionRange to make the NPC befriendable."
},
"DropList": {
"Value": "Empty",
"Description": "The NPC's drop list."
},
"FlockArray": {
"Value": [ ],
"TypeHint": "String",
"Description": "The set of NPCs belonging to this flock type"
},
"ClimbHeight": {
"Value": 1,
"Description": "The maximum climb height, in blocks."
},
"AttitudeGroup": {
"Value": "Prey",
"Description": "The attitude group this NPC belongs to."
},
"PlayerDefaultAttitude": {
"Value": "Revered",
"Description": "The default attitude towards the player."
},
"AlertedTimeoutGiveUp": {
"Value": [ 5, 12 ],
"Description": "The timeout after which an alerted NPC will give up on the target, in seconds."
},
"GrazingBlockSet": {
"Value": "Grass",
"Description": "The type of block that this NPC will graze on top of."
},
"DayTimePeriod": {
"Value": [ 6.01, 17.99 ],
"Description": "The hour range considered to be daytime for this NPC (inclusive). Hours should be written with decimal fractions."
},
"DayTimeNapWeight": {
"Value": 2,
"Description": "The weight used to determine if the NPC should have a short nap during the day. Set to 0 to disable."
},
"DayTimeNapTimeRange": {
"Value": [ 10, 12 ],
"Description": "The duration range of daytime naps, in seconds."
},
"DayFlavorAnimation": {
"Value": "",
"Description": "The flavor animation to play during the day. Ignored if null or empty."
},
"AttractiveItemSet": {
"Value": [ "Tool_Feedbag" ],
"Description": "The list of items that are deemed attractive (there's a chance targets holding them will be followed)."
},
"FoodBlockSet": {
"Value": "Livestock_Feeding",
"Description": "The type of block that this NPC will occasionally seek out to munch on."
},
"WeightFollowItem": {
"Value": 100,
"Description": "The probability the NPC will follow an attractive item when held by a non-hostile target, in percent."
},
"FollowItemPreDelay": {
"Value": [ 1, 2 ],
"Description": "The time delay before an NPC starts following an item."
},
"FollowItemTimeoutEnabled": {
"Value": false,
"Description": "Whether the NPC will follow an attractive item with a timeout. If set to false, make sure FollowItemTimeout is properly configured."
},
"FollowItemTimeout": {
"Value": [ 20, 40 ],
"Description": "The duration of the follow item behaviour, after which the NPC will give up on the target. Requires FollowItemTimeoutEnabled to be set to true."
},
"FollowItemDistance": {
"Value": [ 2, 2.5 ],
"Description": "The minimum distance which the NPC will retain from a target holding an attractive item."
},
"GreetAnimation": {
"Value": "Alerted",
"Description": "The flavor animation to play when greeting another NPC or player. Ignored if null or empty."
},
"GreetStateTimeout": {
"Value": [ 4, 10 ],
"Description": "The timeout after which an alerted NPC will give up on the target, in seconds."
},
"GreetTimeout": {
"Value": [ "PT2H", "PT12H" ],
"Description": "The timeout between consecutive greetings."
},
"IgnoreAttitudeOverride": {
"Value": 30,
"Description": "The attitude override after an NPC gets angry at a player."
},
"EatTimeout": {
"Value": [ "PT8H", "PT12H" ],
"Description": "The timeout between consecutive meals."
},
"IsPettable": {
"Value": true,
"Description": "Whether players can pet the NPC."
},
"PetAnimation": {
"Value": "Alerted",
"Description": "The animation the NPC will play when petted."
},
"PetRequiredAttitudes": {
"Value": [ "Friendly", "Revered" ],
"Description": "The attitude groups of players that can pet the NPC."
},
"FeedRequiredAttitudes": {
"Value": [ "Friendly", "Revered" ],
"Description": "The attitude groups of players that can feed the NPC by hand."
},
"PetTimeout": {
"Value": [ "PT15M", "PT15M" ],
"Description": "The timeout between consecutive pets."
},
"IsHarvestable": {
"Value": false,
"Description": "Whether this NPC can be 'harvested'. This includes shearing, milking, etc."
},
"HarvestInteractionContext": {
"Value": "",
"Description": "The interaction context of the harvest tool. If empty, no tool is needed to harvest the NPC."
},
"HarvestInteractionRequiredItems": {
"Value": [ ],
"TypeHint": "String",
"Description": "The collection of items that enable the harvest interaction."
},
"HarvestRequiredAttitudes": {
"Value": [ "Friendly", "Revered", "Ignore" ],
"Description": "The attitude groups of players that can harvest the NPC."
},
"HarvestDropList": {
"Value": "",
"Description": "The drop list that's executed when the NPC is harvested."
},
"HarvestParticles": {
"Value": "Alerted",
"Description": "The particle system that is spawned when the NPC is harvested."
},
"HarvestSound": {
"Value": "SFX_Sheep_Sheared",
"Description": "The sound that plays when NPC is harvested."
},
"HarvestTimeout": {
"Value": [ "P1D", "P1D" ],
"Description": "The minimum time between consecutive harvests. Expressed in the ISO-8601 time period notation, where both values of the array must have the same prefix (either 'PT' or 'P')."
},
"HarvestModelSlot": {
"Value": "",
"Description": "The model attachment slot where the 'harvested' state is displayed."
},
"HarvestModelAttachmentHarvestable": {
"Value": "",
"Description": "The attachment that should be rendered when the NPC can be harvested."
},
"HarvestModelAttachmentHarvested": {
"Value": "",
"Description": "The attachment that should be rendered when the NPC was harvested and is in timeout."
},
"HarvestAddItemBucket": {
"Value": "",
"Description": "Item to add when player holds Container_Bucket (e.g., milk bucket for milking)."
},
"HarvestAddItemDecoBucket": {
"Value": "",
"Description": "Item to add when player holds Deco_Bucket (e.g., milk bucket for milking)."
},
"ProduceItem": {
"Value": "",
"Description": "The item this NPC produces (poop, eggs, etc)."
},
"ProduceTimeout": {
"Value": [ "PT6H", "PT36H" ],
"Description": "The timeout between consecutive produces."
},
"DayFlavorAnimationLength": {
"Value": [ 3, 5 ],
"Description": "How long the daytime flavor animation will be played for, in seconds."
},
"AttackWhenStartled": {
"Value": false,
"Description": "Whether this NPC attacks when startled."
},
"Attack": {
"Value": "",
"Description": "The attack interaction this NPC will use."
},
"AttackRange": {
"Value": 5,
"Description": "The range at which the NPC can identify an attacker."
},
"MaxSpeed": {
"Value": 4,
"Description": "The maximum walking speed of the NPC."
},
"MaxHealth": {
"Value": 100,
"Description": "The maximum health of the NPC."
},
"MaxRotationSpeed": {
"Value": 360,
"Description": "The maximum rotation speed, in degrees per second."
},
"RunThreshold": {
"Value": 0.5,
"Description": "The speed ratio at which the NPC switches to run animation (e.g if MaxSpeed is 10, and RunThreshold is set to 0.55, the NPC will start running at speed 5.5)."
},
"DeathParticles": {
"Value": "Effect_Death",
"Description": "The particle system that spawns when the NPC's corpse disappears."
},
"DropDeathItemsInstantly": {
"Value": false,
"Description": "Whether the NPC's drop list should be executed when the NPC dies. If set to false, items drop when the corpse disappears."
},
"DeathAnimationTime": {
"Value": 2,
"Description": "The time it takes for this NPC's corpse to disappear."
},
"IsMemory": {
"Value": false,
"Description": "Whether the NPC is a memory."
},
"MemoriesCategory": {
"Value": "Livestock",
"Description": "The category of the memory."
},
"MemoriesNameOverride": {
"Value": "",
"Description": "If set, overrides the memory name."
},
"IsMountable": {
"Value": false,
"Description": "Whether this NPC can be mounted."
},
"MountAnchorX": {
"Value": 0
},
"MountAnchorY": {
"Value": 0
},
"MountAnchorZ": {
"Value": 0
},
"MountMovementConfig": {
"Value": "Mount"
},
"BreathesInWater": {
"Value": false,
"Description": "Whether this NPC can breathe underwater."
},
"NameTranslationKey": {
"Value": "server.npcRoles.Template.name",
"Description": "The translation key for the NPC name display"
}
},
"IsMemory": { "Compute": "IsMemory" },
"MemoriesCategory": { "Compute": "MemoriesCategory" },
"MemoriesNameOverride": { "Compute": "MemoriesNameOverride" },
"DropList": { "Compute": "DropList" },
"FlockSpawnTypes": { "Compute": "FlockArray" },
"FlockSpawnTypesRandom": true,
"DisableDamageGroups": [ "Self" ],
"Appearance": { "Compute": "Appearance" },
"DefaultPlayerAttitude": { "Compute": "PlayerDefaultAttitude" },
"DefaultNPCAttitude": "Ignore",
"AttitudeGroup": { "Compute": "AttitudeGroup" },
"ApplySeparation": true,
"SeparationDistance": { "Compute": "SeparationDistance" },
"SeparationWeight": 1,
"SeparationDistanceTarget": { "Compute": "SeparationDistance" },
"SeparationNearRadiusTarget": 2,
"SeparationFarRadiusTarget": 7,
"BreathesInWater": { "Compute": "BreathesInWater" },
"KnockbackScale": 0.5,
"DeathParticles": { "Compute": "DeathParticles" },
"DropDeathItemsInstantly": { "Compute": "DropDeathItemsInstantly" },
"DeathAnimationTime": { "Compute": "DeathAnimationTime" },
"MotionControllerList": [
{
"Type": "Walk",
"MaxWalkSpeed": { "Compute": "MaxSpeed" },
"Gravity": 15,
"MaxFallSpeed": 15,
"JumpHeight": 0.1,
"MaxRotationSpeed": { "Compute": "MaxRotationSpeed" },
"Acceleration": 100,
"RunThreshold": { "Compute": "RunThreshold" },
"DescentAnimationType": "Fall",
"DescentSteepness": 2.5,
"DescentBlending": 1,
"JumpDescentSteepness": 8,
"MaxClimbHeight": { "Compute": "ClimbHeight" },
"FenceBlockSet": "Fence"
}
],
"StateTransitions": [
{
"States": [
{
"From": [ "Idle" ],
"To": [ "Sleep" ]
}
],
"Actions": {
"Reference": "Component_ActionList_Sleep"
}
},
{
"States": [
{
"From": [ "Sleep" ],
"To": [ "Alerted", "Flee", "Idle" ]
}
],
"Actions": {
"Reference": "Component_ActionList_Wake"
}
},
{
"$Comment": "Always clear animation when moving from Alerted or Flee state.",
"States": [
{
"To": [ ],
"From": [ "Alerted", "Flee" ]
}
],
"Actions": [
{
"Type": "PlayAnimation",
"Slot": "Status"
},
{
"Type": "SetFlag",
"Name": "AnimationBlock",
"SetTo": false
}
]
},
{
"$Comment": "Always clear target and reset instructions when going back to idle.",
"States": [
{
"To": [ "Idle" ],
"From": [ ]
}
],
"Actions": [
{
"Type": "ReleaseTarget"
},
{
"Type": "ResetInstructions"
},
{
"Type": "PlayAnimation",
"Slot": "Status"
}
]
},
{
"$Comment": "Clear idle anims",
"States": [
{
"To": [ ],
"From": [ "Idle" ]
}
],
"Actions": [
{
"Type": "PlayAnimation",
"Slot": "Status"
}
]
}
],
"MaxHealth": { "Compute": "MaxHealth" },
"InteractionVars": {
"Melee_Damage": {
"Interactions": [
{
"$Comment": "Config for a successful melee hit, default values for Effects and HitShape are not overwritten here, see each NPC_ file",
"Parent": "NPC_Attack_Melee_Damage",
"DamageCalculator": {
"Type": "Absolute",
"BaseDamage": {
"Physical": 5
},
"RandomPercentageModifier": 0.1
}
}
]
}
},
"Instructions": [
{
"$Comment": "This is separate so it can run all the time regardless of the rest of the script",
"Continue": true,
"Instructions": [
{
"$Comment": "Update flock member leash positions to match the leader.",
"Enabled": { "Compute": "!isEmptyStringArray(FlockArray)" },
"Continue": true,
"Sensor": {
"Type": "And",
"Sensors": [
{
"Type": "FlockLeader"
},
{
"Type": "Self",
"Filters": [
{
"Type": "Flock",
"FlockStatus": "Follower"
}
]
}
]
},
"Actions": [
{
"Type": "Timeout",
"Delay": [ 0.5, 2 ],
"Action": {
"Type": "SetLeashPosition",
"ToTarget": true
}
}
]
},
{
"$Comment": "Join eligible flocks if not a member of a flock.",
"Enabled": { "Compute": "!isEmptyStringArray(FlockArray)" },
"Sensor": {
"Type": "Mob",
"Range": 20,
"ExcludeOwnType": false,
"LockOnTarget": true,
"Filters": [
{
"Type": "NPCGroup",
"IncludeGroups": [ "Self" ]
},
{
"Type": "Flock",
"FlockStatus": "NotMember"
}
]
},
"Actions": [
{
"Type": "JoinFlock"
}
]
}
]
},
{
"Continue": true,
"$Comment": "This is separate so it can run all the time regardless of the rest of the script, when in water go straight to panic to get out",
"Instructions": [
{
"Sensor": {
"Type": "And",
"Sensors": [
{
"Type": "InWater"
},
{
"Type": "Not",
"Sensor": {
"Type": "State",
"State": "Panic"
}
}
]
},
"Actions": [
{
"Type": "State",
"State": "Panic"
}
]
}
]
},
{
"$Comment": "If there are configured attachments for the 'harvestable' state, apply them",
"Enabled": { "Compute": "IsHarvestable" },
"Continue": true,
"Sensor": {
"Type": "Alarm",
"Name": "Harvest_Ready",
"State": "Passed",
"Clear": true
},
"Instructions": [
{
"Enabled": { "Compute": "!isEmpty(HarvestModelSlot)" },
"Actions": [
{
"Type": "ModelAttachment",
"Slot": { "Compute": "HarvestModelSlot" },
"Attachment": { "Compute": "HarvestModelAttachmentHarvestable" }
}
]
}
]
},
{
"Continue": true,
"Instructions": [
{
"$Comment": "Clear the pet alarm when it finishes",
"Enabled": { "Compute": "IsPettable" },
"Continue": true,
"Sensor": {
"Type": "Alarm",
"Name": "Pet_Ready",
"State": "Passed",
"Clear": true
},
"Actions": [
{
"Type": "Nothing"
}
]
},
{
"$Comment": "Clear the greet alarm when it finishes",
"Continue": true,
"Sensor": {
"Type": "Alarm",
"Name": "Greet_Ready",
"State": "Passed",
"Clear": true
},
"Actions": [
{
"Type": "Nothing"
}
]
},
{
"$Comment": "Clear the eat alarm when it finishes",
"Continue": true,
"Sensor": {
"Type": "Alarm",
"Name": "Eat_Ready",
"State": "Passed",
"Clear": true
},
"Actions": [
{
"Type": "Nothing"
}
]
}
]
},
{
"$Comment": "Initialize the produce alarm. This prevents NPCs from producing as soon as they spawn in",
"Enabled": { "Compute": "!isEmpty(ProduceItem)" },
"Sensor": {
"Type": "Alarm",
"Name": "Produce_Ready",
"State": "Unset"
},
"Actions": [
{
"Type": "SetAlarm",
"Name": "Produce_Ready",
"DurationRange": { "Compute": "ProduceTimeout" }
}
]
},
{
"Instructions": [
{
"Sensor": {
"Type": "State",
"State": "Idle"
},
"Instructions": [
{
"$Comment": "Switch to flee state if any flock member engages a target TODO switch to attack if you are very close and can attack? otherwise flee.",
"Enabled": { "Compute": "!isEmptyStringArray(FlockArray)" },
"Sensor": {
"Type": "Beacon",
"Message": "Flock_Attack",
"TargetSlot": "LockedTarget",
"Range": { "Compute": "HearingRange" }
},
"Actions": [
{
"Type": "State",
"State": "Alerted"
}
]
},
{
"Reference": "Component_Instruction_Damage_Check",
"Modify": {
"_ExportStates": [ "Flee.Switch", "Panic" ],
"AlertedRange": { "Compute": "AlertedRange" }
}
},
{
"$Comment": "Check if there are any potential things that can alert the NPC",
"Sensor": {
"Reference": "Component_Sensor_Standard_Detection",
"Modify": {
"ViewRange": { "Compute": "ViewRange" },
"ViewSector": { "Compute": "ViewSector" },
"HearingRange": { "Compute": "HearingRange" },
"AbsoluteDetectionRange": { "Compute": "AbsoluteDetectionRange" },
"Attitudes": [ "Hostile" ]
}
},
"Actions": [
{
"Type": "State",
"State": "Alerted"
}
]
},
{
"$Comment": "Produce an item",
"Enabled": { "Compute": "!isEmpty(ProduceItem)" },
"Sensor": {
"Type": "Alarm",
"Name": "Produce_Ready",
"State": "Passed"
},
"Actions": [
{
"Type": "DropItem",
"Item": { "Compute": "ProduceItem" },
"Distance": [ 0.8, 0.8 ],
"DropSector": [ 170, 190 ],
"Delay": [ 0, 0 ],
"ThrowSpeed": 14
},
{
"Type": "SetAlarm",
"Name": "Produce_Ready",
"DurationRange": { "Compute": "ProduceTimeout" }
}
]
},
{
"$Comment": "If the target is holding a liked item, follow it",
"Enabled": { "Compute": "!isEmptyStringArray(AttractiveItemSet)" },
"Continue": true,
"Sensor": {
"Type": "And",
"Sensors": [
{
"Reference": "Component_Sensor_Standard_Detection",
"Modify": {
"ViewRange": { "Compute": "ViewRange" },
"ViewSector": { "Compute": "ViewSector" },
"HearingRange": { "Compute": "SmellingRange" },
"AbsoluteDetectionRange": { "Compute": "AbsoluteDetectionRange" },
"Attitudes": [ "Revered", "Friendly" ]
}
}
]
},
"Instructions": [
{
"Sensor": {
"Type": "Target",
"Filters": [
{
"Type": "ItemInHand",
"Items": { "Compute": "AttractiveItemSet" }
},
{
"Type": "Attitude",
"Attitudes": [ "Revered", "Friendly" ]
}
]
},
"Type": "Random",
"ExecuteFor": [ 15, 20 ],
"Instructions": [
{
"Weight": { "Compute": "WeightFollowItem" },
"Sensor": {
"Type": "Target"
},
"HeadMotion": {
"Type": "Watch"
},
"BodyMotion": {
"Type": "MatchLook"
},
"ActionsBlocking": true,
"Actions": [
{
"Type": "PlayAnimation",
"Slot": "Status",
"Animation": "Alerted"
},
{
"Type": "SpawnParticles",
"ParticleSystem": "Hearts_Subtle",
"Offset": { "Compute": "ParticleOffset" },
"TargetNodeName": "Head"
},
{
"Type": "Timeout",
"Delay": { "Compute": "FollowItemPreDelay" }
},
{
"Type": "State",
"State": "SeekFood"
}
]
},
{
"Enabled": { "Compute": "WeightFollowItem < 100" },
"Weight": { "Compute": "100 - WeightFollowItem" },
"Sensor": {
"Type": "Target"
},
"ActionsBlocking": true,
"Actions": [
{
"Type": "Nothing"
}
]
}
]
}
]
},
{
"Sensor": {
"Type": "State",
"State": ".EatFromBlock"
},
"Instructions": [
{
"Sensor": {
"Type": "Block",
"Range": 2,
"MaxHeight": 4,
"Blocks": { "Compute": "FoodBlockSet" },
"Random": true
},
"HeadMotion": {
"Type": "Aim"
},
"BodyMotion": {
"Type": "MatchLook"
},
"ActionsBlocking": true,
"Actions": [
{
"Type": "PlayAnimation",
"Slot": "Status",
"Animation": "Eat"
},
{
"Type": "Timeout",
"Delay": [ 4, 6 ]
},
{
"Type": "ResetBlockSensors"
},
{
"Type": "State",
"State": "SeekFood.Ate"
}
]
},
{
"Sensor": {
"Type": "Block",
"Range": { "Compute": "ViewRange" },
"MaxHeight": 4,
"Blocks": { "Compute": "FoodBlockSet" },
"Random": true
},
"BodyMotion": {
"Type": "Seek",
"RelativeSpeed": 0.6,
"StopDistance": 0.5,
"RelaxedMoveConstraints": false
},
"HeadMotion": {
"Type": "Watch"
}
},
{
"Sensor": {
"Type": "Any"
},
"ActionsBlocking": true,
"Actions": [
{
"Type": "PlayAnimation",
"Slot": "Status"
},
{
"Type": "Timeout",
"Delay": [ 2, 4 ]
},
{
"Type": "ResetBlockSensors"
},
{
"Type": "State",
"State": ".Default"
}
]
}
]
},
{
"$Comment": "Execute daytime idle behaviors.",
"Type": "Random",
"ExecuteFor": [ 20, 30 ],
"Sensor": {
"Type": "Time",
"Period": { "Compute": "DayTimePeriod" },
"CheckDay": true
},
"Instructions": [
{
"Weight": 20,
"Instructions": [
{
"$Comment": "Check if there are any surrounding players to greet",
"Sensor": {
"Type": "And",
"Sensors": [
{
"Reference": "Component_Sensor_Standard_Detection",
"Modify": {
"ViewRange": { "Compute": "ViewRange" },
"ViewSector": { "Compute": "ViewSector" },
"HearingRange": { "Compute": "HearingRange" },
"AbsoluteDetectionRange": { "Compute": "AbsoluteDetectionRange" },
"Attitudes": [ "Revered", "Friendly" ]
}
},
{
"Type": "Alarm",
"Name": "Greet_Ready",
"State": "Unset"
}
]
},
"Actions": [
{
"Type": "State",
"State": "Greet"
}
]
},
{
"$Comment": "No nearby players to greet or greet alarm hasn't finished",
"Actions": [
{
"Type": "ResetInstructions"
},
{
"Type": "State",
"State": ".Default"
}
]
}
]
},
{
"$Comment": "Regular wander.",
"Weight": 20,
"Instructions": [
{
"Continue": true,
"Actions": [
{
"Type": "Crouch",
"Crouch": false
}
]
},
{
"Reference": "Component_Instruction_Leash_To_Flock_Leader",
"Modify": {
"Enabled": { "Compute": "!isEmptyStringArray(FlockArray)" },
"WanderRadius": { "Compute": "WanderRadius" },
"RelativeSpeed": 0.3,
"StopDistance": 3
}
},
{
"BodyMotion": {
"Type": "Sequence",
"Looped": true,
"Motions": [
{
"Type": "Timer",
"Time": [ 1, 5 ],
"Motion": {
"Type": "WanderInCircle",
"Radius": { "Compute": "WanderRadius" },
"MaxHeadingChange": 60,
"RelativeSpeed": 0.18
}
},
{
"Type": "Timer",
"Time": [ 3, 8 ],
"Motion": {
"Type": "Nothing"
}
}
]
}
}
]
},
{
"$Comment": "TODO: grazing component seems to be borked",
"Weight": 10,
"Instructions": [
{
"Sensor": {
"Type": "Self",
"Filters": [
{
"Type": "StandingOnBlock",
"BlockSet": { "Compute": "GrazingBlockSet" }
}
]
},
"ActionsBlocking": true,
"Actions": [
{
"Type": "PlayAnimation",
"Slot": "Status",
"Animation": "Eat"
},
{
"Type": "Timeout",
"Delay": [ 5, 6 ]
},
{
"Type": "PlayAnimation",
"Slot": "Status"
},
{
"Type": "ResetInstructions"
}
]
},
{
"$Comment": "They are not standing on grazing block",
"Actions": [
{
"Type": "ResetInstructions"
},
{
"Type": "State",
"State": ".Default"
}
]
}
]
},
{
"Enabled": { "Compute": "!isEmpty(FoodBlockSet)" },
"Weight": 10,
"Instructions": [
{
"Sensor": {
"Type": "And",
"Sensors": [
{
"Type": "Alarm",
"Name": "Eat_Ready",
"State": "Unset"
},
{
"Type": "Block",
"Range": { "Compute": "ViewRange" },
"MaxHeight": 4,
"Blocks": { "Compute": "FoodBlockSet" },
"Random": true
}
]
},
"Actions": [
{
"Type": "State",
"State": ".EatFromBlock"
}
]
},
{
"$Comment": "No nearby blocks to eat from",
"Actions": [
{
"Type": "ResetInstructions"
},
{
"Type": "State",
"State": ".Default"
}
]
}
]
},
{
"$Comment": "Play a daytime flavor animation.",
"Enabled": { "Compute": "!isEmpty(DayFlavorAnimation)" },
"Weight": 3,
"Instructions": [
{
"ActionsBlocking": true,
"Actions": [
{
"Type": "PlayAnimation",
"Slot": "Status",
"Animation": { "Compute": "DayFlavorAnimation" }
},
{
"Type": "Timeout",
"Delay": { "Compute": "DayFlavorAnimationLength" }
},
{
"Type": "PlayAnimation",
"Slot": "Status"
},
{
"Type": "ResetInstructions"
}
]
}
]
},
{
"$Comment": "Nap.",
"Enabled": { "Compute": "DayTimeNapWeight > 0" },
"Weight": { "Compute": "DayTimeNapWeight" },
"Instructions": [
{
"Actions": [
{
"Type": "State",
"State": "Sleep.Nap"
}
]
}
]
}
]
},
{
"$Comment": "Sleep time.",
"Actions": [
{
"Type": "Timeout",
"Delay": [ 2, 4 ],
"Action": {
"Type": "Sequence",
"Actions": [
{
"Type": "State",
"State": "Sleep"
}
]
}
}
]
}
]
},
{
"Sensor": {
"Type": "State",
"State": "Sleep"
},
"Instructions": [
{
"$Comment": "Wake up if an enemy attacks a flock member.",
"Enabled": { "Compute": "!isEmptyStringArray(FlockArray)" },
"Sensor": {
"Type": "Beacon",
"Message": "Flock_Attack",
"TargetSlot": "LockedTarget"
},
"Actions": [
{
"Type": "State",
"State": "Alerted"
}
]
},
{
"$Comment": "Just a little nap.",
"Enabled": { "Compute": "DayTimeNapWeight > 0" },
"Sensor": {
"Type": "State",
"State": ".Nap"
},
"Instructions": [
{
"$Comment": "Start the nap timer",
"Continue": true,
"Sensor": {
"Type": "Any",
"Once": true
},
"Actions": [
{
"Type": "TimerStart",
"Name": "NapTimer",
"StartValueRange": { "Compute": "DayTimeNapTimeRange" },
"RestartValueRange": { "Compute": "DayTimeNapTimeRange" }
},
{
"Type": "TimerRestart",
"Name": "NapTimer"
}
]
},
{
"Reference": "Component_Instruction_Wild_Sleep_State",
"Modify": {
"_ExportStates": [ "Panic", "Panic", "Flee.Switch", "Idle" ],
"HearingRange": { "Compute": "HearingRange" },
"Attitudes": [ "Hostile", "Neutral" ],
"WakeupSensor": "Component_Sensor_Timed_Nap"
}
}
]
},
{
"$Comment": "Night-time sleep.",
"Instructions": [
{
"Reference": "Component_Instruction_Wild_Sleep_State",
"Modify": {
"_ExportStates": [ "Panic", "Panic", "Flee.Switch", "Idle" ],
"HearingRange": { "Compute": "HearingRange" },
"Attitudes": [ "Hostile", "Neutral" ],
"DayTimePeriod": { "Compute": "DayTimePeriod" }
}
}
]
}
]
},
{
"$Comment": "Used when receiving something like a flock beacon that may potentially result in the NPC becoming alerted but could also be discarded with a random chance.",
"Sensor": {
"Type": "State",
"State": "Alerted"
},
"Instructions": [
{
"$Comment": "Play the alerted animation when entering the state",
"Continue": true,
"Sensor": {
"Type": "Any",
"Once": true
},
"Actions": [
{
"Type": "PlayAnimation",
"Slot": "Status",
"Animation": "Alerted"
}
]
},
{
"$Comment": "Starting a timer to get out of alerted state if nothing else got us out of there",
"Sensor": {
"Type": "Target"
},
"Continue": true,
"ActionsBlocking": true,
"Actions": [
{
"Type": "Timeout",
"Delay": { "Compute": "AlertedTimeoutGiveUp" }
},
{
"Type": "State",
"State": "Idle"
}
]
},
{
"$Comment": "Check for damage",
"Reference": "Component_Instruction_Damage_Check",
"Modify": {
"_ExportStates": [ "Flee.Switch", "Panic" ],
"AlertedRange": { "Compute": "AlertedRange" }
}
},
{
"$Comment": "Watching a target always, if we have any",
"Continue": true,
"Sensor": {
"Type": "Target",
"Range": { "Compute": "AlertedRange" }
},
"HeadMotion": {
"Type": "Watch"
}
},
{
"Sensor": {
"$Comment": "If target is reasonably close, the NPC will flee",
"Type": "Target",
"Range": { "Compute": "AlertedActionRange" },
"Filters": [
{
"Type": "LineOfSight"
}
]
},
"Actions": [
{
"Type": "State",
"State": "Flee.Switch"
}
]
},
{
"$Comment": "No target, back to idle",
"Sensor": {
"Type": "Not",
"Sensor": {
"Type": "Target"
}
},
"Actions": [
{
"Type": "Timeout",
"Delay": [ 2, 2 ],
"Action": {
"Type": "State",
"State": "Idle"
}
}
]
}
]
},
{
"Sensor": {
"Type": "State",
"State": "Greet"
},
"Instructions": [
{
"$Comment": "Play the greet animation when entering the state",
"Continue": true,
"Sensor": {
"Type": "Any",
"Once": true
},
"Actions": [
{
"Type": "PlayAnimation",
"Slot": "Status",
"Animation": { "Compute": "GreetAnimation" }
}
]
},
{
"$Comment": "Check for damage",
"Reference": "Component_Instruction_Damage_Check",
"Modify": {
"_ExportStates": [ "Flee.Switch", "Panic" ],
"AlertedRange": { "Compute": "AlertedRange" }
}
},
{
"$Comment": "Starting a timer to get out of greet state if nothing else got us out of there. TODO: expose the timer duration",
"Continue": true,
"Sensor": {
"Type": "Target"
},
"ActionsBlocking": true,
"Actions": [
{
"Type": "Timeout",
"Delay": { "Compute": "GreetStateTimeout" }
},
{
"Type": "SetAlarm",
"Name": "Greet_Ready",
"DurationRange": { "Compute": "GreetTimeout" }
},
{
"Type": "State",
"State": "Idle"
}
]
},
{
"$Comment": "Watching a target always, if we have any",
"Continue": true,
"Sensor": {
"Type": "Target",
"Range": { "Compute": "AlertedRange" }
},
"HeadMotion": {
"Type": "Watch"
}
},
{
"Enabled": { "Compute": "!isEmptyStringArray(AttractiveItemSet)" },
"$Comment": "If the target is holding a liked item, follow it",
"Sensor": {
"Type": "And",
"Sensors": [
{
"Type": "Target",
"Range": { "Compute": "ViewRange" },
"Filters": [
{
"Type": "ItemInHand",
"Items": { "Compute": "AttractiveItemSet" }
},
{
"Type": "Attitude",
"Attitudes": [ "Revered", "Friendly" ]
}
]
}
]
},
"Type": "Random",
"ExecuteFor": [ 15, 20 ],
"Instructions": [
{
"Weight": { "Compute": "WeightFollowItem" },
"Sensor": {
"Type": "Target"
},
"ActionsBlocking": true,
"Actions": [
{
"Type": "SpawnParticles",
"ParticleSystem": "Hearts_Subtle",
"Offset": { "Compute": "ParticleOffset" },
"TargetNodeName": "Head"
},
{
"Type": "Timeout",
"Delay": { "Compute": "FollowItemPreDelay" }
},
{
"Type": "State",
"State": "SeekFood"
}
]
},
{
"Enabled": { "Compute": "WeightFollowItem < 100" },
"Weight": { "Compute": "100 - WeightFollowItem" },
"Sensor": {
"Type": "Target"
},
"ActionsBlocking": true,
"Actions": [
{
"Type": "Nothing"
}
]
}
]
},
{
"$Comment": "No target, back to idle",
"Sensor": {
"Type": "Not",
"Sensor": {
"Type": "Target"
}
},
"Actions": [
{
"Type": "Timeout",
"Delay": [ 2, 2 ],
"Action": {
"Type": "State",
"State": "Idle"
}
}
]
}
]
},
{
"Sensor": {
"Type": "State",
"State": "SeekFood"
},
"Instructions": [
{
"Reference": "Component_Instruction_Damage_Check",
"Modify": {
"_ExportStates": [ "Flee.Switch", "Panic" ],
"AlertedRange": { "Compute": "AlertedRange" }
}
},
{
"$Comment": "If enabled, start a timer to give up on chasing a target",
"Enabled": { "Compute": "FollowItemTimeoutEnabled" },
"Continue": true,
"Sensor": {
"Type": "Target"
},
"ActionsBlocking": true,
"Actions": [
{
"Type": "Timeout",
"Delay": { "Compute": "FollowItemTimeout" }
},
{
"Type": "State",
"State": ".GiveUp"
}
]
},
{
"Sensor": {
"Type": "State",
"State": ".Ate"
},
"Instructions": [
{
"Continue": true,
"Sensor": {
"Type": "Target",
"Range": { "Compute": "AlertedRange" },
"Filters": [
{
"Type": "LineOfSight"
}
]
},
"HeadMotion": {
"Type": "Watch"
}
},
{
"ActionsBlocking": true,
"Actions": [
{
"Type": "SetAlarm",
"Name": "Eat_Ready",
"DurationRange": { "Compute": "EatTimeout" }
},
{
"$Comment": "No need to greet another player after being fed",
"Type": "SetAlarm",
"Name": "Greet_Ready",
"DurationRange": { "Compute": "GreetTimeout" }
},
{
"Type": "SetStat",
"Stat": "Health",
"Value": { "Compute": "MaxHealth" }
},
{
"Type": "Timeout",
"Delay": [ 3, 5 ]
},
{
"Type": "State",
"State": "Idle"
}
]
}
]
},
{
"$Comment": "Watching a target always, if we have any",
"Continue": true,
"Sensor": {
"Type": "Target",
"Range": { "Compute": "AlertedRange" }
},
"HeadMotion": {
"Type": "Watch"
}
},
{
"Sensor": {
"Type": "State",
"State": ".GiveUp"
},
"Instructions": [
{
"Sensor": {
"Type": "And",
"Sensors": [
{
"Type": "Target",
"Range": { "Compute": "AlertedRange" }
},
{
"Type": "Alarm",
"Name": "Eat_Ready",
"State": "Unset"
}
]
},
"ActionsBlocking": true,
"Actions": [
{
"Type": "PlayAnimation",
"Slot": "Status"
},
{
"Type": "Timeout",
"Delay": [ 3, 6 ]
},
{
"Type": "PlayAnimation",
"Slot": "Status",
"Animation": "Alerted"
},
{
"Type": "SpawnParticles",
"ParticleSystem": "Angry",
"Offset": { "Compute": "ParticleOffset" },
"TargetNodeName": "Head"
},
{
"Type": "State",
"State": "Idle"
}
]
},
{
"Actions": [
{
"Type": "Timeout",
"Delay": [ 3, 5 ],
"Action": {
"Type": "State",
"State": "Idle"
}
}
]
}
]
},
{
"Enabled": { "Compute": "!isEmptyStringArray(AttractiveItemSet)" },
"$Comment": "If the target is holding a liked item, follow it",
"Sensor": {
"Type": "Target",
"Range": { "Compute": "ViewRange" },
"Filters": [
{
"Type": "ItemInHand",
"Items": { "Compute": "AttractiveItemSet" }
},
{
"Type": "Attitude",
"Attitudes": [ "Revered", "Friendly" ]
}
]
},
"BodyMotion": {
"Type": "MaintainDistance",
"DesiredDistanceRange": { "Compute": "FollowItemDistance" },
"RelativeForwardsSpeed": 0.3,
"RelativeBackwardsSpeed": 0.3
},
"Actions": [
{
"Type": "PlayAnimation",
"Slot": "Status",
"Animation": "Curious"
}
]
},
{
"$Comment": "Target is no longer holding an item or is too far away, give up and go back to idle",
"Sensor": {
"Type": "Target"
},
"ActionsBlocking": true,
"ActionsAtomic": true,
"Actions": [
{
"Type": "State",
"State": ".GiveUp"
}
]
},
{
"Actions": [
{
"Type": "Timeout",
"Delay": [ 2, 3 ],
"Action": {
"Type": "State",
"State": "Idle"
}
}
]
}
]
},
{
"Sensor": {
"Type": "State",
"State": "Flee"
},
"Instructions": [
{
"$Comment": "TODO: Add a state message",
"Enabled": { "Compute": "!isEmptyStringArray(FlockArray)" },
"Continue": true,
"Sensor": {
"Type": "Any",
"Once": true
},
"Actions": [
{
"Type": "FlockBeacon",
"Message": "Flock_Attack",
"SendTargetSlot": "LockedTarget"
}
]
},
{
"Reference": "Component_Instruction_Damage_Check",
"Modify": {
"_ExportStates": [ "Flee.Switch", "Panic" ],
"AlertedRange": { "Compute": "AlertedRange" }
}
},
{
"Sensor": {
"Type": "State",
"State": ".Switch"
},
"Instructions": [
{
"Sensor": {
"Type": "Target",
"TargetSlot": "LockedTarget",
"Range": { "Compute": "AttackRange" }
},
"Instructions": [
{
"Continue": true,
"Sensor": {
"Type": "Target",
"Once": true
},
"Actions": [
{
"$TODO": "Maybe friendly lifestock doesnt override it for player when hit",
"Type": "OverrideAttitude",
"Attitude": "Hostile",
"Duration": { "Compute": "IgnoreAttitudeOverride" }
}
]
},
{
"Enabled": { "Compute": "AttackWhenStartled" },
"Sensor": {
"Type": "Target",
"Filters": [
{
"Type": "Not",
"Filter": {
"Type": "ViewSector",
"ViewSector": 270
}
},
{
"Type": "Not",
"Filter": {
"Type": "Attitude",
"Attitudes": [ "Revered", "Friendly" ]
}
}
]
},
"ActionsBlocking": true,
"Actions": [
{
"Type": "PlayAnimation",
"Slot": "Status",
"Animation": "Alerted"
},
{
"Type": "Timeout",
"Delay": [ 0.2, 0.2 ]
},
{
"Type": "PlayAnimation",
"Slot": "Status"
},
{
"Type": "State",
"State": ".Attack"
}
]
},
{
"Actions": [
{
"Type": "State",
"State": ".Default"
}
]
}
]
},
{
"Sensor": {
"Type": "Target",
"TargetSlot": "LockedTarget",
"Range": { "Compute": "AlertedRange" }
},
"Actions": [
{
"Type": "State",
"State": ".Default"
}
]
},
{
"Actions": [
{
"Type": "State",
"State": "Panic"
}
]
}
]
},
{
"Sensor": {
"Type": "State",
"State": ".Attack"
},
"ActionsBlocking": true,
"Actions": [
{
"Type": "Attack",
"Attack": { "Compute": "Attack" },
"AttackPauseRange": [ 1, 2 ]
},
{
"Type": "Timeout",
"Delay": [ 0.3, 0.3 ],
"Action": {
"Type": "State",
"State": ".Default"
}
}
]
},
{
"Sensor": {
"Type": "Target",
"Range": { "Compute": "AlertedRange + 3" }
},
"BodyMotion": {
"Type": "Flee",
"SlowDownDistance": { "Compute": "AlertedRange - 3" },
"StopDistance": { "Compute": "AlertedRange + 3" },
"RelativeSpeed": 0.68
},
"Actions": [
{
"Type": "Timeout",
"Delay": [ 8, 8 ],
"Action": {
"Type": "State",
"State": ".Switch"
}
}
]
},
{
"Actions": [
{
"Type": "Timeout",
"Delay": [ 3, 6 ],
"Action": {
"Type": "State",
"State": "Idle"
}
}
]
}
]
},
{
"Sensor": {
"Type": "State",
"State": "Panic"
},
"Instructions": [
{
"Continue": true,
"Sensor": {
"Type": "Any",
"Once": true
},
"Actions": [
{
"Type": "PlayAnimation",
"Slot": "Status",
"Animation": "Alerted"
}
]
},
{
"Continue": true,
"Actions": [
{
"Type": "Timeout",
"Delay": [ 6, 12 ],
"Action": {
"Type": "State",
"State": "Idle"
}
}
]
},
{
"Sensor": {
"Type": "Damage",
"Combat": true
},
"BodyMotion": {
"Type": "Flee",
"SlowDownDistance": 9,
"StopDistance": 14,
"RelativeSpeed": 1,
"RelaxedMoveConstraints": false
}
},
{
"BodyMotion": {
"Type": "WanderInCircle",
"Radius": 10,
"MaxHeadingChange": 90,
"RelativeSpeed": 1,
"RelaxedMoveConstraints": true
}
}
]
},
{
"Sensor": {
"Type": "State",
"State": "$Tamed",
"IgnoreMissingSetState": true
},
"Instructions": [
{
"Sensor": {
"Reference": "Component_Sensor_Standard_Detection",
"Modify": {
"ViewRange": { "Compute": "ViewRange" },
"ViewSector": { "Compute": "ViewSector" },
"HearingRange": { "Compute": "SmellingRange" },
"AbsoluteDetectionRange": { "Compute": "AbsoluteDetectionRange" },
"Attitudes": [ "Revered", "Friendly" ],
"GetNPCs": false
}
},
"Instructions": [
{
"Sensor": {
"Type": "Any",
"Once": true
},
"Actions": [
{
"Type": "SpawnParticles",
"ParticleSystem": "Hearts",
"Offset": { "Compute": "ParticleOffset" },
"TargetNodeName": "Head"
}
]
},
{
"Sensor": {
"Type": "Target",
"Range": { "Compute": "AlertedRange" },
"Filters": [
{
"Type": "LineOfSight"
}
]
},
"HeadMotion": {
"Type": "Watch"
},
"Actions": [
{
"Type": "SetAlarm",
"Name": "Eat_Ready",
"DurationRange": { "Compute": "EatTimeout" }
},
{
"Type": "Timeout",
"Delay": [ 2, 2 ],
"Action": {
"Type": "State",
"State": "SeekFood"
}
}
]
},
{
"Actions": [
{
"Type": "Timeout",
"Delay": [ 2, 2 ],
"Action": {
"Type": "State",
"State": "Idle"
}
}
]
}
]
}
]
},
{
"Sensor": {
"Type": "State",
"State": "$Harvest"
},
"Instructions": [
{
"$Comment": "Base harvest logic: particles, sound, alarm (always runs)",
"Continue": true,
"Sensor": {
"Type": "Any",
"Once": true
},
"Actions": [
{
"Type": "PlayAnimation",
"Slot": "Status",
"Animation": "Alerted"
},
{
"Type": "SpawnParticles",
"ParticleSystem": { "Compute": "HarvestParticles" },
"Offset": { "Compute": "ParticleOffset" },
"TargetNodeName": "Head"
},
{
"Type": "PlaySound",
"SoundEventId": { "Compute": "HarvestSound" }
},
{
"Type": "SetAlarm",
"Name": "Harvest_Ready",
"DurationRange": { "Compute": "HarvestTimeout" }
}
]
},
{
"$Comment": "Drop item only if HarvestDropList is set",
"Enabled": { "Compute": "!isEmpty(HarvestDropList)" },
"Continue": true,
"Sensor": {
"Type": "Any",
"Once": true
},
"Actions": [
{
"Type": "DropItem",
"DropList": { "Compute": "HarvestDropList" },
"Distance": [ 0.2, 0.5 ],
"Delay": [ 0, 0 ],
"DropSector": [ -360, 360 ],
"PitchHigh": false,
"ThrowSpeed": 14
}
]
},
{
"$Comment": "Replace buckets",
"Enabled": { "Compute": "!isEmpty(HarvestAddItemBucket) || !isEmpty(HarvestAddItemDecoBucket)" },
"Continue": true,
"Sensor": {
"Type": "Any",
"Once": true
},
"Instructions": [
{
"Enabled": { "Compute": "!isEmpty(HarvestAddItemBucket)" },
"Sensor": {
"Type": "Target",
"Filters": [
{
"Type": "ItemInHand",
"Items": [ "Container_Bucket" ]
}
]
},
"Actions": [
{
"Type": "Inventory",
"UseTarget": true,
"Operation": "RemoveHeldItem"
},
{
"Type": "Inventory",
"UseTarget": true,
"Operation": "Add",
"Item": { "Compute": "HarvestAddItemBucket" },
"Count": 1
}
]
},
{
"Enabled": { "Compute": "!isEmpty(HarvestAddItemDecoBucket)" },
"Sensor": {
"Type": "Target",
"Filters": [
{
"Type": "ItemInHand",
"Items": [ "Container_Bucket" ]
}
]
},
"Actions": [
{
"Type": "Inventory",
"UseTarget": true,
"Operation": "RemoveHeldItem"
},
{
"Type": "Inventory",
"UseTarget": true,
"Operation": "Add",
"Item": { "Compute": "HarvestAddItemDecoBucket" },
"Count": 1
}
]
}
]
},
{
"$Comment": "Replace Deco_Bucket with milk when held",
"Enabled": { "Compute": "!isEmpty(HarvestAddItemDecoBucket)" },
"Continue": true,
"Sensor": {
"Type": "And",
"Sensors": [
{
"Type": "Any",
"Once": true
},
{
"Type": "Target",
"Filters": [
{
"Type": "ItemInHand",
"Items": [ "Deco_Bucket" ]
}
]
}
]
},
"Actions": [
{
"Type": "Inventory",
"UseTarget": true,
"Operation": "RemoveHeldItem"
},
{
"Type": "Inventory",
"UseTarget": true,
"Operation": "Add",
"Item": { "Compute": "HarvestAddItemDecoBucket" },
"Count": 1
}
]
},
{
"$Comment": "If there are configured attachments for the 'harvested' state, apply them",
"Enabled": { "Compute": "IsHarvestable && !isEmpty(HarvestModelSlot)" },
"Continue": true,
"Actions": [
{
"Type": "ModelAttachment",
"Slot": { "Compute": "HarvestModelSlot" },
"Attachment": { "Compute": "HarvestModelAttachmentHarvested" }
}
]
},
{
"ActionsBlocking": true,
"Actions": [
{
"Type": "Timeout",
"Delay": [ 2, 3 ]
},
{
"Type": "State",
"State": "Idle"
}
]
}
]
}
]
}
],
"InteractionInstruction": {
"Instructions": [
{
"Continue": true,
"Actions": [
{
"Type": "LockOnInteractionTarget",
"TargetSlot": "InteractionTarget"
}
]
},
{
"Enabled": { "Compute": "IsPettable" },
"TreeMode": true,
"Instructions": [
{
"InvertTreeModeResult": true,
"Sensor": {
"$Comment": "Check the negative first so we can exit early and avoid the rest of the logic",
"Type": "Not",
"Sensor": {
"Type": "And",
"Sensors": [
{
"Type": "Alarm",
"Name": "Pet_Ready",
"State": "Unset"
},
{
"Type": "Not",
"Sensor": {
"Type": "State",
"State": "Sleep"
}
},
{
"Type": "CanInteract",
"Attitudes": { "Compute": "PetRequiredAttitudes" }
},
{
"Type": "Target",
"TargetSlot": "InteractionTarget",
"Filters": [
{
"Type": "Not",
"Filter": {
"Type": "ItemInHand",
"Hand": "Main",
"Items": [ "*" ]
}
}
]
}
]
}
},
"Actions": [
{
"Type": "Nothing"
}
]
},
{
"InvertTreeModeResult": true,
"Continue": true,
"Sensor": {
"Type": "Any"
},
"Actions": [
{
"Type": "SetInteractable",
"Interactable": true,
"Hint": "server.interactionHints.pet"
}
]
},
{
"Sensor": {
"Type": "HasInteracted"
},
"Instructions": [
{
"Sensor": {
"Type": "Target"
},
"Actions": [
{
"Type": "PlayAnimation",
"Slot": "Status",
"Animation": { "Compute": "PetAnimation" }
},
{
"Type": "SpawnParticles",
"ParticleSystem": "Hearts_Subtle",
"Offset": { "Compute": "ParticleOffset" },
"TargetNodeName": "Head"
},
{
"Type": "SetAlarm",
"Name": "Pet_Ready",
"DurationRange": { "Compute": "PetTimeout" }
}
]
}
]
}
]
},
{
"TreeMode": true,
"Instructions": [
{
"InvertTreeModeResult": true,
"Sensor": {
"$Comment": "Check the negative first so we can exit early and avoid the rest of the logic",
"Type": "Not",
"Sensor": {
"Type": "And",
"Sensors": [
{
"Type": "Alarm",
"Name": "Eat_Ready",
"State": "Unset"
},
{
"Type": "State",
"State": "SeekFood"
},
{
"Type": "Not",
"Sensor": {
"Type": "State",
"State": "SeekFood.Ate"
}
},
{
"Type": "CanInteract",
"Attitudes": { "Compute": "FeedRequiredAttitudes" }
},
{
"Type": "Target",
"TargetSlot": "InteractionTarget",
"Filters": [
{
"Type": "ItemInHand",
"Hand": "Main",
"Items": { "Compute": "AttractiveItemSet" }
}
]
}
]
}
},
"Actions": [
{
"Type": "Nothing"
}
]
},
{
"InvertTreeModeResult": true,
"Continue": true,
"Sensor": {
"Type": "Any"
},
"Actions": [
{
"Type": "SetInteractable",
"Interactable": true,
"Hint": "server.interactionHints.feed"
}
]
},
{
"Sensor": {
"Type": "HasInteracted"
},
"Instructions": [
{
"Sensor": {
"Type": "Target",
"TargetSlot": "InteractionTarget"
},
"Actions": [
{
"Type": "Inventory",
"UseTarget": true,
"Operation": "RemoveHeldItem",
"Count": 1
},
{
"Type": "SpawnParticles",
"ParticleSystem": "Hearts_Subtle",
"Offset": { "Compute": "ParticleOffset" },
"TargetNodeName": "Head"
},
{
"Type": "State",
"State": "SeekFood.Ate"
}
]
}
]
}
]
},
{
"Enabled": { "Compute": "IsHarvestable" },
"TreeMode": true,
"Instructions": [
{
"InvertTreeModeResult": true,
"Sensor": {
"$Comment": "Check the negative first so we can exit early and avoid the rest of the logic",
"Type": "Not",
"Sensor": {
"Type": "And",
"Sensors": [
{
"Type": "Alarm",
"Name": "Harvest_Ready",
"State": "Unset"
},
{
"Type": "CanInteract",
"Attitudes": { "Compute": "HarvestRequiredAttitudes" }
},
{
"Type": "Target",
"TargetSlot": "InteractionTarget",
"Filters": [
{
"Enabled": { "Compute": "!isEmptyStringArray(HarvestInteractionRequiredItems)" },
"Type": "ItemInHand",
"Hand": "Main",
"Items": { "Compute": "HarvestInteractionRequiredItems" }
}
]
}
]
}
},
"Actions": [
{
"Type": "Nothing"
}
]
},
{
"InvertTreeModeResult": true,
"Continue": true,
"Sensor": {
"Type": "Any"
},
"Actions": [
{
"Type": "SetInteractable",
"Interactable": true,
"Hint": ""
}
]
},
{
"Sensor": {
"Enabled": { "Compute": "!isEmpty(HarvestInteractionContext)" },
"Type": "InteractionContext",
"Context": { "Compute": "HarvestInteractionContext" }
},
"Actions": [
{
"Type": "State",
"State": "$Harvest"
}
]
}
]
},
{
"Enabled": { "Compute": "IsMountable" },
"TreeMode": true,
"Instructions": [
{
"InvertTreeModeResult": true,
"Sensor": {
"$Comment": "Check the negative first so we can exit early and avoid the rest of the logic",
"Type": "Not",
"Sensor": {
"Type": "And",
"Sensors": [
{
"Type": "CanInteract",
"ViewSector": 360,
"Attitudes": [ "Revered", "Friendly" ]
},
{
"Type": "Not",
"Sensor": {
"Type": "State",
"State": "Sleep"
}
}
]
}
},
"Actions": [
{
"Type": "Nothing"
}
]
},
{
"InvertTreeModeResult": true,
"Continue": true,
"Sensor": {
"Type": "Any"
},
"Actions": [
{
"Type": "SetInteractable",
"Interactable": true,
"Hint": "server.interactionHints.mount"
}
]
},
{
"Sensor": {
"Type": "HasInteracted"
},
"Actions": [
{
"Type": "PlayAnimation",
"Slot": "Status"
},
{
"Type": "Mount",
"AnchorX": { "Compute": "MountAnchorX" },
"AnchorY": { "Compute": "MountAnchorY" },
"AnchorZ": { "Compute": "MountAnchorZ" },
"MovementConfig": { "Compute": "MountMovementConfig" }
}
]
}
]
},
{
"$Comment": "Only now that we've failed to match all possible interactions do we set interactability to false.",
"Actions": [
{
"Type": "SetInteractable",
"Interactable": false
}
]
}
]
},
"NameTranslationKey": { "Compute": "NameTranslationKey" }
}