TUTORIAL: SCUMM interface

Started by That Guy, Mon 05/09/2005 19:31:30

Previous topic - Next topic

That Guy

Okay, so like a typical n00b I decided to try and implement my own SCUMM-style interface without reading any tutorials.  The following is what I came up with... which, upon finaly perusing the older tutorials in the archive, I feel is a fairly clean, straightforward method.

This tutorial is compatible with 2.7 - use for earlier versions at your own risk!

First, here's a shot of the bar in action.  I'd provide you with actual graphics, but as they're styled for a sci-fi game they probably wouldn't fit in your typical SCUMM adventure.

This script assumes your player character has a script name of "cPlayer".  So wherever you see "cPlayer", substitute your own character's script name, characters[EGO], or whatever.  However you refer to your main character in the script.



Step 1: Create the GUI

This part is pretty easy.  You'll need a new GUI object that spans the width of the screen and is as tall as you want your SCUMM bar to be.  Put a custom inventory object on the right, and your stock nine verbs on the left.  Use graphical (image-based) buttons rather than the standard GUI buttons, and don't type anything in the button label.  If you really want a professional-looking effect, provide mouseover images to "light up" your verbs.

After you've added your buttons to the GUI, you need to give the GUI, as well as all the buttons, names.  This is so that you can access them via the script.  I called the GUI "gScummbar" and each button is named in the format "bVerb", so the "Give" button is "bGive".  You give the buttons names by clicking on the button itself in the GUI editor, then clicking on the "script name" property and filling it in there.  Ditto the GUI.

Step 2: Create some stuff to play with

This method works with any object (inventory, character, or hotspot) with no changes.  So put some stuff in your game to interact with.  You'll need 'em to test with.

Step 3: Add the scripting

Open up your global script and add this at the top.  It defines nine string variables with the SCUMM verbs, and also a single string variable that holds our currently-pending verb.

Code: ags

// verb constants

string vGive;
string vPickup;
string vWalkto;
string vUse;
string vOpen;
string vLookat;
string vPush;
string vClose;
string vTalkto;
string vPull;

string verb;


Then, wherever you first perform your start game initialization, add the following.  I have a function called startNewGame() but you can just as easily put it in the master game_start() method.

Code: ags

// set up SCUMM verbs
  
  StrCopy(vGive, 	"Give");
  StrCopy(vPickup,	"Pick up");
  StrCopy(vWalkto,	"Walk to");
  StrCopy(vUse,	"Use");
  StrCopy(vOpen,	"Open");
  StrCopy(vLookat,	"Look at");
  StrCopy(vPush,	"Push");
  StrCopy(vClose,	"Close");
  StrCopy(vTalkto,	"Talk to");
  StrCopy(vPull,	"Pull");
 
  StrCopy(verb, 	vWalkto);
	
  // this line makes the GUI visible, assuming you've named it "gScummbar" in the GUI editor.  Substitute with your own GUI objectname.

  gScummbar.Visible = true;



Okay, now we've got our nine verbs.  Next we need to set up the interface_click method so that it handles our button-pushing.  Here's that method.

Code: ags

function interface_click(int interface, int button) 
  {  
    if (interface == gScummbar.ID)
    {
      if (button != 2)  // this line is now superfluous, since there is no clickable button #2.
      {
        if (button == bGive.ID)
        {
           StrCopy(verb,  vGive);
					
           mouse.Mode = eModeUseinv;
        }
					
        if (button == bPickup.ID)
        {
           StrCopy(verb,  vPickup);
					
           mouse.Mode = eModeInteract;
        }
					
        if (button == bUse.ID)
        {
           StrCopy(verb,  vUse);
					
           mouse.Mode = eModeInteract;
        }
					
        if (button == bOpen.ID)
        {
           StrCopy(verb,  vOpen);
					
           mouse.Mode = eModeInteract;
        }
					
        if (button == bLookat.ID)
        {
           StrCopy(verb,  vLookat);
					
           mouse.Mode = eModeLookat;
        }
					
        if (button == bPush.ID)
        {
           StrCopy(verb,  vPush);
					
           mouse.Mode = eModeInteract;
        }
					
        if (button == bClose.ID)
        {
           StrCopy(verb,  vClose);
					
           mouse.Mode = eModeInteract;
        }
					
        if (button == bTalkto.ID)
        {
           StrCopy(verb,  vTalkto);
					
           mouse.Mode = eModeTalkto;
        }
					
        if (button == bPull.ID)
        {
           StrCopy(verb,  vPull);
					
           mouse.Mode = eModeInteract;
        }
      }
    }
  }


