NPCClient is a program designed to handle as many as 1000 npc’s concurrently. Since NPCs are also scripted in xml rather than programmed in C++, this means that a naïve implementation would require 1000 scripts for these 1000 npcs. In this implementation, however, npc scripts are designed to be shared across multiple NPCs. Each NPC in npcclient is assigned to an “NPCType,” which is a set of behavior scripts and reaction scripts which determine how the npc will walk, talk, fight or act like an animal. This feature makes for excellent scalability and productivity of the npc scripter, but means certain aspects are more complex. The biggest example of this is the divide between npc-specific information and data that is shared at the NpcType level. For example consider this NpcType script:
<npctype name="Wanderer"> <behavior name="walk" decay="0" growth="0" initial="50"> <move vel="1" anim="walk" /> </behavior> <behavior name="turn" completion_decay="100" growth="0" initial="0"> <rotate type="random" min="90" max="270" anim="walk" vel="30" /> </behavior> <react event="collision" behavior="turn" delta="100" /> <react event="out of bounds" behavior="turn" delta="100" /> </npctype>
There will be a lot more detail on how this script works in later sections of the NPC Scripting, but for now just note that this basic type of NPC will walk and he will turn, and that events of collisions and being out of bounds will make him turn. Wandering at its most basic level, is these two behaviors.
Connection to the Database
Now consider these two npc definitions found in sc_npc_definitions table:
|4||Scary Orc||Wanderer||dark forest|
Each of these NPCs defined here is a “Wanderer”, but one wanders in the “dark forest” while the other wanders in the “sunny meadow”. The region defining the “out of bounds” condition is named at the npc level even though the behaviors are shared.
In general, this type of separation of situation-specific data and general archetype behavior information goes on throughout npcclient scripting. The more you, the npc scripter, understands and leverages these differences the less scripting you will have to do and the less maintenance you will have to do to add new npcs, change maps or add new behaviors to existing ones.
|name||string||Mandatory||The name of this NPC Type.|
|parent||string||Name of parent NPCTypes. Behaviors and reaction from the parents will be inherited into the new NPCType. Multiple inheritance is possible: parent="<parent1>,<parent2>,...,<parentN>"|
|ang_vel||float||2PI||The default rate for turning for this NPC Type.|
|vel||float,$WALK,$RUN||1.5 or inherited value if parent||The default velocity for moving for this NPC Type. $WALK,$RUN looks up values from the NPC.|
|collide||string||Global perception to fire for collision perceptions (Movement operations)|
|out_of_bounds||string||Global perception to fire for out of bounds (Movement operations)|
|in_bound||string||Global perception to fire for in bounds (Movement operations)|
|falling||string||Global perception to fire for falling (Movement operations)|
Inherit NPC Types
The following example show how the Baker inherit the beavior of the Citizen.
Ex: <npctype name="Citizen" vel="$WALK" > <behavior ... /> ... <react ... /> </npctype> <npctype name="Baker" parent="Citizen" ang_vel="1.0" > <behavior ... /> ... <react ... /> </npctype>