<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://planeshift.top-ix.org//pswiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Naeg</id>
	<title>PSwiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://planeshift.top-ix.org//pswiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Naeg"/>
	<link rel="alternate" type="text/html" href="https://planeshift.top-ix.org//pswiki/index.php/Special:Contributions/Naeg"/>
	<updated>2026-04-06T02:13:03Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.1</generator>
	<entry>
		<id>https://planeshift.top-ix.org//pswiki/index.php?title=HowTo_Add_a_NPC_Operation&amp;diff=10131</id>
		<title>HowTo Add a NPC Operation</title>
		<link rel="alternate" type="text/html" href="https://planeshift.top-ix.org//pswiki/index.php?title=HowTo_Add_a_NPC_Operation&amp;diff=10131"/>
		<updated>2013-04-04T16:35:24Z</updated>

		<summary type="html">&lt;p&gt;Naeg: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
&lt;br /&gt;
NOTE: In Work&lt;br /&gt;
&lt;br /&gt;
# Create new Operation Class in npcoperations&lt;br /&gt;
# Add Operation to npcbehave&lt;br /&gt;
# Create new Queue-Command in networkmgr&lt;br /&gt;
# Modify npcmessages&lt;br /&gt;
# Process Command in npcmanager and execute desired action&lt;br /&gt;
&lt;br /&gt;
== New Operation Class ==&lt;br /&gt;
&lt;br /&gt;
Example: LootOperation&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcoperations.h&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
/** Loot will make the NPC loot specified items&lt;br /&gt;
 *&lt;br /&gt;
 *  This class is the implementation of the loot operations&lt;br /&gt;
 *  used in behavior scripts for NPCS.&lt;br /&gt;
 *&lt;br /&gt;
 *  Examples: &amp;lt;pre&amp;gt;&lt;br /&gt;
 *  \&amp;lt;loot type=&amp;quot;all&amp;quot;     /\&amp;gt;&lt;br /&gt;
 *  \&amp;lt;loot type=&amp;quot;weapons&amp;quot; /\&amp;gt; &amp;lt;/pre&amp;gt;&lt;br /&gt;
 */&lt;br /&gt;