Whoo.  A little messy, huh?  Well, what it does is first see if the interface we clicked is our SCUMM bar.

Then we check the button pressed against all the IDs the game assigns to our buttons, accessable via their ID property.

What we do here is copy the string value of the verb button into our global verb variable.  Then, we set the mouse mode equal to the relevant mode.  The reason we do this is because AGS handles clicking on objects internally based on the mode of the mouse.  We'll use this to trigger our object interaction scripts shortly.  Patience, we're almost ready!

Next, we need to set up unhandled_event().  This method gets called every time an action is performed on an object and that action has no script associated with it.  Basically, we want to reset the verb and remove EGO's active inventory object if they attempt an unhandled interaction.

Code: ags

function unhandled_event(int what, int type) {
  
  StrCopy(verb,  vWalkto);
				  
  mouse.Mode = eModeWalkto;
			
  cPlayer.ActiveInventory = null;
}


Okay, here's the ugly one.  on_mouse_click().  We need to handle clicking on stuff and updating the SCUMM bar.  First, though, go into your game's General Settings and check the box marked "Handle Inventory in script".  This tells the game to call on_mouse_click() whenever you click on the inventory pane in your SCUMM bar.  Normally, the game won't!  With this box checked, it will - passing a value of eMouseLeftInv for button.

Code: ags

function on_mouse_click(MouseButton button) // called when a mouse button is clicked. button is either LEFT or RIGHT
{
  if (IsGamePaused() == 1) // Game is paused, so scram outta the function
  {
      return;
  }
  
   if (button == eMouseLeft) 
  {
      ProcessClick(mouse.x,mouse.y, mouse.Mode);

        StrCopy(verb,  vWalkto);

        mouse.Mode = eModeWalkto;
  }
  
   if (button == eMouseRight)
  {
      string loc;
				
      GetLocationName(mouse.x,  mouse.y,  loc);
				
      if (StrLen(loc) == 0)
      {
         StrCopy(verb,  vWalkto);
				  
         mouse.Mode = eModeWalkto;
					
         cPlayer.ActiveInventory = null;
      }
   }
	
      if (button == eMouseLeftInv)
      {
         InventoryItem *item = InventoryItem.GetAtScreenXY(mouse.x, mouse.y);
		
         if (cPlayer.ActiveInventory == null)
         {			
            // depending on the verb, we may want to run the interaction on this item
					
            if ((StrComp(verb, vGive) != 0) && (StrComp(verb, vUse) != 0))
            {
                if (item != null)
                     item.RunInteraction(mouse.Mode);
            }
            else
            {
                if (StrComp(verb, vUse) == 0)
                    if (item.IsInteractionAvailable(eModeInteract) == 1)
                    {
                         item.RunInteraction(mouse.Mode);
						
                         return;
                    }
					
                    cJustin.ActiveInventory = item;
				
                    mouse.Mode = eModeUseinv;
            }
         }
         else
         {
            if (item != null)
                  item.RunInteraction(mouse.Mode);
      }
  }
}


There's currently three types of clicks we need to care about.  Left click (eMouseLeft) processes clicks in the standard way - which is good, because we want the game to do as much of the dirty work for us as possible.  Basically, as long as you've correctly set the mouse's mode and have the methods set up correctly, the AGS engine will do its thing.  We'll see how that works shortly.

