stop player from entering certain rooms if they have an attribute

I'm trying to get it so that if the player object has a specific boolean attribute set to true, they can access some rooms but cannot access others, but if it is false, they can access all rooms. The way I'm denoting this is with a "specialroom" boolean I have on the rooms that can only be accessed with the attribute on false. Any help?


I'd suggest changing the changedparent script attribute of the player:

  if (game.pov = this) {
    if (IsDefined("oldvalue")) {
      if (GetBoolean (this, "restrictmovement") and GetBoolean (this.parent, "specialroom")) {
        msg ("You can't go into special rooms right now!")
        this.suppressdescriptions = true
        this.parent = oldvalue
        this.suppressdescriptions = null
      }
      else if (not GetBoolean (this, "suppressdescriptions")) {
        OnEnterRoom(oldvalue)
      }
    }
    else {
      OnEnterRoom(null)
    }
    if (game.gridmap) {
      MergePOVCoordinates
    }
  }
  this.hasbeenmoved = true

That script checks the attributes whenever the player moves from one room to another. If they have the boolean restrictmovement and the room they're moving to has specialroom, it moves them back again instead of running the room's exit/enter scripts. It also uses a temporary attribute suppressdescription to make sure that moving them back doesn't trigger any "on enter" scripts for the room they were trying to leave.


Io

Mrangel's suggestion should work, but if you don't want to risk mucking around with changedparent, here's how I would do it:

First, you have the right idea with the specialroom booleans. You have the attribute Player.CanAccessAll boolean and rooms with the SomeRoom.SpecialRoom boolean.

But how to make the player forbidden from going there to begin with?

The answer is exits, exits that instead of simply moving the player, instead run a script.

And instead of just ANY old script, they run a Function, so that you can just write the code once instead of having to rewrite it for every exit.

So you have Room1, and Room2, and 2 exits leading back and forth. Room2 is special, so Room2.SpecialRoom=True.

Exit-From-Room1-To-Room2, then, you select 'run a script' instead of moving the player automatically.

Don't put any script in yet! Next, create a new function. Call it, I dunno, SpecialRoomMove. Give it parameter Destination. And have the function's script be, in psuedocode:

if Destination.SpecialRoom=True and Player.CanAccessAll=False{
msg("That room is forbidden!")
}
else{
move Player to Destination
}

And now just go back to your exit, plop that function in, with parameter 'this.to'. This should work; if player.CanAccessAll is false AND Destination.SpecialRoom is True, then they can't enter. In every other case, they move in like normal.

Hope this helps!


mrangel's code seems to crash the program. Don't know if I did something wrong but when I set the attribute with DevMode and tried to move to a forbidden room the game seized up and crashed after a few seconds. As for lo's code, I have yet to put it on all exits in the game to get it working. Hopefully I can find something for the start script to do it because doing it manually for somewhere between 50-75 times does not seem particularly enticing.


Io

Keep in mind, it doesn't need to be in every exit to 'work', per say. It should work fine on a per-exit basis.

As for a StartScript... I guess you could search every object, use a FilterByAttribute to get the ones with a 'type' attribute of exit', and change their WhateverExit.runscript to True and WhateverExit.script to the necessary code.


I can't figure out what I've got wrong there.

It might crash if you set restrictmovement when the player is already in a special room, because as soon as they move it says "You can't go there", then moves the player back to where they were previously, which triggers the script again, which displays another message and tries to move them back, causing an infinite loop.

A little tweak:

  if (game.pov = this) {
    if (not GetBoolean (this, "suppressdescriptions")) {
      if (IsDefined("oldvalue")) {
        if (GetBoolean (this, "restrictmovement") and GetBoolean (this.parent, "specialroom")) {
          msg ("You can't go into special rooms right now!")
          this.suppressdescriptions = true
          this.parent = oldvalue
          this.suppressdescriptions = null
        }
        else {
          OnEnterRoom(oldvalue)
        }
      }
      else {
        OnEnterRoom(null)
      }
    }
    if (game.gridmap) {
      MergePOVCoordinates
    }
  }
  this.hasbeenmoved = true

Sorry about that; I didn't initially consider that possibility.


I see. The start room is one of those special rooms and the player initially does not have the attribute. The loop thing probably explains it.


mrangels new option seems to be working wonderfully.


It's probably worth noting that there are two different ways you could approach this. You could prevent the player from changing location (using the method shown above), or you could prevent them moving (by making a modification to the go command, or by locking all the exits).

The main difference between these two methods is that the one I suggested above will trigger whenever the player is moved. So it will also stop your other scripts from moving a player into a special room when the flag is set, which may not be desirable. If you have a script that moves the player into a special room and you want it to ignore the restriction, the easiest way would probably be to change the specialroom boolean on the destination to false, move the player, and then set it back to true again.


Log in to post a reply.

Support

Forums