Lathan's Gold (New problems)

This is a DnD Solo adventure where the player can play DnD by themselves. I am converting the adventure into a Quest format,
BUT, I hit a snag...
I'm trying to set-up the game so that the player can select 1 of the 6 starting characters, which each have their own quest....
I'm thinking of showing the 6 characters in the starting room, and the player select one of them to play their quest...

My question it this:
How, or what command, would I use to make the player become an object???
I can select that the player can become the object, but I can't make the player become the object...
(I've also got other ways to change the player to the stats of the selected character, but they are having their own problems...)


Never mind… I think I found it in the docs I downloaded...
(But I'm off to work so I can't test this until I get back...)


There's a ChangePOV command.

You can also just do game.pov = someobject if you don't want to run the room enter scripts for the new character's location.
(Most of the code for dealing with a change of POV is in the script attribute game.changedpov so it's run automatically)


I may try the ChangePOV on another project...
I was having problems with my command that loaded the new character info to the player. But got that fixed and working.


OK, new problem:
I have the game set to clear the screen on enter of new rooms.
I'm using the game setting, not ClearScreen on every room.
I want to be able to turn if off for rooms that auto-move the player, and get the room description of both rooms.
IE:
(Room 1)
You enter the room and the floor drops out from under you!
(move player to room 2)
(Room 2)
You hit the new floor hard!


OK, I got that one solved...
I did a:
Wait for keypress, them moved the player to the new room.
But, I got a hard one for ya...
The player runs into a storm that will move the player to a new random room...
IE: R=DiceRoll("2d4") * 10 + DiceRoll("2d4")
this provides a number from 22 to 88...
BUT, I now need to move the player to that room #.
As in room "V" +R
or if R=55, then move the player to room V55...
I "almost" have it, the room # is generated, but...
I get a long list of errors because Quest didn't "really" move the player there...
But... the player.parent=V55...
(FYI, the code is now 355k, and I still have more to add!)


Fixed!!!
Here is the code...

// new ship location VR1
R1 = DiceRoll("2d4") *10 + DiceRoll("2d4")
msg ("R1= " +R1)
wait {
  V = "V"+R1
 // RM = split("V55")
 // Vr = ObjectListItem (RM, 0)
 player.V=V
 Vr=GetObject(player.V)
  MoveObject (player, Vr)
}

The // part was an attempt to make a 1 object list, then use that... (failed)
But the GetObject did work, the player.V is just a local created attribute.
Actually... Just using V, turned it into an object!
Vr=GetObject(V)


OK, a new one for ya...
Is there a command that would be similar to "LastRoom"???
Like something Quest uses to go back one turn with "undo".
When the player enters a room, I want different descriptions depending on the exit they used to get there...
Like:
You step off your boat onto the dock. After being at sea for so long, the unmoving dock makes you walk like a drunken sailor...
(and when you return...)
You return to the dock ready to return to your ship.

(Actually, I'm gona keep that description!)
You will always enter the dock from the sea side, so I guess {once} could work...

Or, 2 docks, one for each direction...


When the player enters a room, I want different descriptions depending on the exit they used to get there...

That's an interesting idea, and wouldn't be too hard to implement.
The room description is caused by this script, which is the player objects' changedparent script:

      if (game.pov = this) {
        if (IsDefined("oldvalue")) {
          OnEnterRoom(oldvalue)
        }
        else {
          OnEnterRoom(null)
        }
        if (game.gridmap) {
          MergePOVCoordinates
        }
      }
      this.hasbeenmoved = true

I would suggest just adding a line:

      if (game.pov = this) {
        if (IsDefined("oldvalue")) {
          this.lastroom = oldvalue
          OnEnterRoom(oldvalue)
        }
        else {
          OnEnterRoom(null)
        }
        if (game.gridmap) {
          MergePOVCoordinates
        }
      }
      this.hasbeenmoved = true

Then you can easily examine game.pov.lastroom in your room description to find out where they came from.
(Noting that if you're using the text processor, you'd have to use {either rather than {if, because the text processor's if is very limited and doesn't support object attributes properly)


So, basically, make my own "LastRoom" attribute...
That' easy.


OK, a new one, although more of a "am I doing (understanding) this right???" type of thing...
You arrive at an island, you can {exit:land} on the shore.
(I may change this to a command so that the TE purists can type 'land' or 'dock' instead of clicking on the link)
On the shore you can {command:explore} the island...
This moves you to the inner part of the island.
Now, my question:
Do I need the {command:explore} on every island room to make it work???
My guess is 'yes' based on how Quest is acting...
Also...
Island_1, it's {command:explore1}
Island_2, it's {command:explore2}
Island_3, it's {command:explore3}


Another head scratcher...
I have been using exits for commands to do more than just moving from room to room...
I can click the {exit:enter} link and that works, but typing "enter" does not work... BUT I know there are some text adventure purist that like to type every command instead of mouse clicking...
So... I'm backing up my non-directional exits with commands so that the player can {enter} a shop by mouse click,
but typing "enter" does not work.
I found do (object, string attribute name) in the docs, but the "example" does not help...
Is there a way to make a command, I assume using the do() command that will call the exit script?
OR, and this idea just came to mind...
Drop the {exit} and put the code in a command...
(Game code up to 430K but that is without the encounter and combat code yet... 450+ rooms, but you will not normally be visiting every room, most of them, about 300+, are just world map travel locations.)
I can post what I got so far if anyone wants a preview... but there are some tracking messages that will not be visible in the final version.


If you want a player to be able to be able to type the name of an exit as if it were a command, you could have a turnscript something like…

exitnames = Split("north;east;south;west;northeast;northwest;southeast;southwest;in;out;up;down;n;e;s;w;ne;nw;se;sw;o;u;d")
foreach (ex, ScopeExits()) {
  alias = LCase (GetDisplayAlias (ex))
  if (not ListContains (exitnames, alias)) {
    list add (exitnames, alias)
  }
}
go.pattern = "^go (to )?(?<exit>.*)$|^(?<exit>"+Join(exitnames, "|")+")$"

This adds the aliases of any currently accessible non-directional exits to the pattern of the "go" command, so that they can be typed on their own in the same way as "north", "sw", etc.

Depending how those exits are set up, you could have that in your enter-room script, or as a turnscript.

Given the size of your game, I think it would be easier to add a script like that than creating a whole bunch of new commands.


Most rooms follow the normal compass, only a "few" use: enter, leave, dock...
I "think" a light came on allowing me to understand that code...
So... that this would do is add "dock" to the list of exit.names so that typing "dock"
will do the same as clicking the {exit:doc} link???
Will that code work, as-is, without any changes needed???


I think it should work like that, but I've not tested it yet.

That script just modifies the go command so that "dock" is an alternate way of typing "go dock".
By default, the "go" command will accept either go (any text) or north;east;south;west;northeast;northwest;southeast;southwest;in;out;up;down;n;e;s;w;ne;nw;se;sw;o;u;d as its pattern. This script just adds the aliases of all exits in scope to that list.

You should just be able to drop the command into the enterroom script, or a turnscript, so that it adjusts the pattern whenever exits enter or leave scope.


I got mixed results with it...
I broke it down with msg's to see what it was doing.
"go enter" worked most of the time, "enter" rarely worked.
I even changed the text that the script loaded into the list so that the exit would be listed as "go exit"...
That did not provide consistent predictable behavior...
Most of my commands and exits are clickable, go I may turn off the key entries and just have clickable commands.

But... just got to get the combat working like the original adventure was set-up, and I will be ready to spring this on everyone...
(and a few other tweaks here and there...)
And as planed, I added a new playable character, may add a few more.


I got mixed results with it...
I broke it down with msg's to see what it was doing.
"go enter" worked most of the time, "enter" rarely worked.

I'm not sure where the problem is.

Could you show me what it's setting go.pattern to in a room where it doesn't work?

Do you have an "enter" command as well? This script should make "enter" have the same effect as "go enter"; but it may be overridden by an actual enter command.

I even changed the text that the script loaded into the list so that the exit would be listed as "go exit"...

That should make the script do nothing at all. The ^go (to )? already matches any command that starts with "go ", so making it match the same string again will have no effect.


Actually... looks like none of the "enter", "dock", "leave" exit directions work...
I got a reduced version that is just the starting town.
http://textadventures.co.uk/games/view/1jlqt1dmi0kc685tia4upa/lathans-gold-2-specularum-only
But you can see the no working directions.
Regular directions work.


"go enter" seems to work as soon as there's an exit named "enter".

If you add the code I gave you, I would expect it to work. Doesn't it?
I don't have the desktop version of Quest, so I can't edit your game to test it myself.


Hello. I kinda don't know how to make those links that take you to places, like go to pit but in link form. A little help?


It does find all the exits for the current room, BUT, it does not know what to do with the exit.
I've used a cleared list so that ONLY the exit will show up in the list.
But, it does not take the exit called "enter".


Sorry, I can't understand what you're saying there.

it does not know what to do with the exit.

It doesn't need to do anything with the exit. It's modifying the command pattern.

Can you show the game with this code in so I can test it? Or add a debug statement to display the new value of go.pattern so we can see if I've made some odd mistake I can't see in the code?


A S17
You are in front of the Hippogriff Inn. You may enter the inn and have a good meal and rest for the night. Or you may follow the roads leadingnorthwest,southeast, southwest, northeast, or south.

Exit: enter
Exit: northwest
Exit: southeast
Exit: southwest
Exit: northeast
Exit: south
List: All: ; ; enter; northwest; southeast; southwest; northeast; south;
CSE=Object: Intro

]enter
I don't understand your command.

] go enter (takes me into the inn.)

But it understands the Quest directions: northwest; southeast; southwest; northeast; south
just not enter.
My modified command looks like this for testing:

// exitnames = Split("north;east;south;west;northeast;northwest;southeast;southwest;in;out;up;down;n;e;s;w;ne;nw;se;sw;o;u;d")
exitnames = Split("")
foreach (ex, ScopeExits()) {
  alias = LCase (GetDisplayAlias (ex))
  if (not ListContains (exitnames, alias)) {
    list add (exitnames, alias)
    msg ("Exit: " + alias)
  }
}
msg ("All: " + exitnames)
go.pattern = "^go (to )?(?<exit>.*)$|^(?<exit>"+Join(exitnames, "|")+")$"

I have figured out everything but the go.pattern… No idea on how to figure that mess out.
This is in the Turn script and not in every room.

CSE=Object: Intro
is from a script so that I can test where the player is for location related action.


Sorry. After staring at the code for half an hour, I finally realise why this isn't working.
Caching means that command patterns are locked (any changes to them will be ignored) after the first time a command is run.

Quest doesn't provide any way to flush this cache; I would consider this to be a defect in the core.

Can't believe I didn't spot that sooner.


Here's a slightly more complex one; not so neat, but might work:

if (ListCount (FilterByAttribute (FilterByAttribute (AllCommands(), "parent", game.pov.parent), "prototype", go)) = 0) {
  exitnames = Split("north;east;south;west;northeast;northwest;southeast;southwest;in;out;up;down;n;e;s;w;ne;nw;se;sw;o;u;d")
  matched = false
  foreach (ex, ScopeExits()) {
    alias = LCase (GetDisplayAlias (ex))
    if (not ListContains (exitnames, alias)) {
      list add (exitnames, alias)
      matched = true
    }
  }
  if (matched) {
    newcmd = CloneObjectAndMoveHere (go)
    newcmd.pattern = "^(?<exit>"+Join(exitnames, "|")+")$"
  }
}

OK, I solved it...
I just added all the non-directional exit to the exitnames list.
IE:
exitnames = Split("enter;dock;leave;stay;north;east;south;west;northeast;northwest;southeast;southwest;in;out;up;down;n;e;s;w;ne;nw;se;sw;o;u;d")
and made it a function that runs when the game starts.
If I remember correctly, enter would work sometimes, and some places, but not all times and places.
Now, I just got to add all my exits for it to work!
So... My function now looks like this:
exitnames = Split("inn;enter;dock;leave;stay;north;east;south;west;northeast;northwest;southeast;southwest;in;out;up;down;n;e;s;w;ne;nw;se;sw;o;u;d") go.pattern = "^go (to )?(?<exit>.*)$|^(?<exit>"+Join(exitnames, "|")+")$"


I thought about that; but wasn't sure if some of those exits might be words for which it would be strange to get the "You can't go there" message if the player types them in the wrong location.


AAARRRGGGG!!!!
I have not had much luck with the "Int" commands... (GetInt, IsInt, ToInt)
It's like Quest does not like them...
Here is a combat message:
You lead your party of 4 marines to fight the 4 Giant Draco Lizards.
Lost= 2.5
Error running script: Error compiling expression 'ToInt(Lost)': FunctionCallElement: Could find not function 'ToInt(Double)'
Your party suffered 2.5 losses.
And you killed Error running script: Error compiling expression 'GetInt(Monster.MNumber *.75)': FunctionCallElement: Could find not function 'GetInt(Double)'

It will not convert "Lost", which is 2.5, to either 2 or 3 depending on how the rounding goes...
And the code bit...

case (50) {
   lost = (player.Party *.5)
   Kill (player.Party, lost)
   msg ("Your party suffered " + lost + " losses.")
 }

I know... lost and Lost...
"Lost" is used in the Kill() function.
"lost" is used in the msg() parts.


ToInt converts strings to integers.

To convert a double to an int, you use the functions Ceiling (always rounds up), Floor (rounds down), or Round.


Similarly, IsInt tests a string to see if it contains all digits. You can only use it on strings. If you want to test if a variable is an integer, you would do if (TypeOf (some_variable) = "int") {


In Basic, Int would round numbers...
I=int(3.45)
So, I=3
Thanks, that explains why I was not having any luck with this.
I guess I need to use Round instead of Int...


Bump... just because I'm still working on this...
(somewhat...)


This topic is now closed. Topics are closed after 60 days of inactivity.

Support

Forums