A right click (eMouseRight) will eventually call the default object interaction for that object.  You can check in the AGS manual under "custom object properties" for a way to handle this - or wait for me to implement it and then update this tutorial again.  ;D  It's simple enough.  Right now, though, all the script does is reset the default verb to "Walk to" and clear any active objects if the player right-clicks on a blank spot on screen.

The biggie is a left click on the inventory, aka eMouseLeftInv.  What we do here is check if there's an inventory item under the mouse.  If so, we must have just clicked on it.  So if we don't have an active inventory item and the user is working on constructing a "Give..." or "Use..." sentence, then we want to set the player's activeInventory object to the item we just clicked on.  Otherwise, we want to run the object's interaction script.  If, however, the verb is either "Give" or "Use" and we don't already have an inventory item active (or in the case of Use, if there's no directly-defined Use interaction - we'll see how that works in a sec), we'll set the player object's activeInventory to the item we just clicked on and also set the mouse's mode to eUseinv.  Then, when we run this script again, the next time we click on an inventory object the game will automatically perform a "use item on item" interaction since activeInventory contains an object.

We're in the home stretch.  Now we have to set up the actual statusbar text and get the game to process clicks on things.

Here's how we construct the text.  First, add a label to your SCUMM bar, and make it the width of the GUI.  I called it "command".

Then, in repeatedly_execute()...

Code: ags

function repeatedly_execute() 
  {
  // put anything you want to happen every game cycle here
  
      // update SCUMM bar
		
      string target, text, line;
		
      StrCopy(target,  "");
		
      if (cPlayer.ActiveInventory != null)
            cPlayer.ActiveInventory.GetName(target);
			
      if (StrComp(verb, vGive) == 0)
            if (StrLen(target) > 0)
                  StrCat(target, " to");
			
      if (StrComp(verb, vUse) == 0)
            if (StrLen(target) > 0)
                  StrCat(target, " with");
				
      StrCopy(text, verb);
		
      if (StrLen(target) > 0)
            StrCat(text,  " ");
		
      StrCat(text, target);
		
      // FORMAT: verb (active inventory + linkword) hotspot
		
      StrFormat(line, "%s @OVERHOTSPOT@", text);
			
      command.SetText(line);
			
  }


Basically, we format a string to contain our current verb, the active inventory object (if any), a link word (for "Give (item) to..." or "Use (item) on..." interactions), and the current hotspot - which can be anything.

Finally, we need stuff to happen if the user interacts with objects.  We'll do three of them here; a "Look at" command, a "Use" command, and a "Use (item) with (something) command.

First, let's set up our player's PDA so that if he looks at it, he tells the user "I never go anywhere without my trusty PDA."

Create the inventory item, then click on "Interactions".  Under "Look at item", add a "Run Script" interaction, where the script is;

Code: ags

cPlayer.Say("I never go anywhere without my trusty CyberLink PDA.");


Okay, so what does this do, and why does it work?

When you click on the LOOK AT button on your SCUMM bar, the interface_click() method is called.  It sees that LOOK AT is the clicked button, then copies "Look at" to the verb object.  Next, it sets the mouse mode to eLookat.  Then, when the on_mouse_click() method is called for the inventory item upon being clicked on, the script sees the mouse is in eLookat mode and runs the interaction for "Look at item".  The script above runs, and our hero speaks.  Meanwhile, the SCUMM text bar reads "Look at PDA" for the duration of the action because of how we formatted the text.

Next, let's make it so our player can use his PDA to go to a cool PDA interface screen that I defined as room #2 via the "Use" command.

Click on "Interaction" for your item, then add "Run script" for the "Interact with" event.  The script is as follows;

Code: ags

if (StrComp(verb, vUse) == 0)
{
  cPlayer.ChangeRoom(2);
}
else
   cPlayer.Say("That's not how you use a PDA.");


This script first checks the active verb to make sure the player clicked "Use" in order to interact with the item, because it is also possible, using this script, to click on Push, Pull, Open, Close, or Give (and perhaps others; any time the eInteract mode is assigned to the mouse in interface_click(), this event will fire) in order to interact with the PDA.  If the player did click Use, then the PDA, the player will go to the PDA's "closeup view" room.

