SOLVED: Problem finding regions

Started by Fanomatic, Sat 02/02/2019 16:47:05

Previous topic - Next topic

Fanomatic

Hello there everyone, I'm a beginner at AGS and I've run into a problem related to regions.

I've tried but I can't seem to figure it out on my own, so I thought I'd check with the forum. I haven't found another instance of this issue, so I don't 'think' anyone has asked it before, but if so I apologize :)

It bears mentioning that I'm using the 9-verb extension.

So, I've made a room that is a prison. The room is divided by wall/bars the player can't pass through until they open locked doors that allows them to, so the player shouldn't be able to perform actions that affects objects in the part of the room they aren't in, provided they haven't opened the door to let them through.

The region setup looks roughly like this.



Currently I'm doing a check every time I click on something, like this:

(Global script)
Code: ags
// Check if what the player clicks are in the same region as the player.
function checkArea()
{
  Region*playerRegion = Region.GetAtRoomXY(player.x, player.y); //get current player region
  Region*clickedRegion = Region.GetAtRoomXY(mouse.x, mouse.y); //get current mouse region
  Wait(10);

  //debug dialog
  player.Say("Player region is %d.", Region.GetAtRoomXY(player.x, player.y));
  player.Say("Mouse region is %d.", clickedRegion);
  
    //If the player clicks the same region the player is in it can always interact.
    if (clickedRegion == playerRegion)
    {
      canWalkToObject = true;
    }
    
    //If player clicks on region 1
    if (clickedRegion == region[1])
    {
      if (playerRegion == region[2])
        {
            sayCantReach();
            canWalkToObject = false;
        }
      else if (playerRegion == region[3])
        {
          if (cellDoorIsOpen == false)
          {
            sayCantReach();
            canWalkToObject = false;
          }
          else
          {
            canWalkToObject = true;
          }
        }
      else if (playerRegion == region[4])
        {
          sayCantReach();
          canWalkToObject = false;
        }
      
    }
    //If player clicks on region 2
    else if (clickedRegion == region[2])
    {
      if (playerRegion == region[1])
        {
            sayCantReach();
            canWalkToObject = false;
        }
      else if (playerRegion == region[3])
        {
          if (cellDoor2IsOpen == false)
            {
              sayCantReach();
              canWalkToObject = false;
            }
          else
            {
              canWalkToObject = true;
            }
        }
      else if (playerRegion == region[4])
      {
        sayCantReach();
        canWalkToObject = false;
      }
    }
    
    //If player clicks on region 3
    else if (clickedRegion == region[3])
    {
      if (playerRegion == region[1])
        {
          if (cellDoorIsOpen == false)
          {
            sayCantReach();
            canWalkToObject = false;
          }
          else
          {
            canWalkToObject = true;
          }
        }
      else if (playerRegion == region[2])
        {
          if (cellDoor2IsOpen == false)
          {
            sayCantReach();
            canWalkToObject = false;
          }
          else
          {
            canWalkToObject = true;
          }
        }
      else if (playerRegion == region[4])
      {
        sayCantReach();
        canWalkToObject = false;
      }
    }
    if (clickedRegion == region[4])
    {

    }
  }


Then in the room script I do this (verb check area example)

Code: ags
  // Push
  else if(UsedAction(eGA_Push)) 
  {
    checkArea();
    if (canWalkToObject == false)
    {
      return;
    }
    else
    {
      if (player == cFive)
      {
        player.Say("No, I like the Feng Shui here.");
      }
      else if (player == cFuzzy)
      {
        player.Say("Fuzzy can't move it!");
      }
      else
      {
        player.Say("");
      }
    }
  }


The problem is that when I use ”push” on the chili as in the example I get:

Player region is 0.
Mouse region is 0.

And it doesn't matter what I click on, I still get 0.

I'm not very experienced at programming yet, so if you have any ideas on how to do this better I'm thanksful for tips. :)

Thanks beforehand!

Buckethead

I'm not really sure why your regions aren't registering. I think it might have something to with how AGS processes clicks. Hopefully someone else can shed some light on that.
Anyway, you are making it needlessly complex for yourself. If you want to stop the player (or other character) from going to certain parts of the room you could just divide to room up in different walkable areas. Then turn off areas where you should not be able to go. If there is not walkable area active characters can't walk to the location unless you tell them to walk anywhere.

Khris

Just in case this is a scrolling room, it should be

Code: ags
  Region*clickedRegion = Region.GetAtRoomXY(mouse.x + GetViewportX(), mouse.y + GetViewportY());


