Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - That Guy

#1
Hey, guess who?

.NET Profit has been cancelled.  I was relying on my wife to be the primary translator, cultural advisor, and supplier of Chinese text for the building graphics... and we divorced late last year.  Few months after my last update, to be precise.

I would like to resurrect the game concept eventually, but for the time being I'm working on another AGS project entitled "No Laughing Matter".  When it's far enough along to provide screenshots, I'll post a thread for it.
#2
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...
#3
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.
#4
Quote from: Geoffkhan on Sat 03/12/2005 20:42:55
"Ai ya, mei guo ren bu hao?"

Hmmmmm...Ã,  :-\

It's placeholder text until I can get a proper translation for "You big jerk!"
#5
Hi everyone,

I haven't been abducted by eco-terrorists or anything... merely packed up and moved halfway across the country.Ã,  It took forever to buy a house, find a job, get unpacked, hook up the Internet, etc... but I'm back, and once I stop being distracted by The Movies (stellar game!) I'll be picking up where I left off on .NET Profit.Ã,  I also got a great new Photoshop book and have been getting much better, I think, so I can produce better-looking stuff in much less time.

Still no word on a release... and I'm actually struggling a bit with how to make the game engaging, since sitting around hacking websites doesn't make for much of a story.Ã,  I don't want to just plain clone Neuromancer, you know?

Anyhow, hope everyone has a great Holiday, and I'll have a new update soon.
#6
QuoteAs Steve says, if verb is NOT vGive then the second half of the test won't be done and the interaction will be run.

True.Ã,  I see that now.Ã,  I really need to stop coding at 2am.Ã,  ;DÃ,  The condition made sense logically, but not *logically*.

The condition did in fact need to be fired for any verb other than vGive (so the NOT vGive was correct), but it shouldn't fire for vUse UNLESS the item had an Interact event.  So that seems like it should require an OR condition, because an AND condition would have thrown out any of the other verb combos other than vUse with an event.  I think.  Geesh.

Anyway, in case anyone was curious, I restructured the conditions to the following, which works just dandy;

Code: ags

// 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;
}
#7
It's the section of the SCUMM tutorial that handled running Use/Use with conditions.Ã,  Here's the code;

Code: ags

if ((StrComp(verb, vGive) != 0) || ((StrComp(verb, vUse) == 0) && (item.IsInteractionAvailable(eModeInteract) == 1)))
{
Ã,  Ã, item.runInteraction(mode);
}


Using that code, the runInteraction method always got called for "Use" verbs, whether the item had an Interact event defined or not, so I have to assume it was either getting thrown out of the parser or unconditionally returning true.  Just to make sure I wasn't going crazy, I replaced it with a custom property on the object, and tested that, like so:

Code: ags

if ((StrComp(verb, vGive) != 0) || ((StrComp(verb, vUse) == 0) && (item.GetProperty("shouldUse") == 1)))


And again, it always returned true regardless of the value of the "shouldUse" property.Ã,  It's like the parser never even tested the last part of the && condition.

I broke the condition up into multiple lines and it all works fine now, but I'm still a little confused.Ã,  ???
#8
I have an inventory object with an interaction defined for "Look at object" and nothing else.

However, calling IsInteractionAvailable() on that object with a parameter of eInteract is returning 1, as though an interaction was defined.

Is this a bug, or am I doing something wrong?

EDIT:  I noticed that if my IF/THEN logic got too complex, the final conditional didn't get evaluated no matter what, whether it used IsActionAvailable() or even GetProperty().

the logic went something like this;

