User Tools

Site Tools


lua:scriptenvironments

Script Environments

All prog scripts run in the scripting environment that is attached to the game object to which the trigger is attached. For instance, mprogs run in the environment of the mob that is running the script. Each individual environment represents the “global” scope for the script, and thusly a “global” variable or function in one environment cannot be accessed from a script running in a different environment.

There are a few ways to share values between different script environments, the most simple to use being shared table.

Simple interactions

The most common way to manipulate an outside environment is with the Prog Trigger mechanism. Mob Progs, Obj Progs, Room Progs and Area Progs all return a CH object, and some return an OBJ object.

For example, in this simple script, a Mob Prog will return the name of a CH, which is a property of CH.

-- GRALL. Let's say HI! to PCs
if ch.ispc then -- ispc is also a property of CH
  say("HI "..ch.name.."!")
end

These simple interactions often depend on the method that wants to be called being available to the environment that is calling it. For example, damage() is a method of CH, so if a mob wanted to damage a PC upon entering a room, it would be quite simple:

-- GRALL. Our PC entered this room
mob:damage(ch, 5000, true, "holy")

And now our char has been damaged for 5000 hitpoints.

Because damage() is a method of CH, this could easily be rewritten so that the PC damages themselves:

-- GRALL. Our PC entered this room
ch:damage(ch, 5000, true, "holy")

There is no qualitative difference between the two versions.

Executing a single method in another environment

In our above example damage() could be used in two different ways because the method belongs to CH. But what if you wanted an object to damage a player? OBJ does not have the method damage(), so you must “break out” into the CH environment.

In this example an object will hurt a player who tries to drop it:

-- DROP. Damage a player who tries to drop this object.
echo("You can't drop me! I'll hurt you!")
ch1:damage(ch1, 5000, true)
return false -- don't let them drop the object

Since “ch1” is one of the script arguments this will work. However, not all Obj Progs return a ch1. For instance, if we wanted an object that hurts a player every 5 seconds they're carrying it, you'd need to break out in other ways:

-- TIMER 5 seconds. Damage the player every 5 seconds.
if obj.carriedby then -- Make sure it's being carried
  obj.carriedby:damage(obj.carriedby, 5000, true)
end

In this case OBJs have a property “carriedby” which returns a CH if the object is being carried. By using this property we can “break out” of the OBJ environment into a CH environment that contains the damage() method.

Finding the correct environment

There are many global functions that will return a single environment or a table of environments. The most commonly used are getmobworld(), getpc(), getroom() and getobjworld(). Below are some examples.

getmobworld() and getobjworld()

These two functions work the same way. Only getmobworld() is shown, but the examples can be made to fit getobjworld(), as long as you use methods and properties common to OBJs, not CHs.

-- Let's find a mob with vnum 22000 and make him "sleep". We know there's only one mob with that vnum.
getmobworld(22000)[1]:mdo("sleep")

Since we know there's only one mob with the vnum 22000 we can use the bracket notation to target that mob. getmobworld() returns a table of mobs, so if there's only one mob we know that mob will be the first in the table. If there is more than one we have to loop through the list:

-- Make mob 22000 in room 22050 "sleep"
for _,mobile in ipairs(getmobworld(22000)) do
  if mobile.room.vnum == 22050 then
    mobile:mdo("sleep")
  end
end

In this example we've looped over the getmobworld() list for that vnum, but also “broke out” in a more conventional way. A mob has a ROOM property, which has a vnum property. In that way we can find out which room a mobile is in and make them sleep if they're in it.

getpc() and getroom()

getpc() takes a string argument. It, like getroom(), can return only one object because PC names are unique.

-- TIMER. Every 5 minutes let's give Vodur a hug. He deserves it.
if getpc("Vodur") then -- First let's make sure he's online
  mob:goto(getpc("Vodur").room.vnum) -- make sure we're going to the room he's in
  mob:mdo("hug vodur")
end

This contrived example is obviously not very useful. In the Cards Against Humanity script we can see how to use getpc() in a more constructive way:

function check_player_num()
  for _,v in ipairs(players) do
    if not(getpc(v.name)) then
      missing_players = {}
      table.insert(missing_players, v.name)
      active_players = #players - #missing_players
    end
  end
  if active_players> 2 then
    start_hand()
  else
    for _,j in ipairs(players) do
      tell(j.name, "We're missing "..util.format_list("and", missing_players).."! We require three players to play, and we currently have "..active_players.."!")
      tell(j.name, "There will be a 30 second break for another player to join, or for "..util.format_list("and", missing_players).." to return.")
      delay(30, final_check)
    end
  end
end

In the function the “players” table, which only contains the strings of a PC's name (and not the CH object) is looped through and checked against getpc() to make sure players haven't logged off.

getroom() is even more straightforward. Since ROOMs of a certain vnum always exist, using getroom() will always allow you to access that ROOMs properties and methods. For instance, we can turn a “dormant” EXIT visible upon a mob's death:

-- DEATH. Make the exit up from 22000 visible.
getroom(22000).up:setflag("dormant", false)

Again, there's no need for any checks, because if the room exists it always exists.

lua/scriptenvironments.txt · Last modified: 2016/02/08 04:45 by vodur