Problem with "walking" inventory item.

Started by Duckbutcher, Thu 11/09/2008 13:14:37

Previous topic - Next topic

Duckbutcher

I've got a clockwork mouse in my inventory. Whenever I "Use" it, I want my main character to put it on the ground and let it wander around the screen (as a 'character' in its own right) until I decide to pick it back up (removing the mouse 'character' from the room and returning the mouse 'item' to my inventory). This should be possible in any room in the game.

Is there any easy way to do this WITHOUT putting conditionals and commands into the repeatedly execute section of every room in my game (something which would take far too much time)? Is there something that can be done from the script of the inventory item itself?

Thanks for your help guys, and be sure to spell everything out for me, I'm still not big on scripting!

paolo

Just off the top of my head (no guarantees this will work), I might do this as follows:

In the repeatedly_execute function for the global script (which will be executed in every room):

Code: ags

if (Mouse.Mode == eModeUserInv && cYourCharactersNameGoesHere.ActiveInventory == iMouse)
{
    cYourCharactersNameGoesHere.LoseInventory(iMouse);
    cMouse.x = 100;    //or wherever you want the mouse to be
    cMouse.y = 100;    //or wherever you want the mouse to be
    cMouse.Visible = true;
}


Then to pick the mouse back up, write the following in the function for interacting with the mouse character:

Code: ags

cMouse.Visible = false;
cYourCharactersNameGoesHere.AddInventory(iMouse);


iMouse is the name of the mouse inventory item, and cMouse and cYourCharactersNameGoesHere are the names of the mouse and player characters, by the way.

Duckbutcher

#2
Thanks for the prompt reply, and I get the gist of what you've said. However, I'm having trouble getting it to work.

if (Mouse.Mode == eModeUserInv && cEgo.ActiveInventory == iMouse)
{
    cEgo.LoseInventory(iMouse);
    cMouse.x = 150;    //or wherever you want the mouse to be
    cMouse.y = 125;    //or wherever you want the mouse to be
    cMouse.Visible = true;
}


This is what I put into repeated ex, and it throws up a message which says: "error (line 701) undefined symbol 'emodeuserinv'.

And in the item script:

cMouse.Visible = false;
cEgo.AddInventory(iMouse); 

And it throws up: "Error (line 1207): 'Visible' is not a public member of 'Character'"

I know roughly what I have to do. I need a variable value every time the mouse is 'used' which is checked by the rep.ex. global script and switches the mouse character off/on or calls it / sends it from another room. I just don't really know how to put it into script! I'm going to go away and see what I can come up with, but in the meantime andy help would be much appreciated!

Also, I'd like the mouse to appear at the character's feet if possible. Is there any way to do this?

Any ideas?

SSH

eModeUserInv is wrong, you want:
eModeUseInv   (no R)

To make a character disappear you need to do:
cMouse.Room=-1;

not cMouse.Visible=false;

and the opposite is cMouse.Room=player.Room;
12

Khris

paolo's code will put the mouse on the ground as soon as it's selected as inv item.

Just put the code inside iMouse_Use() in the global script (or whatever the properly linked function is called).
Put it near the character's feet by setting the cMouse's coords to something like player.x+Random(10)-5, player.y+Random(6)-3.
Alternatively, check which way the player is facing and drop it in front of him.

paolo

#5
Ah, yes - thanks for the corrections to my half-remembered AGS functions (I posted my code from a PC that does not have AGS installed).

Quote from: KhrisMUC on Thu 11/09/2008 18:23:06
Put it near the character's feet by setting the cMouse's coords to something like player.x+Random(10)-5, player.y+Random(6)-3.
Alternatively, check which way the player is facing and drop it in front of him.

