Game Development Community

dev|Pro Game Development Curriculum

RPGDialog - NPC interaction system

by Nelson A. K. Gonsalves · 11/29/2002 (12:27 pm) · 186 comments

RPGDialog is a Torque Game Engine modification that adds standard RPG Dialogs support, including multiple choice questions and question linking(underlined words on a question that perform actions when clicked on). Also included is an editor for creating and editing dialogs easily.

Instructions on installing are included on the zip file.

New download location since geocities is dead

Have fun using it! :)
And let me know of any problems you might find.

Contact me at dk_uo@yahoo.com or leave a comment here.

Features

- Multiple choice questions, present a question and a list of answers and do something depending on which answer the player picks, the choices are numbered and can be picked either by the mouse or by pressing the 1,2,...,9,0 keys on the keyboard, choices after 10 must be selected via mouse.

- Question Links, Ex: "Hello, I'm Mary, how are you?" clicking on the word Mary would trigger an action as if it was a choice in the Multiple choice window.

- Portraits, pictures that represent the NPC, change it depending on the choices of the player or even use them to show the mood of the NPC.

- Sounds, add voice overs or any sound effects that are triggered when the question is displayed.

- Fully functional in multiplayer games, only allowing one player to talk to each NPC at a time, sending a message telling the others that the NPC is busy if they try to talk to it.

- Moving the player too far away from the NPC closes the Dialog automatically.

- Each option triggers a function, allowing complete customization of the actions caused by the dialog, either by using the included functions, altering them or creating your own.

June 8th 2005.
I finnaly got around to giving this a much deserved update!

Firstly I updated the instructions and made a few changes to make it fully compatible with TGE 1.3.

Also I've added buttons to move the answers up and down in the editor, so its now easier to organize the available options.

And finnaly, multiple actions can now be triggered by one response, thanks goes to BrokeAss Games for the idea. To execute multiple actions just add them one after the other without anything separating them, there is one example of this in the test scripts. Ohh, and now clicking on the actions list will add them to the actions edit and not replace them.

I have one warning though, version 1.0 .dla files are incompatible with version 1.3, there is an easy workaround I've used on my files, just open them directly in a text editor and do a quick replace all from "<" to "<END><", add <END> to the end of each line and remove the <END> from the beginning of the line, that should make them 100% compatible.

Let me know if you find any problems.

-Nelson

About the author

Recent Blogs

#81
12/18/2005 (10:40 pm)
Has anyone taken a shot at updating this for TGE 1.4?

Doh, answered my own question...it was pretty easy to setup in 1.4. Once I got it all figured out, took about 15 minutes!

@Nelson - thanks for putting this together!!!
#82
12/26/2005 (9:18 am)
@Jake
What did you do in the 15 minutes? I've just started to look at it. When I run my program, hitting "q" brings up the panel that normally shows the dialog but all that shows in the panel is "continue". I'm walking through setting up the resource to see if I can figure out what is missing but if you have the answer, I would be grateful.
#83
12/27/2005 (7:17 am)
Greetings all :)

I would appreciate a pointer or two if anyione has seen this before:)

I installed this mod into a clean 1.4 starter.fps seemed fine (woohoo)

I Installed it into my mod and changed all the directories it pointed to and fired up my mod, seemed fine (woohooo again)

One problem has surfaced though...

