conditions question

Started by miguel, Tue 07/07/2009 12:04:42

Previous topic - Next topic

miguel

Hi to all, I've been experiencing some odd behaviours with my project:
   Sometimes the engine responds in a way but sometimes doesn't, I understand it's just bad coding or at least not very polished coding anyway.
   My question is:

   if (condition1)==false  { result 1;return; }
   if (condition2)==true   { result 2;return; }
   if (condition3)==true   { result 3;return; }

   Will the engine return at result 2, ALWAYS, or will it run condition 3 and return at that point given the fact that both condition 2 and 3 are the similar (not exactly equal);
   Can the engine skip/get confused?

  Hope I explained myself right.
  Thank you
 
Working on a RON game!!!!!

GuyAwesome

It depends on what exactly is in the conditions, I think, so it's hard to answer based on that example...

However, you may want to look into the else keyword - I think it's considered 'more polished' than using return every time
Code: ags

if (Thing1 == false) {
  Result(1);
  // code will run if Thing1 is false, IGNORING Thing2 and Thing3 (won't check their states)
}
else if (Thing2 == true) {
  Result(2);
  // code will run if Thing1 and Thing2 are true, IGNORING Thing3
  // will not run if Thing1 is false
}
else if (Thing3 == true) {
  Result(3);
  // code will run if Thing1 and Thing3 are true
  // will not run if Thing1 is false, OR Thing2 is true
}
else {
  Result(4);
  // code will run in any other case (i.e. if Thing1 is true and Thing2 and Thing3 are both false)
  // optional condition - I only included it for display. If you don't want anything to happen here, just leave it out :)
}


It doesn't matter if you change the outcomes for Thing2 or Thing3 in an earlier condition (e.g. set Thing2 to true in the Thing1 condition), it goes on their state when the first if runs, and won't re-check until the code is called again.

miguel

Thanks for the quick answer, GuyAwesome,
  I am familiar with the else function, take a look at some simple condition code I have and doesn't work well:

Code: ags

function iwirehook_OtherClick()
{
if ((Label23.Text=="Basin") && (cEgo.Room==32)) {
  disablehotspots();
  goff();
  gGui12.Visible=false;gBLUEINVENTORY.Visible=false;
  cEgo.Walk(200, 215, eBlock);lookup();
    cEgo.Say("Let's see if I can work it out...");
    cEgo.LockViewFrame(51, 0, 0);
    cEgo.Animate(0, 4, eOnce, eBlock);
    cEgo.Say("Yes! I got it!");
    cEgo.LoseInventory(iwirehook);
    progressmade();
    cEgo.AddInventory(iRing);
    UpdateInventory();
    cEgo.LockViewFrame(21, 0, 0);
    cEgo.Walk(cEgo.x, cEgo.y + 10, eBlock);
    cEgo.Say("Well, in the process, the wire got lost down the drain.");
    lookdown();
    cEgo.Say("But this ring is worth much more anyway!");
    /////////////get ring//////////////
    resetglobals();guisetpos();goff();
    enablehotspots();
    return;
  }
   else {
     goff();
     gGui12.Visible=false;gBLUEINVENTORY.Visible=false;
     cEgo.Think("That doesn't work here.");
     resetglobals();guisetpos();goff();enablehotspots();
     return;
   }
}


    Now, most of the times, it runs the else function instead of the first one even if the conditions don't tell the engine to do so.
Working on a RON game!!!!!

GuyAwesome

#3
OK, I might've misunderstood your question, sorry.

I'm not sure why you need the return in there at all, TBH. Unless there's some other use for it I haven't come across* it just stops any further code from running, which is unnecessary there as the if/else should do that automatically. Still, there's no reason that code shouldn't work as you want, provided the conditions (Label text and room) are being met. Maybe throw in a Display line, to check what they're registering as when the function runs? (Display("%s, %d", Label23.Text, cEgo.Room);) Could it be that the Label text is changing before the conditions run, or something?



* Well, there's obviously returning a value (e.g. return a + b;) - which'll also stop further code from running - but is there any other use for return; on its own?

Khris

To make one thing clear: the engine doesn't arbitrarily follow conditions, as in only most of the time. The engine will always do exactly what it is told.
So if the second block gets run, that means that either Label23.Text isn't "Basin" or cEgo.Room isn't 32, or both, at the time the engine hits the if line, without exception.

If the condition "doesn't work well", that means you've made a mistake, plain and simple.

miguel

