scripting_custom_npc_behaviours_on_interaction

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

scripting_custom_npc_behaviours_on_interaction [2020/04/12 05:52] (current)
thorfinio created
Line 1: Line 1:
 +====== Scripting custom Npc behaviours on interaction ======
  
 +It is now possible to script custom npc interaction behaviours to inject into their Finite State Machine Ia by creating custom c# scripts and assigning them to PlayerEffects. Now PlayerEffects support a new property "​npcFSMEffectModifiers"​ which will be used for this and further implementations permitting the use of Custom scripts to be executed on Npcs state machine when an interaction event occurs and the specified playerEffect happens to be active.
 +
 +===== Create a playerEffect with a npcFSMEffectModifier =====
 +
 +Vanilla Player effects are located in the 
 +   ​C:​\Users\{YOUR USERNAME}\AppData\LocalLow\RadicalFiction\HARDTIMES\Mods\Vanilla\PlayerEffects
 +And in the corrisponding folder of any user created mod which implements new player effects.
 +
 +A typical playerEffect containing a definition of a npcFSMEffectModifier looks like this:
 +
 + {
 +   "​effectId":​ "​subway_effect",​
 +   "​intensity":​ 1,
 +   "​minuteStart":​ 0,
 +   "​minutesDuration":​ 0,
 +   "​effectIntervalMinutes":​ 0,
 +   "​lastEffectCheckMinutes":​ 0,
 +   "​effectPlaySound":​ "",​
 +   "​antidoteStatModifier":​ "",​
 +   "​isPassive":​ true,
 +   "​statModifiers":​ [],
 +   "​npcFSMEffectModifiers":​[
 + {
 +   "​npcRoleAffected":​ 1000,
 +   "​actionsOnInteract":​ [
 + {
 +   "​actionClassName":​ "​FsmAskForMetroTicket",​
 +   "​actionInvokePercentage":​ 70
 + }
 +   ]
 + }
 +   ]
 + }
 +
 +As you can see it defines an array called "​**npcFSMEffectModifiers**"​ which contains one or more npcFSMEffectModifier objects. Each one affecting one kind of npc, identified by it's internal class id. 
 +
 +Class ids of all supported npcs are:
 +
 + NPC_ROLE_CIVILIAN = 1000;
 + NPC_ROLE_TRASHER = 1500;
 + NPC_ROLE_COP = 2000;
 + NPC_ROLE_FASCIST = 2500;
 + NPC_ROLE_QUESTGIVER = 3000;
 + NPC_ROLE_DOG = 5000;
 + NPC_ROLE_RAT = 5050;
 + NPC_ROLE_CAT = 5100;
 +
 +So the property called "​**npcRoleAffected**"​ have to be filled with the right class id for the kind of npc we want to modify the behaviour on interaction with the player.
 +
 +After that we have another array of NpcFSMAction objects called "​**actionsOnInteract**",​ each one specifying a single Finite State machine Action which could be invoked by the npc when the player will interact with it.
 +
 +The NpcFSMAction object exposes two properties:
 +  * **actionClassName**:​ which is actual class name of the new state created by the user and that should be provided in the Scripts folder of the mod. The game will then load and compile the class at runtime when needed.
 +  * **actionInvokePercentage**:​ which is the actual percentage that this behaviour will be used instead of the default npc game behaviour.
 +If more that one NpcFSMAction are provided the game will choose one of them randomly. After that will throw a D100 the check against it's actionInvokePercentage and if the check will be successfull the behaviour will be used.
 +
 +===== Creating a custom state machine behaviour class =====
 +User created classe have to be compliant with the game's internal state machine system. Two examples of custom behaviours can be found in the Vanilla game, inside the custom scripts folder:
 +
 +   ​C:​\Users\{YOUR USERNAME}\AppData\LocalLow\RadicalFiction\HARDTIMES\Mods\Vanilla\Scripts
 +Where two custom behaviours are already implemented and used by the vanilla game. You can find them in:
 +   ​C:​\Users\{YOUR USERNAME}\AppData\LocalLow\RadicalFiction\HARDTIMES\Mods\Vanilla\Scripts\CivilianNpcFsmScripts
 +And are:
 +  * **FsmAskForMetroTicket.cs**:​ which is used in the "​subway_effect"​ as seen in the previous example.
 +  * **FsmAskForPot.cs**:​ which is used in the "​punk_concert_effect"​ active when you go to attend a concert at the squat.
 +
 +Referred playerEffects have, oviously, to be active for their custom behaviour to be applicable.
 +
 +In the following example i am showing the content of the **FsmAskForMetroTicket** custom behaviour as you can find it in the Vanilla game:
 + 
 +    using System.Collections;​
 +    using System.Collections.Generic;​
 +    using UnityEngine;​
 +
 +    public class FsmAskForMetroTicket : FsmBaseState,​ IQuestInitiator
 +    {
 + //Init has to initialize this.npc this way!
 +        public override void Init(BaseNpcManager myNpc)
 +        {
 +            this.npc = myNpc;
 +        }
 +        ​
 + //​StartAction is called at the beginning of the action by the game engine
 +        public override void StartAction()
 +        {
 +            //make the npc look in the player direction
 +            npc.FaceTarget();​
 +            ​
 +            //call a function defined later to start a quest when the player interacts with the npc
 +            PickQuest(npc.target.GetComponent<​PlayerManager>​());​
 +        }
 +
 +        public override void ExecuteAction()
 +        {
 +     //Execute action will be called on each frame, while the action is active, to manage statuses and things that have to evolve over time or have to be updated frequently.
 +            //In this example it's not used since the action just fires a quest on behalf of the npc
 +            //Please note that if you want to create a fixed Questgiver character, you have to use the different questgiver mechanics. This is only for randomly fired miniquests on random people you interact with 
 +        }
 +
 +        //Pick quest is actually firing a defined quest, which is the purpose of this custom behaviour.
 +        public void PickQuest(PlayerManager playerManager)
 +        {
 +            //The quest is fired only if the player has not yet compelted it.
 +            if (!playerManager.GetComponent<​PlayerQuestsManager>​().CompletedQuests.ContainsKey("​civilian_asks_metro_ticket"​))
 +            {
 +                playerManager.GetComponent<​PlayerQuestsManager>​().StartQuest("​civilian_asks_metro_ticket",​ this);
 +            }
 +            ​
 +            //VERY IMPORTANT: after completed its job the behaviour will call another action on the state machine, so that the npc will go on it's way (FsmWander) after the interaction.
 +            //Failing to do so will have the npc stop doing anything and just stay there idle and motionless.
 +            npc.SetState(new FsmWander());​
 +        }
 +
 +        public override void FinishAction()
 +        {
 +           //​Finish action is the place to implement logic that has to be executed when the action is completed and the game engine will call this method just before setting a new action as active
 +        }
 +
 +
 +    }
 +
 +
 +
 +===== Test it out =====
 +
 +If everything went as expected npc interacted with will respond with a custom action when interacted with. Obviously, since this behaviour is binded to a playerEffect it will be executed only when such effect is active to the character.
 +Also if you defined a **actionInvokePercentage** which is less than 100 there will be a check to see if this behaviour will be executed or the default one will be fired instead.
 +
 +I used this mechanics in the Vanilla game to define custom actions in the subway and at the punk concert event. Just refer to those examples to see it in action.
 +I hope i didn't forgot anything in this guide ^_^ but in case ping me to let me know. I will be happy to help.
 +
 +\\
 +
 +I would like to expand this feature in the future, so if you have suggestions or things to point out feel free to do it! 
 +
 +If you have problems or find errors in this guide please get in touch at [[mailto:​info@tempi-duri.net|info@tempi-duri.net]].\\
  • scripting_custom_npc_behaviours_on_interaction.txt
  • Last modified: 2020/04/12 05:52
  • by thorfinio