Changing the action line is fine on an entry.. eq changing the command from teleport(0 0 0
0 to kill() is no problem, but changing the text description for the option from teleport me to Kill me again causes chaos... I cannot backspace characters, I can only highlight and overtype, and sometimes the last lketters in the decription vanish and sometimes I can't even highlight and overtype.

I am guessing this is me being stupid, but can't work out which part of my stupidity is attacking me this time:)

Thanks in advance

Regards

Graham
#84
12/27/2005 (9:26 am)
My problem was because I forgot that "rw" has to be changed in the files added by the RPG resource. Everything appears to work ok now.
#85
01/04/2006 (5:56 am)
Jee'zz Creepers!

Working on this for the 2nd day and seeing that so many wrote *works outta the box and all that* really makes me feel like a moron.

I have a clean project 1.3.5 + SGLP and some minor GUI adjustments.

Did a fresh download of the pack from Gonsalves site and started to add the code in the files. Then moved the new files into place. And even forced the files into the project by adding them manually in MsVS.NET2003.

Running the program and starting a mission allows me to use F5 to toggle in and out of the RPGEditor but trying to use the SpawnTestNPC() brings me this error;
==>spawnTestNPC();
starter.fps/server/scripts/RPGDialog.cs (173): Unable to find function AIPlayer::spawn

I can see that my code in the freshly downloaded RPGDialog.cs is not the same as the code Sebastian Potter posted above.

function SpawnTestNPC()
{
   %player = AIPlayer::spawn("a test NPC","359.973 304.759 217.766");
   %player.RPGDialogScript = "Test";
   %player.RPGDialogPortrait = "Test.png";
   %player.RPGDialogStartQuestion = 1;
   %player.RPGDialogBusy = false;
   %player.RPGDialogBusyText = 'Sorry but I\'m busy talking to %1 right now.';
   %player.RPGDialogTalkingTo = 0;

   return %player;
}

function SpawnNPC(%Name,%Script,%Portrait,%startQuestion,%location)
{
   %player = AIPlayer::spawn(%Name,%location);
   %player.RPGDialogScript = %Script;
   %player.RPGDialogPortrait = %Portrait;
   %player.RPGDialogStartQuestion = %startQuestion;
   %player.RPGDialogBusy = false;
   %player.RPGDialogBusyText = 'Sorry but I\'m busy talking to %1 right now.';
   %player.RPGDialogTalkingTo = 0;
   
   return %player;
}

I even added AiPlayer.cc and AiPlayer.cs to my project....

Anyone got a suggestion ?
#86
01/04/2006 (10:03 am)
Figured out that AIPlayer::spawn is not inside the files of my Torque folders, nor the SGLP folders I have.
And the function is not defined inside aiPlayer.h, cs or cc.......

Tried Sebastians code but that gave me another error....

So now Im totally lost :/
#87
01/04/2006 (11:04 am)
@Christian

It sounds like an error that others have had.

Dan Thiel recommended the following (above):
"1 - changing "rw" directory references to "starter.fps" including the directories within the .zip.
2 - moved the datablock PlayerData(LightMaleHumanArmor) from the "demo" to your project if it doesn't exist, otherwise the "spawnTestNPC();" function will not work.
3 - in the directions it reference "rw\client\default.cs" This location wasn't quite right for me. "

In particular, make sure that you check the RPGDialog files and change every instance of "/rw" to "/starter.fps" within the files. For example, in \NewFiles\common\RPGDialogEditor\default.cs, there are four references to "rw" that have to be changed to refer to your project directory instead of \rw. Also, make sure that the files in \NewFiles\rw were placed in the proper folders in your project directory.

After I followed Dan's advice, I was able to get the resource working in both 1.3 and 1.4.

Hope this helps.
#88
01/04/2006 (12:23 pm)
Thx Judith!

You made me rethink it all, and I found 1 thing I hadent coped to its full extent.
The 'datablock' was not a file or object standalone. But it could be code....

Looking into the files of RW, I saw that player.cs had datablock PlayerData(LightMaleHumanArmor)
I did a look into my projects player.cs and noticed that it had datablock PlayerData(PlayerBody)

So a swift change of the RPGDialog.cs dataBlock = PlayerBody; // was LightMaleHumanArmor did the trick.
#89
01/07/2006 (7:15 am)
Another question to the folks here!

I did implement BrokeAss Games code to this but like DejaBlue I am having a hard time coping this one;
I looked at BrokeAss Games Guipic
and its not at all like mine

Maybe that it why I dont seem to be able to have the NPC hand me a weapon.....

BTW: anyone made stuff like Mark Francombe mentioned aboue to go along with this ressource ?
#90
01/07/2006 (7:42 am)
Hi Christian,
I actually did get this working, but have accidentaly broken it once or twice, there are some definate holes in my knowledge and so I have stopped working with it for a while to concentrate on other things (graphics visuals etc) Right now I have a working gui (one that pops up on the NPC when you hit Q) but it refuses to implement the command right now, I have fixed this before, and I know I will again, but its down to making lots of different copies of my game to try to get other things working with out scrwing up stuff... Prob is ALWAYS down to directories changing and having to fix/remember where to fix 'em!!!

Where I got stumped (and still am) is needing to create totally different NPC's in different places with different models/textures and different RPGDialog conversation routines. Making different characters basically.
Despite masses of help from Chris (Lombard) I never quite got there, there seems to be a bit of a learning curve from changing the way the demo works to how I NEED TIT TO WORK... ha ha ha, still not over that one!
WHat I need(ed), is all NPC info in ONE file with differnt meshes/convasations/ positions AND THEN (long way off) to implement a simple inventory so that one charater can say to you "If you go to Mr Smith, he will give you the key to the cellar" and then when you get there Mr Smith to say, "Sure you can have the key, if you bring me some beer" etc etc....
so no help from me Im afraid, but good luck!!!

Mark
#91
01/07/2006 (9:23 am)
Seems that we still are some that works on this one ;o)

