Adventure Game Studio

AGS Support => Advanced Technical Forum => Topic started by: Cine Beast on Wed 31/08/2011 20:33:40

Title: Need help perfecting a unique cursor system.
Post by: Cine Beast on Wed 31/08/2011 20:33:40
Yo, Cine Beast here - asking for aid yet again.  :-[

I'm developing a game that uses the tried-and-true Sierra interface, but I want to mix things up with one of the cursors (a cursor I've added).

I have made a Wand cursor that can be directed just like the others, but I want the following to occur when I left-click a hotspot/object/everything:

A Text GUI appears with a list of spells -
I pick a spell in the textbox and hit "Cast" -
The spell is cast, and the target is affected.

In short, a system similar to the interface in 7 Days a Skeptic & 6 Days a Sacrifice.

I'm pretty much done, but there is an inescapable problem: the GUI shows up, but when I hit "Cast," the effect does not occur.

This is the messy code for when I left-click the hotspot:

  gSpell.Visible = true;
  if (currentspell == 1 && heroicspell == true) {//So, if Incendio is chosen AND cast, the following occurs.
    cEgo.Say("Incendio!");
    Display("Fire streams from your wand and sets the blackness ablaze.");
    heroicspell = false;//So the player just casts the spell once.
    mouse.UseModeGraphic(eModeMagic);
  }

I have it set that when in the GUI, if you select "Incendio," the int "currentspell" is set to 1, and when you click "Cast," the bool "heroicspell" is set to true, so this really should work.

I think the problem is that by the time I've selected the spell and cast it, the function has already ended, and I've missed my chance. If so, I suppose I need some way for the function to repeat, or else become Blocked just after the GUI becomes visible.

I hope I made my problem clear. Thanks in advance.
Title: Re: Need help perfecting a unique cursor system.
Post by: Khris on Wed 31/08/2011 21:15:02
You have to run the actual interaction code after the Cast button is pressed, not after the hotspot is clicked.

In the global script, in the section on_mouse_click / eMouseLeft, you should have:

 else if (button == eMouseLeft) {
   ProcessClick(mouse.x, mouse.y, mouse.Mode );
 }


replace this with:

 else if (button == eMouseLeft) {
   if (mouse.Mode != eModeMagic) ProcessClick(mouse.x, mouse.y, mouse.Mode );
   else if (GetLocationType(mouse.x, mouse.y) != eLocationNothing) Cast(mouse.x, mouse.y);
 }


Now put this above the on_mouse_click function:

int cast_lt, cast_id, cast_ia;

void Cast(int x, int y) {

 cast_lt = GetLocationType(x, y);
  cast_ia = IsInteractionAvailable(x, y, eModeMagic);
 
 if (cast_lt == eLocationCharacter) {
   Character*c = Character.GetAtScreenXY(x, y);
   cast_id = c.ID;
 }
 if (cast_lt == eLocationObject) {
   Object*o = Object.GetAtScreenXY(x, y);
   cast_id = o.ID;
 }
 if (cast_lt == eLocationHotspot) {
   Hotspot*h = Hotspot.GetAtScreenXY(x, y);
   cast_id = h.ID;
 }

 gSpell.Visible = true;
}


Now put this in the button's OnClick function:

 String no_event = "The spell fizzles.";
 gSpell.Visible = false;

 if (cast_lt == eLocationCharacter) {
   Character*c = character[cast_id];
   if (cast_ia) c.RunInteraction(eModeMagic);
   else Display(no_event);
 }
 if (cast_lt == eLocationObject) {
   Object*o = object[cast_id];
   if (cast_ia) o.RunInteraction(eModeMagic);
   else Display(no_event);
 }
 if (cast_lt == eLocationHotspot) {
   Hotspot*h = hotspot[cast_id];
   if (cast_ia) h.RunInteraction(eModeMagic);
   else Display(no_event);
 }


So everytime you click on something with the magic cursor, the GUI opens. After clicking the Cast buttons, the GUI is closed. Then AGS checks whether there's a function linked to the "Magic ..." event of whatever was clicked. If there isn't, the game simply displays "The spell fizzles." If there is, the function is executed.

So you'd put this in the hotspot's Magic event function:

 if (currentspell == 1) {   // Incendio is chosen
   cEgo.Say("Incendio!");
   Display("Fire streams from your wand and sets the blackness ablaze.");
 }