Now let's make it possible to give our trusty PDA away to another character, named cGuy.

Click on "Interaction" for said character.

Add an action to "Use inventory on character."  Add a condition "if inventory item was used (1)".  Instead of 1, use whatever number you assigned to the PDA.  For me, it's the first item I created, so it's 1.  Then again, add a Run Script event and make sure the verb used was Give, like so;

Code: ags


if (StrComp(verb, vGive) == 0)
{
  cGuy.say("Thanks man, but I don't need your PDA.");
}
else
{
  // the other way this script will run is if you attempt to "use PDA with Guy".  In that case...

  cGuy.say("What the heck are you doing?");
}



That's it!  Now when you click Give, then the PDA, then the other guy, your sentence bar will construct "Give PDA to (other guy's name)" and go to the new screen.  Why?  Because clicking Give puts the mouse into "interact" mode, and clicking the PDA, since we're working with the GIVE verb, sets the PDA as our active inventory item and then forces the mouse into Useinv mode instead.  Then, when we click the other guy, the game knows that since the mouse is in eUseinv mode and there's an active inventory item, to run the "use item on object" interaction.

Enjoy!

Pumaman

Thanks for contributing this tutorial! When it's finalized, would you mind if it was transferred to a webpage and linked on the AGS resources page?

In terms of suggestions -- you might consider using the 2.7-style GUI click handlers rather than using interface_click, since it does make things a bit easier to read.

But good work  :D

That Guy

Quote from: Pumaman on Mon 05/09/2005 19:56:53
Thanks for contributing this tutorial! When it's finalized, would you mind if it was transferred to a webpage and linked on the AGS resources page?

Not at all.  ;D  That SCUMM interface is a tricky little devil...

strazer

Very nice. We need a proper, current tutorial for this kind of thing.
Has anyone worked with this and can give some comments?

A few things I've noticed:

Quote from: That Guy on Mon 05/09/2005 19:31:30Well, what it does is first see if the interface we clicked is our SCUMM bar.  If it's the first GUI you created, it should have an ID of 1.  Otherwise, substitute whatever ID# you defined it as.

There are certain situations where using the interface_click function is indeed easier. So if you want to use it, I suggest doing this:

    if (interface == gScummbar.ID)

(in AGS v2.62, this also works: if (interface == SCUMMBAR) )

Makes the code easier to read. Likewise you can do

      if (button == btnGive.ID)

and you don't need those constants.

This is especially important because deleting a GUI control renumbers the remaining ones and the script could get messed up.

Btw, for the purpose of this tutorial, you should replace "cJustin" with "player".

Please edit your first post to complete your tutorial. Once it's finished, I'll clean up this thread and move it to the Technical Archive.

Thank you!

ilSilente

#4
about on_mouse_click function:
Code: ags

  if (IsGamePaused() == 1) // Game is paused, so do nothing (ie. don't allow mouse click)
  {
  }

Here the script execution goes on even when the game is paused.

Try:
Code: ags

  if (IsGamePaused() == 1) // Game is paused, so do nothing (ie. don't allow mouse click)
  {
     return;
  }


in SCUMM, some inventory items can be used directly (for instance: Use glass of water to drink the water). So, I suggest:
Code: ags