Nice suggestion. I thought about putting it near the player after I'd posted. Esprit d'escalier (http://en.wikipedia.org/wiki/Esprit_d%27escalier)...

Quote from: SSH on Thu 11/09/2008 15:40:08
To make a character disappear you need to do:
cMouse.Room=-1;

not cMouse.Visible=false;

and the opposite is cMouse.Room=player.Room;

An alternative way of disabling and hiding a character is as follows:

Code: ags

cMouse.on = false;


and then of course

Code: ags

cMouse.on = true;


to turn the character back on.

Duckbutcher

#6
Thanks for all your help guys, and sorry if I seem a bit dim, but I'm still stumbling! I've had a bit of a mess about with this (I had to change emodeUseInv to eModeUse in the end as I was still getting an error, even with the spelling correction).

This is how the first bit of code is looking:

// script for Inventory item 16 (Clockwork Mouse): Use inventory item
 
  // script for inventory 16. Interact inventory item
if (Mouse.Mode == eModeUse && cEgo.ActiveInventory == iMouse)
{
    cEgo.LoseInventory(iMouse);
    cMouse.x = 150;    //or wherever you want the mouse to be
    cMouse.y = 125;    //or wherever you want the mouse to be
    cMouse.on = true;
}

This doesn't seem to work. It's doing something though, because the "Use" command isn't followed by the "Use Mouse With..." on the status line - it just highlights and then vanishes. The mouse character doesn't appear and the item stays in the inventory.

This is a script for the item itself. I wasn't getting anything by putting it into the global rep.ex - perhaps I'm missing something.

Am I making some hideously obvious mistake??

EDIT: So I tried a different approach. I've got a variable called "ratvar" which is changed to 1 when the player uses the item. Then I tried to put this in the global rep.ex:

//-----------------------------------------------------
   if (GetGraphicalVariable("ratvar") == 1) {
   SetGraphicalVariable("ratvar"), 0);
    cEgo.LoseInventory(iMouse);
    cMouse.x = 150;    //or wherever you want the mouse to be
    cMouse.y = 125;    //or wherever you want the mouse to be
    cMouse.on = true;
  }
//-----------------------------------------------------

I thought this would work, but it keeps throwing up "unexpected if"s and "Unexpected  (" .

So I'm still stumped!

paolo

You have an extra ) in the following line:

Code: ags

SetGraphicalVariable("ratvar"), 0);


I think it should probably be:

Code: ags

SetGraphicalVariable("ratvar", 0);


Duckbutcher

Quote from: paolo on Fri 12/09/2008 16:16:49
You have an extra ) in the following line:

Code: ags

SetGraphicalVariable("ratvar"), 0);


I think it should probably be:

Code: ags

SetGraphicalVariable("ratvar", 0);



It still says "unexpected if"!


paolo

#9
What line is the unexpected if on? Can you give the code where it is complaining about the if? (It might not be the code you have already posted.)

The other thing might be that you need to use your mouse inventory item on something for the script to be triggered. I assume that you now want to do the following:

* Select mouse in inventory
* Use mouse on ground - mouse appears on ground and is removed from inventory.

You could try creating a hotspot or region on the ground (either one should work) and then moving this code:

Code: ags

if (Mouse.Mode == eModeUse && cEgo.ActiveInventory == iMouse)
{
    cEgo.LoseInventory(iMouse);
    cMouse.x = 150;    //or wherever you want the mouse to be
    cMouse.y = 125;    //or wherever you want the mouse to be
    cMouse.on = true;
}


