{"id":583,"date":"2016-11-18T11:57:43","date_gmt":"2016-11-18T11:57:43","guid":{"rendered":"http:\/\/smartfoxserver.com\/blog\/?p=583"},"modified":"2016-11-18T12:01:04","modified_gmt":"2016-11-18T12:01:04","slug":"ways-of-working-with-npcs-in-a-multiplayer-game-p-1","status":"publish","type":"post","link":"https:\/\/smartfoxserver.com\/blog\/ways-of-working-with-npcs-in-a-multiplayer-game-p-1\/","title":{"rendered":"Ways of working with NPCs in a multiplayer game (p.1)"},"content":{"rendered":"<p>The topic of managing NPCs in games is an interesting and less discussed one. In this article we&#8217;re going to cover some concepts and strategies to work with NPCs in our\u00a0multiplayer game, focusing on different modalities of\u00a0interaction with real players and the game environment.<\/p>\n<p><!--more--><\/p>\n<p><strong>NOTE<\/strong>: as a prerequisite for this article we assume you have at least a basic understanding of how Extension development works in SFS2X. If you need a refresher please <a title=\"Developing extensions\" href=\"http:\/\/docs2x.smartfoxserver.com\/AdvancedTopics\/server-side-extensions\" target=\"_blank\">check this article<\/a>.<\/p>\n<h2>\u00bb The basics<\/h2>\n<p>Let&#8217;s start with the basics of creating\u00a0one or more NPCs in an SFS2X extension, which is very easy:<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nUser myNpc = getApi().createNPC(&quot;npc&quot;, getParentZone(), false);\r\n<\/pre>\n<p>Essentially we just need to provide a unique <em>username<\/em>\u00a0and a reference to the current Zone. The last parameter is called <em>forceLogin\u00a0<\/em>and is set to true if you want to kick out another User that exists with the same\u00a0<em>username<\/em>.<\/p>\n<p>In return this api call gives us a regular\u00a0<strong>User<\/strong> object that represents the new (virtual) player and that behaves exactly like any other user in the system. We can join it in a Room, set some User Variables or send chat messages to other people on its behalf.<\/p>\n<p>Like any other client the User object also has a <strong>Session<\/strong> object linked\u00a0to it that represents the connection.\u00a0In this case however the Session&#8217;s type is set to <strong>VOID<\/strong> which indicates\u00a0a connection-less session (i.e. no socket is really used).<\/p>\n<p>You can verify\u00a0this by running this code and checking out\u00a0the output:<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nSystem.out.println(&quot;Session type: &quot; + myNpc.getSession().getType());\r\n<\/pre>\n<p>whereas a real player will have a Session of type <strong>DEFAULT<\/strong> (for TCP), <strong>WEBSOCKET<\/strong> or <strong>BLUEBOX<\/strong> depending on the type of connection in use.<\/p>\n<h2>\u00bb\u00a0Controlling the NPCs<\/h2>\n<p>There are essentially three modalities\u00a0that we normally employ\u00a0to control non player characters in a game:<\/p>\n<ol>\n<li><strong>Direct player\/NPC interaction:<\/strong>\u00a0e.g. a player clicks or sends a message to a specific NPC in the game<\/li>\n<li><strong>NPC Triggers<\/strong>: a player enters the &#8220;range&#8221; or Area of Interest \u00a0(AOI) of a certain NPC which in turn activates a reaction (NPC starts shooting or chasing or\u00a0a dialogue is initiated etc&#8230;)<\/li>\n<li><strong>Independent NPC activity<\/strong>: the NPC is running its own AI logic, unrelated to other player&#8217;s actions<\/li>\n<\/ol>\n<p>Depending on our game complexity and requirements we may to employ\u00a0one, two or all three modalities. Let&#8217;s now\u00a0discuss each one a little more in detail and\u00a0see how they should work.<\/p>\n<p><strong>1) Direct player\/NPC interaction<\/strong><\/p>\n<p><a href=\"http:\/\/smartfoxserver.com\/blog\/wp-content\/uploads\/2016\/11\/NPC1-zelda.gif\"><img loading=\"lazy\" class=\" size-full wp-image-585 alignnone\" src=\"http:\/\/smartfoxserver.com\/blog\/wp-content\/uploads\/2016\/11\/NPC1-zelda.gif\" alt=\"NPC1-zelda\" width=\"480\" height=\"320\" \/><\/a><\/p>\n<p>This approach is very\u00a0simple to implement. A\u00a0common use case is a player clicking directly on a character and activating a dialogue or similar action. Since\u00a0the request is initiated by the player we can\u00a0implement this by sending\u00a0an Extension call with the ID of the NPC (user id) and a code for the action to be performed, for example &#8220;dialogue&#8221;.<\/p>\n<p>This in turn is\u00a0handled on the server side where a\u00a0dialogue tree is available and the conversation begins. Easy peasy.<\/p>\n<p>In terms of NPC state it is convenient to attach it directly to the NPC&#8217;s User object so that it&#8217;s accessible at any time. In other words we can create any class that models our non player character&#8217;s state and then store it\u00a0in the User&#8217;s object as shown in the following pseudo-code:<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npublic class NpcState\r\n{\r\n\t\/\/ declare fields\r\n\r\n\t\/\/ some methods\r\n\tpublic int getCoins() { ... }\r\n\r\n\tpublic void setCoins(int amount) { ... }\r\n\r\n\tpublic List getInventory() {\u00a0... }\r\n\r\n\tpublic boolean isActive() { ... }\r\n}\r\n\r\n\/\/ attach state to User object\r\nnpcUser.setProperty(&quot;state&quot;, new NpcState());\r\n\r\n\/\/ ...\r\n\/\/ ...\r\n\/\/ later the object can be accessed and modified\r\n\r\nNpcState state = (NpcState) npcUser.getProperty(&quot;state&quot;);\r\nstate.setCoins(100);\r\n\r\n<\/pre>\n<p><strong>2) NPC Triggers<\/strong><\/p>\n<p><a href=\"http:\/\/smartfoxserver.com\/blog\/wp-content\/uploads\/2016\/11\/NPC2-bastion.jpg\"><img loading=\"lazy\" class=\" size-full wp-image-590 alignnone\" src=\"http:\/\/smartfoxserver.com\/blog\/wp-content\/uploads\/2016\/11\/NPC2-bastion.jpg\" alt=\"NPC2-bastion\" width=\"480\" height=\"320\" srcset=\"https:\/\/smartfoxserver.com\/blog\/wp-content\/uploads\/2016\/11\/NPC2-bastion.jpg 480w, https:\/\/smartfoxserver.com\/blog\/wp-content\/uploads\/2016\/11\/NPC2-bastion-300x200.jpg 300w\" sizes=\"(max-width: 480px) 100vw, 480px\" \/><\/a><\/p>\n<p>Triggers will activate NPCs based on different parameters, a typical example is proximity. For instance enemies will detect the player and start shooting or chasing him once he&#8217;s close enough.<\/p>\n<p>To work with triggers we can\u00a0create a basic event system that allows the Extension to send\u00a0internal notifications\u00a0when a certain NPC detects\u00a0a player in its range. This can be implemented in a myriad of ways depending on the nature of the game and its rules, but essentially it boils down to a simple detection loop.<\/p>\n<p>Here&#8217;s a pseudo-code example for a 2D game:<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nvoid onPlayerMove(User user)\r\n{\r\n\tfloat x = user.getVariable(&quot;x&quot;);\r\n\tfloat y = user.getVariable(&quot;y&quot;);\r\n\r\n\tfor (User npc : npcList)\r\n\t{\r\n\t\tif (npc.detectPresence(x, y))\r\n\t\t{\r\n\t\t\tdispatchEvent(new DetectionEvent(npc, user));\r\n\t\t}\r\n\t}\r\n}\r\n<\/pre>\n<p>The <strong>onPlayerMove(&#8230;)\u00a0<\/strong>method is triggered every time a player changes his position: we loop through all NPCs and check if the player falls within the &#8220;detection area&#8221; of the NPC. If it does we can dispatch a new event and trigger the specific logic for this occurrence (e.g. the NPC starts chasing the player).<\/p>\n<p>This approach is\u00a0particularly effective used in conjunction with <a title=\"MMORoom overview\" href=\"http:\/\/docs2x.smartfoxserver.com\/AdvancedTopics\/mmo-rooms\" target=\"_blank\">MMORooms<\/a> and the relative <a title=\"MMO Api\" href=\"http:\/\/docs2x.smartfoxserver.com\/AdvancedTopics\/advanced-mmo-api\" target=\"_blank\">MMO Api<\/a> available in SmartFoxServer 2X. The MMORoom can handle thousands of players by partitioning the virtual 2D\/3D space in smaller sectors and updating players that fall within each other&#8217;s AOI.<\/p>\n<p>This way the loop through an NPC list\u00a0becomes far more optimized as we don&#8217;t need to verify every NPC in the Room but only those that are in the immediate surroundings\u00a0of the player.<\/p>\n<p><strong>3) Independent NPC activity<\/strong><\/p>\n<p><a href=\"http:\/\/smartfoxserver.com\/blog\/wp-content\/uploads\/2016\/11\/NPC3-icewinddale.jpg\"><img loading=\"lazy\" class=\" size-full wp-image-595 alignnone\" src=\"http:\/\/smartfoxserver.com\/blog\/wp-content\/uploads\/2016\/11\/NPC3-icewinddale.jpg\" alt=\"NPC3-icewinddale\" width=\"480\" height=\"320\" srcset=\"https:\/\/smartfoxserver.com\/blog\/wp-content\/uploads\/2016\/11\/NPC3-icewinddale.jpg 480w, https:\/\/smartfoxserver.com\/blog\/wp-content\/uploads\/2016\/11\/NPC3-icewinddale-300x200.jpg 300w\" sizes=\"(max-width: 480px) 100vw, 480px\" \/><\/a><\/p>\n<p>Sometimes NPCs stand still waiting for something to happen, maybe looping through simple &#8220;idle&#8221; animations but there are also many use cases where we need them to move\u00a0around or\u00a0be active in the game world.<\/p>\n<p>This independent activity is not triggered by direct player action or events\u00a0and needs to be carried on while the NPC is unengaged. We may have a shop keeper tending to his emporium, a farmer doing work in his land, or some vehicle driving around in the traffic. Regardless of the specific task, this activity runs independently of player&#8217;s actions\u00a0as a server side simulation.<\/p>\n<p>The simulation can be set in motion via a Scheduler&#8217;s task running at specific intervals. Inside the task we can go analyze\u00a0the list of active NPCs, determine those that need an update and finally call the relative class or method that handles the AI.<\/p>\n<p>In pseudo-code it would look like this:<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nclass NPCUpdateTask implements Runnable\r\n{\r\n\tpublic void run()\r\n\t{\r\n\t\tfor (User npc : npcList)\r\n\t\t{\r\n\t\t\tif (npc.isActive())\r\n\t\t\t{\r\n\t\t\t\tif (npc.getType() == NPCType.CITIZEN)\r\n\t\t\t\t\tupdateCitizen(npc);\r\n\r\n\t\t\t\telse (if npc.getType() == NPCType.GUARD)\r\n\t\t\t\t\tupdateGuard(npc);\r\n\r\n\t\t\t\telse if (npc.getType() == NPCType.PET)\r\n\t\t\t\t\tupdatePet(npc);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\/\/ Extension's init method\r\n@Override\r\npublic void init()\r\n{\r\n\tgetApi().getSystemScheduler().scheduleAtFixedRate(new NPCUpdateTask(), 0, 500, TimeUnit.MILLISECONDS)\r\n}\r\n<\/pre>\n<p>Since NPCs are represented by User objects we can use\u00a0standard\u00a0User Variables and get all players updated immediately.\u00a0Additionally, when using MMORooms, all these updates will be distributed to those players that fall in range with the NPC visibility, which is very helpful when there&#8217;re hundreds of NPC in the game.<\/p>\n<h2>\u00bb\u00a0Managing the NPCs<\/h2>\n<p>Before we wrap up this overview there&#8217;s one final consideration to make about the\u00a0management of NPCs. We have mentioned non player characters integrate seamlessly in SFS2X because they are represented with same (User) class employed for players.<\/p>\n<p>While this is useful,\u00a0it can make it difficult to access a list of available NPCs without searching them in global user list, available at Zone level. To avoid these potentially long and sub-optimal searches we recommend keeping a local List (or Map) of the NPCs created.<\/p>\n<p>This way we have immediate access to what we need and we don&#8217;t need to delve through\u00a0the massive global user list.<\/p>\n<h2>\u00bb\u00a0Conclusion<\/h2>\n<p>We have taken a bird&#8217;s eye look at the basic strategies and modes of interaction with NPCs, but the story isn&#8217;t over yet. In the next article we will approach this topic from a different angle and explore another solution to implement interactive NPCs.<\/p>\n<p>Stay tuned for part two.<\/p>\n<p>Until then if you have questions you can <a title=\"Join the conversation\" href=\"http:\/\/www.smartfoxserver.com\/forums\/index.php\" target=\"_blank\">join the conversation over at our forums<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The topic of managing NPCs in games is an interesting and less discussed one. In this article we&#8217;re going to cover some concepts and strategies to work with NPCs in our\u00a0multiplayer game, focusing on different modalities of\u00a0interaction with real players and the game environment.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[23],"tags":[77,10,78,76,7],"_links":{"self":[{"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/posts\/583"}],"collection":[{"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/comments?post=583"}],"version-history":[{"count":18,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/posts\/583\/revisions"}],"predecessor-version":[{"id":604,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/posts\/583\/revisions\/604"}],"wp:attachment":[{"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/media?parent=583"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/categories?post=583"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/tags?post=583"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}