making a telephone that you can actually talk to NPCs on

I have made a phone using the switch script (http://docs.textadventures.co.uk/quest/multiple_choices___using_a_switch_script.html).

It works fine, but is there a way to actually intereact with your NPCs with it, i.e. can I talk to NPC chacter 'Phil' if Phil is not in the room? I'm thinking that I could move Phil to the current room when the player phones him, but the problem is if the player 'looks' they will see him, I could make him scenery but they could still 'examine phil', you could also give things to Phil which also wouldn't make sense!

Is there a way to do this or am I wasting my time?


Can you call a function for each phone number you dial? Say...

dial 555-1212
Fred picks up and says, "What do you want?"

  • call function FredCall which will have the communication you need built into the function.

I think it would work. As a matter of fact, I feel like maybe trying to do this too.

Or, maybe if that doesn't work, copy-paste this NPC, then move new NPC to current room but mark him as scenery. In the look at description you can change it from the original to something like "Fred's not here right now but you recall he had red hair and a face riddled with freckles."

I think I'd go with the second choice. Sounds pretty simple.


Include an 'end call' function, to remove the copied NPC from the room once the conversation has ended.


The best method I've found and read about (but not actually employed) is to move the player to a special room once the phone call has initiated.

Clone the NPC the player calls to the special room as well, then mark the NPC and change the description, like XanMag says.

Once you 'END THE CALL' or 'HANG UP', move the player back to the room he/she started in and delete the cloned NPC.


There's got to be an easier method.

I'm wanting two-way radios, which is the same thing as having phones, but I'm leery of it now.

I'm thinking of trying to add a script dictionary attribute to the phone (or maybe the player), similar to the way we set up TOPICS for ASK/TELL keys.

I don't think fooling around with script dictionaries is possible/easy at all when creating games online, though. (Just so no online-only folks waste any time looking into using them. Unless they wished to use Code View.)

http://docs.textadventures.co.uk/quest/using_dictionaries.html


In the look at description you can change it from the original to something like "Fred's not here right now but you recall he had red hair and a face riddled with freckles."

>x Dave
Dave? Dave's not here, man!


Okay...

Here's a LOOSE draft that works.

UPDATE: Now entering you can enter a direction (or GO a direction) and you will hang up, then go that direction. (But it still describes the first room first. Aargh! I need to learn to utilize SCOPE!)

OLD CODE SAMPLE. See this post for the latest version.
<!--Saved by Quest 5.7.6404.15496-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="phone tag">
    <gameid>7981973c-cf89-4111-96ce-36fabf6a3e32</gameid>
    <version>1.0</version>
    <firstpublished>2017</firstpublished>
    <feature_asktell />
    <attr name="feature_advancedwearables" type="boolean">false</attr>
    <feature_advancedscripts />
  </game>
  <object name="office">
    <inherit name="editor_room" />
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <object name="phone">
      <inherit name="editor_object" />
      <look type="string"></look>
      <feature_startscript />
      <feature_usegive />
      <use type="script"><![CDATA[
        msg ("You can't just USE it.<br/><br/>(Try entering: CALL SUE)<br/><br/>(Then, ask SUE about PAPER.)")
      ]]></use>
    </object>
    <exit alias="north" to="reception area">
      <inherit name="northdirection" />
    </exit>
  </object>
  <object name="reception area">
    <inherit name="editor_room" />
    <object name="Sue">
      <inherit name="editor_object" />
      <inherit name="namedfemale" />
      <topics type="stringdictionary">
        <item>
          <key>paper</key>
          <value>It's in your desk.</value>
        </item>
        <item>
          <key>staples</key>
          <value>They are in your drawer.</value>
        </item>
      </topics>
      <scenery type="boolean">false</scenery>
      <askdefault type="script">
        msg ("\"Ask me about paper,\" demands Sue.")
      </askdefault>
      <look type="script">
        if (player.parent = phone_call_room) {
          msg ("It's hard to see her through the phone!")
        }
        else {
          msg ("Sue looks like she might punch you.")
        }
      </look>
      <ask type="scriptdictionary">
        <item key="paper">
          msg ("\"You have no paper,\" says Sue. \"And you have no secretary. Remember? I QUIT!!!\"")
        </item>
        <item key="staples">
          foreach (obj, GetDirectChildren(scenery)) {
            list add (list, obj)
          }
        </item>
      </ask>
      <tell type="scriptdictionary">
        <item key="paper">
          msg ("no paper")
        </item>
      </tell>
    </object>
    <exit alias="south" to="office">
      <inherit name="southdirection" />
    </exit>
  </object>
  <command>
    <pattern>call #text#</pattern>
    <script>
      phone.locale_now = player.parent
      msg ("You call " + text + "...")
      text = LCase(text)
      switch (text) {
        case ("sue") {
          CloneObjectAndMove (Sue, phone_call_room)
          MoveObject (player, phone_call_room)
        }
        case (911) {
          msg ("It's engaged.")
        }
        default {
          msg ("Try CALL SUE")
        }
      }
    </script>
  </command>
  <object name="phone_call_room">
    <inherit name="editor_room" />
    <usedefaultprefix type="boolean">false</usedefaultprefix>
    <hangup type="string"></hangup>
    <bye type="string"></bye>
    <disconnect type="string"></disconnect>
    <descprefix type="string"></descprefix>
    <objectslistprefix>You can hear</objectslistprefix>
    <alias>On the Phone</alias>
    <dropdestination type="object">player</dropdestination>
    <look type="script">
    </look>
    <command name="disconnect call">
      <pattern>bye;goodbye;say goodbye;hang up;disconnect;say bye;tell #text# bye</pattern>
      <script>
        msg ("You hang up.")
        MoveObject (player, phone.locale_now)
        foreach (obj, (GetAllChildObjects(phone_call_room))) {
          RemoveObject (obj)
          msg ("FOR TESTING:")
          msg ("Removed:")
          msg (obj)
        }
      </script>
    </command>
    <command name="nogo">
      <pattern type="string"><![CDATA[^go to (?<text>.*)$|^go (?<text>.*)$|^(?<text>north|east|south|west|northeast|northwest|southeast|southwest|in|out|up|down|n|e|s|w|ne|nw|se|sw|o|u|d)$]]></pattern>
      <script>
        msg ("You hang up.")
        MoveObject (player, phone.locale_now)
        foreach (obj, (GetAllChildObjects(phone_call_room))) {
          RemoveObject (obj)
        }
        HandleSingleCommand (player.currentcommand)
      </script>
      <scope>phone.locale_now</scope>
    </command>
  </object>
  <command name="asking the room about">
    <pattern>ask about #text#</pattern>
    <script>
      npcs = NewObjectList()
      opts = NewStringDictionary()
      foreach (o, GetDirectChildren(player.parent)) {
        if (HasAttribute(o, "ask")) {
          list add (npcs, o)
          dictionary add (opts, o.name, GetDisplayAlias(o))
        }
      }
      if (ListCount(npcs) = 0) {
        msg ("You can ask, but no one is here to tell you anything.")
      }
      else if (ListCount(npcs) = 1) {
        DoAskTell (ObjectListItem(npcs, 0), text, "ask", "askdefault", "DefaultAsk")
      }
      else {
        game.askabouttext = text
        ShowMenu ("Ask who?", opts, true) {
          if (not result = null) {
            o = GetObject(result)
            DoAskTell (o, game.askabouttext, "ask", "askdefault", "DefaultAsk")
          }
        }
      }
    </script>
  </command>
  <verb>
    <property>hangup</property>
    <pattern>hang up</pattern>
    <defaultexpression>"You can't hang up " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>bye</property>
    <pattern>bye</pattern>
    <defaultexpression>"You can't bye " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>disconnect</property>
    <pattern>disconnect</pattern>
    <defaultexpression>"You can't disconnect " + object.article + "."</defaultexpression>
  </verb>
</asl>
Sample transcript --- **phone tag**

You are in an office.
You can see a phone.
You can go north.

> call sue
You call sue...

On the Phone.
You can hear Sue.

> ask sue about paper
"You have no paper," says Sue. "And you have no secretary. Remember? I QUIT!!!"

> n
You hang up.

You are in an office.
You can see a phone.
You can go north.

You are in a reception area.
You can see Sue.
You can go south.

> undo
Undo: n

> s
You can't go there.

> call sue
You call sue...

On the Phone.
You can hear Sue.

> s
You hang up.

You are in an office.
You can see a phone.
You can go north.
You can't go there.


Don't move the NPC. Just change the scope of the command that you're using (to talk to the NPC) to include the room that the NPC is in:

http://docs.textadventures.co.uk/quest/advanced_scope.html


Don't move the NPC. Just change the scope of the command that you're using (to talk to the NPC) to include the room that the NPC is in:

I can't figure out how to work that. Been trying for an hour...

I've put everything I can think of in that field.

Would you, could you, possibly use the above game as an example.

I'm in the office. I want to call Sue.

What do I put in <scope></scope>?


(filler for getting edited post updated)


have the dialogue/conversation scripting (Script Attribute/s) on each of your npcs, which can be done within your telephone's scripting:

<object name="room_1">
  <inherit name="editor_room" />
</object>

<object name="room_2">
  <inherit name="editor_room" />
</object>

<object name="player">
  <inherit name="editor_object" />
  <inherit name="editor_player" />
  <attr name="parent" type="object">room_1</attr>
</object>

<object name="telephone_object">
  <inherit name="editor_object" />
  <attr name="parent" type="object">room_1</attr>
  <attr name="call_stringlist_attribute" type="simplestringlist">joe; jeff; john</attr>
  <attr name="displayverbs" type="listextend">call_script_attribute</attr>
  <attr name="call_script_attribute" type="script">
    <![CDATA[
      DisplayList (telephone_object.call_stringlist_attribute, true)
      msg ("(Type in the number of your choice)")
      get input {
        if (IsInt (result)) {
          input_integer_variable = ToInt (result)
          list_count_integer_variable = ListCount (telephone_object.call_stringlist_attribute)
          if (input_integer_variable > 0 and input_integer_variable < list_count_integer_variable) {
            list_item_index_number_integer_variable = input_integer_variable - 1
            npc_string_variable = StringListItem (telephone_object.call_stringlist_attribute, list_item_index_number_integer_variable)
            npc_object_variable = GetObject (npc_string_variable)
            do (npc_object_variable, "dialogue_script_attribute")
          } else { // if 'out-of-bounds' input
            msg ("wrong input, try again")
          }
        } else { // if not a number/integer input
          msg ("wrong input, try again")
        }
      }
    ]]>
  </attr>
</object>

<object name="joe">
  <inherit name="editor_object" />
  <attr name="parent" type="object">room_2</attr>
  <attr name="topics_stringlist_attribute" type="simplestringlist">princess; dragon; wizard</attr>
  <attr name="displayverbs" type="listextend">dialogue_script_attribute</attr>
  <attr name="dialogue_script_attribute" type="script">
    show menu ("Topic?", joe.topics_stringlist_attribute, false) {
      switch (result) {
        case ("princess") {
          msg ("PRINCESS_SCRIPTING")
        }
        case ("dragon") {
          msg ("DRAGON_SCRIPTING")
        }
        case ("wizard") {
          msg ("WIZARD_SCRIPTING")
        }
      }
    }
  </attr>
</object>

<object name="jeff">
  <inherit name="editor_object" />
  <attr name="parent" type="object">room_2</attr>
  <attr name="topics_stringlist_attribute" type="simplestringlist">magic; elementals; spells</attr>
  <attr name="displayverbs" type="listextend">dialogue_script_attribute</attr>
  <attr name="dialogue_script_attribute" type="script">
    show menu ("Topic?", jeff.topics_stringlist_attribute, false) {
      switch (result) {
        case ("magic") {
          msg ("MAGIC_SCRIPTING")
        }
        case ("elementals") {
          msg ("ELEMENTALS_SCRIPTING")
        }
        case ("spells") {
          msg ("SPELLS_SCRIPTING")
        }
      }
    }
  </attr>
</object>

<object name="john">
  <inherit name="editor_object" />
  <attr name="parent" type="object">room_2</attr>
  <attr name="topics_stringlist_attribute" type="simplestringlist">equipment; weapons; armors</attr>
  <attr name="displayverbs" type="listextend">dialogue_script_attribute</attr>
  <attr name="dialogue_script_attribute" type="script">
    show menu ("Topic?", john.topics_stringlist_attribute, false) {
      switch (result) {
        case ("equipment") {
          msg ("EQUIPMENT_SCRIPTING")
        }
        case ("weapons") {
          msg ("WEAPONS_SCRIPTING")
        }
        case ("armors") {
          msg ("ARMORS_SCRIPTING")
        }
      }
    }
  </attr>
</object>

If I put Sue.parent, it doesn't work. But, if actually put the room name: reception area, I can interact with Sue.

Now, if I can change the scope of the command on the fly...

Or... entering USE PHONE could set player.on_phone to true.

Then, the command CALL #TEXT#, would start with an if (player.on_phone) to negate the ability to ask people who aren't in the room things while you're not 'on_phone'.

This can be done, I know it!

Without being boxed in by printed lists of topics to choose from...

My aim is for the player to walk around while talking...

I'm going to try to clone the NPC into the phone, the set the scope for the phone!!!


Currently searching for the correct code to change the attribute scope of the command ask to phone_call_room or null. On the fly. On demand. From with a turn script.


UPDATE:

See this newer post for the solution.


Making progress...

Now you can walk around and talk to Sue on the phone. You HANG UP, or TELL SUE BYE, or BYE to end the call.

Enjoy, poke holes, and make suggestions!

TODO:

  • Add the NPC answering the phone: "Hello?"

  • Make it a 'generic' command.

    • This will involve at least one more list, to check for objects which can receive calls
    • Make that 2 more. I will include an 'Ask about:' list when SPEAK TO PLAYER is entered
  • Work in the ASK THE ROOM ABOUT script, so you can just enter 'ASK ABOUT topic', instead of 'ASK SUE ABOUT topic'.

  • Turn it into a library.


Here's the playable example:
http://textadventures.co.uk/games/view/n_ofxynz7ukw_idosgcojq/phone-tag


UPDATE:

See this newer post for the solution.


Just updated it again.

TODO:

  • Add pane displaying person whom who are speaking with, along with TALK TO as a button

  • Convert to library, with guide (with screenshots)

  • Listen to Dark Side of the Moon.

NOTE: This is NOT an ordered list. Floyd may come first!


The alternative scope needs a call #object# command pattern. You can change the scope on-the-fly as it is just an attribute of the command:

call.scope = "room2"

I think what you're doing works better though, since using call #text# as the command pattern should give you more design flexibility -- then Sue can move to different rooms and it doesn't matter.


Updated again...

Getting better and better...

Use phone: displays a menu list of people with the attribute cancall.

Speak to NPC: displays a menu list of topics.

I only need (want) to have the NPC name show up in a pane, so you can click SPEAK TO. Then, you could do it all without typing! Or completely by using the parser... which is how I'd do it... but I'm a weirdo!


TODO:

  • Find out how to turn the CustomStatus pane off. (I saw it something of Pixie's...)

  • Convert to lilbrary, with guide and screenshots


UPDATE:

See this newer post for the solution.


Find out how to turn the CustomStatus pane off. (I saw it something of Pixie's...)

Game object --> Interface tab --> Game panes --> uncheck "Show a custom status pane".


@Dcoder

Oh, sorry... I meant on the fly. That way, the CustomStatus would only appear while using the phone. (Right now is just says either "Your phone is on standby." or "You are speaking with: (NPC NAME HERE).")


Dcoder, you're totally invited to our group project, if you'd like to collaborate with us.

http://textadventures.co.uk/forum/design/topic/3usjedp8bkcgxdbfsd-jza/were-starting-up-a-group-project-who-wants-to-collaborate-the-pixie-has-a-temp

We're going to have two-way communication devices now...


The alternative scope needs a call #object# command pattern. You can change the scope on-the-fly as it is just an attribute of the command:

call.scope = "room2"

I think what you're doing works better though, since using call #text# as the command pattern should give you more design flexibility -- then Sue can move to different rooms and it doesn't matter.

I'm cloning Sue into an imaginary room called phone_call_room. Then removing Sue1 on hang-up.

I'm going to use this code sample you put here for other awesome things, though.

Thanks much!


Oh, sorry... I meant on the fly. That way, the CustomStatus would only appear while using the phone. (Right now is just says either "Your phone is on standby." or "You are speaking with: (NPC NAME HERE).")

Silly of me to think that you would ask me such a simple question : ) Yeah, that should be simple, but I couldn't find the answer.

request (Hide, "Panes")

hides all the panes, but I couldn't figure out the proper nomenclature for just the custom status pane. Went into HTML tools in-game and it lists it as "customStatusPane", but that didn't work either. Pix would know.

I'm cloning Sue into an imaginary room called phone_call_room. Then removing Sue1 on hang-up.

What if you just left Sue1 (hanging!) in your imaginary room, instead of removing the clone? You would always have both a physical and virtual Sue in your game (slightly less coding hassle). Just a thought.


JS.eval ("$('#customStatusPane').css('display', 'none')")

JS.eval ("$('#customStatusPane').css('display', 'block')")

JS.setCustomStatus ("You are speaking with: " + speaker + ".")

Bwahaha!


That was fast!

Now that you've posted that, now I remember that that's the same way you turn the map off/on, with #gridPanel instead.


I couldn't figure out the proper nomenclature for just the custom status pane. Went into HTML tools in-game and it lists it as "customStatusPane", but that didn't work either. Pix would know.

I followed the same path of deductions, which landed me at Pixie's wiki. I found most of the info there, but I got that second JS.eval line from w3schools.


TODO:

  • Figure out how the heck to remove a displayverb from a clone but not the original. (It yells at me about inherited something-or-another. I don't want the clone to have 'Look at' listed, but I don't want to mess with the 'Look at' displayverb on the original object. This is because I am cloning the person I'm calling into the player's location. Wait... what if I'm talking to Sue, then I enter the room with Sue, and it shows TWO Sues in the pane!?! AARGH! I may have to just make a Command Pane! Yeah, that's it! I'll make a Command Pane that says SPEAK TO CALLER.

  • Convert to a library


That was fast!

I stole your DCODER ring!

<Insert MANIACAL LAUGH here!>


SUCCESS!

TODO:

  • Go back in and set the command to call the function.

  • Make into a library

  • Make a step by step with screenshots, for the online crowd.

Play it here: https://textadventures.co.uk/games/view/n_ofxynz7ukw_idosgcojq/phone-tag


See also here:http://docs.textadventures.co.uk/quest/advanced_scope.html


@ Richard:

you probably just have to over-ride/over-write the 'displayverbs' Stringlist Attribute, as any inherited Attribute (from cloning and/or via Object Types / Types), is locked/blocked from being modified, until/unless you do so.

for example:

<object name="room">
</object>

<object name="ball">
  <attr name="color" type="string">red</attr>
</object>

// scripting:

clone_object_variable = CloneObject (ball)

clone_object_variable.parent = room // or: set (clone_object_variable, "parent", room)

set (clone_object_variable, "color", "red") // this over-rides/over-writes the inherited Attribute (which you can't manipulate), wiping it out, and instead creates (and replaces it with) a normal (non-inherited) Attribute of it, which you can now manipulate, for example:

set (clone_object_variable, "color", "blue") // this can probably be done directly (don't need to do the 'set red' code line above), and it'll over-ride/over-write the inherited Attribute, but I just did this as two steps ('set red' and then as 'set blue') to show it.

// ------------------------

example with Object Types / Types:

<object name="ball">
  <inherit name="ball_type" />
  // directly in-code (tag) over-riding/over-writing:
  // <attr name="color" type="string">red</attr>  // same stuff as said above with the clone example
  // <attr name="color" type="string">blue</attr> // same stuff as said above with the clone example
</object>

<type name="ball_type">
  <attr name="color" type="string">red</attr>
</type>

// or as scripting:

set (ball, "color", "red") // same stuff as said above with the clone example
set (ball, "color", "blue") // or: ball.color = "blue" // same stuff as said above with the clone example

set (clone_object_variable, "color", "red") // this over-rides/over-writes the inherited Attribute (which you can't manipulate), wiping it out, and instead creates (and replaces it with) a normal (non-inherited) Attribute of it, which you can now manipulate

Ah! I was just trying list add. I didn't see set!


UPDATE:

...but I got the same error when I tried set. (Probably a 5.7 thing...)


I ended up doing this:

Call #text# command

result = text
CallUp (result)

CallUp function

if (not (player.on_phone)) {
  player.on_phone = true
  msg ("You call " + CapFirst(result) + "...")
  msg ("")
  result = LCase(result)
  switch (result) {
    case ("sue") {
      msg ("\"Hello?\" Sue doesn't seem pleased to see your number displayed on her incoming call list.")
      msg ("")
      suecheck = false
      foreach (o, AllObjects()) {
        if (o.name = "Sue1") {
          suecheck = true
        }
      }
      if (not (suecheck)) {
        CloneObjectAndMove (Sue, phone_call_room)
        msg ("Put a Sue in the phone room.")
        game.cancall = NewStringList()
        list add (game.cancall, "Sue")
      }
      else {
        MoveObject (Sue1, phone_call_room)
      }
      sue2check = false
      foreach (ob, AllObjects()) {
        if (ob.name = "Sue2") {
          sue2check = true
        }
      }
      if (not (sue2check)) {
        if (not (player.parent = Sue.parent)) {
          CloneObjectAndMove (Sue, player.parent)
          msg ("Put a Sue in there with you.")
        }
        else {
          CloneObjectAndMove (Sue, office)
          msg ("Put a Sue in the office.")
        }
        Sue2.displayverbs = NewStringList()
        list add (Sue2.displayverbs, "Speak to")
        Sue2.look = "You can't see her through the phone."
      }
      else {
        MoveObjectHere (Sue2)
        msg ("Put a Sue here.")
      }
      JS.setCommands ("Speak to Sue;Hang up")
    }
    case (911) {
      msg ("It's engaged.")
    }
    default {
      msg ("Try CALL SUE")
    }
  }
}
else {
  msg ("You already have a call in progress.")
}

HangUp command

Pattern:
bye;goodbye;say goodbye;hang up;disconnect;say bye;tell #text# bye

if (player.on_phone) {
  player.on_phone = false
  msg ("You hang up.")
  foreach (obj, (GetAllChildObjects(phone_call_room))) {
    RemoveObject (obj)
    msg ("FOR TESTING:")
    msg ("Removed:")
    msg (obj)
    JS.setCommands ("Look;Wait")
    if (not (Sue2.parent = null)) {
      RemoveObject (Sue2)
      msg ("Removed Sue2.")
    }
  }
}
else {
  msg ("You are not currently using the phone.")
}

on_the_phone turn script

if (player.on_phone) {
  if (not (Sue2.parent = null)) {
    if (not (player.parent = Sue.parent)) {
      if (not (Sue2.parent = player.parent)) {
        MoveObjectHere (Sue2)
        msg ("Moved Sue2 here (on phone script).")
      }
    }
  }
  speaker = ListItem(game.cancall, 0)
  JS.eval ("$('#customStatusPane').css('display', 'block')")
  JS.setCustomStatus ("You are speaking with: " + speaker + ".")
  JS.eval ("$('#commandPane').css('display', 'block')")
  JS.eval ("$('#commandPane').insertAfter($('#compassAccordion'))")
  set (ask, "scope", "phone_call_room")
  set (speak, "scope", "phone_call_room")
  msg ("<br/>NOTE: You are currently using your phone.")
  request (SetInterfaceString, "TypeHereLabel=You are speaking to " + (GetDisplayName(ListItem((GetDirectChildren(phone_call_room)), 0))) + ".")
}
else {
  JS.eval ("$('#customStatusPane').css('display', 'none')")
  JS.eval ("$('#commandPane').css('display', 'none')")
  set (ask, "scope", " ")
  request (SetInterfaceString, "TypeHereLabel=Type here.")
}

start script

player.on_phone = false
Sue.cancall = true

Advanced scripts --> user interface initialisation

JS.eval ("$('#customStatusPane').css('display', 'none')")
JS.eval ("$('#commandPane').css('display', 'none')")
JS.setCommands ("Look;Wait")

Sue - ask

if (player.on_phone) {
  if (not (player.parent = Sue.parent)) {
    msg ("\"You have no paper,\" says Sue. \"And you have no secretary. Remember? I QUIT!!!\"")
  }
  else {
    msg ("\"Why are you talking to me on the phone when we're in the same room?!?\" Sue huffs.")
  }
}
else {
  msg ("\"You have no paper,\" says Sue. \"And you have no secretary. Remember? I QUIT!!!\"")
}

phone - use

if (not player.on_phone) {
  game.cancall = NewList ()
  foreach (o, AllObjects()) {
    if (HasAttribute(o, "cancall")) {
      if (not (o.parent = null)) {
        list add (game.cancall, o.name)
      }
    }
  }
  ShowMenu ("Who would you like to call?", game.cancall, true) {
    if (not result = null) {
      CallUp (result)
    }
  }
}
else {
  msg ("You're already using the phone.")
}

ask about #text# command

if (player.on_phone) {
  npcs = NewObjectList()
  opts = NewStringDictionary()
  foreach (o, GetDirectChildren(phone_call_room)) {
    if (HasAttribute(o, "ask")) {
      list add (npcs, o)
      dictionary add (opts, o.name, GetDisplayAlias(o))
    }
  }
  if (ListCount(npcs) = 0) {
    msg ("You can ask, but no one is here to tell you anything.")
  }
  else if (ListCount(npcs) = 1) {
    DoAskTell (ObjectListItem(npcs, 0), text, "ask", "askdefault", "DefaultAsk")
  }
  else {
    game.askabouttext = text
    ShowMenu ("Ask who?", opts, true) {
      if (not result = null) {
        o = GetObject(result)
        DoAskTell (o, game.askabouttext, "ask", "askdefault", "DefaultAsk")
      }
    }
  }
}
else {
  npcs = NewObjectList()
  opts = NewStringDictionary()
  foreach (o, GetDirectChildren(player.parent)) {
    if (HasAttribute(o, "ask")) {
      list add (npcs, o)
      dictionary add (opts, o.name, GetDisplayAlias(o))
    }
  }
  if (ListCount(npcs) = 0) {
    msg ("You can ask, but no one is here to tell you anything.")
  }
  else if (ListCount(npcs) = 1) {
    DoAskTell (ObjectListItem(npcs, 0), text, "ask", "askdefault", "DefaultAsk")
  }
  else {
    game.askabouttext = text
    ShowMenu ("Ask who?", opts, true) {
      if (not result = null) {
        o = GetObject(result)
        DoAskTell (o, game.askabouttext, "ask", "askdefault", "DefaultAsk")
      }
    }
  }
}

You can talk to Sue in the office, and her verb list in the pane is only "Speak to." If you enter her room, it switches to "Look at;Speak to".

If you examine her while in the room (whether on or off the phone), you get her description. If you examine her while on the phone and not in the room, it says, 'you can't see her through the phone.'

If you ask her something while on the phone and in the room with her, she yells at you for doing so.


I think you can do it online just like this. (NOTE: I am 99% sure I never clicked on the Attributes tab - which doesn't exist online. If this is true, this should work online.)


I've updated the online example game. (It has 'testing' messages, so I'd know what Sue was where and when she was moved/cloned.)

http://textadventures.co.uk/games/view/n_ofxynz7ukw_idosgcojq/phone-tag


TODO:

  • Replace Sue, Sue1, and Sue2 with 'generic' expressions via iteration (foreach ), if possible (which it most probably is).
    • RESEARCH: Is there an attribute for a 'cloned object' I could use for this? That would make it easy to search through objects to find the NPC being phoned!
  • Convert to a library.

I think you should be able to use 'set', for example:

<game name="example_game">
  <attr name="start" type="script">
    script_variable => msg ("blah scripting")
    set (npc, "dialogue", script_variable)
    set (npc, "displayverbs", "dialogue") // or try this: set (npc, "listextend", "dialogue") // or try this: set (npc, "displayverbs") --- you'd then need to use a 'list add' for the "dialogue" option to be added to the blank/empty list
    list add (npc.displayverbs, "fight")
  </attr>
<game>

<object name="npc">
  <inherit name="npc_type" />
</object>

<type name="npc_type">
  <attr name="dialogue" type="script">
    msg ("blah scripting")
  </attr>
  <attr name="displayverbs" type="simplestringlist">dialogue</attr>
</type>

see if this works (I'm too lazy/busy to test it myself at the moment), if not, let me know.


PUBLIC SERVICE ANNOUNCEMENT / PICKS OF THE WEEK

I'd like to apologize for my up-to-the-minute, stream-of-consciousness-like posts throughout this thread.

Thanks to XanMag, Dcoder, hegemonkhan, and The Pixie for all the puzzle pieces, and NecroDeath for posting the inquiry which began all the fun! (And I'm not being facetious! That was FUN!)


Speaking of NecroDeath, has everyone one played his entry this past SpringThing thing? It's GOOD!

The Bony King of Nowhere


One of XanMag's (I am currently playing this one. Great stuff!):
Xanadu - The World's Only Hope


One of The Pixie's (This is great, too, and you'll flip when you see the interface!)
Deeper 2.0


DarkLizerd's game will keep you on your toes:
Wumpus 2.0


Today's thread was brought to you by the letter &#79;, which translates to: O.


HK,

I tried this:

set (Sue2, "displayverbs", "Speak to")

Sue2 is the second clone of Sue, which is probably what was throwing the monkey wrench into the works. (Or maybe it is because it's a list or because of the type of list it is... That stuff still trips me up.)

It threw this at me:

Error running script: Error evaluating expression 'not ListContains(baselist, displayverb)': ListContains function expected list parameter but was passed 'Speak to'
Error running script: Error evaluating expression 'Join(GetDisplayVerbs(object), "/")': Value cannot be null.Parameter name: values
Error running script: Error evaluating expression 'not ListContains(baselist, displayverb)': ListContains function expected list parameter but was passed 'Speak to'
Error running script: Error evaluating expression 'not ListContains(baselist, displayverb)': ListContains function expected list parameter but was passed 'Speak to'

...but when I tried:

Sue2.displayverbs = NewStringList()
list add (Sue2.displayverbs, "Speak to")

...that did the trick.

Check out the working model:

http://textadventures.co.uk/games/view/n_ofxynz7ukw_idosgcojq/phone-tag


oops.... MY BAD.... I totally forgot you were using a clone, yep, that'd be the issue: using 'Sue' (original Object) and not the clone.

again, sorry about that!

and ah, using the 'Sue2.displayverbs = NewStringList ()' is probably required too: you likely can't use the 'set' Function with Lists, or maybe it's just that the 'set' can't be used to over-ride/over-write an inherited list attribute... but it's likely again that you can't use 'set' at all with Lists.

nice job of finding the way for it to work!


about clones:

you'd have to do this (easiest way) for your scripting:

clone_object_variable = CloneObject (Sue)
// clone_object_variable = Sue2 // if done again (and again): Sue3, Sue4, etc etc etc
// you can also assign its (the clone Object's) 'parent' and/or add it (the clone Object) to a List (Stringlist or Objectlist)
clone_object_variable.displayverbs = NewStringList ()
list add (clone_object_variable.displayverbs, "Speak to")


HK,

No apologies necessary! You're awesome all day long in my book!

Thinking of trying to use set may not have helped this time, but I was completely unaware of set, so you still taught me something I can use in the future. (Now, I know.)


A simple and efficient method to find and remove any newly created clones on hang-up is still eluding me, too.
(Iteration kicks my butt!)

When I call Sue: (I have this part working perfectly.)

  1. Sue is cloned - Sue1 is moved to a room specifically designed to 'house' the NPC being telephoned. (phone_call_room)
  2. Sue is cloned again - Sue2 is moved to the location of the player, this is to display a Sue on the side pane with a single option: SPEAK TO. Clicking this brings up Sue's topics menu.

Now, when I hang up:

  1. All objects in phone_call_room are removed from play. (This one's easy.)

  2. Sue2 is removed from play (specifically, by object name).

The second one is easy when Sue is the only NPC in the game, but I'd like a way to iterate through any existing clones so theHangUp script could handle things without specifying the object name. (On second thought, just because I'm not using any other clones right now, this would most likely cause problems if I were to use clones for something else later in the game.)

Perhaps using foreach and StartsWith together would be a good way to script HangUp to find and remove the second clone of the NPC.

OR m Maybe I should just create an object list attribute for the phone!

Each time I clone an NPC, I'd add them to that list, then HangUp could simply remove each object from said list via foreach...


(filler for getting this edited post updated/posted)


you can store the created Clone into an Object reference/pointer Attribute (single clone per Attribute) or a List Attribute (Objectlist or Stringlist) (mutliple clones per List Attribute --- but then you can't know the specific clones as far as I know --- Pixie might know of a way), that way you can get to it from anywhere in your game/code. And if using a List, you can push/pop (add/remove) them, but there's no way of knowing/indentifying-specific clones: you can only use their ordering to do so (if you're using a design that maintains/uses their ordering/adding-into the List, you can then remove them or use them in the same order: this design is known as pushing/popping items on-to/off-of a stack/queue, a design/method of doing Data Structure/Management programming: ht.tp://introcs.cs.princeton.edu/java/43stack/ and ht.tps://www.cs.cmu.edu/~adamchik/15-121/lectures/Stacks%20and%20Queues/Stacks%20and%20Queues.html).


Pixie might know of better ways and/or of a way to know the specific clones... but I can't think of any other ways or of a way to know a specific clone (aside from only knowing a single specific clone using an Object reference/pointer Attribute)


the 'set' and 'do' Functions are powerful/useful as they do NOT use the dot notation and you can concatenate with/within them as well (sometimes it's convenient to do), whereas you can do so with 'invoke' Function

for (impractical/stupid/lame) example:

<game name="example_game">

  <attr name="color_list" type="simplestringlist">red;blue;yellow</attr>

  <attr name="red_script_attribute" type="script">
    msg ("red")
  </attr>

    <attr name="blue_script_attribute" type="script">
    msg ("blue")
  </attr>

  <attr name="yellow_script_attribute" type="script">
    msg ("yellow")
  </attr>

  <attr name="start" type="script">
    item_string_variable = StringListItem (game.color_list, GetRandomInt (0, ListCount (game.color_list) - 1))
    do (game, item_string_variable + "_script_attribute")
    // whereas, you can't do this with the 'invoke' Function as it uses the dot notation (and also no concatenation within it):
    // correct_item_string_variable = item_string_variable + "_script_attribute"
    // invoke (game.correct_item_string_variable)
    // ERROR! there is NO 'correct_item_string_variable' Script Attribute contained within the 'game' Game Settings Object
  </attr>

</game>

Log in to post a reply.

Support

Forums