So your saying that its something that 'are broken'. Well gotta look it all over again then, must be a typo then :/

now!
Some of the stuff you are at now I got working. Dunno how to start off, but heres the info I have....

In Starter.fps/server/scripts/game.cs at line 53 right after exec("./aiPlayer.cs");
I add exec("./NPCharacters.cs");

This script I execute is placed in Starter.fps/server/scripts/NPCharacters.cs

[code]
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Spawning in the various NPC's
//-----------------------------------------------------------------------------

function spawnEveryone()
{
SpawnNPC("Fleinn Far
#92
01/08/2006 (2:06 am)
I'm in a hurry, but I felt real bad posting some mods and getting back to fixes/updates.
This supports multiple actions (don't forget to add a - at the end of several commands back to back with no spaces).
The sell/buy/reward/take work great for quests/vendors.
I also included joining a team (I use as faction recruitors).
If I'm missing pieces from other files, let me know, I'll try and post em.
This also has the fix for having to back up before talking to the NPC again.
Sorry this is so long, but I don't have time to cut the pieces out.

This is my RPGDialog.cs file (well most of it). ;)
//-----------------------------------------------------------------------------
// RPGDialog - Presents the player with a question and several answers to select from
// Created by Nelson A. K. Gonsalves
//-----------------------------------------------------------------------------

function getAction(%actionFile,%questionNumber)
{
   %file = new FileObject();
   if(isFile($Pref::Server::RPGDialog::ActionPath@%actionFile@".dla") && %file.openForRead($Pref::Server::RPGDialog::ActionPath@%actionFile@".dla"))
   {
      for(%i=1;%i<%questionNumber;%i++)
      {
         %file.readLine();
         if(%file.isEOF())
            return "<Invalid Question>";
      }
      %action=%file.readLine();
   }
   else if(isFile($RPGDialogEditorPref::ActionPath@%actionFile@".dla") && %file.openForRead($RPGDialogEditorPref::ActionPath@%actionFile@".dla"))
   {
      for(%i=1;%i<%questionNumber;%i++)
      {
         %file.readLine();
         if(%file.isEOF())
            return "<Invalid Question>";
      }
      %action=%file.readLine();
   }

   %file.close();
   %file.delete();
   return %action;
}

function RPGDialogMessageClient(%client,%sender,%npcFile,%questionNumber)
{
   %senderName=%sender.getshapename();
   %portrait=%sender.RPGDialogPortrait;
   %playerName=%client.player.getshapename();

   %sender.RPGDialogBusy=true;
   %sender.RPGDialogTalkingTo=%client;
   %sender.setAimObject(%client.player);
   
   commandToClient(%client,'RPGDialogMessage',%sender,%senderName,%portrait,%npcFile,%questionNumber,%playerName);
   
   CheckRPGDialogStatus(%client,%sender);
}

function serverCmdRPGDialogAnswer(%client,%sender,%questionNumber,%answerNumber)
{
   if(%client==%sender.RPGDialogTalkingTo)
   {
      %npcFile=%sender.RPGDialogScript;

      %Actions=GetAction(%npcFile,%questionNumber);

      if(%Actions!$="<InvalidQuestion>")
      {
         if(strPos(%answerNumber,"QL")>=0)
         {
            %ActionHeaderSize=strlen("<"@%answerNumber@">");
            %NextActionHeaderSize=strlen("<"@getSubStr(%answerNumber,2,strLen(%answerNumber))+1@">");
            %ActionStart=strPos(%Actions,"<"@%answerNumber@">")+%ActionHeaderSize;
            %ActionEnd=strPos(%Actions,"<"@getSubStr(%answerNumber,2,strLen(%answerNumber))+1@">");
         }
         else
         {
            %ActionHeaderSize=strlen("<"@%answerNumber@">");
            %NextActionHeaderSize=strlen("<"@%answerNumber+1@">");
            %ActionStart=strPos(%Actions,"<"@%answerNumber@">")+%ActionHeaderSize;
            %ActionEnd=strPos(%Actions,"<"@%answerNumber+1@">");
         }


         if(%ActionEnd>=0)
         {
            %ActionEnd=%ActionEnd-%ActionStart;
         }
         else
         {
            %ActionEnd=strlen(%Actions);
         }

         // BrokeAss Games Multi-Response Add-On

         %SubActions=getSubStr(%Actions,%ActionStart,%ActionEnd);

      for(%i=1;%i<%ActionEnd;%i++){
      //%bla=true;
      //while(%bla){ <- Loops are bad

         %ParamStart=strPos(%SubActions,"(")+1;
         %ParamEnd=strPos(%SubActions,")")-%ParamStart;
         %Param=getSubStr(%SubActions,%ParamStart,%ParamEnd);

         %Action=getSubStr(%SubActions,0,%ParamStart-1);
         //echo("SubActions: " @ %SubActions); //Parser Debugging
         //echo("Action: " @ %Action @ " Param: " @ %Param); //Parser Debugging

         if(%Param!$="")
         {
            eval(%Action@"("@%Param@","@%client@","@%sender@",\""@%npcFile@"\");");
            %SubActions=getSubStr(%SubActions,%ParamEnd+%ParamStart+1,%ActionEnd);
         }
         else
         {
            eval(%Action@"("@%client@","@%sender@",\""@%npcFile@"\");");
            %SubActions=getSubStr(%SubActions,%ParamEnd+%ParamStart+1,%ActionEnd);
         }

         if(%SubActions$="-")
         {
            //%bla=false; // <- I said loops are bad
            break;
         }

        } // End Multi-Response Add-On
      }
      else
      {
      echo("ERROR::Invalid Question/Answer!!\nnpcFile = "@%npcFile@"\nquestionNumber = "@%questionNumber);
      }
   }
}

function serverCmdRPGDialogRay(%client)
{
   %StartPos=%client.player.gettransform();
   %Eye = %client.player.getEyeVector();
   %EndPos = vectorScale(%Eye, -1);
   %EndPos = vectorsub(%StartPos,%EndPos);

   InitContainerRadiusSearch(%EndPos, 0.5, $TypeMasks::PlayerObjectType);

   %rayCast=ContainerSearchNext();
   while(%rayCast != 0 )
   {
      if(%rayCast.aiPlayer && %rayCast.RPGDialogScript!$="")
      {
         if(!%rayCast.RPGDialogBusy)
         {
            RPGDialogMessageClient(%client, %rayCast, %rayCast.RPGDialogScript,%rayCast.RPGDialogStartQuestion); //start dialog.
            return;
         }
         else
         {
            if(IsRPGDialogBusy(%rayCast))
            {
               if(%client!=%raycast.RPGDialogTalkingTo)
               {
                  messageClient(%client, '', %rayCast.RPGDialogBusyText, %raycast.RPGDialogTalkingTo.player.getShapeName());
                  return;
               }
               else
                  return;
            }
            else
            {
               RPGDialogMessageClient(%client, %rayCast, %rayCast.RPGDialogScript,%rayCast.RPGDialogStartQuestion); //start dialog.
               return;
            }
         }
      }
      %rayCast=ContainerSearchNext();
   }
}

function IsRPGDialogBusy(%AiPlayerID)
{
   InitContainerRadiusSearch(%AiPlayerID.getTransform(), 3, $TypeMasks::PlayerObjectType);
   %rayCastBusyCheck=ContainerSearchNext();
   while(%rayCastBusyCheck != 0 )
   {
      if(%rayCastBusyCheck==(%AiPlayerID.RPGDialogTalkingTo).player)
      {
         return(true);
      }
      %rayCastBusyCheck=ContainerSearchNext();
   }
   return(false);
}

function CheckRPGDialogStatus(%Client,%Sender) //Checks if the player has moved since he started the dialog, moving too far from the sender will cancel the dialog
{
   InitContainerRadiusSearch(%Sender.getTransform(), 2, $TypeMasks::PlayerObjectType);
   %rayCast=ContainerSearchNext();
   while(%rayCast != 0 )
   {
      if(%rayCast==%Client.player)
      {
         schedule(1000,0,"CheckRPGDialogStatus",%Client,%Sender);
         return;
      }
      %rayCast=ContainerSearchNext();
   }
   CommandToClient(%client,'CloseRPGDialog');
   %Sender.RPGDialogBusy=false;
   %Sender.RPGDialogTalkingTo=0;
   %Sender.clearAim();
}

function SpawnTestNPC()
{
   %player = new AIPlayer() {
      dataBlock = PlayerBody;
      aiPlayer = true;
      RPGDialogScript = "Test";
      RPGDialogPortrait = "Test.png";
      RPGDialogStartQuestion = 1;
      RPGDialogBusy = false;
      RPGDialogBusyText = 'Sorry but I\'m busy talking to %1 right now.';
      RPGDialogTalkingTo = 0;
   };
   MissionCleanup.add(%player);

   // Player setup
   %player.setMoveSpeed(8);
   %player.setTransform(pickSpawnPoint());
   %player.setEnergyLevel(60);
   %player.setShapeName(%player);
   return %player;
}

//------------------------------------------------------------------------------
// RPGDialog Script Functions - functions bellow are made to be used by the
// dialog scripts.
// The commented out lines that start with <ActionList> are used when populating the action
// list on the RPGDialog Editor.
//------------------------------------------------------------------------------

//<ActionList>GotoQuestion(QuestionNumber)
function GotoQuestion(%questionNumber,%client,%sender,%npcFile)
{
   RPGDialogMessageClient(%client, %sender, %npcFile, %questionNumber);
}

//<ActionList>CloseDialog()
function CloseDialog(%client,%sender,%npcFile)
{
   //sendind nothing to the client will close the dialog without anything else happening
   %sender.RPGDialogBusy=false;
   %sender.RPGDialogTalkingTo=0;
}

//<ActionList>MoveTo(Position)
function MoveTo(%position,%client,%sender,%npcFile)
{
   %sender.setAimLocation(%position);
   %sender.setMoveDestination(%position);
   CloseDialog(%client,%sender,%npcFile);
}

//<ActionList>KillPlayer()
function KillPlayer(%client,%sender,%npcFile)
{
   %client.player.kill("Sudden");
   CloseDialog(%client,%sender,%npcFile);
}

//<ActionList>KillSender()
function KillSender(%client,%sender,%npcFile)
{
   %sender.kill("Sudden");
   CloseDialog(%client,%sender,%npcFile);
}

//<ActionList>DamagePlayer(Amount)
function DamagePlayer(%DamageAmount,%client,%sender,%npcFile)
{
   %client.player.damage(0, %sender.getposition(), %damageAmount, "Sudden");
   CloseDialog(%client,%sender,%npcFile);
}

//<ActionList>DamageSender(Amount)
function DamageSender(%DamageAmount,%client,%sender,%npcFile)
{
   %sender.damage(0, %sender.getposition(), %damageAmount, "Sudden");
   CloseDialog(%client,%sender,%npcFile);
}

//<ActionList>TeleportPlayer(Position)
function TeleportPlayer(%Pos,%client,%sender,%npcFile)
{
   %client.player.setTransform(%Pos);
   CloseDialog(%client,%sender,%npcFile);
}

//<ActionList>TeleportSender(Position)
function TeleportSender(%Pos,%client,%sender,%npcFile)
{
   %sender.setTransform(%Pos);
   CloseDialog(%client,%sender,%npcFile);
}

//<ActionList>RenamePlayer(NewName)
function RenamePlayer(%NewName,%client,%sender,%npcFile)
{
   messageAllExcept(%client, -1, 'MsgPlayerRenamed', '\c1%1 is now known as %2.',%client.player.getshapeName(),%NewName);
   messageClient(%client, 'MsgPlayerRenamed', '\c1You are now known as %1.',%NewName);
   %client.player.setshapeName(%NewName);
   CloseDialog(%client,%sender,%npcFile);
}

//<ActionList>RenameSender(NewName)
function RenameSender(%NewName,%client,%sender,%npcFile)
{
   messageAll('MsgAIRenamed','\c1%1 is now known as %2.',%sender.getshapename(),%NewName);
   %sender.setshapeName(%NewName);
   CloseDialog(%client,%sender,%npcFile);
}

//<ActionList>ChangeStartQuestion(QuestionNumber)
function ChangeStartQuestion(%NewQuestion,%client,%sender,%npcFile)
{
   %sender.RPGDialogStartQuestion=%NewQuestion;
   CloseDialog(%client,%sender,%npcFile);
}

//<ActionList>ChangeStartQuestionAndOpen(QuestionNumber)
function ChangeStartQuestionAndOpen(%NewQuestion,%client,%sender,%npcFile)
{
   %sender.RPGDialogStartQuestion=%NewQuestion;
   RPGDialogMessageClient(%client, %sender, %sender.RPGDialogScript,%NewQuestion);
}

//<ActionList>ChangeStartQuestionAndGoto(StartQuestion,GotoQuestion)
function ChangeStartQuestionAndGoto(%NewStartQuestion,%GoTo,%client,%sender,%npcFile)
{
   %sender.RPGDialogStartQuestion=%NewQuestion;
   RPGDialogMessageClient(%client, %sender, %sender.RPGDialogScript,%GoTo);
}

//<ActionList>ChangeScript(ScriptName,QuestionNumber)
function ChangeScript(%NewScript,%StartQuestion,%client,%sender,%npcFile)
{
   if(%NewScript!$="" && isFile($RPGDialogEditorPref::ActionPath@%NewScript@".dla"))
   {
   %sender.RPGDialogScript=%NewScript;
   %sender.RPGDialogStartQuestion=%StartQuestion;
   CloseDialog(%client,%sender,%npcFile);
   }
}

//<ActionList>ChangeScriptAndOpen(ScriptName,QuestionNumber)
function ChangeScriptAndOpen(%NewScript,%StartQuestion,%client,%sender,%npcFile)
{

   if(%NewScript!$="" && isFile($RPGDialogEditorPref::ActionPath@%NewScript@".dla"))
   {
      %sender.RPGDialogScript=%NewScript;
      %sender.RPGDialogStartQuestion=%StartQuestion;
      RPGDialogMessageClient(%client, %sender, %NewScript,%StartQuestion);
   }
}

//<ActionList>ChangePortrait(NewPortrait)
function ChangePortrait(%NewPortrait,%client,%sender,%npcFile)
{
   %sender.RPGDialogPortrait=%NewPortrait;
   CloseDialog(%client,%sender,%npcFile);
}

//<ActionList>ChangePortraitAndGoto(NewPortrait,QuestionNumber)
function ChangePortraitAndGoto(%NewPortrait,%QuestionNumber,%client,%sender,%npcFile)
{
   %sender.RPGDialogPortrait=%NewPortrait;
   RPGDialogMessageClient(%client, %sender, %sender.RPGDialogScript,%QuestionNumber);
}

//<ActionList>SellItem(Item,Price,Currency,Amount)
function SellItem(%item,%price,%currency,%amount,%client,%sender,%npcFile)
{
   if(%client.player.getInventory(%currency) >= %price){
   %client.player.incInventory(%item, %amount);
   %client.player.decInventory(%currency, %price);
   %sender.player.incInventory(%currency, %price);
   messageClient(%client, 'SellItem', '\c1You have purchased %1 %2(s) for %3 %4 from %5.',%amount,%item,(%price*%amount),%currency,%sender.name);
   } else {
   messageClient(%client, 'SellItem', '\c1You do not have %3 %4 to buy %1 %2(s) from %5.',%amount,%item,(%price*%amount),%currency,%sender.name);
   }

   //RPGDialogMessageClient(%client, %sender, %sender.RPGDialogScript,%QuestionNumber);
   CloseDialog(%client,%sender,%npcFile);
}
//<ActionList>BuyItem(Item,Price,Currency,Amount)
function BuyItem(%item,%price,%currency,%amount,%client,%sender,%npcFile)
{
   if(%client.player.getInventory(%item) >= %amount){
   %client.player.decInventory(%item, %amount);
   %client.player.incInventory(%currency, %price);
   %sender.player.decInventory(%currency, %price);
   messageClient(%client, 'BuyItem', '\c1You have sold %1 %2(s) for %3 %4 to %5.',%amount,%item,(%price*%amount),%currency,%sender.name);
   } else {
   messageClient(%client, 'BuyItem', '\c1You do not have %1 %2(s) to sell for %3 %4 to %5.',%amount,%item,(%price*%amount),%currency,%sender.name);
   }
   CloseDialog(%client,%sender,%npcFile);
}
//<ActionList>GiveItem(Item,Amount)
function GiveItem(%item,%amount,%client,%sender,%npcFile)
{
   if(%sender.player.getInventory(%item) >= %amount){
   %client.player.incInventory(%item, %amount);
   %sender.decInventory(%item, %amount);
   messageClient(%client, 'GiveItem', '\c1%3 has given you %1 %2(s).',%amount,%item,%sender.name);
   } else {
   messageClient(%client, 'TakeItem', '\c1%3 does not have %1 %2(s) to give you.',%amount,%item,%sender.name);
   }
   CloseDialog(%client,%sender,%npcFile);
}
//<ActionList>TakeItem(Item,Amount)
function TakeItem(%item,%amount,%client,%sender,%npcFile)
{
   if(%client.player.getInventory(%item) >= %amount){
   %sender.player.incInventory(%item, %amount);
   %client.decInventory(%item, %amount);
   messageClient(%client, 'TakeItem', '\c1You have given %1 %2(s) to %3.',%amount,%item,%sender.name);
   } else {
   messageClient(%client, 'TakeItem', '\c1You do not have %1 %2(s) to give to %3.',%amount,%item,%sender.name);
   }
   CloseDialog(%client,%sender,%npcFile);
}
//<ActionList>RewardItem(Item,Amount)
function RewardItem(%item,%amount,%client,%sender,%npcFile)
{
   %client.player.incInventory(%item, %amount);
   messageClient(%client, 'RewardItem', '\c1You have been rewarded %1 %2(s) by %3.',%amount,%item,%sender.name);
   CloseDialog(%client,%sender,%npcFile);
}
//<ActionList>SayChat(ChatMessage)
function SayChat(%chatmessage,%client,%sender,%npcFile)
{
   messageClient(%client, 'SayChat', '\c1%1 Says: %2',%sender.name,%chatmessage);
   CloseDialog(%client,%sender,%npcFile);
}
//<ActionList>JoinFaction(Faction)
function JoinFaction(%teamid,%client,%sender,%npcFile)
{
   %client.joinTeam(%teamid);
   CloseDialog(%client,%sender,%npcFile);
}

Ari
*Edit: Removed a mildly rude comment in the code. It was not targeted at the original programmer, but served as reminder to myself when I kept getting a certain bug and forgetting why.
#93
01/08/2006 (2:26 am)
A tip on adding this to existing AI.
I just modify any AI I'm using so that it looks similar to the following in functions like somebot::onAdd and somebot::create.

%player = new AIPlayer() {
      dataBlock = PlayerBody;
      aiPlayer = true;
      RPGDialogScript = "Test"; <- Add
      RPGDialogPortrait = "Test.png"; <- Add
      RPGDialogStartQuestion = 1; <- Add
      RPGDialogBusy = false; <- Add
      RPGDialogBusyText = 'Sorry but I\'m busy talking to %1 right now.'; <- Add
      RPGDialogTalkingTo = 0; <- Add
      name = "MultiBot";
   };
Chasing a bot down to talk to it can be a pain depending on the AI you use.

Ari
#94
01/08/2006 (6:01 pm)
link is bad
EDIT:Nevermind my mistake
#95
01/08/2006 (8:18 pm)
I can't seem to get it to download either :(
#96
01/09/2006 (7:57 am)
@ Brokeass Games
Thanks for the repost, that backup2talk bugfix is great ;o)

This is the one doing this, or ?
if(%rayCast.aiPlayer && %rayCast.RPGDialogScript!$="")
Not sure I got it right, but the code is working. The teamgranting is not good if the game aint teamgame. But the idea is great for our planned Odin, Loki........... sets

Im still not sure how your buy/sell, reward system works though.
It seems to me that there is soemthing vital missing (or is it just be being dumb/blind).
After all your gui link displayes a gui I cant seem to get up.....

BTW: I notice that you dont have the function SpawnNPC(%Name,%Script,%Portrait,%startQuestion,%location, %dBlock,%faction) in there. Did you place that in your NPC script ?

Well, back to meddle with the scripts and the editor again :/
#97
01/09/2006 (12:34 pm)
@Christian S
#98
01/10/2006 (12:06 am)
Now...to see if it works in 1.4...
#99
01/10/2006 (12:10 am)
He he Midhir, good luck ;o)