You should also make sure you've actually drawn Regions, and not Walkbehinds or Hotspots.

Fanomatic

#3
QuoteAnyway, you are making it needlessly complex for yourself. If you want to stop the player (or other character) from going to certain parts of the room you could just divide to room up in different walkable areas.

Oh yeah, I forgot to mention that this this is a DoTT style game featuring 3 player characters the player can switch between and move around (currently there are 2 implemented). I actually use both walkable areas and regions. I use walkable areas to stop the player from walking outside the 'rooms' and regions to determine if the player characters are allowed to interact with other player characters or objects (i.e. if they are in the same region).

One of the reasons I need to use regions is because the player characters should be able to give items to each other, and I need a dynamic system for that to work. Before when a player character gave an item to another player character outside their walkable area they would just walk as far as possible on their current walkable area towards the other character and then 'give' the item to the character when they reached the edge of the walkable area. They would give the item to the other PC even if they weren't really close enough for that to make sense.

Quote from: Khris on Sun 03/02/2019 10:06:40
Just in case this is a scrolling room, it should be

Code: ags
  Region*clickedRegion = Region.GetAtRoomXY(mouse.x + GetViewportX(), mouse.y + GetViewportY());


You should also make sure you've actually drawn Regions, and not Walkbehinds or Hotspots.

Ah, thanks! Yes, it's a scrolling room. I added this to the code.

Hmmm, I'm sure I've drawn regions and the player characters are definitly inside the regions, so I'm not sure why they don't register.
Actually I'm not even sure 'if' they don't register. The dialogue says '0', but I seem to be getting different results after the getViewport fix. Not sure if there is another way of debugging this?


I'm currently trying to make a player-character give another player character an item ("ichili"), but only the first character ("cFive") can give the chili to "cFuzzy" for some reason.

When "cFuzzy" gives the chili to "cFive" he walks over to the character or to the closest edge of the Walkable area, but then nothing else happens.

"cFive" can give the item to "cFuzzy", but ignores the "canWalkToObject" and just gives the chili to cfuzzy as soon as it reaches the edge of the walkable area.

The expected result would be that if both player characters are in the same "area" the active PC would give the item to the other PCs inventory. Otherwise they would say something like, "I can't reach him/her". I don't know why it's not working.

The "give" code looks like this:

Code: ags
      if (player.ActiveInventory == iChili)
      {
        checkArea();
        if (canWalkToObject == true)
        {
            if (player == cFive)
            {
              cFuzzy.Say("Oh, Fuzzy like!");
              cFive.LoseInventory(iChili);
              cFuzzy.AddInventory(iChili);
            }
            else if (player == cFuzzy)
            {
              cFive.Say("Thanks!");
              cFuzzy.LoseInventory(iChili);
              cFive.AddInventory(iChili);
            }
            else
            {
              
            }
        }
        else
        {
          sayCantReachPlayer();
        }
      }


If you need more info I will try and provide it. I really appreciate all the help I can get. Thanks!

Khris

This

Code: ags
  player.Say("Player region is %d.", Region.GetAtRoomXY(player.x, player.y));
  player.Say("Mouse region is %d.", clickedRegion);


should be

Code: ags
  player.Say("Player region is %d.", playerRegion.ID);
  player.Say("Mouse region is %d.", clickedRegion.ID);


Not sure what happens when the pointer is coerced into an int, but I'm pretty sure it's not the actual ID.

Fanomatic

Thanks! Well, something happened... now it says:

"Player region is 1"
"Mouse region is 1"

It's nice to at least get a 'valid' region, but it's probably not the correct ID as you say. I tried standing in region 3 (outside cell) and region 4 (windowsill) while interacting with the chili (in region 1), but I still get the "region is 1" message for both player and mouse region.

Based on what you wrote I also changed this:

Code: ags
    //If the player clicks the same region the player is in it can always interact.
    if (clickedRegion == playerRegion)
    {
      canWalkToObject = true;
    }


To this:

Code: ags
    //If the player clicks the same region the player is in it can always interact.
    if (clickedRegion.ID == playerRegion.ID)
    {
      canWalkToObject = true;
    }


Unfortunately it still doesn't seem to work. Right now I can give items to player characters even if they are not in the same area.

Here's my 'give' script. Perhaps something is wrong with it?