This way you won't have to put duplicate code into every hotspot's event functions. The game will also pretend that you can cast every spell on anything up until the Cast button is actually clicked, i.e. every hotspot will display the spell GUI first before giving the "that doesn't work message".
Title: Re: Need help perfecting a unique cursor system.
Post by: Cine Beast on Wed 31/08/2011 21:54:03
*whistle*

Wow, thanks for all the effort, man, that's awesome.

I'm getting an error right now, though, in the code above the on_mouse_click function:

int cast_lt, cast_id;

void Cast(int x, int y) {

  cast_lt = GetLocationType(x, y);
 
  if (lt == eLocationCharacter) {                                   < Right here . . . AGS finds the 'symbol lt undefined.'
    Character*c = Character.GetAtScreenXY(x, y);
    cast_id = c.ID;

I'm afraid that this level of coding is over my head, so I don't know what the problem could be.
Title: Re: Need help perfecting a unique cursor system.
Post by: pcj on Wed 31/08/2011 22:00:37
It looks like you mis-copied the code, it should be cast_lt, not just lt.
Title: Re: Need help perfecting a unique cursor system.
Post by: Khris on Wed 31/08/2011 22:01:36
Sorry, yeah, I feared this would happen because I changed the variable name while writing the code :)

I have corrected the code, so either re-paste it or manually replace every "lt" with "cast_lt".

What the code does is store the type of what was clicked (cast_lt) and its ID (cast_id) for later use; then after Cast is clicked, use these two variables to process the actual action.
Title: Re: Need help perfecting a unique cursor system.
Post by: Cine Beast on Wed 31/08/2011 22:32:02
Okay, okay, gettin' there . . .  ;D

Now a different error is assailing me, though:


  if (cast_lt == eLocationHotspot) {
    Hotspot*h = Hotspot.GetAtScreenXY(x, y);
    cast_id = h.id;      < Here.
  }


AGS says that "'.id' is not a public member of 'Hotspot.'"

Huh. Do I need to specify the hotspot or something?
Title: Re: Need help perfecting a unique cursor system.
Post by: pcj on Wed 31/08/2011 22:33:35
The .ID property for Hotspot is capitalized on both letters.  So it should be; cast_id = h.ID;
Title: Re: Need help perfecting a unique cursor system.
Post by: Cine Beast on Wed 31/08/2011 22:51:45
Ah, duh, I should have noticed that.

. . . now AGS insists that ".IsInteractionAvailable" cannot be used the way it is currently being used:


  if (cast_lt == eLocationCharacter) {
    Character*c = character[cast_id];
    if (c.IsInteractionAvailable(eModeMagic)) c.RunInteraction(eModeMagic);  < Here.
    else Display(no_event);
  }


Actually, the error message is rather vague, and it won't let me read the whole thing.

I'm really taking up your time now, sorry.
Title: Re: Need help perfecting a unique cursor system.
Post by: pcj on Wed 31/08/2011 22:57:21
From what I can tell, that line should be:

if (IsInteractionAvailable(c.x,c.y, eModeMagic)) c.RunInteraction(eModeMagic);

And similarly with the other lines.

EDIT: Corrected the suggested modification. I finally got around to reading through the entire code.  ::)
Title: Re: Need help perfecting a unique cursor system.
Post by: Khris on Wed 31/08/2011 23:05:16
pcj: Storing the clicked coordinates is an alternative way of doing this, yes; it can lead to undesired results in certain cases though. Storing what was actually clicked is fool-proof.

I have corrected the code again, sorry for the mess. Re-paste the two long blocks of code and it should really work now :)
Title: Re: Need help perfecting a unique cursor system.
Post by: pcj on Wed 31/08/2011 23:07:37
Yeap, I see what you're doing now.
Title: Re: Need help perfecting a unique cursor system.
Post by: Cine Beast on Wed 31/08/2011 23:16:04
 ;D

It works just like I hoped it would!

Thanks for all the help, dudes. If you ever need anything from me (not that I have much to offer at this point), just let me know.
Title: Re: Need help perfecting a unique cursor system.
Post by: Khris on Wed 31/08/2011 23:17:55
Glad it finally does, I should at least test for syntax errors with that many lines of code I guess :=