#5
I'm sure I made a mistake then, but one thing that confuses me is:

   label23.text = overhotspot, meaning I'm sure it is 'Basin';
   I am sure the player is on room 32;
   I disable every hotspots after triggering the inventory item (clicking) so that if he mouse goes over other hotspot label23 doesn't get a different reading;

   When disabling hotspot 'Basin', does label23 gets the same treatment, something like label23.text=="" ?


P.S: are the forums different somehow? I'm getting this different letter type and some threads aren't separated?
Working on a RON game!!!!!

GuyAwesome

Do you have some sort of strange triggering going on there, or what? The code you posted seems to be an InventoryItem's OtherClick() function (i.e. any mode other than Look, interact, talk or Use Inv on an item), so unless you're calling it from a Hotspot interaction (for some reason?) the mouse won't be over the 'Basin' Hotspot. (Or am I missing something about how overhotspot works? Assuming you even mean the @OVERHOTSPOT@ token, and not your own script.) Or, it might be that @OVERHOTSPOT@ - if that IS what you're using -  registers as just that, rather than the actual Hotspot name.

If you've already disabled the Hotspot somewhere then it won't show up in @OVERHOTSPOT@ or Hotspot.GetAtScreenXY, which a custom overhotspot script will probably use. (It's simply not there to be recognised.) If you're talking about that disablehotspots(); line you've got, the condition is already running by then so it won't affect it.
Did you try that Display line I suggested to see what's actually going on here? As KhrisMUC said, the engine won't arbitarily skip conditions on a whim :) so one or more of your conditions must not be being met.

And the forums look perfectly normal to me...

Khris

#7
A wild guess: are you using an inv gui that pops up at the cursor's position to use an inv item on a hotspot?
Because this would explain the seemingly random behavior: if you click the inv item while the mouse is still over the basin hotspot, the first code block is run, but clicking iwirehook outside the hotspot will run the else block.

You have to use another method. Store the hotspot/object/character the player clicked on in pointer variables, then run the appropriate interaction.

(Also note that if my guess is correct, that info should have been in your opening post ;))

miguel

#8
GuyAwesome: thanks for your explanation again,

KhrisMUC: you got it right, this is something that I just can't make it. I use a label to store the hotspot (label23 equals mouse.getatscreen(mouse.x,mouse.y) and it works 90% of the time. Doesn't that do the same as a pointer?
       About one year ago, you helped me with the same problem. Your solution was:
           Label23.Text = Game.GetLocationName(mouse.x, mouse.y);
       I've been using it since.
              And yes, I should have told more info about it. Sorry.

Anyway, because it works 90% of the time, I wondered AGS might have that odd behaviour. And I should have known better. I'll take a look at those pointers in the manual.

Thanks

GuyAwesome: I'm telling you, and I'm not crazy, the page's formatting is different, maybe it's Firefox? It doesn't bother me anyway.

Update: I think that by disabling the label when I rightclick does the trick, I'm still testing but I think I got it.
Working on a RON game!!!!!

Khris

Yes, and that code is fine for displaying what's under the mouse. But if you right click a hotspot to open a non-blocking GUI, then move the mouse to an inv item on that GUI, there's no guarantee that the label's text will still be the hotspot's name, in fact it's more unlikely than likely if you have to move the mouse to an inv item a few rows down. This is in no way a reliable method.

If it's safe to use the hotspot's name to distinguish between all of them, all you need to do is store the name in a global string variable immediately after the right click.
What I'd do is this:

Code: ags
//above on_mouse_click
int mx, my;

// inside on_mouse_click, eMouseRight

    if (GetLocationType(mouse.x, mouse.y) != eLocationNothing) {
      mx = mouse.x
      my = mouse.y;
      // open inv GUI
    }
    else mx = -1;  // player clicked on nothing

// inside on_mouse_click, eMouseLeftInv

    if (mx != -1) {
      // close inv GUI
      player.ActiveInventory = inventory[game.inv_activated];
      ProcessClick(mx, my, eModeUseinv);        // simulate a use inv click at the location stored above
    }


Note that I have no idea how the rest of your interface works, so the code probably isn't usable without some adjustments.

miguel

I guess I'm doing a workaround, immediately after the right click I disable what reads the screen for hotspots (label23), I do whatever I have to and then just before 'returning' I enable label23.
I've been testing it and it's working fine.

Anyway, I do use rightclick on hotspots/characters to open VerbGui's, and then one of the verbs opens an inventory window, leftclick selects an item and rightclick examines the item. Your code would work perfectly I believe. But since I've got it running I'll save your code for future uses and keep my workaround going.
Thanks again.
Working on a RON game!!!!!

SMF spam blocked by CleanTalk