if (button == eMouseLeftInv)
{
	InventoryItem *item = InventoryItem.GetAtScreenXY(mouse.x, mouse.y);

	if (item != null)
	{	
		if (cJustin.ActiveInventory == null)
		{
			// depending on the verb, we may want to run the interaction on this item
			if ((StrComp(verb, vGive) == 0) || ((StrComp(verb, vUse) == 0)
				&& (!item.isInteractionAvaiable(eModeIntecact))))
	                	cJustin.ActiveInventory = item;
				// Take the item only if the verb GIVE is selected, or if the verb USE is select AND there is no use for the item
			else
				item.RunInteraction(mouse.Mode);
		}
		else
		{
			item.RunInteraction(mouse.Mode);
	}

	StrCopy(verb,  vWalkto);
	mouse.Mode = eModeWalkto;
	cJustin.ActiveInventory = null;
}

I did nbot try to put it into AGS, so the syntax may be wrong. The check on isIntecactionAvaiable can also be extended to other modes (using isInteractionAvaiable(Mouse.mode)).

Again, I hate games where a non-interaction click reset the status (last 3 lines in the code above).

magintz

Wow this looks very helpful, I may look at it later on this evening.
When I was a little kid we had a sand box. It was a quicksand box. I was an only child... eventually.

That Guy

Bump.

Tutorial's been updated.  I was pleasantly surprised to find out that it handled the "Walk to" command with no additional code required.  Simply left-click while the verb line reads "walk to" anywhere walkable, and voila; she walks.

strazer

Thanks for the update.

Quote from: That Guy on Mon 05/09/2005 19:31:30This script assumes your player character has a script name of "cPlayer".  So wherever you see "cPlayer", substitute your own character's script name, characters[EGO], or whatever.  However you refer to your main character in the script.

What I meant is using just "player" which always points to the current player character. This way the user won't have to substitute his player character's name.
Can you please try if it works?

Unless there any more comments or bug reports, I'll move the thread to the Tech Archive once it leaves the first page.

ZayanM

Thanks for the tutorial.
I tried making my own GUI but couldn't get the different new commands to work. So, I followed this tutorial and found out about using string comparisons. But now my problem is when calling the functions in the interactions. So testing it,

if (StrComp(verb,  vPickup) == 0){
cEgo.AddInventory(iKey);}
else
cEgo.Say("I can't pick it up that way.");
}

..should be it.  But it says vPickup is unidentified in Room 1 script. I can't export the global variable since it is a string  either. What am I missing here?

That Guy

QuoteBut it says vPickup is unidentified in Room 1 script. I can't export the global variable since it is a string  either. What am I missing here?

Good question.  I'm sure I ran into (and solved) this problem somehow but I can't remember how I handled it.  I'll check my scripts tonight when I get home and get back to you.

That Guy

Hello again...

Here's what you do to circumvent that problem.Ã,  I'll use an object (some cash) from Justin's hotel room as an example.

Code: ags
string verb;

GetGlobalString(0, verb);

if (StrComp(verb, "Pick up") == 0)
{
Ã,  Ã, cJustin.AddInventory(icash);
	
Ã,  Ã, oCash.Visible = false;
	
Ã,  Ã, cJustin.Say("It never hurts to have some cash on hand.");
}


that's the Run (Interact) Script for the oCash object.Ã,  What I did was, in repeatedly_execute() copy the contents of the verb variable to Global String 0, like so;
      
SetGlobalString(0, verb);

Then, you just check the contents of the verb in the object script like you do for anything else.

Sorry for the omission...

strazer

Better yet, for AGS v2.70 and below, define each string as an array of characters (letters). This allows you to export/import it:

Code: ags

// main script

char vGive[200];
export vGive;
// and same for the others


Code: ags

// main script header

import char vGive[200];
// and same for the others


In AGS v2.71, use the "String" type instead of "string" and export/import that.
You might have to adjust other parts of this tutorial as well, though.

ZayanM

I haven't tried it out yet, but Thanks for the help and tutorial.

Lazarus

I've just found this tutorial and was wondering how you go about defining unhandled responses for "using an inventory item" and "giving an inventory item"

I've tried several ways but I can't quite get it right here's my last attempt:
Code: ags
Ã,  else if ((StrComp(verb, vGive) == 1) && (StrComp(verb, vUse) != 0)) {
Ã, Ã,  Display("I don't want to give that to %s.", locname);
Ã, Ã,  }
Ã,  else if ((StrComp(verb, vUse) == 1) && (StrComp(verb, vGive) != 0)) {
Ã, Ã,  Display("I can't use that on %s.", locname);
Ã, Ã,  }


*Currently using AGS Editor 2.70 (Build 2.70.601)*

MacGyver12345