from where it is and into the code for any click on the hotspot or region. (Alternatively, if the function exists, you can put it in the function for interacting with the hotspot/region and then you don't need "Mouse.Mode == eModeUse && ".)

Then, if that works, you can do something clever like replacing these two lines:

Code: ags

    cMouse.x = 150;    //or wherever you want the mouse to be
    cMouse.y = 125;    //or wherever you want the mouse to be


with

Code: ags

    if (GetRegionAt(Mouse.x, Mouse.y) == 1)
    {
        cMouse.x = Mouse.x;
        cMouse.y = Mouse.y;
    }


for a region, or the equivalent for a hotspot, where 1 is the number of the region or hotspot (change this as appropriate).

Note that the above is very likely not correct AGS code (again, this is half-remembered stuff) but what this will do is make the mouse appear where you click provided that the point where you clicked is somewhere in the ground region or hotspot.

Again, I'm sure someone else can turn this into correct AGS code for me :)

If this still doesn't work, I'll have a look to see if I can knock something up in AGS over the weekend.

Duckbutcher

#10
It's the same code I put in an earler post. It's in the repeatedly execute section of the global script. It finds fault with the "if" on the first line, and if I remove the "If" it throws up errors about everything else too...

//-----------------------------------------------------
   if (GetGraphicalVariable("ratvar" == 1) {
   SetGraphicalVariable("ratvar", 0);
    cEgo.LoseInventory(iMouse);
    cMouse.x = 150;    //or wherever you want the mouse to be
    cMouse.y = 125;    //or wherever you want the mouse to be
    cMouse.on = true;
  }
//-----------------------------------------------------

Using the mouse on a region on the ground is something I may have to do as a last resort, but I'd rather have the action triggered just by clicking "Use" and then "Mouse". The puzzle in question involves something coming out of a hiding place to chase the mouse, you see, not having the mouse "used" ON anything in particular.

Thanks so much for your help. I've been using AGS for two years now, and still come unstuck on script issues like this, so your assistance is much appreciated!

DoorKnobHandle

Code: ags

if (GetGraphicalVariable("ratvar" == 1) 


should be:

Code: ags

if (GetGraphicalVariable("ratvar") == 1) 

Duckbutcher

Quote from: dkh on Fri 12/09/2008 16:48:55
Code: ags

if (GetGraphicalVariable("ratvar" == 1) 


should be:

Code: ags

if (GetGraphicalVariable("ratvar") == 1) 


Yep, already adressed that, thanks. The problem is with the "if" at the moment.

Thanks though!

paolo

#13
OK, I've written a test game and got this working. It's much simpler than you might think!

Assuming you have the following:

* A character called cMouse
* An inventory item called iMouse, which the player either starts out with or has obtained during the game

and that you are using AGS 3.0, do the following:

* Scrap the code for putting down the mouse that you have written so far.
* Create a hotspot in your room that covers the floor area; call the hotspot hFloor
* From the "Show this room's" menu for the room, select "Hotspots".
* Click on the lightning icon, then click to create a function for "Use inventory on hotspot" (the automatically generated function should be called hHotspot1_UseInv).
* Write this code in hHotspot1_UseInv():

Code: ags

  if (cEgo.ActiveInventory == iMouse)
  {
    cEgo.LoseInventory(iMouse);
    
    if (Hotspot.GetAtScreenXY(mouse.x, mouse.y) == hFloor)
    {
      cMouse.x = mouse.x;
      cMouse.y = mouse.y;
      cMouse.on = true;
    }
  }


* Select "Nothing" from the "Show this room's" menu.
* Click on the lightning icon, then click to create a function for "Enters room before fade-in" (the function should be called room_Load)
* Write this code in roomLoad():

Code: ags

  cMouse.on = false;


* Go to your mouse character.
* Click on the lightning icon, then click to create a function for "Interact character (this function should be called cMouse_Interact).
* Write this code in cMouse_Interact():

Code: ags

  cEgo.AddInventory(iMouse);
  cMouse.on = false;


And that should be it... let me know if this works now.

What I've done is made it so that the mouse will be put down at the point where you click on the floor. If you click somewhere that isn't the floor, the mouse won't appear.

Making the mouse move around of its own accord, assuming that this is what you want to do, is another matter :) Broadly speaking, though, you'll want something in the repeatedly_execute function of the global script that does the following:

Code: ags

if (cMouse.on)    //is the mouse on the floor?
{
   //do something here to move the mouse around
}



Duckbutcher

Thanks a lot for your help. I'm using AGS 2.71, but I'm sure I'll be able to get this working.

I was hoping to have the function activated simply by "Using" the item, rather than "using it on" something, ie a hotspot,  that way it would work in any room and wouldn't be tied to a specific one.

I may have to go away and re-think the whole puzzle! Thanks for the code though, I'm sure I'll be able to use it in some capacity.

paolo

#15
Quote from: Duckbutcher on Sat 13/09/2008 00:09:54
Thanks a lot for your help. I'm using AGS 2.71, but I'm sure I'll be able to get this working.

You're welcome. Ah, if I'd known you were using AGS 2.71 I'd have coded it up there. Never mind. The above code should work in 2.71 as well, provided you put it in the right place in the scripts (use the "i" button for the room to get the room interactions and the "Interaction..." button for the mouse character to get its interactions).

Quote from: Duckbutcher on Sat 13/09/2008 00:09:54
I was hoping to have the function activated simply by "Using" the item, rather than "using it on" something, ie a hotspot,  that way it would work in any room and wouldn't be tied to a specific one.

I don't understand what you mean by just "using" the item. Generally you have to use an item on something before anything happens. Do you mean that just selecting the mouse item in the inventory with the "use" cursor makes the mouse appear? That is, so that "Use mouse on" would appear (briefly) as the name of the action, but then you wouldn't need to click anywhere else for the mouse to appear? That is what I thought you meant in the first place. I'll have another go at doing this.

EDIT: OK, this works for me:

* Remove the code you wrote for interacting with the hotspot (the code in hHotspot1_UseInv(), or whatever the function is called in 2.71)
* Put the following code in repeatedly_execute() in the global script:

Code: ags

  if (gInventory.Visible && cEgo.ActiveInventory == iMouse) //has user selected mouse?
  {
    cEgo.LoseInventory(iMouse);
    cMouse.x = cEgo.x + 20;
    cMouse.y = cEgo.y;
    cMouse.on = true;

    Mouse.Mode = eModeInteract;
    gInventory.Visible = false;
  }


When you click on the mouse in the inventory, it will appear next to Roger and will disappear from the inventory. The inventory window is closed and the mouse cursor goes back to "interact" mode (otherwise the cursor would still be the mouse inventory item).

Duckbutcher

#16
"Error Line 738 Undefined symbol 'gInventory'."

It seems I'm doomed to be foiled repeatedly on this one.

Could the fact I'm using the Proskritos MI2 template be relevant in any way?

EDIT: I got rid of a couple of lines, specifically the ones which I believe refer to the mouse icon mode and the inventory window, as with a lucasarts template, these would be irrelevant:

   if (cEgo.ActiveInventory == iMouse) //has user selected mouse?
  {
    cEgo.LoseInventory(iMouse);
    cMouse.x = cEgo.x + 20;
    cMouse.y = cEgo.y;
    cMouse.on = true;

   
  }

The game starts without error, but when I attempt to "Use" the mouse, the game crashes and says :

Error: run_text_script1: error -6 running function 'repeatedly_execute':
Error: Null pointer referenced
in Global Script (line 265)
from Global script (line 710)

The lines it mentioned are as follows:

265:  madetext=String.Format("%s%s %s ", madetext, RemoveExtension(player.ActiveInventory.Name), Tmode[mode].preposition);

710: UpdateActionBar(mouse.x+GetViewportX(),mouse.y+GetViewportY());

Sorry, this seems to be going on for ever and ever...

paolo

Quote from: Duckbutcher on Sat 13/09/2008 15:16:57
Could the fact I'm using the Proskritos MI2 template be relevant in any way?

[snip]

Error: run_text_script1: error -6 running function 'repeatedly_execute':
Error: Null pointer referenced
in Global Script (line 265)
from Global script (line 710)

The lines it mentioned are as follows:

265:  madetext=String.Format("%s%s %s ", madetext, RemoveExtension(player.ActiveInventory.Name), Tmode[mode].preposition);

710: UpdateActionBar(mouse.x+GetViewportX(),mouse.y+GetViewportY());

Yes, it could very well be to do with the fact that you are using a different user interface from me. I'm not familiar with the template you are using, so that might be a problem.

One thing - did you copy and paste my code exactly? You've got cMouse, iMouse, Mouse and mouse in the code I posted - getting one of these wrong would cause problems, although it would be more likely that your game would not compile rather than it would compile and then crash when you run it.

Quote from: Duckbutcher on Sat 13/09/2008 15:16:57
Sorry, this seems to be going on for ever and ever...

Welcome to the wonderful world of programming :) Don't worry - it always takes a few tries to get something working.

Sorry I can't be of any more assistance. I'm sure someone else will be able to help you out here.

Mazoliin

Couldn't this work?

if (player.ActiveInventory == iMouse && mouse.IsButtonDown(eMouseLeft)){
  //All your code here
}

Here you have to click some where on the screen to use the mouse, not just click on the mouse in the inventory. Then the actionbar should be able to update, but I can't promise it will work.

Can you get a link to the template so that I/others can play around with it?

SMF spam blocked by CleanTalk