Code: ags
  // GIVE TO (characters only)
  else if(UsedAction(eGA_GiveTo))
  {
      if (player.ActiveInventory == iMonsterArm)
      {
          player.Say("Nah, that would be rude!");
      }
      else if (player.ActiveInventory == iChili)
      {
        checkArea();
        if (canWalkToObject == true)
        {
            if (player == cFive)
            {
              cFuzzy.Say("Oh, Fuzzy like!");
              cFive.LoseInventory(iChili);
              cFuzzy.AddInventory(iChili);
            }
            else if (player == cFuzzy)
            {
              cFive.Say("Thanks!");
              cFuzzy.LoseInventory(iChili);
              cFive.AddInventory(iChili);
            }
            else
            {
              
            }
        }
        else
        {
          sayCantReachPlayer();
        }
      }
      else if (player.ActiveInventory == imutatedChili)
      {
        checkArea();
        if (canWalkToObject == true)
        {
          if (player == cFive)
          {
            cFuzzy.Say("Oooh, Fuzzy like!");
            cFive.LoseInventory(imutatedChili);
            cFuzzy.AddInventory(imutatedChili);
          }
          else if (player == cFuzzy)
          {
            cFive.Say("Thanks!");
            cFuzzy.LoseInventory(imutatedChili);
            cFive.AddInventory(imutatedChili);
          }
          else
          {
            
          }
        }
        else
        {
          sayCantReachPlayer();
        }
      }
  }  

Khris

IMO it's pointless to troubleshot that give script until we find out why your debug messages say 1 for a region that's clearly not region 1.

Put a label lblDebug on a "visibility: normal" GUI, then put this in repeatedly_execute:
Code: ags
  Region* mouseRegion = Region.GetAtRoomXY(mouse.x + GetViewportX(), mouse.y + GetViewportY());
  lblDebug.Text = StringFormat("Mouse region: %d", mouseRegion.ID);


Let's make sure you're testing the correct regions against each other, not something else.

Fanomatic

#7
Yes, you're right. I really appreciate your help.

I added the debug GUI and it registers the regions fine as I drag the mouse around. Really helpful.

It seems when a PC stands far to the right of region 3 (outside cell) it registers as region 1 (inside cell), but as I move it further to the left, about 50% into the region, the middle of the room, it actually says the player region is 3 and that my mouse region is 1 in my debug dialog.

Hmmm, could there be an offset somehow?

EDIT: I added another label for player region to the debug as well. It clearly switches from region 1 to region 3 as I walk left and cross over to the left part of the region. The mouse cursor region seems to be correct though.

Khris

Can you clarify what you mean?
It sounds like the character's debug message shows the "wrong" region? Does the player character walk where you click? Are the view sprites centered?

Fanomatic

Here's a picture of what's going on. Hopefully it should make things clearer :)



Yes, the PC walks where I click within the walkable area.

Hmm, I'm not sure if the sprites are centered. Where do I see that?

Khris

The first image alone is giving me a headache. How on earth is the player on region 1?

By sprites being centered I mean that the pixels that make up the character should be centered horizontally within the sprite. But an offset like that would require a huge sprite with the pixels severely off-center.

At this point I'm going to suggest you upload the game files somewhere so I can take a look.

Fanomatic

QuoteThe first image alone is giving me a headache. How on earth is the player on region 1?

I know, right!? It's really confusing.

QuoteAt this point I'm going to suggest you upload the game files somewhere so I can take a look.

Thanks, I'll PM you a link to the game project. Maybe you can make sense of it.

Crimson Wizard

You know... it actually feels like lookup for "player's region" does unnecessarily account for viewport scroll.

Can you show your current code for getting player's region?

Khris

#13
Yeah, that's exactly what's happening.

Fanomatic:
Character coordinates are room coordinates, mouse coordinates are screen coordinates. You're using both in a function that expects room coordinates, which means you need to add the viewport offset to the mouse coordinates, but not to player.x/.y

You had this
Code: ags
  Region*playerRegion = Region.GetAtRoomXY(player.x, player.y); //get current player region, fine
  Region*clickedRegion = Region.GetAtRoomXY(mouse.x, mouse.y); //get current mouse region, wrong, needs viewport offset


and I told you

Quote from: Khris on Sun 03/02/2019 10:06:40
Just in case this is a scrolling room, it should be

Code: ags
  Region*clickedRegion = Region.GetAtRoomXY(mouse.x + GetViewportX(), mouse.y + GetViewportY());

which was supposed to imply that the playerRegion line is fine  :)

Fanomatic

Ahaa, I see! Yes, now it works. :)

Thanks guys, you really helped me out! Much appreciated!

I'm marking this issue as solved now.

I will make a a project thread for this game once I'm done with a proper playable demo I can show off.

SMF spam blocked by CleanTalk