if ((something) || ((one thing) && (another thing))

then (another thing) always returned true, no matter what the condition should have been.  did I get too complicated and break something in the parser?
#9
They're basically grey slip-ons.  The kind "Weird Al" Yankovic wears, 'cept not as colorful.  I have three pair myself, but they're all of the black "kung fu" variety.

That bedspread... oh, how it gave me fits.  I'm not happy with the way it textured at all, but I'm terrible at doing cloth.
#10
bump.

you know you wanted to see another screenshot.  ;D

Game'll be on hold for a few weeks.  I'm moving cross-country and my computer's going into a box for a while.
#11
Advanced Technical Forum / Re: Properties
Sat 10/09/2005 05:31:32
QuoteFor instance, if I assign a property to a character, can I access it from code?

Yes, although AFAIK properties are read-only.  You have to set them in the editor.

QuoteAlso, If i create a struct how can I persist the struct when the game is save.  i.e. save the users experience points when he saves his game.

Pretty much all of your variables are stored when you save your game, although if this extends to the values within structs I can't say for sure.

Just out of curiosity, why would you need a struct just for experience points?
#12
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.
#13
Quote from: Dambuilder on Sun 04/09/2005 01:47:57
Heh, that professor reminds of Dr. Ed! XD
Some funky looking sprites you got there!

looks more like Dr. Scratchansniff from the Animaniacs, to me.  ;D  Or maybe a younger Hubert Farnsworth.

guess there's just only so many ways you can draw an old mad scientist.

Anyway, this looks really cool.  The style's darn original!
#14
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...
#15
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!
#16
yikes.  good catch.  As J2ME deviates so little from Java I'd have expected them to be identical in this case.  I know it's an issue in J2ME, 'cause it's bit us in the butts several times over the last few years.  ;D

Never mind then, carry on.
#17
Gents,

I would like to mention, although I'm not sure how much bearing it has on the topic at hand, that Java (and J2ME, which is what I'm currently working in) does not perform "lazy" evaluation, either.

I was reminded of it reading this because one of our junior programmers was having trouble reproducing a bug in his game and had it traced to a line that read;

Code: ags

while ((list != null) && (list [x] != "some value"))
Ã,  Ã, doSomething();


And when I pointed out to him that the second list-sub-x test was causing the NullPointerException error QA was reporting, he went off on a tirade about how "that sort of thing works in C, I know it does!", forcing me to tackle him to the carpet and beat him into submission with my coffee mug.Ã,  When he calmed down, I mentioned to him that whether it "works" or not is irrelevant, because it made little sense from a logical point of view; you have no business testing an item in an array if the array itself may be null.

I advised him to restructure his code as such;

Code: ags

if (list != null)
Ã,  Ã, if (list[x] != "some value")
Ã,  Ã,  Ã,  doSomething();


Which, of course, made it work.Ã,  As Java was designed to avoid some of the common pitfalls of C coding conventions, I thought it would be relevant to mention that it doesn't do "lazy" evals.

Regards,
TG
#18
Quote from: Anarcho on Mon 29/08/2005 18:46:13esper: My girlfriend actually told me that I should sell Emily Enough, but I didn't do it for two reasons: 1) As "professional"Ã,  as EE might seem to some, it's really lacking compared to most commercial products.Ã, 

Don't sell yourself short, my friend.  About the only thing, in my opinion, that would keep Emily from being commercial quality is the length.  The entire game would probably have been the opening chapter of a much larger title.  Otherwise, it's right up there with Day of the Tentacle as far as fully-realized characters and unique art style goes.  Can't comment on the bugs, didn't find any other than a minor glitch with the save screen.

This is coming from a guy who developed an adventure game for the mobile market last year, btw.  ;)
#19
AGS Games in Production / Re: .NET Profit
Wed 31/08/2005 00:12:39
Quote from: DCillusion on Tue 30/08/2005 22:48:15
A cyberpunk future where you live in China & hook-up with your brother's wife?

......quite a healthy fantasy life you've crafted for yourself. ;)

LOL  ;D

My wife's Chinese, so it's her sister I'm modelling the character after.

There's a lot of rationale behind the setting and character choices.

The game's set in China because, for one thing, nearly every cyberpunk type setting is Japanese or urban America.  It's too cliche.  Plus, I've spent all of one day in Tokyo but months in northern China, and I have bunches of photos of the cities I can use.

My wife's a camera-shy accountant with a name unpronounceable to most Westerners.  Her sister's a camera-hogging attention-getter who used to be a small-time TV personality, with a much more palatable first name.  Plus, I have several full-length photos of her dressed nicely I can use for reference - including one of her and me (aka, "Justin") posing in the middle of Tiananmen Square.  That picture was the whole inspiration for it, really... don't be surprised if it finds its way into the game somehow.  ;D  Conversely, I have very few pictures of my wife where she's not looking incredibly businesslike (actually, I just have very few pictures of my wife, period), which isn't very suitable for a game...
#20
AGS Games in Production / Re: .NET Profit
Tue 30/08/2005 21:48:00
yes, that's me in the title screen.  8)

I'm heavily into the use of photos for reference and paintovers, so I figured it would be easiest to use my own photo for Justin since I can get more, in any pose, as needed.  ;D

Justin's girlfriend will be based on my sister-in-law, also.
SMF spam blocked by CleanTalk