Brokeass Games, I just took a look at the GUi's again (and do I feel dumb)

Your question field is just moded and adjusted slightly to what is default in the ressource one. Sorry for being blind. And not that hard yet at code ^^

PS: it works ;o)
#100
01/13/2006 (10:07 pm)
hey this is a great resource!! but i am having a few problems. first off i get the following errors in the console
common/RPGDialogEditor/editorMain.cs (204): Unable to find object: 'Answer2' attempting to call function 'delete'
common/RPGDialogEditor/editorMain.cs (205): Unable to find object: 'Action2' attempting to call function 'delete'
common/RPGDialogEditor/editorMain.cs (206): Unable to find object: 'editAnswer2Button' attempting to call function 'delete'
common/RPGDialogEditor/editorMain.cs (207): Unable to find object: 'moveAnswer2UpButton' attempting to call function 'delete'
common/RPGDialogEditor/editorMain.cs (208): Unable to find object: 'moveAnswer2DownButton' attempting to call function 'delete'
although i havnt really noticed any problems with this yet.......
the thing im having the probem with is that, every time i try to press the backspace or delete button when editing a script in the in-game editor i get the following errors
Fatal: (../engine/core/stringBuffer.cc @ 178) StringBuffer::cut - len >= 1.
Cannot display alerts in full screen mode. Dumping message to console...
Fatal: (../engine/core/stringBuffer.cc @ 178), StringBuffer::cut - len >= 1.
any ideas? thanks