I GOT A FEVER, AND THE ONLY PRESCRIPTION, IS MORE COWBELL!!

Dualnames

Well, here have this(you can set any possible interface and combinations of them with this module)


Control Modes(Scumm,BASS,Sierra)
http://ledzepforever.googlepages.com/ControlModes.rar
Worked on Strangeland, Primordia, Hob's Barrow, The Cat Lady, Mage's Initiation, Until I Have You, Downfall, Hunie Pop, and every game in the Wadjet Eye Games catalogue (porting)

MacGyver12345

Quote from: Dualnames on Wed 19/08/2009 08:40:06
Well, here have this(you can set any possible interface and combinations of them with this module)


Control Modes(Scumm,BASS,Sierra)
http://ledzepforever.googlepages.com/ControlModes.rar
is there supposed to be a module that comes in the file? theres only a txt file that i dont really understand. :-\
I GOT A FEVER, AND THE ONLY PRESCRIPTION, IS MORE COWBELL!!

monkey0506

The ControlModes.scm file is the module. You would import it into AGS 3 by right clicking on Scripts and then selecting "Import script..." (or similar, don't have AGS directly available right now).

In any case, there's the option in the Game preferences whether or not to "Enforce new-style Strings". As long as that's turned off (false) then this code would work fine.

MacGyver12345

I GOT A FEVER, AND THE ONLY PRESCRIPTION, IS MORE COWBELL!!

monkey0506

#19
One other thing I noticed that was outdated was the usage of interface_click. That wouldn't be automatically called any more and needs to be updated to the appropriate event handlers.

Just for reference, I'll take the opportunity to upgrade the script to work with the latest version of AGS. The guide above is still relevant, so I'll just post the updated code. This will be a (virtual) 1-to-1 conversion, I will make only very minimal changes to the code other than updating it.

Quote from: That Guy on Mon 05/09/2005 19:31:30This script assumes your player character has a script name of "cPlayer".

NOTE: All versions of AGS from 2.7 forward support the player keyword which always points toward the current player character. This is especially useful if you have multiple playable characters and change control of them throughout the game (as in DoTT).

Step 3: Add the scripting

Quote from: That Guy on Mon 05/09/2005 19:31:30Open up your global script and add this at the top.

NOTE: This is the file GlobalScript.asc for AGS 3+.

Code: ags

// verb constants

String vGive; // note the capital 'S' here, that indicates a new-style String
String vPickup; // AGS is case-sensitive, so this IS important
String vWalkto;
String vUse;
String vOpen;
String vLookat;
String vPush;
String vClose;
String vTalkto;
String vPull;

String verb;


Code: ags

// set up SCUMM verbs
  
  vGive   = "Give";
  vPickup = "Pick up";
  vWalkto = "Walk to";
  vUse    = "Use";
  vOpen   = "Open";
  vLookat = "Look at";
  vPush   = "Push";
  vClose  = "Close";
  vTalkto = "Talk to";
  vPull   = "Pull";

  verb    = vWalkto;
	
  // this line makes the GUI visible, assuming you've named it "gScummbar" in the GUI editor.  Substitute with your own GUI objectname.

  gScummbar.Visible = true;



Quote from: That Guy on Mon 05/09/2005 19:31:30Next we need to set up the interface_click method so that it handles our button-pushing.

NOTE: interface_click has been deprecated and will no longer be automatically called. As such I'm updating the code to the more modern event handlers which work for AGS 2.7+.

Code: ags
function bGive_Click(GUIControl *control, MouseButton button) {
  verb = vGive;

  mouse.Mode = eModeUseinv;
}

function bPickup_Click(GUIControl *control, MouseButton button) {
  verb = vPickup;

  mouse.Mode = eModeInteract;
}

function bUse_Click(GUIControl *control, MouseButton button) {
  verb = vUse;

  mouse.Mode = eModeInteract;
}

function bOpen_Click(GUIControl *control, MouseButton button) {
  verb = vOpen;

  mouse.Mode = eModeInteract;
}

function bLookat_Click(GUIControl *control, MouseButton button) {
  verb = vLookat;

  mouse.Mode = eModeLookat;
}

function bPush_Click(GUIControl *control, MouseButton button) {
  verb = vPush;

  mouse.Mode = eModeInteract;
}

function bClose_Click(GUIControl *control, MouseButton button) {
  verb = vClose;

  mouse.Mode = eModeInteract;
}

function bTalkto_Click(GUIControl *click, MouseButton button) {
  verb = vTalkto;

  mouse.Mode = eModeTalkto;
}

function bPull_Click(GUIControl *control, MouseButton button) {
  verb = vPull;

  mouse.Mode = eModeInteract;
}


Code: ags
function unhandled_event(int what, int type) {
  
  verb = vWalkto;
				  
  mouse.Mode = eModeWalkto;
			
  player.ActiveInventory = null; // changed from cPlayer - this keyword will auto-update if player changes
}


Code: ags
function on_mouse_click(MouseButton button) // called when a mouse button is clicked. button is either LEFT or RIGHT
{
  if (IsGamePaused() == 1) // Game is paused, so scram outta the function
  {
      return;
  }
  
   if (button == eMouseLeft) 
  {
      ProcessClick(mouse.x,mouse.y, mouse.Mode);

        verb = vWalkto;

        mouse.Mode = eModeWalkto;
  }
  
   if (button == eMouseRight)
  {
      String loc;
				
      loc = Game.GetLocationName(mouse.x,  mouse.y);
				
      if (loc.Length == 0)
      {
         verb = vWalkto;
				  
         mouse.Mode = eModeWalkto;
					
         player.ActiveInventory = null; // changed from cPlayer
      }
   }
	
      if (button == eMouseLeftInv)
      {
         InventoryItem *item = InventoryItem.GetAtScreenXY(mouse.x, mouse.y);
		
         if (player.ActiveInventory == null) // changed from cPlayer
         {			
            // depending on the verb, we may want to run the interaction on this item
					
            if ((verb != vGive) && (verb != vUse))
            {
                if (item != null)
                     item.RunInteraction(mouse.Mode);
            }
            else
            {
                if (verb == vUse)
                    if (item.IsInteractionAvailable(eModeInteract) == 1)
                    {
                         item.RunInteraction(mouse.Mode);
						
                         return;
                    }
					
                    player.ActiveInventory = item; // changed from cJustin - assumed the player is expected here
				
                    mouse.Mode = eModeUseinv;
            }
         }
         else
         {
            if (item != null)
                  item.RunInteraction(mouse.Mode);
      }
  }
}


Code: ags
function repeatedly_execute() 
  {
  // put anything you want to happen every game cycle here
  
      // update SCUMM bar
		
      String target, text, line;
		
      target = "";
		
      if (player.ActiveInventory != null) // changed from cPlayer
            target = player.ActiveInventory.Name; // changed from cPlayer
			
      if (verb == vGive)
            if (target.Length > 0)
                  target = target.Append(" to");
			
      if (verb == vUse)
            if (target.Length > 0)
                  target = target.Append(" with");
				
      text = verb;
		
      if (target.Length > 0)
            text = text.Append(" ");
		
      text = text.Append(target);
		
      // FORMAT: verb (active inventory + linkword) hotspot
		
      line = String.Format("%s @OVERHOTSPOT@", text);
			
      command.Text = line;
			
  }


Code: ags
if (verb == vUse)
{
  player.ChangeRoom(2); // changed from cPlayer
}
else
   player.Say("That's not how you use a PDA."); // changed from cPlayer


Code: ags
if (verb == vGive)
{
  cGuy.Say("Thanks man, but I don't need your PDA."); // corrected capitalization of Say
}
else
{
  // the other way this script will run is if you attempt to "use PDA with Guy".  In that case...

  cGuy.Say("What the heck are you doing?"); // corrected capitalization of Say
}


As of this writing this code is relevant to all versions of AGS 2.71 and higher. It will not compile under any previous versions.

SMF spam blocked by CleanTalk