class LootOperation : public ScriptOperation&lt;br /&gt;
{&lt;br /&gt;
protected:&lt;br /&gt;
    csString type; ///&amp;lt; Type of items to loot&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
&lt;br /&gt;
    LootOperation(): ScriptOperation(&amp;quot;Loot&amp;quot;) {};&lt;br /&gt;
    virtual ~LootOperation() {};&lt;br /&gt;
    virtual OperationResult Run(NPC* npc,bool interrupted);&lt;br /&gt;
    virtual bool Load(iDocumentNode* node);&lt;br /&gt;
    virtual ScriptOperation* MakeCopy();&lt;br /&gt;
};&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcoperations.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
bool LootOperation::Load(iDocumentNode *node)&lt;br /&gt;
{&lt;br /&gt;
    type = node-&amp;gt;GetAttributeValue(&amp;quot;type&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    if(type.IsEmpty())&lt;br /&gt;
        type = &amp;quot;all&amp;quot;;&lt;br /&gt;
    &lt;br /&gt;
    return true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ScriptOperation* LootOperation::MakeCopy()&lt;br /&gt;
{&lt;br /&gt;
    LootOperation* op = new LootOperation;&lt;br /&gt;
&lt;br /&gt;
    op-&amp;gt;type = type;&lt;br /&gt;
&lt;br /&gt;
    return op;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ScriptOperation::OperationResult LootOperation::Run(NPC *npc, bool interrupted)&lt;br /&gt;
{&lt;br /&gt;
    npcclient-&amp;gt;GetNetworkMgr()-&amp;gt;QueueLootCommand(npc-&amp;gt;GetActor(), type);&lt;br /&gt;
    &lt;br /&gt;
    return OPERATION_COMPLETED; // Nothing more to do for this op.&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Add Operation to npcbehave ==&lt;br /&gt;
Add new operation to Behavior::LoadScript():&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcbehave.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
bool Behavior::LoadScript(iDocumentNode *node,bool top_level)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
        else if ( strcmp( node-&amp;gt;GetValue(), &amp;quot;loot&amp;quot; ) == 0 )&lt;br /&gt;
        {&lt;br /&gt;
            op = new LootOperation;&lt;br /&gt;
        }&lt;br /&gt;
   // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== New Queue-Command ==&lt;br /&gt;
src/npcclient/networkmgr.h&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
    /**&lt;br /&gt;
     * Send a command to loot selected target.&lt;br /&gt;
     */&lt;br /&gt;
    void QueueLootCommand(gemNPCActor *entity, const csString&amp;amp; type);&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
src/npcclient/networkmgr.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
void NetworkManager::QueueLootCommand(gemNPCActor *entity, const csString&amp;amp; type)&lt;br /&gt;
{&lt;br /&gt;
    CheckCommandsOverrun(sizeof(uint8_t) + sizeof(uint32_t) + (type.Length()+1));&lt;br /&gt;
&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add((int8_t) psNPCCommandsMessage::CMD_LOOT);&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add(entity-&amp;gt;GetEID().Unbox());&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add(type);&lt;br /&gt;
&lt;br /&gt;
    if(outbound-&amp;gt;msg-&amp;gt;overrun)&lt;br /&gt;
    {&lt;br /&gt;
        CS_ASSERT(!&amp;quot;NetworkManager::QueueLootCommand put message in overrun state!\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    cmd_count++;&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Modify npcmessages ==&lt;br /&gt;
&lt;br /&gt;
Add new CMD to PerceptionType:&lt;br /&gt;
&lt;br /&gt;
src/common/net/npcmessages.h&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
    enum PerceptionType&lt;br /&gt;
    {&lt;br /&gt;
        // Commands go from superclient to server&lt;br /&gt;
        // [...]&lt;br /&gt;
        CMD_CONTROL,&lt;br /&gt;
	CMD_LOOT, // new CMD for looting&lt;br /&gt;
        // Perceptions go from server to superclient&lt;br /&gt;
        PCPT_ANYRANGEPLAYER,&lt;br /&gt;
        // [...]&lt;br /&gt;
    };&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add new case to psNPCCOmmandsMessage::ToString():&lt;br /&gt;
&lt;br /&gt;
src/common/net/npcmessages.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
csString psNPCCommandsMessage::ToString(NetBase::AccessPointers * accessPointers)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
&lt;br /&gt;
	    case psNPCCommandsMessage::CMD_LOOT:&lt;br /&gt;
            {&lt;br /&gt;
                msgtext.Append(&amp;quot;CMD_LOOT: &amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                // Extract the data&lt;br /&gt;
                EID entity_id = EID(msg-&amp;gt;GetUInt32());&lt;br /&gt;
                csString type = msg-&amp;gt;GetStr();&lt;br /&gt;
&lt;br /&gt;
                // Make sure we haven&#039;t run past the end of the buffer&lt;br /&gt;
                if(msg-&amp;gt;overrun)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug2(LOG_SUPERCLIENT,msg-&amp;gt;clientnum,&amp;quot;Received incomplete CMD_LOOT from NPC client %u.\n&amp;quot;,msg-&amp;gt;clientnum);&lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                msgtext.AppendFmt(&amp;quot;EID: %u Type: %s&amp;quot;, entity_id.Unbox(), type.GetData());&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
            // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Process Command ==&lt;br /&gt;
Add case for new Command in NPCManager::HandleCommandList():&lt;br /&gt;
&lt;br /&gt;
src/server/npcmanager.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
void NPCManager::HandleCommandList(MsgEntry* me,Client* client)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
            case psNPCCommandsMessage::CMD_LOOT:&lt;br /&gt;
            {&lt;br /&gt;
                EID entity_id = EID(list.msg-&amp;gt;GetUInt32());&lt;br /&gt;
                csString type = list.msg-&amp;gt;GetStr();&lt;br /&gt;
                Debug3(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;--&amp;gt;Got loot cmd: Entity %s to loot for %s\n&amp;quot;,&lt;br /&gt;
                       ShowID(entity_id), type.GetData());&lt;br /&gt;
&lt;br /&gt;
                // Make sure we haven&#039;t run past the end of the buffer&lt;br /&gt;
                if(list.msg-&amp;gt;overrun)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug2(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;Received incomplete CMD_LOOT from NPC client %u.\n&amp;quot;, me-&amp;gt;clientnum);&lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                gemActor* actor = dynamic_cast&amp;lt;gemActor*&amp;gt;(gemSupervisor-&amp;gt;FindObject(entity_id));&lt;br /&gt;
                &lt;br /&gt;
                if(actor)&lt;br /&gt;
                {&lt;br /&gt;
                    if(psserver-&amp;gt;GetUserManager()-&amp;gt;CheckTargetLootable(actor, NULL))&lt;br /&gt;
                    {&lt;br /&gt;
                        psserver-&amp;gt;GetUserManager()-&amp;gt;LootMoney(actor, NULL);&lt;br /&gt;
                        psserver-&amp;gt;GetUserManager()-&amp;gt;LootItems(actor, NULL, type);&lt;br /&gt;
                    }&lt;br /&gt;
                    // TODO: Add inventory change perception to make npc put items into tribe&#039;s resources&lt;br /&gt;
                }&lt;br /&gt;
                else&lt;br /&gt;
                     Error1(&amp;quot;NPC Client try to loot with no existing npc&amp;quot;);&lt;br /&gt;
                &lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
        // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Test ==&lt;br /&gt;
&lt;br /&gt;
Create a behavior to test with:&lt;br /&gt;
&lt;br /&gt;
Add new &amp;lt;behavior&amp;gt; and &amp;lt;react event&amp;gt; to AbstractTribesman in sc_npctypes.sql.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
INSERT INTO sc_npctypes VALUES(&amp;quot;109&amp;quot;,&amp;quot;AbstractTribesman&amp;quot;,&amp;quot;DoNothing,Move&amp;quot;,0,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;1&amp;quot;,&lt;br /&gt;
&#039;&amp;lt;!-- Abstract base npc type for tribes --&amp;gt;&lt;br /&gt;
&amp;lt;!-- [...] --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;behavior name=&amp;quot;test_loot&amp;quot; &amp;gt;&lt;br /&gt;
  &amp;lt;loot type=&amp;quot;all&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/behavior&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;react event=&amp;quot;test_loot&amp;quot; behavior=&amp;quot;test_loot&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;!-- [...] --&amp;gt;&lt;br /&gt;
&#039;);&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reload the table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;mysql -u planeshift -pplaneshift planeshift&lt;br /&gt;
&lt;br /&gt;
mysql&amp;gt; source sc_npctypes.sql;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On the  psclient click on a NPC Hunter or Miner (has to be one of these due to &amp;quot;AbstractTribesman&amp;quot;) and execute these commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
/debugnpc&lt;br /&gt;
&lt;br /&gt;
/percept test_loot test_loot&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Depending on where you sent DEBUG Messages, you can either see them in psnpcclient or psserver. Make sure LOG_SUPERCLIENT is active (setlog LOG_SUPERCLIENT).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine documents]] [[Category:NPCClient Design]]&lt;/div&gt;</summary>
		<author><name>Naeg</name></author>
	</entry>
	<entry>
		<id>https://planeshift.top-ix.org//pswiki/index.php?title=HowTo_Add_a_NPC_Operation&amp;diff=10130</id>
		<title>HowTo Add a NPC Operation</title>
		<link rel="alternate" type="text/html" href="https://planeshift.top-ix.org//pswiki/index.php?title=HowTo_Add_a_NPC_Operation&amp;diff=10130"/>
		<updated>2013-04-02T22:04:25Z</updated>

		<summary type="html">&lt;p&gt;Naeg: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
&lt;br /&gt;
NOTE: In Work&lt;br /&gt;
&lt;br /&gt;
# Create new Operation Class in npcoperations&lt;br /&gt;
# Add Operation to npcbehave&lt;br /&gt;
# Create new Queue-Command in networkmgr&lt;br /&gt;
# Modify npcmessages&lt;br /&gt;
# Process Command in npcmanager and execute desired action&lt;br /&gt;
&lt;br /&gt;
== New Operation Class ==&lt;br /&gt;
&lt;br /&gt;
Example: LootOperation&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcoperations.h&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
/** Loot will make the NPC loot specified items&lt;br /&gt;
 *&lt;br /&gt;
 *  This class is the implementation of the loot operations&lt;br /&gt;
 *  used in behavior scripts for NPCS.&lt;br /&gt;
 *&lt;br /&gt;
 *  Examples: &amp;lt;pre&amp;gt;&lt;br /&gt;
 *  \&amp;lt;loot type=&amp;quot;all&amp;quot;     /\&amp;gt;&lt;br /&gt;
 *  \&amp;lt;loot type=&amp;quot;weapons&amp;quot; /\&amp;gt; &amp;lt;/pre&amp;gt;&lt;br /&gt;
 */&lt;br /&gt;
class LootOperation : public ScriptOperation&lt;br /&gt;
{&lt;br /&gt;
protected:&lt;br /&gt;
    csString type; ///&amp;lt; Type of items to loot&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
&lt;br /&gt;
    LootOperation(): ScriptOperation(&amp;quot;Loot&amp;quot;) {};&lt;br /&gt;
    virtual ~LootOperation() {};&lt;br /&gt;
    virtual OperationResult Run(NPC* npc,bool interrupted);&lt;br /&gt;
    virtual bool Load(iDocumentNode* node);&lt;br /&gt;
    virtual ScriptOperation* MakeCopy();&lt;br /&gt;
};&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcoperations.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
bool LootOperation::Load(iDocumentNode *node)&lt;br /&gt;
{&lt;br /&gt;
    type = node-&amp;gt;GetAttributeValue(&amp;quot;type&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    if(type.IsEmpty())&lt;br /&gt;
        type = &amp;quot;all&amp;quot;;&lt;br /&gt;
    &lt;br /&gt;
    return true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ScriptOperation* LootOperation::MakeCopy()&lt;br /&gt;
{&lt;br /&gt;
    LootOperation* op = new LootOperation;&lt;br /&gt;
&lt;br /&gt;
    op-&amp;gt;type = type;&lt;br /&gt;
&lt;br /&gt;
    return op;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ScriptOperation::OperationResult LootOperation::Run(NPC *npc, bool interrupted)&lt;br /&gt;
{&lt;br /&gt;
    npcclient-&amp;gt;GetNetworkMgr()-&amp;gt;QueueLootCommand(npc-&amp;gt;GetActor(), type);&lt;br /&gt;
    &lt;br /&gt;
    return OPERATION_COMPLETED; // Nothing more to do for this op.&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Add Operation to npcbehave ==&lt;br /&gt;
Add new operation to Behavior::LoadScript():&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcbehave.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
bool Behavior::LoadScript(iDocumentNode *node,bool top_level)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
        else if ( strcmp( node-&amp;gt;GetValue(), &amp;quot;loot&amp;quot; ) == 0 )&lt;br /&gt;
        {&lt;br /&gt;
            op = new LootOperation;&lt;br /&gt;
        }&lt;br /&gt;
   // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== New Queue-Command ==&lt;br /&gt;
src/npcclient/networkmgr.h&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
    /**&lt;br /&gt;
     * Send a command to loot selected target.&lt;br /&gt;
     */&lt;br /&gt;
    void QueueLootCommand(gemNPCActor *entity, const csString&amp;amp; type);&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
src/npcclient/networkmgr.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
void NetworkManager::QueueLootCommand(gemNPCActor *entity, const csString&amp;amp; type)&lt;br /&gt;
{&lt;br /&gt;
    CheckCommandsOverrun(sizeof(uint8_t) + sizeof(uint32_t) + (type.Length()+1));&lt;br /&gt;
&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add((int8_t) psNPCCommandsMessage::CMD_LOOT);&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add(entity-&amp;gt;GetEID().Unbox());&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add(type);&lt;br /&gt;
&lt;br /&gt;
    if(outbound-&amp;gt;msg-&amp;gt;overrun)&lt;br /&gt;
    {&lt;br /&gt;
        CS_ASSERT(!&amp;quot;NetworkManager::QueueLootCommand put message in overrun state!\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    cmd_count++;&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Modify npcmessages ==&lt;br /&gt;
&lt;br /&gt;
Add new CMD to PerceptionType:&lt;br /&gt;
&lt;br /&gt;
src/common/net/npcmessages.h&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
    enum PerceptionType&lt;br /&gt;
    {&lt;br /&gt;
        // Commands go from superclient to server&lt;br /&gt;
        // [...]&lt;br /&gt;
        CMD_CONTROL,&lt;br /&gt;
	CMD_LOOT, // new CMD for looting&lt;br /&gt;
        // Perceptions go from server to superclient&lt;br /&gt;
        PCPT_ANYRANGEPLAYER,&lt;br /&gt;
        // [...]&lt;br /&gt;
    };&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add new case to psNPCCOmmandsMessage::ToString():&lt;br /&gt;
&lt;br /&gt;
src/common/net/npcmessages.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
csString psNPCCommandsMessage::ToString(NetBase::AccessPointers * accessPointers)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
&lt;br /&gt;
	    case psNPCCommandsMessage::CMD_LOOT:&lt;br /&gt;
            {&lt;br /&gt;
                msgtext.Append(&amp;quot;CMD_LOOT: &amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                // Extract the data&lt;br /&gt;
                EID entity_id = EID(msg-&amp;gt;GetUInt32());&lt;br /&gt;
                csString type = msg-&amp;gt;GetStr();&lt;br /&gt;
&lt;br /&gt;
                // Make sure we haven&#039;t run past the end of the buffer&lt;br /&gt;
                if(msg-&amp;gt;overrun)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug2(LOG_SUPERCLIENT,msg-&amp;gt;clientnum,&amp;quot;Received incomplete CMD_LOOT from NPC client %u.\n&amp;quot;,msg-&amp;gt;clientnum);&lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                msgtext.AppendFmt(&amp;quot;EID: %u Type: %s&amp;quot;, entity_id.Unbox(), type.GetData());&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
            // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Process Command ==&lt;br /&gt;
Add case for new Command in NPCManager::HandleCommandList():&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcmanager.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
void NPCManager::HandleCommandList(MsgEntry* me,Client* client)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
            case psNPCCommandsMessage::CMD_LOOT:&lt;br /&gt;
            {&lt;br /&gt;
                EID entity_id = EID(list.msg-&amp;gt;GetUInt32());&lt;br /&gt;
                csString type = list.msg-&amp;gt;GetStr();&lt;br /&gt;
                Debug4(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;--&amp;gt;Got loot cmd: Entity %s to loot for %s\n&amp;quot;,&lt;br /&gt;
                       ShowID(entity_id), type.GetData());&lt;br /&gt;
&lt;br /&gt;
                // Make sure we haven&#039;t run past the end of the buffer&lt;br /&gt;
                if(list.msg-&amp;gt;overrun)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug2(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;Received incomplete CMD_LOOT from NPC client %u.\n&amp;quot;, me-&amp;gt;clientnum);&lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                gemNPCActor* npc = dynamic_cast&amp;lt;gemNPCActor*&amp;gt;(gemSupervisor-&amp;gt;FindObject(entity_id));&lt;br /&gt;
                &lt;br /&gt;
                /*  NEEDED?&lt;br /&gt;
                psCharacter* chardata = NULL;&lt;br /&gt;
                &lt;br /&gt;
                if(npc) chardata = npc-&amp;gt;GetCharacterData();&lt;br /&gt;
                &lt;br /&gt;
                if(!chardata)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug1(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;Couldn&#039;t find character data.\n&amp;quot;);&lt;br /&gt;
                    break;&lt;br /&gt;
                }*/&lt;br /&gt;
                &lt;br /&gt;
                if(npc)&lt;br /&gt;
                {&lt;br /&gt;
                    psserver-&amp;gt;GetUserManager()-&amp;gt;LootMoney(client);&lt;br /&gt;
                    psserver-&amp;gt;GetUserManager()-&amp;gt;LootItems(client, type);&lt;br /&gt;
                    &lt;br /&gt;
                    if(npc-&amp;gt;GetTribeID())&lt;br /&gt;
                    {&lt;br /&gt;
                        // add loot to tribe&#039;s resources&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                else&lt;br /&gt;
                     Error1(&amp;quot;NPC Client try to loot with no existing npc&amp;quot;);&lt;br /&gt;
                &lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
        // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Test ==&lt;br /&gt;
&lt;br /&gt;
Create a behavior to test with:&lt;br /&gt;
&lt;br /&gt;
Add new &amp;lt;behavior&amp;gt; and &amp;lt;react event&amp;gt; to AbstractTribesman in sc_npctypes.sql.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
INSERT INTO sc_npctypes VALUES(&amp;quot;109&amp;quot;,&amp;quot;AbstractTribesman&amp;quot;,&amp;quot;DoNothing,Move&amp;quot;,0,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;1&amp;quot;,&lt;br /&gt;
&#039;&amp;lt;!-- Abstract base npc type for tribes --&amp;gt;&lt;br /&gt;
&amp;lt;!-- [...] --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;behavior name=&amp;quot;test_loot&amp;quot; &amp;gt;&lt;br /&gt;
  &amp;lt;loot type=&amp;quot;all&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/behavior&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;react event=&amp;quot;test_loot&amp;quot; behavior=&amp;quot;test_loot&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;!-- [...] --&amp;gt;&lt;br /&gt;
&#039;);&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reload the table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;mysql -u planeshift -pplaneshift planeshift&lt;br /&gt;
&lt;br /&gt;
mysql&amp;gt; source sc_npctypes.sql;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On the  psclient click on a NPC Hunter or Miner (has to be one of these due to &amp;quot;AbstractTribesman&amp;quot;) and execute these commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
/debugnpc&lt;br /&gt;
&lt;br /&gt;
/percept test_loot test_loot&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine documents]] [[Category:NPCClient Design]]&lt;/div&gt;</summary>
		<author><name>Naeg</name></author>
	</entry>
	<entry>
		<id>https://planeshift.top-ix.org//pswiki/index.php?title=HowTo_Add_a_NPC_Operation&amp;diff=10129</id>
		<title>HowTo Add a NPC Operation</title>
		<link rel="alternate" type="text/html" href="https://planeshift.top-ix.org//pswiki/index.php?title=HowTo_Add_a_NPC_Operation&amp;diff=10129"/>
		<updated>2013-04-02T18:46:28Z</updated>

		<summary type="html">&lt;p&gt;Naeg: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
&lt;br /&gt;
NOTE: In Work&lt;br /&gt;
&lt;br /&gt;
# Create new Operation Class in npcoperations&lt;br /&gt;
# Add Operation to npcbehave&lt;br /&gt;
# Create new Queue-Command in networkmgr&lt;br /&gt;
# Modify npcmessages&lt;br /&gt;
# Process Command in npcmanager and execute desired action&lt;br /&gt;
&lt;br /&gt;
== New Operation Class ==&lt;br /&gt;
&lt;br /&gt;
Example: LootOperation&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcoperations.h&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
/** Loot will make the NPC loot specified items&lt;br /&gt;
 *&lt;br /&gt;
 *  This class is the implementation of the loot operations&lt;br /&gt;
 *  used in behavior scripts for NPCS.&lt;br /&gt;
 *&lt;br /&gt;
 *  Examples: &amp;lt;pre&amp;gt;&lt;br /&gt;
 *  \&amp;lt;loot type=&amp;quot;all&amp;quot;     /\&amp;gt;&lt;br /&gt;
 *  \&amp;lt;loot type=&amp;quot;weapons&amp;quot; /\&amp;gt; &amp;lt;/pre&amp;gt;&lt;br /&gt;
 */&lt;br /&gt;
class LootOperation : public ScriptOperation&lt;br /&gt;
{&lt;br /&gt;
protected:&lt;br /&gt;
    csString type; ///&amp;lt; Type of items to loot&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
&lt;br /&gt;
    LootOperation(): ScriptOperation(&amp;quot;Loot&amp;quot;) {};&lt;br /&gt;
    virtual ~LootOperation() {};&lt;br /&gt;
    virtual OperationResult Run(NPC* npc,bool interrupted);&lt;br /&gt;
    virtual bool Load(iDocumentNode* node);&lt;br /&gt;
    virtual ScriptOperation* MakeCopy();&lt;br /&gt;
};&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcoperations.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
bool LootOperation::Load(iDocumentNode *node)&lt;br /&gt;
{&lt;br /&gt;
    type = node-&amp;gt;GetAttributeValue(&amp;quot;type&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    if(type.IsEmpty())&lt;br /&gt;
        type = &amp;quot;all&amp;quot;;&lt;br /&gt;
    &lt;br /&gt;
    return true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ScriptOperation* LootOperation::MakeCopy()&lt;br /&gt;
{&lt;br /&gt;
    LootOperation* op = new LootOperation;&lt;br /&gt;
&lt;br /&gt;
    op-&amp;gt;type = type;&lt;br /&gt;
&lt;br /&gt;
    return op;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ScriptOperation::OperationResult LootOperation::Run(NPC *npc, bool interrupted)&lt;br /&gt;
{&lt;br /&gt;
    npcclient-&amp;gt;GetNetworkMgr()-&amp;gt;QueueLootCommand(npc-&amp;gt;GetActor(), type);&lt;br /&gt;
    &lt;br /&gt;
    return OPERATION_COMPLETED; // Nothing more to do for this op.&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Add Operation to npcbehave ==&lt;br /&gt;
Add new operation to Behavior::LoadScript():&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcbehave.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
bool Behavior::LoadScript(iDocumentNode *node,bool top_level)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
        else if ( strcmp( node-&amp;gt;GetValue(), &amp;quot;loot&amp;quot; ) == 0 )&lt;br /&gt;
        {&lt;br /&gt;
            op = new LootOperation;&lt;br /&gt;
        }&lt;br /&gt;
   // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== New Queue-Command ==&lt;br /&gt;
src/npcclient/networkmgr.h&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
    /**&lt;br /&gt;
     * Send a command to loot selected target.&lt;br /&gt;
     */&lt;br /&gt;
    void QueueLootCommand(gemNPCActor *entity, const csString&amp;amp; type);&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
src/npcclient/networkmgr.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
void NetworkManager::QueueLootCommand(gemNPCActor *entity, const csString&amp;amp; type)&lt;br /&gt;
{&lt;br /&gt;
    CheckCommandsOverrun(sizeof(uint8_t) + sizeof(uint32_t) + (type.Length()+1));&lt;br /&gt;
&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add((int8_t) psNPCCommandsMessage::CMD_LOOT);&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add(entity-&amp;gt;GetEID().Unbox());&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add(type);&lt;br /&gt;
&lt;br /&gt;
    if(outbound-&amp;gt;msg-&amp;gt;overrun)&lt;br /&gt;
    {&lt;br /&gt;
        CS_ASSERT(!&amp;quot;NetworkManager::QueueLootCommand put message in overrun state!\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    cmd_count++;&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Modify npcmessages ==&lt;br /&gt;
&lt;br /&gt;
Add new CMD to PerceptionType:&lt;br /&gt;
&lt;br /&gt;
src/common/net/npcmessages.h&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
    enum PerceptionType&lt;br /&gt;
    {&lt;br /&gt;
        // Commands go from superclient to server&lt;br /&gt;
        // [...]&lt;br /&gt;
        CMD_CONTROL,&lt;br /&gt;
	CMD_LOOT, // new CMD for looting&lt;br /&gt;
        // Perceptions go from server to superclient&lt;br /&gt;
        PCPT_ANYRANGEPLAYER,&lt;br /&gt;
        // [...]&lt;br /&gt;
    };&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add new case to psNPCCOmmandsMessage::ToString():&lt;br /&gt;
&lt;br /&gt;
src/common/net/npcmessages.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
csString psNPCCommandsMessage::ToString(NetBase::AccessPointers * accessPointers)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
&lt;br /&gt;
	    case psNPCCommandsMessage::CMD_LOOT:&lt;br /&gt;
            {&lt;br /&gt;
                msgtext.Append(&amp;quot;CMD_LOOT: &amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                // Extract the data&lt;br /&gt;
                EID entity_id = EID(msg-&amp;gt;GetUInt32());&lt;br /&gt;
                csString type = msg-&amp;gt;GetStr();&lt;br /&gt;
&lt;br /&gt;
                // Make sure we haven&#039;t run past the end of the buffer&lt;br /&gt;
                if(msg-&amp;gt;overrun)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug2(LOG_SUPERCLIENT,msg-&amp;gt;clientnum,&amp;quot;Received incomplete CMD_LOOT from NPC client %u.\n&amp;quot;,msg-&amp;gt;clientnum);&lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                msgtext.AppendFmt(&amp;quot;EID: %u Type: %s&amp;quot;, entity_id.Unbox(), type.GetData());&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
            // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Process Command ==&lt;br /&gt;
Add case for new Command in NPCManager::HandleCommandList():&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcmanager.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
void NPCManager::HandleCommandList(MsgEntry* me,Client* client)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
            case psNPCCommandsMessage::CMD_LOOT:&lt;br /&gt;
            {&lt;br /&gt;
                EID entity_id = EID(list.msg-&amp;gt;GetUInt32());&lt;br /&gt;
                csString type = list.msg-&amp;gt;GetStr();&lt;br /&gt;
                Debug4(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;--&amp;gt;Got loot cmd: Entity %s to loot for %s\n&amp;quot;,&lt;br /&gt;
                       ShowID(entity_id), type.GetData());&lt;br /&gt;
&lt;br /&gt;
                // Make sure we haven&#039;t run past the end of the buffer&lt;br /&gt;
                if(list.msg-&amp;gt;overrun)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug2(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;Received incomplete CMD_LOOT from NPC client %u.\n&amp;quot;, me-&amp;gt;clientnum);&lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                gemNPCActor* npc = dynamic_cast&amp;lt;gemNPCActor*&amp;gt;(gemSupervisor-&amp;gt;FindObject(entity_id));&lt;br /&gt;
                &lt;br /&gt;
                /*  NEEDED?&lt;br /&gt;
                psCharacter* chardata = NULL;&lt;br /&gt;
                &lt;br /&gt;
                if(npc) chardata = npc-&amp;gt;GetCharacterData();&lt;br /&gt;
                &lt;br /&gt;
                if(!chardata)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug1(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;Couldn&#039;t find character data.\n&amp;quot;);&lt;br /&gt;
                    break;&lt;br /&gt;
                }*/&lt;br /&gt;
                &lt;br /&gt;
                if(npc)&lt;br /&gt;
                {&lt;br /&gt;
                    psserver-&amp;gt;GetUserManager()-&amp;gt;LootMoney(client);&lt;br /&gt;
                    psserver-&amp;gt;GetUserManager()-&amp;gt;LootItems(client, type);&lt;br /&gt;
                    &lt;br /&gt;
                    if(npc-&amp;gt;GetTribeID())&lt;br /&gt;
                    {&lt;br /&gt;
                        // add loot to tribe&#039;s resources&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                else&lt;br /&gt;
                     Error1(&amp;quot;NPC Client try to loot with no existing npc&amp;quot;);&lt;br /&gt;
                &lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
        // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Test ==&lt;br /&gt;
&lt;br /&gt;
Create a behavior to test with:&lt;br /&gt;
&lt;br /&gt;
Add new &amp;lt;behavior&amp;gt; and &amp;lt;react event&amp;gt; to AbstractTribesman in sc_npctypes.sql and reload the table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
INSERT INTO sc_npctypes VALUES(&amp;quot;109&amp;quot;,&amp;quot;AbstractTribesman&amp;quot;,&amp;quot;DoNothing,Move&amp;quot;,0,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;1&amp;quot;,&lt;br /&gt;
&#039;&amp;lt;!-- Abstract base npc type for tribes --&amp;gt;&lt;br /&gt;
&amp;lt;!-- [...] --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;behavior name=&amp;quot;test_loot&amp;quot; &amp;gt;&lt;br /&gt;
  &amp;lt;loot type=&amp;quot;all&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/behavior&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;react event=&amp;quot;test_loot&amp;quot; behavior=&amp;quot;test_loot&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;!-- [...] --&amp;gt;&lt;br /&gt;
&#039;);&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
From client /percept ... test_loot to execute the function. Do /debug_npc first to monitor.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine documents]] [[Category:NPCClient Design]]&lt;/div&gt;</summary>
		<author><name>Naeg</name></author>
	</entry>
	<entry>
		<id>https://planeshift.top-ix.org//pswiki/index.php?title=HowTo_Add_a_NPC_Operation&amp;diff=10128</id>
		<title>HowTo Add a NPC Operation</title>
		<link rel="alternate" type="text/html" href="https://planeshift.top-ix.org//pswiki/index.php?title=HowTo_Add_a_NPC_Operation&amp;diff=10128"/>
		<updated>2013-04-01T21:24:24Z</updated>

		<summary type="html">&lt;p&gt;Naeg: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
&lt;br /&gt;
NOTE: In Work&lt;br /&gt;
&lt;br /&gt;
# Create new Operation Class in npcoperations&lt;br /&gt;
# Add Operation to npcbehave&lt;br /&gt;
# Create new Queue-Command in networkmgr&lt;br /&gt;
# Modify npcmessages&lt;br /&gt;
# Process Command in npcmanager and execute desired action&lt;br /&gt;
&lt;br /&gt;
== New Operation Class ==&lt;br /&gt;
&lt;br /&gt;
Example: LootOperation&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcoperations.h&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
/** Loot will make the NPC loot specified items&lt;br /&gt;
 *&lt;br /&gt;
 *  This class is the implementation of the loot operations&lt;br /&gt;
 *  used in behavior scripts for NPCS.&lt;br /&gt;
 *&lt;br /&gt;
 *  Examples: &amp;lt;pre&amp;gt;&lt;br /&gt;
 *  \&amp;lt;loot type=&amp;quot;all&amp;quot;     /\&amp;gt;&lt;br /&gt;
 *  \&amp;lt;loot type=&amp;quot;weapons&amp;quot; /\&amp;gt; &amp;lt;/pre&amp;gt;&lt;br /&gt;
 */&lt;br /&gt;
class LootOperation : public ScriptOperation&lt;br /&gt;
{&lt;br /&gt;
protected:&lt;br /&gt;
    csString type; ///&amp;lt; Type of items to loot&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
&lt;br /&gt;
    LootOperation(): ScriptOperation(&amp;quot;Loot&amp;quot;) {};&lt;br /&gt;
    virtual ~LootOperation() {};&lt;br /&gt;
    virtual OperationResult Run(NPC* npc,bool interrupted);&lt;br /&gt;
    virtual bool Load(iDocumentNode* node);&lt;br /&gt;
    virtual ScriptOperation* MakeCopy();&lt;br /&gt;
};&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcoperations.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
bool LootOperation::Load(iDocumentNode *node)&lt;br /&gt;
{&lt;br /&gt;
    type = node-&amp;gt;GetAttributeValue(&amp;quot;type&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    if(type.IsEmpty())&lt;br /&gt;
        type = &amp;quot;all&amp;quot;;&lt;br /&gt;
    &lt;br /&gt;
    return true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ScriptOperation* LootOperation::MakeCopy()&lt;br /&gt;
{&lt;br /&gt;
    LootOperation* op = new LootOperation;&lt;br /&gt;
&lt;br /&gt;
    op-&amp;gt;type = type;&lt;br /&gt;
&lt;br /&gt;
    return op;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ScriptOperation::OperationResult LootOperation::Run(NPC *npc, bool interrupted)&lt;br /&gt;
{&lt;br /&gt;
    npcclient-&amp;gt;GetNetworkMgr()-&amp;gt;QueueLootCommand(npc-&amp;gt;GetActor(), type);&lt;br /&gt;
    &lt;br /&gt;
    return OPERATION_COMPLETED; // Nothing more to do for this op.&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Add Operation to npcbehave ==&lt;br /&gt;
Add new operation to Behavior::LoadScript():&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcbehave.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
bool Behavior::LoadScript(iDocumentNode *node,bool top_level)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
        else if ( strcmp( node-&amp;gt;GetValue(), &amp;quot;loot&amp;quot; ) == 0 )&lt;br /&gt;
        {&lt;br /&gt;
            op = new LootOperation;&lt;br /&gt;
        }&lt;br /&gt;
   // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== New Queue-Command ==&lt;br /&gt;
src/npcclient/networkmgr.h&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
    /**&lt;br /&gt;
     * Send a command to loot selected target.&lt;br /&gt;
     */&lt;br /&gt;
    void QueueLootCommand(gemNPCActor *entity, const csString&amp;amp; type);&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
src/npcclient/networkmgr.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
void NetworkManager::QueueLootCommand(gemNPCActor *entity, const csString&amp;amp; type)&lt;br /&gt;
{&lt;br /&gt;
    CheckCommandsOverrun(sizeof(uint8_t) + sizeof(uint32_t) + (type.Length()+1));&lt;br /&gt;
&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add((int8_t) psNPCCommandsMessage::CMD_LOOT);&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add(entity-&amp;gt;GetEID().Unbox());&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add(type);&lt;br /&gt;
&lt;br /&gt;
    if(outbound-&amp;gt;msg-&amp;gt;overrun)&lt;br /&gt;
    {&lt;br /&gt;
        CS_ASSERT(!&amp;quot;NetworkManager::QueueLootCommand put message in overrun state!\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    cmd_count++;&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Modify npcmessages ==&lt;br /&gt;
&lt;br /&gt;
Add new CMD to PerceptionType:&lt;br /&gt;
&lt;br /&gt;
src/common/net/npcmessages.h&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
    enum PerceptionType&lt;br /&gt;
    {&lt;br /&gt;
        // Commands go from superclient to server&lt;br /&gt;
        // [...]&lt;br /&gt;
        CMD_CONTROL,&lt;br /&gt;
	CMD_LOOT, // new CMD for looting&lt;br /&gt;
        // Perceptions go from server to superclient&lt;br /&gt;
        PCPT_ANYRANGEPLAYER,&lt;br /&gt;
        // [...]&lt;br /&gt;
    };&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add new case to psNPCCOmmandsMessage::ToString():&lt;br /&gt;
&lt;br /&gt;
src/common/net/npcmessages.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
csString psNPCCommandsMessage::ToString(NetBase::AccessPointers * accessPointers)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
&lt;br /&gt;
	    case psNPCCommandsMessage::CMD_LOOT:&lt;br /&gt;
            {&lt;br /&gt;
                msgtext.Append(&amp;quot;CMD_LOOT: &amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                // Extract the data&lt;br /&gt;
                EID entity_id = EID(msg-&amp;gt;GetUInt32());&lt;br /&gt;
                csString type = msg-&amp;gt;GetStr();&lt;br /&gt;
&lt;br /&gt;
                // Make sure we haven&#039;t run past the end of the buffer&lt;br /&gt;
                if(msg-&amp;gt;overrun)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug2(LOG_SUPERCLIENT,msg-&amp;gt;clientnum,&amp;quot;Received incomplete CMD_LOOT from NPC client %u.\n&amp;quot;,msg-&amp;gt;clientnum);&lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                msgtext.AppendFmt(&amp;quot;EID: %u Type: %s&amp;quot;, entity_id.Unbox(), type.GetData());&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
            // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Process Command ==&lt;br /&gt;
Add case for new Command in NPCManager::HandleCommandList():&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcmanager.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
void NPCManager::HandleCommandList(MsgEntry* me,Client* client)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
            case psNPCCommandsMessage::CMD_LOOT:&lt;br /&gt;
            {&lt;br /&gt;
                EID entity_id = EID(list.msg-&amp;gt;GetUInt32());&lt;br /&gt;
                csString type = list.msg-&amp;gt;GetStr();&lt;br /&gt;
                Debug4(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;--&amp;gt;Got loot cmd: Entity %s to loot for %s\n&amp;quot;,&lt;br /&gt;
                       ShowID(entity_id), type.GetData());&lt;br /&gt;
&lt;br /&gt;
                // Make sure we haven&#039;t run past the end of the buffer&lt;br /&gt;
                if(list.msg-&amp;gt;overrun)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug2(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;Received incomplete CMD_LOOT from NPC client %u.\n&amp;quot;, me-&amp;gt;clientnum);&lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                gemNPCActor* npc = dynamic_cast&amp;lt;gemNPCActor*&amp;gt;(gemSupervisor-&amp;gt;FindObject(entity_id));&lt;br /&gt;
                &lt;br /&gt;
                /*  NEEDED?&lt;br /&gt;
                psCharacter* chardata = NULL;&lt;br /&gt;
                &lt;br /&gt;
                if(npc) chardata = npc-&amp;gt;GetCharacterData();&lt;br /&gt;
                &lt;br /&gt;
                if(!chardata)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug1(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;Couldn&#039;t find character data.\n&amp;quot;);&lt;br /&gt;
                    break;&lt;br /&gt;
                }*/&lt;br /&gt;
                &lt;br /&gt;
                if(npc)&lt;br /&gt;
                {&lt;br /&gt;
                    psserver-&amp;gt;GetUserManager()-&amp;gt;LootMoney(client);&lt;br /&gt;
                    psserver-&amp;gt;GetUserManager()-&amp;gt;LootItems(client, type);&lt;br /&gt;
                    &lt;br /&gt;
                    if(npc-&amp;gt;GetTribeID())&lt;br /&gt;
                    {&lt;br /&gt;
                        // add loot to tribe&#039;s resources&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                else&lt;br /&gt;
                     Error1(&amp;quot;NPC Client try to loot with no existing npc&amp;quot;);&lt;br /&gt;
                &lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
        // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Test ==&lt;br /&gt;
&lt;br /&gt;
Create a behavior to test with:&lt;br /&gt;
&lt;br /&gt;
Add new &amp;lt;behavior&amp;gt; and &amp;lt;react event&amp;gt; to AbstractTribesman in sc_npctypes.sql and reload the table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
INSERT INTO sc_npctypes VALUES(&amp;quot;109&amp;quot;,&amp;quot;AbstractTribesman&amp;quot;,&amp;quot;DoNothing,Move&amp;quot;,0,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;1&amp;quot;,&lt;br /&gt;
&#039;&amp;lt;!-- Abstract base npc type for tribes --&amp;gt;&lt;br /&gt;
&amp;lt;!-- [...] --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;behavior &amp;quot;test_loot&amp;quot; &amp;gt;&lt;br /&gt;
  &amp;lt;loot type=&amp;quot;all&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/behavior&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;react event=&amp;quot;test_loot&amp;quot; behavior=&amp;quot;test_loot&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;!-- [...] --&amp;gt;&lt;br /&gt;
&#039;);&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
From client /percept ... test_loot to execute the function. Do /debug_npc first to monitor.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine documents]] [[Category:NPCClient Design]]&lt;/div&gt;</summary>
		<author><name>Naeg</name></author>
	</entry>
	<entry>
		<id>https://planeshift.top-ix.org//pswiki/index.php?title=HowTo_Add_a_NPC_Operation&amp;diff=10127</id>
		<title>HowTo Add a NPC Operation</title>
		<link rel="alternate" type="text/html" href="https://planeshift.top-ix.org//pswiki/index.php?title=HowTo_Add_a_NPC_Operation&amp;diff=10127"/>
		<updated>2013-04-01T20:45:28Z</updated>

		<summary type="html">&lt;p&gt;Naeg: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
&lt;br /&gt;
NOTE: In Work&lt;br /&gt;
&lt;br /&gt;
# Create new Operation Class in npcclient/npcoperations&lt;br /&gt;
# Add Operation to npcbehave&lt;br /&gt;
# Create new Queue-Command in npcclient/networkmgr&lt;br /&gt;
# Modify common/net/npcmessages&lt;br /&gt;
# Process Command in npcclient/npcmanager and execute desired action&lt;br /&gt;
&lt;br /&gt;
== New Operation Class ==&lt;br /&gt;
&lt;br /&gt;
Example: LootOperation&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcoperations.h&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
/** Loot will make the NPC loot specified items&lt;br /&gt;
 *&lt;br /&gt;
 *  This class is the implementation of the loot operations&lt;br /&gt;
 *  used in behavior scripts for NPCS.&lt;br /&gt;
 *&lt;br /&gt;
 *  Examples: &amp;lt;pre&amp;gt;&lt;br /&gt;
 *  \&amp;lt;loot type=&amp;quot;all&amp;quot;     /\&amp;gt;&lt;br /&gt;
 *  \&amp;lt;loot type=&amp;quot;weapons&amp;quot; /\&amp;gt; &amp;lt;/pre&amp;gt;&lt;br /&gt;
 */&lt;br /&gt;
class LootOperation : public ScriptOperation&lt;br /&gt;
{&lt;br /&gt;
protected:&lt;br /&gt;
    csString type; ///&amp;lt; Type of items to loot&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
&lt;br /&gt;
    LootOperation(): ScriptOperation(&amp;quot;Loot&amp;quot;) {};&lt;br /&gt;
    virtual ~LootOperation() {};&lt;br /&gt;
    virtual OperationResult Run(NPC* npc,bool interrupted);&lt;br /&gt;
    virtual bool Load(iDocumentNode* node);&lt;br /&gt;
    virtual ScriptOperation* MakeCopy();&lt;br /&gt;
};&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcoperations.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
bool LootOperation::Load(iDocumentNode *node)&lt;br /&gt;
{&lt;br /&gt;
    type = node-&amp;gt;GetAttributeValue(&amp;quot;type&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    if(type.IsEmpty())&lt;br /&gt;
        type = &amp;quot;all&amp;quot;;&lt;br /&gt;
    &lt;br /&gt;
    return true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ScriptOperation* LootOperation::MakeCopy()&lt;br /&gt;
{&lt;br /&gt;
    LootOperation* op = new LootOperation;&lt;br /&gt;
&lt;br /&gt;
    op-&amp;gt;type = type;&lt;br /&gt;
&lt;br /&gt;
    return op;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ScriptOperation::OperationResult LootOperation::Run(NPC *npc, bool interrupted)&lt;br /&gt;
{&lt;br /&gt;
    npcclient-&amp;gt;GetNetworkMgr()-&amp;gt;QueueLootCommand(npc-&amp;gt;GetActor(), type);&lt;br /&gt;
    &lt;br /&gt;
    return OPERATION_COMPLETED; // Nothing more to do for this op.&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Add Operation to npcbehave ==&lt;br /&gt;
Add new operation to Behavior::LoadScript():&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcbehave.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
bool Behavior::LoadScript(iDocumentNode *node,bool top_level)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
        else if ( strcmp( node-&amp;gt;GetValue(), &amp;quot;loot&amp;quot; ) == 0 )&lt;br /&gt;
        {&lt;br /&gt;
            op = new LootOperation;&lt;br /&gt;
        }&lt;br /&gt;
   // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== New Queue-Command ==&lt;br /&gt;
src/npcclient/networkmgr.h&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
    /**&lt;br /&gt;
     * Send a command to loot selected target.&lt;br /&gt;
     */&lt;br /&gt;
    void QueueLootCommand(gemNPCActor *entity, const csString&amp;amp; type);&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
src/npcclient/networkmgr.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
void NetworkManager::QueueLootCommand(gemNPCActor *entity, const csString&amp;amp; type)&lt;br /&gt;
{&lt;br /&gt;
    CheckCommandsOverrun(sizeof(uint8_t) + sizeof(uint32_t) + (type.Length()+1));&lt;br /&gt;
&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add((int8_t) psNPCCommandsMessage::CMD_LOOT);&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add(entity-&amp;gt;GetEID().Unbox());&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add(type);&lt;br /&gt;
&lt;br /&gt;
    if(outbound-&amp;gt;msg-&amp;gt;overrun)&lt;br /&gt;
    {&lt;br /&gt;
        CS_ASSERT(!&amp;quot;NetworkManager::QueueLootCommand put message in overrun state!\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    cmd_count++;&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Modify npcmessages ==&lt;br /&gt;
&lt;br /&gt;
Add new CMD to PerceptionType:&lt;br /&gt;
&lt;br /&gt;
src/common/net/npcmessages.h&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
    enum PerceptionType&lt;br /&gt;
    {&lt;br /&gt;
        // Commands go from superclient to server&lt;br /&gt;
        // [...]&lt;br /&gt;
        CMD_CONTROL,&lt;br /&gt;
	CMD_LOOT, // new CMD for looting&lt;br /&gt;
        // Perceptions go from server to superclient&lt;br /&gt;
        PCPT_ANYRANGEPLAYER,&lt;br /&gt;
        // [...]&lt;br /&gt;
    };&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add new case to psNPCCOmmandsMessage::ToString():&lt;br /&gt;
&lt;br /&gt;
src/common/net/npcmessages.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
csString psNPCCommandsMessage::ToString(NetBase::AccessPointers * accessPointers)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
&lt;br /&gt;
	    case psNPCCommandsMessage::CMD_LOOT:&lt;br /&gt;
            {&lt;br /&gt;
                msgtext.Append(&amp;quot;CMD_LOOT: &amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                // Extract the data&lt;br /&gt;
                EID entity_id = EID(msg-&amp;gt;GetUInt32());&lt;br /&gt;
                csString type = msg-&amp;gt;GetStr();&lt;br /&gt;
&lt;br /&gt;
                // Make sure we haven&#039;t run past the end of the buffer&lt;br /&gt;
                if(msg-&amp;gt;overrun)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug2(LOG_SUPERCLIENT,msg-&amp;gt;clientnum,&amp;quot;Received incomplete CMD_LOOT from NPC client %u.\n&amp;quot;,msg-&amp;gt;clientnum);&lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                msgtext.AppendFmt(&amp;quot;EID: %u Type: %s&amp;quot;, entity_id.Unbox(), type.GetData());&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
            // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Process Command ==&lt;br /&gt;
Add case for new Command in NPCManager::HandleCommandList():&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcmanager.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
void NPCManager::HandleCommandList(MsgEntry* me,Client* client)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
            case psNPCCommandsMessage::CMD_LOOT:&lt;br /&gt;
            {&lt;br /&gt;
                EID entity_id = EID(list.msg-&amp;gt;GetUInt32());&lt;br /&gt;
                csString type = list.msg-&amp;gt;GetStr();&lt;br /&gt;
                Debug4(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;--&amp;gt;Got loot cmd: Entity %s to loot for %s\n&amp;quot;,&lt;br /&gt;
                       ShowID(entity_id), type.GetData());&lt;br /&gt;
&lt;br /&gt;
                // Make sure we haven&#039;t run past the end of the buffer&lt;br /&gt;
                if(list.msg-&amp;gt;overrun)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug2(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;Received incomplete CMD_LOOT from NPC client %u.\n&amp;quot;, me-&amp;gt;clientnum);&lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                gemNPCActor* npc = dynamic_cast&amp;lt;gemNPCActor*&amp;gt;(gemSupervisor-&amp;gt;FindObject(entity_id));&lt;br /&gt;
                &lt;br /&gt;
                /*  NEEDED?&lt;br /&gt;
                psCharacter* chardata = NULL;&lt;br /&gt;
                &lt;br /&gt;
                if(npc) chardata = npc-&amp;gt;GetCharacterData();&lt;br /&gt;
                &lt;br /&gt;
                if(!chardata)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug1(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;Couldn&#039;t find character data.\n&amp;quot;);&lt;br /&gt;
                    break;&lt;br /&gt;
                }*/&lt;br /&gt;
                &lt;br /&gt;
                if(npc)&lt;br /&gt;
                {&lt;br /&gt;
                    psserver-&amp;gt;GetUserManager()-&amp;gt;LootMoney(client);&lt;br /&gt;
                    psserver-&amp;gt;GetUserManager()-&amp;gt;LootItems(client, type);&lt;br /&gt;
                    &lt;br /&gt;
                    if(npc-&amp;gt;GetTribeID())&lt;br /&gt;
                    {&lt;br /&gt;
                        // add loot to tribe&#039;s resources&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                else&lt;br /&gt;
                     Error1(&amp;quot;NPC Client try to loot with no existing npc&amp;quot;);&lt;br /&gt;
                &lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
        // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Test ==&lt;br /&gt;
&lt;br /&gt;
Create a behavior to test with:&lt;br /&gt;
&lt;br /&gt;
Add new &amp;lt;behavior&amp;gt; and &amp;lt;react event&amp;gt; to AbstractTribesman in sc_npctypes.sql and reload the table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
INSERT INTO sc_npctypes VALUES(&amp;quot;109&amp;quot;,&amp;quot;AbstractTribesman&amp;quot;,&amp;quot;DoNothing,Move&amp;quot;,0,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;1&amp;quot;,&lt;br /&gt;
&#039;&amp;lt;!-- Abstract base npc type for tribes --&amp;gt;&lt;br /&gt;
&amp;lt;!-- [...] --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;behavior &amp;quot;test_loot&amp;quot; &amp;gt;&lt;br /&gt;
  &amp;lt;loot type=&amp;quot;all&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/behavior&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;react event=&amp;quot;test_loot&amp;quot; behavior=&amp;quot;test_loot&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;!-- [...] --&amp;gt;&lt;br /&gt;
&#039;);&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
From client /percept ... test_loot to execute the function. Do /debug_npc first to monitor.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine documents]] [[Category:NPCClient Design]]&lt;/div&gt;</summary>
		<author><name>Naeg</name></author>
	</entry>
	<entry>
		<id>https://planeshift.top-ix.org//pswiki/index.php?title=HowTo_Add_a_NPC_Operation&amp;diff=10126</id>
		<title>HowTo Add a NPC Operation</title>
		<link rel="alternate" type="text/html" href="https://planeshift.top-ix.org//pswiki/index.php?title=HowTo_Add_a_NPC_Operation&amp;diff=10126"/>
		<updated>2013-04-01T20:08:18Z</updated>

		<summary type="html">&lt;p&gt;Naeg: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
&lt;br /&gt;
NOTE: In Work&lt;br /&gt;
&lt;br /&gt;
# Create new Operation Class in npcclient/npcoperations&lt;br /&gt;
# Add Operation to npcbehave&lt;br /&gt;
# Create new Queue-Command in npcclient/networkmgr&lt;br /&gt;
# Modify common/net/npcmessages&lt;br /&gt;
# Process Command in npcclient/npcmanager and execute desired action&lt;br /&gt;
&lt;br /&gt;
== New Operation Class ==&lt;br /&gt;
&lt;br /&gt;
Example: LootOperation&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcoperations.h&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
/** Loot will make the NPC loot specified items&lt;br /&gt;
 *&lt;br /&gt;
 *  This class is the implementation of the loot operations&lt;br /&gt;
 *  used in behavior scripts for NPCS.&lt;br /&gt;
 *&lt;br /&gt;
 *  Examples: &amp;lt;pre&amp;gt;&lt;br /&gt;
 *  \&amp;lt;loot type=&amp;quot;all&amp;quot;     /\&amp;gt;&lt;br /&gt;
 *  \&amp;lt;loot type=&amp;quot;weapons&amp;quot; /\&amp;gt; &amp;lt;/pre&amp;gt;&lt;br /&gt;
 */&lt;br /&gt;
class LootOperation : public ScriptOperation&lt;br /&gt;
{&lt;br /&gt;
protected:&lt;br /&gt;
    csString type; ///&amp;lt; Type of items to loot&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
&lt;br /&gt;
    LootOperation(): ScriptOperation(&amp;quot;Loot&amp;quot;) {};&lt;br /&gt;
    virtual ~LootOperation() {};&lt;br /&gt;
    virtual OperationResult Run(NPC* npc,bool interrupted);&lt;br /&gt;
    virtual bool Load(iDocumentNode* node);&lt;br /&gt;
    virtual ScriptOperation* MakeCopy();&lt;br /&gt;
};&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcoperations.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
bool LootOperation::Load(iDocumentNode *node)&lt;br /&gt;
{&lt;br /&gt;
    type = node-&amp;gt;GetAttributeValue(&amp;quot;type&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    if(type.IsEmpty())&lt;br /&gt;
        type = &amp;quot;all&amp;quot;;&lt;br /&gt;
    &lt;br /&gt;
    return true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ScriptOperation* LootOperation::MakeCopy()&lt;br /&gt;
{&lt;br /&gt;
    LootOperation* op = new LootOperation;&lt;br /&gt;
&lt;br /&gt;
    op-&amp;gt;type = type;&lt;br /&gt;
&lt;br /&gt;
    return op;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ScriptOperation::OperationResult LootOperation::Run(NPC *npc, bool interrupted)&lt;br /&gt;
{&lt;br /&gt;
    npcclient-&amp;gt;GetNetworkMgr()-&amp;gt;QueueLootCommand(npc-&amp;gt;GetActor(), type);&lt;br /&gt;
    &lt;br /&gt;
    return OPERATION_COMPLETED; // Nothing more to do for this op.&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Add Operation to npcbehave ==&lt;br /&gt;
Add new operation to Behavior::LoadScript():&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcbehave.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
bool Behavior::LoadScript(iDocumentNode *node,bool top_level)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
        else if ( strcmp( node-&amp;gt;GetValue(), &amp;quot;loot&amp;quot; ) == 0 )&lt;br /&gt;
        {&lt;br /&gt;
            op = new LootOperation;&lt;br /&gt;
        }&lt;br /&gt;
   // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== New Queue-Command ==&lt;br /&gt;
src/npcclient/networkmgr.h&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
    /**&lt;br /&gt;
     * Send a command to loot selected target.&lt;br /&gt;
     */&lt;br /&gt;
    void QueueLootCommand(gemNPCActor *entity, const csString&amp;amp; type);&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
src/npcclient/networkmgr.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
void NetworkManager::QueueLootCommand(gemNPCActor *entity, const csString&amp;amp; type)&lt;br /&gt;
{&lt;br /&gt;
    CheckCommandsOverrun(sizeof(uint8_t) + sizeof(uint32_t) + (type.Length()+1));&lt;br /&gt;
&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add((int8_t) psNPCCommandsMessage::CMD_LOOT);&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add(entity-&amp;gt;GetEID().Unbox());&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add(type);&lt;br /&gt;
&lt;br /&gt;
    if(outbound-&amp;gt;msg-&amp;gt;overrun)&lt;br /&gt;
    {&lt;br /&gt;
        CS_ASSERT(!&amp;quot;NetworkManager::QueueLootCommand put message in overrun state!\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    cmd_count++;&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Modify npcmessages ==&lt;br /&gt;
&lt;br /&gt;
Add new CMD to PerceptionType:&lt;br /&gt;
&lt;br /&gt;
src/common/net/npcmessages.h&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
    enum PerceptionType&lt;br /&gt;
    {&lt;br /&gt;
        // Commands go from superclient to server&lt;br /&gt;
        // [...]&lt;br /&gt;
        CMD_CONTROL,&lt;br /&gt;
	CMD_LOOT, // new CMD for looting&lt;br /&gt;
        // Perceptions go from server to superclient&lt;br /&gt;
        PCPT_ANYRANGEPLAYER,&lt;br /&gt;
        // [...]&lt;br /&gt;
    };&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add new case to psNPCCOmmandsMessage::ToString():&lt;br /&gt;
&lt;br /&gt;
src/common/net/npcmessages.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
csString psNPCCommandsMessage::ToString(NetBase::AccessPointers * accessPointers)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
&lt;br /&gt;
	    case psNPCCommandsMessage::CMD_LOOT:&lt;br /&gt;
            {&lt;br /&gt;
                msgtext.Append(&amp;quot;CMD_LOOT: &amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                // Extract the data&lt;br /&gt;
                EID entity_id = EID(msg-&amp;gt;GetUInt32());&lt;br /&gt;
                csString type = msg-&amp;gt;GetStr();&lt;br /&gt;
&lt;br /&gt;
                // Make sure we haven&#039;t run past the end of the buffer&lt;br /&gt;
                if(msg-&amp;gt;overrun)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug2(LOG_SUPERCLIENT,msg-&amp;gt;clientnum,&amp;quot;Received incomplete CMD_LOOT from NPC client %u.\n&amp;quot;,msg-&amp;gt;clientnum);&lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                msgtext.AppendFmt(&amp;quot;EID: %u Type: %s&amp;quot;, entity_id.Unbox(), type.GetData());&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
            // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Process Command ==&lt;br /&gt;
Add case for new Command in NPCManager::HandleCommandList():&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcmanager.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
void NPCManager::HandleCommandList(MsgEntry* me,Client* client)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
            case psNPCCommandsMessage::CMD_LOOT:&lt;br /&gt;
            {&lt;br /&gt;
                EID entity_id = EID(list.msg-&amp;gt;GetUInt32());&lt;br /&gt;
                csString type = list.msg-&amp;gt;GetStr();&lt;br /&gt;
                Debug4(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;--&amp;gt;Got loot cmd: Entity %s to loot for %s\n&amp;quot;,&lt;br /&gt;
                       ShowID(entity_id), type.GetData());&lt;br /&gt;
&lt;br /&gt;
                // Make sure we haven&#039;t run past the end of the buffer&lt;br /&gt;
                if(list.msg-&amp;gt;overrun)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug2(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;Received incomplete CMD_LOOT from NPC client %u.\n&amp;quot;, me-&amp;gt;clientnum);&lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                gemNPCActor* npc = dynamic_cast&amp;lt;gemNPCActor*&amp;gt;(gemSupervisor-&amp;gt;FindObject(entity_id));&lt;br /&gt;
                &lt;br /&gt;
                /*  NEEDED?&lt;br /&gt;
                psCharacter* chardata = NULL;&lt;br /&gt;
                &lt;br /&gt;
                if(npc) chardata = npc-&amp;gt;GetCharacterData();&lt;br /&gt;
                &lt;br /&gt;
                if(!chardata)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug1(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;Couldn&#039;t find character data.\n&amp;quot;);&lt;br /&gt;
                    break;&lt;br /&gt;
                }*/&lt;br /&gt;
                &lt;br /&gt;
                if(npc)&lt;br /&gt;
                {&lt;br /&gt;
                    psserver-&amp;gt;GetUserManager()-&amp;gt;LootMoney(client);&lt;br /&gt;
                    psserver-&amp;gt;GetUserManager()-&amp;gt;LootItems(client, type);&lt;br /&gt;
                    &lt;br /&gt;
                    if(npc-&amp;gt;GetTribeID())&lt;br /&gt;
                    {&lt;br /&gt;
                        // add loot to tribe&#039;s resources&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                else&lt;br /&gt;
                     Error1(&amp;quot;NPC Client try to loot with no existing npc&amp;quot;);&lt;br /&gt;
                &lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
        // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Test ==&lt;br /&gt;
&lt;br /&gt;
Create a behavior to test with:&lt;br /&gt;
&lt;br /&gt;
Adding this to abstract tribes man sc_npctypes.sql and reload the table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
&amp;lt;behavior &amp;quot;test_loot&amp;quot; /&amp;gt;&lt;br /&gt;
  &amp;lt;loot type=&amp;quot;all&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/behavior&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;react event=&amp;quot;test_loot&amp;quot; behavior=&amp;quot;test_loot&amp;quot; /&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From client /percept ... test_loot to execute the function. Do /debug_npc first to monitor.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine documents]] [[Category:NPCClient Design]]&lt;/div&gt;</summary>
		<author><name>Naeg</name></author>
	</entry>
	<entry>
		<id>https://planeshift.top-ix.org//pswiki/index.php?title=HowTo_Add_a_NPC_Operation&amp;diff=10123</id>
		<title>HowTo Add a NPC Operation</title>
		<link rel="alternate" type="text/html" href="https://planeshift.top-ix.org//pswiki/index.php?title=HowTo_Add_a_NPC_Operation&amp;diff=10123"/>
		<updated>2013-04-01T17:40:55Z</updated>

		<summary type="html">&lt;p&gt;Naeg: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
&lt;br /&gt;
NOTE: In Work&lt;br /&gt;
&lt;br /&gt;
# Create new Operation Class in npcclient/npcoperations&lt;br /&gt;
# Add Operation to npcbehave&lt;br /&gt;
# Create new Queue-Command in npcclient/networkmgr&lt;br /&gt;
# Modify common/net/npcmessages&lt;br /&gt;
# Process Command in npcclient/npcmanager and execute desired action&lt;br /&gt;
&lt;br /&gt;
== New Operation Class ==&lt;br /&gt;
&lt;br /&gt;
Example: LootOperation&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcoperations.h&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
/** Loot will make the NPC loot specified items&lt;br /&gt;
 *&lt;br /&gt;
 *  This class is the implementation of the loot operations&lt;br /&gt;
 *  used in behavior scripts for NPCS.&lt;br /&gt;
 *&lt;br /&gt;
 *  Examples: &amp;lt;pre&amp;gt;&lt;br /&gt;
 *  \&amp;lt;loot type=&amp;quot;all&amp;quot;     /\&amp;gt;&lt;br /&gt;
 *  \&amp;lt;loot type=&amp;quot;weapons&amp;quot; /\&amp;gt; &amp;lt;/pre&amp;gt;&lt;br /&gt;
 */&lt;br /&gt;
class LootOperation : public ScriptOperation&lt;br /&gt;
{&lt;br /&gt;
protected:&lt;br /&gt;
    csString type; ///&amp;lt; Type of items to loot&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
&lt;br /&gt;
    LootOperation(): ScriptOperation(&amp;quot;Loot&amp;quot;) {};&lt;br /&gt;
    virtual ~LootOperation() {};&lt;br /&gt;
    virtual OperationResult Run(NPC* npc,bool interrupted);&lt;br /&gt;
    virtual bool Load(iDocumentNode* node);&lt;br /&gt;
    virtual ScriptOperation* MakeCopy();&lt;br /&gt;
};&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcoperations.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
bool LootOperation::Load(iDocumentNode *node)&lt;br /&gt;
{&lt;br /&gt;
    type = node-&amp;gt;GetAttributeValue(&amp;quot;type&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    if(type.IsEmpty())&lt;br /&gt;
        type = &amp;quot;all&amp;quot;;&lt;br /&gt;
    &lt;br /&gt;
    return true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ScriptOperation* LootOperation::MakeCopy()&lt;br /&gt;
{&lt;br /&gt;
    LootOperation* op = new LootOperation;&lt;br /&gt;
&lt;br /&gt;
    op-&amp;gt;type = type;&lt;br /&gt;
&lt;br /&gt;
    return op;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ScriptOperation::OperationResult LootOperation::Run(NPC *npc, bool interrupted)&lt;br /&gt;
{&lt;br /&gt;
    npcclient-&amp;gt;GetNetworkMgr()-&amp;gt;QueueLootCommand(npc-&amp;gt;GetActor(), type);&lt;br /&gt;
    &lt;br /&gt;
    return OPERATION_COMPLETED; // Nothing more to do for this op.&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Add Operation to npcbehave ==&lt;br /&gt;
Add new operation to Behavior::LoadScript():&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcbehave.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
bool Behavior::LoadScript(iDocumentNode *node,bool top_level)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
        else if ( strcmp( node-&amp;gt;GetValue(), &amp;quot;loot&amp;quot; ) == 0 )&lt;br /&gt;
        {&lt;br /&gt;
            op = new LootOperation;&lt;br /&gt;
        }&lt;br /&gt;
   // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== New Queue-Command ==&lt;br /&gt;
src/npcclient/networkmgr.h&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
    /**&lt;br /&gt;
     * Send a command to loot selected target.&lt;br /&gt;
     */&lt;br /&gt;
    void QueueLootCommand(gemNPCActor *entity, const csString&amp;amp; type);&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
src/npcclient/networkmgr.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
void NetworkManager::QueueLootCommand(gemNPCActor *entity, const csString&amp;amp; type)&lt;br /&gt;
{&lt;br /&gt;
    CheckCommandsOverrun(sizeof(uint8_t) + sizeof(uint32_t) + (type.Length()+1));&lt;br /&gt;
&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add((int8_t) psNPCCommandsMessage::CMD_LOOT);&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add(entity-&amp;gt;GetEID().Unbox());&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add(type);&lt;br /&gt;
&lt;br /&gt;
    if(outbound-&amp;gt;msg-&amp;gt;overrun)&lt;br /&gt;
    {&lt;br /&gt;
        CS_ASSERT(!&amp;quot;NetworkManager::QueueLootCommand put message in overrun state!\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    cmd_count++;&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Modify npcmessages ==&lt;br /&gt;
&lt;br /&gt;
Add new CMD to PerceptionType:&lt;br /&gt;
&lt;br /&gt;
src/common/net/npcmessages.h&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
    enum PerceptionType&lt;br /&gt;
    {&lt;br /&gt;
        // Commands go from superclient to server&lt;br /&gt;
        // [...]&lt;br /&gt;
        CMD_CONTROL,&lt;br /&gt;
	CMD_LOOT, // new CMD for looting&lt;br /&gt;
        // Perceptions go from server to superclient&lt;br /&gt;
        PCPT_ANYRANGEPLAYER,&lt;br /&gt;
        // [...]&lt;br /&gt;
    };&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add new case to psNPCCOmmandsMessage::ToString():&lt;br /&gt;
&lt;br /&gt;
src/common/net/npcmessages.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
csString psNPCCommandsMessage::ToString(NetBase::AccessPointers * accessPointers)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
&lt;br /&gt;
	    case psNPCCommandsMessage::CMD_LOOT:&lt;br /&gt;
            {&lt;br /&gt;
                msgtext.Append(&amp;quot;CMD_LOOT: &amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                // Extract the data&lt;br /&gt;
                EID entity_id = EID(msg-&amp;gt;GetUInt32());&lt;br /&gt;
                csString type = msg-&amp;gt;GetStr();&lt;br /&gt;
&lt;br /&gt;
                // Make sure we haven&#039;t run past the end of the buffer&lt;br /&gt;
                if(msg-&amp;gt;overrun)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug2(LOG_SUPERCLIENT,msg-&amp;gt;clientnum,&amp;quot;Received incomplete CMD_LOOT from NPC client %u.\n&amp;quot;,msg-&amp;gt;clientnum);&lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                msgtext.AppendFmt(&amp;quot;EID: %u Type: %s&amp;quot;, entity_id.Unbox(), type.GetData());&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
            // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Process Command ==&lt;br /&gt;
Add case for new Command in NPCManager::HandleCommandList():&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcmanager.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
void NPCManager::HandleCommandList(MsgEntry* me,Client* client)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
            case psNPCCommandsMessage::CMD_LOOT:&lt;br /&gt;
            {&lt;br /&gt;
                EID entity_id = EID(list.msg-&amp;gt;GetUInt32());&lt;br /&gt;
                csString type = list.msg-&amp;gt;GetStr();&lt;br /&gt;
                Debug4(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;--&amp;gt;Got loot cmd: Entity %s to loot for %s\n&amp;quot;,&lt;br /&gt;
                       ShowID(entity_id), type.GetData());&lt;br /&gt;
&lt;br /&gt;
                // Make sure we haven&#039;t run past the end of the buffer&lt;br /&gt;
                if(list.msg-&amp;gt;overrun)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug2(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;Received incomplete CMD_LOOT from NPC client %u.\n&amp;quot;, me-&amp;gt;clientnum);&lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                gemNPCActor* npc = dynamic_cast&amp;lt;gemNPCActor*&amp;gt;(gemSupervisor-&amp;gt;FindObject(entity_id));&lt;br /&gt;
                &lt;br /&gt;
                /*  NEEDED?&lt;br /&gt;
                psCharacter* chardata = NULL;&lt;br /&gt;
                &lt;br /&gt;
                if(npc) chardata = npc-&amp;gt;GetCharacterData();&lt;br /&gt;
                &lt;br /&gt;
                if(!chardata)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug1(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;Couldn&#039;t find character data.\n&amp;quot;);&lt;br /&gt;
                    break;&lt;br /&gt;
                }*/&lt;br /&gt;
                &lt;br /&gt;
                if(npc)&lt;br /&gt;
                {&lt;br /&gt;
                    psserver-&amp;gt;GetUserManager()-&amp;gt;LootMoney(client);&lt;br /&gt;
                    psserver-&amp;gt;GetUserManager()-&amp;gt;LootItems(client, type);&lt;br /&gt;
                    &lt;br /&gt;
                    if(npc-&amp;gt;GetTribeID())&lt;br /&gt;
                    {&lt;br /&gt;
                        // add loot to tribe&#039;s resources&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                else&lt;br /&gt;
                     Error1(&amp;quot;NPC Client try to loot with no existing npc&amp;quot;);&lt;br /&gt;
                &lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
        // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine documents]] [[Category:NPCClient Design]]&lt;/div&gt;</summary>
		<author><name>Naeg</name></author>
	</entry>
	<entry>
		<id>https://planeshift.top-ix.org//pswiki/index.php?title=HowTo_Add_a_NPC_Operation&amp;diff=10122</id>
		<title>HowTo Add a NPC Operation</title>
		<link rel="alternate" type="text/html" href="https://planeshift.top-ix.org//pswiki/index.php?title=HowTo_Add_a_NPC_Operation&amp;diff=10122"/>
		<updated>2013-04-01T17:28:49Z</updated>

		<summary type="html">&lt;p&gt;Naeg: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
&lt;br /&gt;
NOTE: In Work&lt;br /&gt;
&lt;br /&gt;
# Create new Operation Class in npcclient/npcoperations&lt;br /&gt;
# Create new Queue-Command in npcclient/networkmgr&lt;br /&gt;
# Modify common/net/npcmessages&lt;br /&gt;
# Process Command in npcclient/npcmanager and execute desired action&lt;br /&gt;
&lt;br /&gt;
== New Operation Class ==&lt;br /&gt;
&lt;br /&gt;
Example: LootOperation&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcoperations.h&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
/** Loot will make the NPC loot specified items&lt;br /&gt;
 *&lt;br /&gt;
 *  This class is the implementation of the loot operations&lt;br /&gt;
 *  used in behavior scripts for NPCS.&lt;br /&gt;
 *&lt;br /&gt;
 *  Examples: &amp;lt;pre&amp;gt;&lt;br /&gt;
 *  \&amp;lt;loot type=&amp;quot;all&amp;quot;     /\&amp;gt;&lt;br /&gt;
 *  \&amp;lt;loot type=&amp;quot;weapons&amp;quot; /\&amp;gt; &amp;lt;/pre&amp;gt;&lt;br /&gt;
 */&lt;br /&gt;
class LootOperation : public ScriptOperation&lt;br /&gt;
{&lt;br /&gt;
protected:&lt;br /&gt;
    csString type; ///&amp;lt; Type of items to loot&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
&lt;br /&gt;
    LootOperation(): ScriptOperation(&amp;quot;Loot&amp;quot;) {};&lt;br /&gt;
    virtual ~LootOperation() {};&lt;br /&gt;
    virtual OperationResult Run(NPC* npc,bool interrupted);&lt;br /&gt;
    virtual bool Load(iDocumentNode* node);&lt;br /&gt;
    virtual ScriptOperation* MakeCopy();&lt;br /&gt;
};&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcoperations.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
bool LootOperation::Load(iDocumentNode *node)&lt;br /&gt;
{&lt;br /&gt;
    type = node-&amp;gt;GetAttributeValue(&amp;quot;type&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    if(type.IsEmpty())&lt;br /&gt;
        type = &amp;quot;all&amp;quot;;&lt;br /&gt;
    &lt;br /&gt;
    return true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ScriptOperation* LootOperation::MakeCopy()&lt;br /&gt;
{&lt;br /&gt;
    LootOperation* op = new LootOperation;&lt;br /&gt;
&lt;br /&gt;
    op-&amp;gt;type = type;&lt;br /&gt;
&lt;br /&gt;
    return op;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ScriptOperation::OperationResult LootOperation::Run(NPC *npc, bool interrupted)&lt;br /&gt;
{&lt;br /&gt;
    npcclient-&amp;gt;GetNetworkMgr()-&amp;gt;QueueLootCommand(npc-&amp;gt;GetActor(), type);&lt;br /&gt;
    &lt;br /&gt;
    return OPERATION_COMPLETED; // Nothing more to do for this op.&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== New Queue-Command ==&lt;br /&gt;
src/npcclient/networkmgr.h&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
    /**&lt;br /&gt;
     * Send a command to loot selected target.&lt;br /&gt;
     */&lt;br /&gt;
    void QueueLootCommand(gemNPCActor *entity, const csString&amp;amp; type);&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
src/npcclient/networkmgr.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
void NetworkManager::QueueLootCommand(gemNPCActor *entity, const csString&amp;amp; type)&lt;br /&gt;
{&lt;br /&gt;
    CheckCommandsOverrun(sizeof(uint8_t) + sizeof(uint32_t) + (type.Length()+1));&lt;br /&gt;
&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add((int8_t) psNPCCommandsMessage::CMD_LOOT);&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add(entity-&amp;gt;GetEID().Unbox());&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add(type);&lt;br /&gt;
&lt;br /&gt;
    if(outbound-&amp;gt;msg-&amp;gt;overrun)&lt;br /&gt;
    {&lt;br /&gt;
        CS_ASSERT(!&amp;quot;NetworkManager::QueueLootCommand put message in overrun state!\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    cmd_count++;&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Modify npcmessages ==&lt;br /&gt;
&lt;br /&gt;
Add new CMD to PerceptionType:&lt;br /&gt;
&lt;br /&gt;
src/common/net/npcmessages.h&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
    enum PerceptionType&lt;br /&gt;
    {&lt;br /&gt;
        // Commands go from superclient to server&lt;br /&gt;
        // [...]&lt;br /&gt;
        CMD_CONTROL,&lt;br /&gt;
	CMD_LOOT, // new CMD for looting&lt;br /&gt;
        // Perceptions go from server to superclient&lt;br /&gt;
        PCPT_ANYRANGEPLAYER,&lt;br /&gt;
        // [...]&lt;br /&gt;
    };&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add new case to psNPCCOmmandsMessage::ToString():&lt;br /&gt;
&lt;br /&gt;
src/common/net/npcmessages.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
csString psNPCCommandsMessage::ToString(NetBase::AccessPointers * accessPointers)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
&lt;br /&gt;
	    case psNPCCommandsMessage::CMD_LOOT:&lt;br /&gt;
            {&lt;br /&gt;
                msgtext.Append(&amp;quot;CMD_LOOT: &amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                // Extract the data&lt;br /&gt;
                EID entity_id = EID(msg-&amp;gt;GetUInt32());&lt;br /&gt;
                csString type = msg-&amp;gt;GetStr();&lt;br /&gt;
&lt;br /&gt;
                // Make sure we haven&#039;t run past the end of the buffer&lt;br /&gt;
                if(msg-&amp;gt;overrun)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug2(LOG_SUPERCLIENT,msg-&amp;gt;clientnum,&amp;quot;Received incomplete CMD_LOOT from NPC client %u.\n&amp;quot;,msg-&amp;gt;clientnum);&lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                msgtext.AppendFmt(&amp;quot;EID: %u Type: %s&amp;quot;, entity_id.Unbox(), type.GetData());&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
            // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Process Command ==&lt;br /&gt;
Add case for new Command in NPCManager::HandleCommandList():&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcmanager.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
void NPCManager::HandleCommandList(MsgEntry* me,Client* client)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
            case psNPCCommandsMessage::CMD_LOOT:&lt;br /&gt;
            {&lt;br /&gt;
                EID entity_id = EID(list.msg-&amp;gt;GetUInt32());&lt;br /&gt;
                csString type = list.msg-&amp;gt;GetStr();&lt;br /&gt;
                Debug4(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;--&amp;gt;Got loot cmd: Entity %s to loot for %s\n&amp;quot;,&lt;br /&gt;
                       ShowID(entity_id), type.GetData());&lt;br /&gt;
&lt;br /&gt;
                // Make sure we haven&#039;t run past the end of the buffer&lt;br /&gt;
                if(list.msg-&amp;gt;overrun)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug2(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;Received incomplete CMD_LOOT from NPC client %u.\n&amp;quot;, me-&amp;gt;clientnum);&lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                gemNPCActor* npc = dynamic_cast&amp;lt;gemNPCActor*&amp;gt;(gemSupervisor-&amp;gt;FindObject(entity_id));&lt;br /&gt;
                &lt;br /&gt;
                /*  NEEDED?&lt;br /&gt;
                psCharacter* chardata = NULL;&lt;br /&gt;
                &lt;br /&gt;
                if(npc) chardata = npc-&amp;gt;GetCharacterData();&lt;br /&gt;
                &lt;br /&gt;
                if(!chardata)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug1(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;Couldn&#039;t find character data.\n&amp;quot;);&lt;br /&gt;
                    break;&lt;br /&gt;
                }*/&lt;br /&gt;
                &lt;br /&gt;
                if(npc)&lt;br /&gt;
                {&lt;br /&gt;
                    psserver-&amp;gt;GetUserManager()-&amp;gt;LootMoney(client);&lt;br /&gt;
                    psserver-&amp;gt;GetUserManager()-&amp;gt;LootItems(client, type);&lt;br /&gt;
                    &lt;br /&gt;
                    if(npc-&amp;gt;GetTribeID())&lt;br /&gt;
                    {&lt;br /&gt;
                        // add loot to tribe&#039;s resources&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                else&lt;br /&gt;
                     Error1(&amp;quot;NPC Client try to loot with no existing npc&amp;quot;);&lt;br /&gt;
                &lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
        // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine documents]] [[Category:NPCClient Design]]&lt;/div&gt;</summary>
		<author><name>Naeg</name></author>
	</entry>
	<entry>
		<id>https://planeshift.top-ix.org//pswiki/index.php?title=HowTo_Add_a_NPC_Operation&amp;diff=10121</id>
		<title>HowTo Add a NPC Operation</title>
		<link rel="alternate" type="text/html" href="https://planeshift.top-ix.org//pswiki/index.php?title=HowTo_Add_a_NPC_Operation&amp;diff=10121"/>
		<updated>2013-04-01T17:15:41Z</updated>

		<summary type="html">&lt;p&gt;Naeg: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
&lt;br /&gt;
NOTE: In Work&lt;br /&gt;
&lt;br /&gt;
# Create new Operation Class in npcclient/npcoperations&lt;br /&gt;
# Create new Queue-Command in npcclient/networkmgr&lt;br /&gt;
# Modify common/net/npcmessages&lt;br /&gt;
# Process Command in npcclient/npcmanager and execute desired action&lt;br /&gt;
&lt;br /&gt;
== New Operation Class ==&lt;br /&gt;
&lt;br /&gt;
Example: LootOperation&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcoperations.h&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
/** Loot will make the NPC loot specified items&lt;br /&gt;
 *&lt;br /&gt;
 *  This class is the implementation of the loot operations&lt;br /&gt;
 *  used in behavior scripts for NPCS.&lt;br /&gt;
 *&lt;br /&gt;
 *  Examples: &amp;lt;pre&amp;gt;&lt;br /&gt;
 *  \&amp;lt;loot type=&amp;quot;all&amp;quot;     /\&amp;gt;&lt;br /&gt;
 *  \&amp;lt;loot type=&amp;quot;weapons&amp;quot; /\&amp;gt; &amp;lt;/pre&amp;gt;&lt;br /&gt;
 */&lt;br /&gt;
class LootOperation : public ScriptOperation&lt;br /&gt;
{&lt;br /&gt;
protected:&lt;br /&gt;
    csString type; ///&amp;lt; Type of items to loot&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
&lt;br /&gt;
    LootOperation(): ScriptOperation(&amp;quot;Loot&amp;quot;) {};&lt;br /&gt;
    virtual ~LootOperation() {};&lt;br /&gt;
    virtual OperationResult Run(NPC* npc,bool interrupted);&lt;br /&gt;
    virtual bool Load(iDocumentNode* node);&lt;br /&gt;
    virtual ScriptOperation* MakeCopy();&lt;br /&gt;
};&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcoperations.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
bool LootOperation::Load(iDocumentNode *node)&lt;br /&gt;
{&lt;br /&gt;
    type = node-&amp;gt;GetAttributeValue(&amp;quot;type&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    if(type.IsEmpty())&lt;br /&gt;
        type = &amp;quot;all&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    return true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ScriptOperation* LootOperation::MakeCopy()&lt;br /&gt;
{&lt;br /&gt;
    LootOperation* op = new LootOperation;&lt;br /&gt;
&lt;br /&gt;
    op-&amp;gt;type = type;&lt;br /&gt;
&lt;br /&gt;
    return op;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ScriptOperation::OperationResult LootOperation::Run(NPC *npc, bool interrupted)&lt;br /&gt;
{&lt;br /&gt;
    npcclient-&amp;gt;GetNetworkMgr()-&amp;gt;QueueLootCommand(npc-&amp;gt;GetActor(), type);&lt;br /&gt;
    &lt;br /&gt;
    return OPERATION_COMPLETED; // Nothing more to do for this op.&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== New Queue-Command ==&lt;br /&gt;
src/npcclient/networkmgr.h&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
    /**&lt;br /&gt;
     * Send a command to loot selected target.&lt;br /&gt;
     */&lt;br /&gt;
    void QueueLootCommand(gemNPCActor *entity, const csString&amp;amp; type);&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
src/npcclient/networkmgr.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
void NetworkManager::QueueLootCommand(gemNPCActor *entity, const csString&amp;amp; type);&lt;br /&gt;
{&lt;br /&gt;
    CheckCommandsOverrun(sizeof(uint8_t) + sizeof(uint32_t) + (type.Length()+1));&lt;br /&gt;
&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add((int8_t) psNPCCommandsMessage::CMD_LOOT);&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add(entity-&amp;gt;GetEID().Unbox());&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add(type);&lt;br /&gt;
&lt;br /&gt;
    if(outbound-&amp;gt;msg-&amp;gt;overrun)&lt;br /&gt;
    {&lt;br /&gt;
        CS_ASSERT(!&amp;quot;NetworkManager::QueueLootCommand put message in overrun state!\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    cmd_count++;&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Modify npcmessages ==&lt;br /&gt;
&lt;br /&gt;
Add new CMD to PerceptionType:&lt;br /&gt;
&lt;br /&gt;
src/common/net/npcmessages.h&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
    enum PerceptionType&lt;br /&gt;
    {&lt;br /&gt;
        // Commands go from superclient to server&lt;br /&gt;
        // [...]&lt;br /&gt;
        CMD_CONTROL,&lt;br /&gt;
	CMD_LOOT, // new CMD for looting&lt;br /&gt;
        // Perceptions go from server to superclient&lt;br /&gt;
        PCPT_ANYRANGEPLAYER,&lt;br /&gt;
        // [...]&lt;br /&gt;
    };&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add new case to psNPCCOmmandsMessage::ToString():&lt;br /&gt;
&lt;br /&gt;
src/common/net/npcmessages.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
csString psNPCCommandsMessage::ToString(NetBase::AccessPointers * accessPointers)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
&lt;br /&gt;
	    case psNPCCommandsMessage::CMD_LOOT:&lt;br /&gt;
            {&lt;br /&gt;
                msgtext.Append(&amp;quot;CMD_LOOT: &amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                // Extract the data&lt;br /&gt;
                EID entity_id = EID(msg-&amp;gt;GetUInt32());&lt;br /&gt;
                csString type = msg-&amp;gt;GetStr();&lt;br /&gt;
&lt;br /&gt;
                // Make sure we haven&#039;t run past the end of the buffer&lt;br /&gt;
                if(msg-&amp;gt;overrun)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug2(LOG_SUPERCLIENT,msg-&amp;gt;clientnum,&amp;quot;Received incomplete CMD_LOOT from NPC client %u.\n&amp;quot;,msg-&amp;gt;clientnum);&lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                msgtext.AppendFmt(&amp;quot;EID: %u Type: %s&amp;quot;, entity_id.Unbox(), type.GetData());&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
            // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Process Command ==&lt;br /&gt;
Add case for new Command in NPCManager::HandleCommandList():&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcmanager.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
void NPCManager::HandleCommandList(MsgEntry* me,Client* client)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
            case psNPCCommandsMessage::CMD_LOOT:&lt;br /&gt;
            {&lt;br /&gt;
                EID entity_id = EID(list.msg-&amp;gt;GetUInt32());&lt;br /&gt;
                csString type = list.msg-&amp;gt;GetStr();&lt;br /&gt;
                Debug4(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;--&amp;gt;Got loot cmd: Entity %s to loot for %s\n&amp;quot;,&lt;br /&gt;
                       ShowID(entity_id), type.GetData());&lt;br /&gt;
&lt;br /&gt;
                // Make sure we haven&#039;t run past the end of the buffer&lt;br /&gt;
                if(list.msg-&amp;gt;overrun)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug2(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;Received incomplete CMD_LOOT from NPC client %u.\n&amp;quot;, me-&amp;gt;clientnum);&lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                gemNPCActor* npc = dynamic_cast&amp;lt;gemNPCActor*&amp;gt;(gemSupervisor-&amp;gt;FindObject(entity_id));&lt;br /&gt;
                &lt;br /&gt;
                /*  NEEDED?&lt;br /&gt;
                psCharacter* chardata = NULL;&lt;br /&gt;
                &lt;br /&gt;
                if(npc) chardata = npc-&amp;gt;GetCharacterData();&lt;br /&gt;
                &lt;br /&gt;
                if(!chardata)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug1(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;Couldn&#039;t find character data.\n&amp;quot;);&lt;br /&gt;
                    break;&lt;br /&gt;
                }*/&lt;br /&gt;
                &lt;br /&gt;
                if(npc)&lt;br /&gt;
                {&lt;br /&gt;
                    psserver-&amp;gt;GetUserManager()-&amp;gt;LootMoney(client);&lt;br /&gt;
                    psserver-&amp;gt;GetUserManager()-&amp;gt;LootItems(client, type);&lt;br /&gt;
                    &lt;br /&gt;
                    if(npc-&amp;gt;GetTribeID())&lt;br /&gt;
                    {&lt;br /&gt;
                        // add loot to tribe&#039;s resources&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                else&lt;br /&gt;
                     Error1(&amp;quot;NPC Client try to loot with no existing npc&amp;quot;);&lt;br /&gt;
                &lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
        // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine documents]] [[Category:NPCClient Design]]&lt;/div&gt;</summary>
		<author><name>Naeg</name></author>
	</entry>
	<entry>
		<id>https://planeshift.top-ix.org//pswiki/index.php?title=HowTo_Add_a_NPC_Operation&amp;diff=10120</id>
		<title>HowTo Add a NPC Operation</title>
		<link rel="alternate" type="text/html" href="https://planeshift.top-ix.org//pswiki/index.php?title=HowTo_Add_a_NPC_Operation&amp;diff=10120"/>
		<updated>2013-04-01T17:12:34Z</updated>

		<summary type="html">&lt;p&gt;Naeg: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
&lt;br /&gt;
NOTE: In Work&lt;br /&gt;
&lt;br /&gt;
# Create new Operation Class in npcclient/npcoperations&lt;br /&gt;
# Create new Queue-Command in npcclient/networkmgr&lt;br /&gt;
# Modify common/net/npcmessages&lt;br /&gt;
# Process Command in npcclient/npcmanager and execute desired action&lt;br /&gt;
&lt;br /&gt;
== New Operation Class ==&lt;br /&gt;
&lt;br /&gt;
Example: LootOperation&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcoperations.h&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
/** Loot will make the NPC loot specified items&lt;br /&gt;
 *&lt;br /&gt;
 *  This class is the implementation of the loot operations&lt;br /&gt;
 *  used in behavior scripts for NPCS.&lt;br /&gt;
 *&lt;br /&gt;
 *  Examples: &amp;lt;pre&amp;gt;&lt;br /&gt;
 *  \&amp;lt;loot type=&amp;quot;all&amp;quot;     /\&amp;gt;&lt;br /&gt;
 *  \&amp;lt;loot type=&amp;quot;weapons&amp;quot; /\&amp;gt; &amp;lt;/pre&amp;gt;&lt;br /&gt;
 */&lt;br /&gt;
class LootOperation : public ScriptOperation&lt;br /&gt;
{&lt;br /&gt;
protected:&lt;br /&gt;
    csString type; ///&amp;lt; Type of items to loot&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
&lt;br /&gt;
    LootOperation(): ScriptOperation(&amp;quot;Loot&amp;quot;) {};&lt;br /&gt;
    virtual ~LootOperation() {};&lt;br /&gt;
    virtual OperationResult Run(NPC* npc,bool interrupted);&lt;br /&gt;
    virtual bool Load(iDocumentNode* node);&lt;br /&gt;
    virtual ScriptOperation* MakeCopy();&lt;br /&gt;
};&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcoperations.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
bool LootOperation::Load(iDocumentNode *node)&lt;br /&gt;
{&lt;br /&gt;
    type = node-&amp;gt;GetAttributeValue(&amp;quot;type&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    if(type.IsEmpty())&lt;br /&gt;
        type = &amp;quot;all&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    return true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ScriptOperation* LootOperation::MakeCopy()&lt;br /&gt;
{&lt;br /&gt;
    LootOperation* op = new LootOperation;&lt;br /&gt;
&lt;br /&gt;
    op-&amp;gt;type = type;&lt;br /&gt;
&lt;br /&gt;
    return op;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ScriptOperation::OperationResult LootOperation::Run(NPC *npc, bool interrupted)&lt;br /&gt;
{&lt;br /&gt;
    npcclient-&amp;gt;GetNetworkMgr()-&amp;gt;QueueLootCommand(npc-&amp;gt;GetActor(), type);&lt;br /&gt;
    &lt;br /&gt;
    return OPERATION_COMPLETED; // Nothing more to do for this op.&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== New Queue-Command ==&lt;br /&gt;
src/npcclient/networkmgr.h&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
    /**&lt;br /&gt;
     * Send a command to loot selected target.&lt;br /&gt;
     */&lt;br /&gt;
    void QueueLootCommand(gemNPCActor *entity, const csString&amp;amp; type);&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
src/npcclient/networkmgr.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
void NetworkManager::QueueLootCommand(gemNPCActor *entity, const csString&amp;amp; type);&lt;br /&gt;
{&lt;br /&gt;
    CheckCommandsOverrun(sizeof(uint8_t) + sizeof(uint32_t) + (type.Length()+1));&lt;br /&gt;
&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add((int8_t) psNPCCommandsMessage::CMD_LOOT);&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add(entity-&amp;gt;GetEID().Unbox());&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add(type);&lt;br /&gt;
&lt;br /&gt;
    if(outbound-&amp;gt;msg-&amp;gt;overrun)&lt;br /&gt;
    {&lt;br /&gt;
        CS_ASSERT(!&amp;quot;NetworkManager::QueueLootCommand put message in overrun state!\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    cmd_count++;&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Modify npcmessages ==&lt;br /&gt;
&lt;br /&gt;
Add new CMD to PerceptionType:&lt;br /&gt;
&lt;br /&gt;
src/common/net/npcmessages.h&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
    enum PerceptionType&lt;br /&gt;
    {&lt;br /&gt;
        // Commands go from superclient to server&lt;br /&gt;
        // [...]&lt;br /&gt;
        CMD_CONTROL,&lt;br /&gt;
	CMD_LOOT, // new CMD for looting&lt;br /&gt;
        // Perceptions go from server to superclient&lt;br /&gt;
        PCPT_ANYRANGEPLAYER,&lt;br /&gt;
        // [...]&lt;br /&gt;
    };&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add new case to psNPCCOmmandsMessage::ToString():&lt;br /&gt;
&lt;br /&gt;
src/common/net/npcmessages.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
csString psNPCCommandsMessage::ToString(NetBase::AccessPointers * accessPointers)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
&lt;br /&gt;
	    case psNPCCommandsMessage::CMD_LOOT:&lt;br /&gt;
            {&lt;br /&gt;
                msgtext.Append(&amp;quot;CMD_LOOT: &amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                // Extract the data&lt;br /&gt;
                EID entity_id = EID(msg-&amp;gt;GetUInt32());&lt;br /&gt;
                csString type = msg-&amp;gt;GetStr();&lt;br /&gt;
&lt;br /&gt;
                // Make sure we haven&#039;t run past the end of the buffer&lt;br /&gt;
                if(msg-&amp;gt;overrun)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug2(LOG_SUPERCLIENT,msg-&amp;gt;clientnum,&amp;quot;Received incomplete CMD_LOOT from NPC client %u.\n&amp;quot;,msg-&amp;gt;clientnum);&lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                msgtext.AppendFmt(&amp;quot;EID: %u Type: %s&amp;quot;, entity_id.Unbox(), type.GetData());&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
            // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Process Command ==&lt;br /&gt;
Add case for new Command in NPCManager::HandleCommandList():&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcmanager.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
void NPCManager::HandleCommandList(MsgEntry* me,Client* client)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
            case psNPCCommandsMessage::CMD_LOOT:&lt;br /&gt;
            {&lt;br /&gt;
                EID entity_id = EID(list.msg-&amp;gt;GetUInt32());&lt;br /&gt;
                csString type = list.msg-&amp;gt;GetStr();&lt;br /&gt;
                Debug4(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;--&amp;gt;Got loot cmd: Entity %s to loot for %s\n&amp;quot;,&lt;br /&gt;
                       ShowID(entity_id), type.GetData());&lt;br /&gt;
&lt;br /&gt;
                // Make sure we haven&#039;t run past the end of the buffer&lt;br /&gt;
                if(list.msg-&amp;gt;overrun)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug2(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;Received incomplete CMD_LOOT from NPC client %u.\n&amp;quot;, me-&amp;gt;clientnum);&lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                gemNPC* npc = dynamic_cast&amp;lt;gemNPC*&amp;gt;(gemSupervisor-&amp;gt;FindObject(entity_id));&lt;br /&gt;
                &lt;br /&gt;
                /*  NEEDED?&lt;br /&gt;
                psCharacter* chardata = NULL;&lt;br /&gt;
                &lt;br /&gt;
                if(npc) chardata = npc-&amp;gt;GetCharacterData();&lt;br /&gt;
                &lt;br /&gt;
                if(!chardata)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug1(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;Couldn&#039;t find character data.\n&amp;quot;);&lt;br /&gt;
                    break;&lt;br /&gt;
                }*/&lt;br /&gt;
                &lt;br /&gt;
                if(npc)&lt;br /&gt;
                {&lt;br /&gt;
                    psserver-&amp;gt;GetUserManager()-&amp;gt;LootMoney(client);&lt;br /&gt;
                    psserver-&amp;gt;GetUserManager()-&amp;gt;LootItems(client, type);&lt;br /&gt;
                    &lt;br /&gt;
                    if(npc-&amp;gt;GetTribeID())&lt;br /&gt;
                    {&lt;br /&gt;
                        // add loot to tribe&#039;s resources&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                else&lt;br /&gt;
                     Error1(&amp;quot;NPC Client try to loot with no existing npc&amp;quot;);&lt;br /&gt;
                &lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
        // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine documents]] [[Category:NPCClient Design]]&lt;/div&gt;</summary>
		<author><name>Naeg</name></author>
	</entry>
	<entry>
		<id>https://planeshift.top-ix.org//pswiki/index.php?title=HowTo_Add_a_NPC_Operation&amp;diff=10119</id>
		<title>HowTo Add a NPC Operation</title>
		<link rel="alternate" type="text/html" href="https://planeshift.top-ix.org//pswiki/index.php?title=HowTo_Add_a_NPC_Operation&amp;diff=10119"/>
		<updated>2013-04-01T17:11:55Z</updated>

		<summary type="html">&lt;p&gt;Naeg: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
&lt;br /&gt;
NOTE: In Work&lt;br /&gt;
&lt;br /&gt;
# Create new Operation Class in npcclient/npcoperations&lt;br /&gt;
# Create new Queue-Command in npcclient/networkmgr&lt;br /&gt;
# Modify common/net/npcmessages&lt;br /&gt;
# Process Command in npcclient/npcmanager and execute desired action&lt;br /&gt;
&lt;br /&gt;
=== New Operation Class ===&lt;br /&gt;
&lt;br /&gt;
Example: LootOperation&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcoperations.h&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
/** Loot will make the NPC loot specified items&lt;br /&gt;
 *&lt;br /&gt;
 *  This class is the implementation of the loot operations&lt;br /&gt;
 *  used in behavior scripts for NPCS.&lt;br /&gt;
 *&lt;br /&gt;
 *  Examples: &amp;lt;pre&amp;gt;&lt;br /&gt;
 *  \&amp;lt;loot type=&amp;quot;all&amp;quot;     /\&amp;gt;&lt;br /&gt;
 *  \&amp;lt;loot type=&amp;quot;weapons&amp;quot; /\&amp;gt; &amp;lt;/pre&amp;gt;&lt;br /&gt;
 */&lt;br /&gt;
class LootOperation : public ScriptOperation&lt;br /&gt;
{&lt;br /&gt;
protected:&lt;br /&gt;
    csString type; ///&amp;lt; Type of items to loot&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
&lt;br /&gt;
    LootOperation(): ScriptOperation(&amp;quot;Loot&amp;quot;) {};&lt;br /&gt;
    virtual ~LootOperation() {};&lt;br /&gt;
    virtual OperationResult Run(NPC* npc,bool interrupted);&lt;br /&gt;
    virtual bool Load(iDocumentNode* node);&lt;br /&gt;
    virtual ScriptOperation* MakeCopy();&lt;br /&gt;
};&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcoperations.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
bool LootOperation::Load(iDocumentNode *node)&lt;br /&gt;
{&lt;br /&gt;
    type = node-&amp;gt;GetAttributeValue(&amp;quot;type&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    if(type.IsEmpty())&lt;br /&gt;
        type = &amp;quot;all&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    return true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ScriptOperation* LootOperation::MakeCopy()&lt;br /&gt;
{&lt;br /&gt;
    LootOperation* op = new LootOperation;&lt;br /&gt;
&lt;br /&gt;
    op-&amp;gt;type = type;&lt;br /&gt;
&lt;br /&gt;
    return op;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ScriptOperation::OperationResult LootOperation::Run(NPC *npc, bool interrupted)&lt;br /&gt;
{&lt;br /&gt;
    npcclient-&amp;gt;GetNetworkMgr()-&amp;gt;QueueLootCommand(npc-&amp;gt;GetActor(), type);&lt;br /&gt;
    &lt;br /&gt;
    return OPERATION_COMPLETED; // Nothing more to do for this op.&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== New Queue-Command ===&lt;br /&gt;
src/npcclient/networkmgr.h&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
    /**&lt;br /&gt;
     * Send a command to loot selected target.&lt;br /&gt;
     */&lt;br /&gt;
    void QueueLootCommand(gemNPCActor *entity, const csString&amp;amp; type);&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
src/npcclient/networkmgr.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
void NetworkManager::QueueLootCommand(gemNPCActor *entity, const csString&amp;amp; type);&lt;br /&gt;
{&lt;br /&gt;
    CheckCommandsOverrun(sizeof(uint8_t) + sizeof(uint32_t) + (type.Length()+1));&lt;br /&gt;
&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add((int8_t) psNPCCommandsMessage::CMD_LOOT);&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add(entity-&amp;gt;GetEID().Unbox());&lt;br /&gt;
    outbound-&amp;gt;msg-&amp;gt;Add(type);&lt;br /&gt;
&lt;br /&gt;
    if(outbound-&amp;gt;msg-&amp;gt;overrun)&lt;br /&gt;
    {&lt;br /&gt;
        CS_ASSERT(!&amp;quot;NetworkManager::QueueLootCommand put message in overrun state!\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    cmd_count++;&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Modify npcmessages ===&lt;br /&gt;
&lt;br /&gt;
Add new CMD to PerceptionType:&lt;br /&gt;
&lt;br /&gt;
src/common/net/npcmessages.h&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
    enum PerceptionType&lt;br /&gt;
    {&lt;br /&gt;
        // Commands go from superclient to server&lt;br /&gt;
        // [...]&lt;br /&gt;
        CMD_CONTROL,&lt;br /&gt;
	CMD_LOOT, // new CMD for looting&lt;br /&gt;
        // Perceptions go from server to superclient&lt;br /&gt;
        PCPT_ANYRANGEPLAYER,&lt;br /&gt;
        // [...]&lt;br /&gt;
    };&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add new case to psNPCCOmmandsMessage::ToString():&lt;br /&gt;
&lt;br /&gt;
src/common/net/npcmessages.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
csString psNPCCommandsMessage::ToString(NetBase::AccessPointers * accessPointers)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
&lt;br /&gt;
	    case psNPCCommandsMessage::CMD_LOOT:&lt;br /&gt;
            {&lt;br /&gt;
                msgtext.Append(&amp;quot;CMD_LOOT: &amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                // Extract the data&lt;br /&gt;
                EID entity_id = EID(msg-&amp;gt;GetUInt32());&lt;br /&gt;
                csString type = msg-&amp;gt;GetStr();&lt;br /&gt;
&lt;br /&gt;
                // Make sure we haven&#039;t run past the end of the buffer&lt;br /&gt;
                if(msg-&amp;gt;overrun)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug2(LOG_SUPERCLIENT,msg-&amp;gt;clientnum,&amp;quot;Received incomplete CMD_LOOT from NPC client %u.\n&amp;quot;,msg-&amp;gt;clientnum);&lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                msgtext.AppendFmt(&amp;quot;EID: %u Type: %s&amp;quot;, entity_id.Unbox(), type.GetData());&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
            // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Process Command ===&lt;br /&gt;
Add case for new Command in NPCManager::HandleCommandList():&lt;br /&gt;
&lt;br /&gt;
src/npcclient/npcmanager.cpp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
void NPCManager::HandleCommandList(MsgEntry* me,Client* client)&lt;br /&gt;
{&lt;br /&gt;
    // [...]&lt;br /&gt;
            case psNPCCommandsMessage::CMD_LOOT:&lt;br /&gt;
            {&lt;br /&gt;
                EID entity_id = EID(list.msg-&amp;gt;GetUInt32());&lt;br /&gt;
                csString type = list.msg-&amp;gt;GetStr();&lt;br /&gt;
                Debug4(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;--&amp;gt;Got loot cmd: Entity %s to loot for %s\n&amp;quot;,&lt;br /&gt;
                       ShowID(entity_id), type.GetData());&lt;br /&gt;
&lt;br /&gt;
                // Make sure we haven&#039;t run past the end of the buffer&lt;br /&gt;
                if(list.msg-&amp;gt;overrun)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug2(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;Received incomplete CMD_LOOT from NPC client %u.\n&amp;quot;, me-&amp;gt;clientnum);&lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                gemNPC* npc = dynamic_cast&amp;lt;gemNPC*&amp;gt;(gemSupervisor-&amp;gt;FindObject(entity_id));&lt;br /&gt;
                &lt;br /&gt;
                /*  NEEDED?&lt;br /&gt;
                psCharacter* chardata = NULL;&lt;br /&gt;
                &lt;br /&gt;
                if(npc) chardata = npc-&amp;gt;GetCharacterData();&lt;br /&gt;
                &lt;br /&gt;
                if(!chardata)&lt;br /&gt;
                {&lt;br /&gt;
                    Debug1(LOG_SUPERCLIENT, entity_id.Unbox(), &amp;quot;Couldn&#039;t find character data.\n&amp;quot;);&lt;br /&gt;
                    break;&lt;br /&gt;
                }*/&lt;br /&gt;
                &lt;br /&gt;
                if(npc)&lt;br /&gt;
                {&lt;br /&gt;
                    psserver-&amp;gt;GetUserManager()-&amp;gt;LootMoney(client);&lt;br /&gt;
                    psserver-&amp;gt;GetUserManager()-&amp;gt;LootItems(client, type);&lt;br /&gt;
                    &lt;br /&gt;
                    if(npc-&amp;gt;GetTribeID())&lt;br /&gt;
                    {&lt;br /&gt;
                        // add loot to tribe&#039;s resources&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                else&lt;br /&gt;
                     Error1(&amp;quot;NPC Client try to loot with no existing npc&amp;quot;);&lt;br /&gt;
                &lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
        // [...]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine documents]] [[Category:NPCClient Design]]&lt;/div&gt;</summary>
		<author><name>Naeg</name></author>
	</entry>
	<entry>
		<id>https://planeshift.top-ix.org//pswiki/index.php?title=HowTo_Add_a_NPC_Operation&amp;diff=10118</id>
		<title>HowTo Add a NPC Operation</title>
		<link rel="alternate" type="text/html" href="https://planeshift.top-ix.org//pswiki/index.php?title=HowTo_Add_a_NPC_Operation&amp;diff=10118"/>
		<updated>2013-04-01T15:05:50Z</updated>

		<summary type="html">&lt;p&gt;Naeg: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
&lt;br /&gt;
# Create new Operation Class in npcclient/npcoperations&lt;br /&gt;
# Create new Queue-Command in npcclient/networkmgr&lt;br /&gt;
# Modify net/npcmessages&lt;br /&gt;
# Process Command in npcclient/npcmanager and execute desired action&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine documents]] [[Category:NPCClient Design]]&lt;/div&gt;</summary>
		<author><name>Naeg</name></author>
	</entry>
	<entry>
		<id>https://planeshift.top-ix.org//pswiki/index.php?title=HowTo_Add_a_NPC_Operation&amp;diff=10117</id>
		<title>HowTo Add a NPC Operation</title>
		<link rel="alternate" type="text/html" href="https://planeshift.top-ix.org//pswiki/index.php?title=HowTo_Add_a_NPC_Operation&amp;diff=10117"/>
		<updated>2013-04-01T15:03:39Z</updated>

		<summary type="html">&lt;p&gt;Naeg: Created page with &amp;quot;== Summary ==  # Create new Operation Class in npcclient/npcoperations # Create new Queue-Command in npcclient/networkmgr # Process Command in npcclient/npcmanager and execute...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
&lt;br /&gt;
# Create new Operation Class in npcclient/npcoperations&lt;br /&gt;
# Create new Queue-Command in npcclient/networkmgr&lt;br /&gt;
# Process Command in npcclient/npcmanager and execute desired action&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine documents]] [[Category:NPCClient Design]]&lt;/div&gt;</summary>
		<author><name>Naeg</name></author>
	</entry>
	<entry>
		<id>https://planeshift.top-ix.org//pswiki/index.php?title=NpcClient_Design&amp;diff=10116</id>
		<title>NpcClient Design</title>
		<link rel="alternate" type="text/html" href="https://planeshift.top-ix.org//pswiki/index.php?title=NpcClient_Design&amp;diff=10116"/>
		<updated>2013-04-01T14:58:08Z</updated>

		<summary type="html">&lt;p&gt;Naeg: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Classes ==&lt;br /&gt;
&lt;br /&gt;
The main classes of the NPCClient is the shown in the diagram below. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;uml&amp;gt;&lt;br /&gt;
psNPCClient &amp;quot;1&amp;quot; *-- &amp;quot;1&amp;quot; NetworkManager : network&lt;br /&gt;
psNPCClient &amp;quot;1&amp;quot; *-- &amp;quot;0..N&amp;quot; NPCType : npctypes&lt;br /&gt;
psNPCClient &amp;quot;1&amp;quot; *-- &amp;quot;0..N&amp;quot; NPC : npcs&lt;br /&gt;
NPCType &amp;quot;1&amp;quot; -left--* &amp;quot;1&amp;quot; NPC : brain&lt;br /&gt;
psNPCClient &amp;quot;1&amp;quot; *-- &amp;quot;0..N&amp;quot; Tribe : tribes&lt;br /&gt;
psNPCClient &amp;quot;1&amp;quot; *-- &amp;quot;0..N&amp;quot; gemNPCObject : all_gem_objects&lt;br /&gt;
&amp;lt;/uml&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more details regarding these classes see the [[#Design|Design]] section.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
*[[Network Design]]&lt;br /&gt;
*[[NPCType Design]] (The NPC Brains)&lt;br /&gt;
**[[NPC Perception Design]]&lt;br /&gt;
**[[NPC ScriptOperation Design]]&lt;br /&gt;
*[[Tribe Design]]&lt;br /&gt;
*[[gemNPCObject Design]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*[[NpcClientStartup|On Start Up]]&lt;br /&gt;
*[[NpcClientOnConnection|On Connection]]&lt;br /&gt;
*[[NavMesh Design]]&lt;br /&gt;
&lt;br /&gt;
== Cases ==&lt;br /&gt;
&lt;br /&gt;
*[[NPC Life and Death]]&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
*[[CreateNPC|Create a NPC]] describes how to create a NPC.&lt;br /&gt;
*[[NPC Scripting]] describes how to script NPCs.&lt;br /&gt;
*[[Tribe Scripting]] describes how to script Tribes.&lt;br /&gt;
&lt;br /&gt;
== HowTo&#039;s ==&lt;br /&gt;
&lt;br /&gt;
* [[HowTo Add a NPC Operation]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine documents]] [[Category:NPCClient Design]]&lt;/div&gt;</summary>
		<author><name>Naeg</name></author>
	</entry>
	<entry>
		<id>https://planeshift.top-ix.org//pswiki/index.php?title=NpcClient_Design&amp;diff=10115</id>
		<title>NpcClient Design</title>
		<link rel="alternate" type="text/html" href="https://planeshift.top-ix.org//pswiki/index.php?title=NpcClient_Design&amp;diff=10115"/>
		<updated>2013-04-01T14:56:38Z</updated>

		<summary type="html">&lt;p&gt;Naeg: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Classes ==&lt;br /&gt;
&lt;br /&gt;
The main classes of the NPCClient is the shown in the diagram below. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;uml&amp;gt;&lt;br /&gt;
psNPCClient &amp;quot;1&amp;quot; *-- &amp;quot;1&amp;quot; NetworkManager : network&lt;br /&gt;
psNPCClient &amp;quot;1&amp;quot; *-- &amp;quot;0..N&amp;quot; NPCType : npctypes&lt;br /&gt;
psNPCClient &amp;quot;1&amp;quot; *-- &amp;quot;0..N&amp;quot; NPC : npcs&lt;br /&gt;
NPCType &amp;quot;1&amp;quot; -left--* &amp;quot;1&amp;quot; NPC : brain&lt;br /&gt;
psNPCClient &amp;quot;1&amp;quot; *-- &amp;quot;0..N&amp;quot; Tribe : tribes&lt;br /&gt;
psNPCClient &amp;quot;1&amp;quot; *-- &amp;quot;0..N&amp;quot; gemNPCObject : all_gem_objects&lt;br /&gt;
&amp;lt;/uml&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more details regarding these classes see the [[#Design|Design]] section.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
*[[Network Design]]&lt;br /&gt;
*[[NPCType Design]] (The NPC Brains)&lt;br /&gt;
**[[NPC Perception Design]]&lt;br /&gt;
**[[NPC ScriptOperation Design]]&lt;br /&gt;
*[[Tribe Design]]&lt;br /&gt;
*[[gemNPCObject Design]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*[[NpcClientStartup|On Start Up]]&lt;br /&gt;
*[[NpcClientOnConnection|On Connection]]&lt;br /&gt;
*[[NavMesh Design]]&lt;br /&gt;
&lt;br /&gt;
== Cases ==&lt;br /&gt;
&lt;br /&gt;
*[[NPC Life and Death]]&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
*[[CreateNPC|Create a NPC]] describes how to create a NPC.&lt;br /&gt;
*[[NPC Scripting]] describes how to script NPCs.&lt;br /&gt;
*[[Tribe Scripting]] describes how to script Tribes.&lt;br /&gt;
&lt;br /&gt;
== Howtos ==&lt;br /&gt;
&lt;br /&gt;
* [[Howto Add a NPC Operation]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine documents]] [[Category:NPCClient Design]]&lt;/div&gt;</summary>
		<author><name>Naeg</name></author>
	</entry>
	<entry>
		<id>https://planeshift.top-ix.org//pswiki/index.php?title=NpcClient_Design&amp;diff=10114</id>
		<title>NpcClient Design</title>
		<link rel="alternate" type="text/html" href="https://planeshift.top-ix.org//pswiki/index.php?title=NpcClient_Design&amp;diff=10114"/>
		<updated>2013-04-01T14:55:23Z</updated>

		<summary type="html">&lt;p&gt;Naeg: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Classes ==&lt;br /&gt;
&lt;br /&gt;
The main classes of the NPCClient is the shown in the diagram below. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;uml&amp;gt;&lt;br /&gt;
psNPCClient &amp;quot;1&amp;quot; *-- &amp;quot;1&amp;quot; NetworkManager : network&lt;br /&gt;
psNPCClient &amp;quot;1&amp;quot; *-- &amp;quot;0..N&amp;quot; NPCType : npctypes&lt;br /&gt;
psNPCClient &amp;quot;1&amp;quot; *-- &amp;quot;0..N&amp;quot; NPC : npcs&lt;br /&gt;
NPCType &amp;quot;1&amp;quot; -left--* &amp;quot;1&amp;quot; NPC : brain&lt;br /&gt;
psNPCClient &amp;quot;1&amp;quot; *-- &amp;quot;0..N&amp;quot; Tribe : tribes&lt;br /&gt;
psNPCClient &amp;quot;1&amp;quot; *-- &amp;quot;0..N&amp;quot; gemNPCObject : all_gem_objects&lt;br /&gt;
&amp;lt;/uml&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more details regarding these classes see the [[#Design|Design]] section.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
*[[Network Design]]&lt;br /&gt;
*[[NPCType Design]] (The NPC Brains)&lt;br /&gt;
**[[NPC Perception Design]]&lt;br /&gt;
**[[NPC ScriptOperation Design]]&lt;br /&gt;
*[[Tribe Design]]&lt;br /&gt;
*[[gemNPCObject Design]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*[[NpcClientStartup|On Start Up]]&lt;br /&gt;
*[[NpcClientOnConnection|On Connection]]&lt;br /&gt;
*[[NavMesh Design]]&lt;br /&gt;
&lt;br /&gt;
== Cases ==&lt;br /&gt;
&lt;br /&gt;
*[[NPC Life and Death]]&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
*[[CreateNPC|Create a NPC]] describes how to create a NPC.&lt;br /&gt;
*[[NPC Scripting]] describes how to script NPCs.&lt;br /&gt;
*[[Tribe Scripting]] describes how to script Tribes.&lt;br /&gt;
&lt;br /&gt;
== Howtos ==&lt;br /&gt;
&lt;br /&gt;
* [[Howto add a npc operation]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine documents]] [[Category:NPCClient Design]]&lt;/div&gt;</summary>
		<author><name>Naeg</name></author>
	</entry>
</feed>