Aardwolf MUD Home Page Link

Location: Home / Lua Coding / Lua Mud Howtos

This page contains snippets of code to frequently asked questions when working with the Lua / Mud system. As builders become familiar with the code, useful hints and answers will be added to this page.

How to test for good, evil, neutral?

The old mobprog system had 3 commands for isgood, isevil and isneutral. The Lua based system allows you to be more specific and test the character alignment number. To get the equivalents of the old commands use:

if ch.align >= 875 then .... (good alignment)
if ch.align <= -875 then .... (evil alignment)
if ch.align > -875 and ch.align < 875 then .... (neutral)

How to test for a non-player?

The 'isplayer(CH)' function tests if a character variable is a player. The old mobprog system had no concept of not. In Lua, you would just wrap a 'not' around it:
if not(isplayer(ch)) then
   say("I don't deal with mobs, shoo!")
end

How to do equivalent of 'mob force mob oload aylor-321' etc?

In the old mobprog system, 'mob force' forces the target to execute a MUD command. This works fine in the Lua force also. The exception is 'mob force mob ...' - In the old system this causes the mob being forced to execute an arbitrary line of mobprog code within its own space. Because Lua is a completely separate environment integrated back in to the mud, you cannot simply force a mob to execute a lua statement.

The workaround for this is more flexible, but a little more complex. Using the v2 mobprog example below, the mob loads a new mob, then forces it to load and wield a sword:

--- Create a new mob : forge worker.
mob mload aylor-20
--- Force it to load an aylorian sword on itself
mob force worker mob oload aylor-321
--- Force it to wield it. No 'mob force mob' here - regular MUD command.
mob force wield wield sword

Because the Lua call allows you to change the actors (including self), and because mload returns a CH variable for the mob created, you can combine these to achieve the same results.

You would split this into two progs, then call the second prog changing the 'self' actor to the mob that was just loaded:

--- Create a new mob
local newmob = mload("aylor-20")

--- Call the second prog, as the new mob. Imagine the new prog is aylor-50.
--- We're only changing self to newmob in the call so put nil in the other
--- variable positions. Think of this as "execute aylor-50 as the newmob"
call("aylor-50",nil,nil,nil,newmob)

--- Aylor-50 prog: now being executed as the new mob is simply:
oload("aylor-321")
mdo("wield sword")

How to restrict a wandering mob by sector

This mostly came up because of mobs wandering on the continents - being able to restrict a fish to river only sectors or a mountain lion to the mountains etc

The solution for this involves using the new 'lastroom' character property along with an entry trigger. If the mob tries to enter a sector type you don't want it to be in, transfer it back to its last room.

--- Fish mob, can only wander to another river or a lake.
--- At the point an entry trigger fires, the mob is already in the room
--- it is attempting to move to.

local lastroom = self.lastroom
if lastroom ~= nil then
   if self.room.sector ~= SECT_RIVER and self.room.sector ~= SECT_LAKE then
      rgoto(lastroom)
   end
end

The trigger for this is:

Current Triggers
No   Trigger Type Program       Old Vnum Phrase/Percentage
==   ============ ============= ======== ==================================
 1 - Entry        test-47              0 100

How to use the date/time/timer features

Before working with times and dates in the MUD, an important thing to know is that, internally, all dates and times in the MUD are stored as "Unixtime" which is the number of seconds since Jan 1st 1971. We can use this number to manipulate dates to add/remove/check times.

There are three Luaprog commands that can be used to manipulate dates and times:

mud.unixtime():
  Will give the underlying MUD time in seconds.
   
mud.unixtime(time) : 
  Time must be in the format HH:MM MM/DD/YYYY and will return the corresponding Unixtime in seconds.
   
mud.convtime(utime): 
  Takes a unixtime and returns a human readable format. You can add argument 2 to include seconds and 
  argument 3 to print only minutes and seconds. 
						

There is also a new trigger type TIMER that works like RANDOM but is a fixed time in seconds so you can predict exactly when a prog will run. This is not like adddelay() because it will constantly run once the trigger is set. As this is intended to be used for longer term timers, you cannot set an interval of less than 60 seconds but if you *really* need one we can discuss it as high level imms can set them.

Here are some examples of using these commands:

Converting a human readable date to internal time then back again so you can see that it worked correctly:

  local xmas25   = "07:00 12/25/2025"
  local intxmas = mud.unixtime("07:00 12/25/2025")
  echo("Next Christmas unixtime: " .. intxmas)
  echo("Next Christmas         : " .. convtime(intxmas) .."nr")

Getting the current MUD time and adding a week to it:

local nowtime  = mud.unixtime()
local nextweek = nowtime + 60*60*24*7 -- 60 seconds * 60 minutes * 24 hours * 7 days

echo("The unixtime is        : " .. mud.unixtime())
echo("Next week is unixtime  : " .. nextweek)
echo("Next week is also      : " .. convtime(nextweek))
echo("Next week is also      : " .. convtime(nextweek,2) .. "nr")

Setting a timer on a mob then checking it periodically. The program to do the checking would be in a TIMER trigger. This is just for example, in this case if we wanted the program to run every 2 hours unconditionally we'd set a 7200 second TIMER trigger. This logic would only be needed for a longer term trigger (assume daily reboots) or if the two hours needed to be exact and should not reset over a reboot, which means the timer would have to be saved:


if self.mobdata1 == 0 then
   echo("Two hours from now is  : " .. convtime(nowtime + 60*60*2))
   self.mobdata1 = nowtime + 60*60*2
else
   local timeleft = self.mobdata1 - nowtime
   if timeleft <= 0 then
      say("My timer is up!")
      self.mobdata1 = 0
      -- Do some stuff here - this was really the point of the timer.
   else
      echo("Current time is        : " .. convtime(nowtime,2))
      echo("Mob timer is up at     : " .. convtime(self.mobdata1,2))
      echo("Remaining time on mob  : " .. convtime(timeleft,3))
   end
end

All three of these examples run together in a single program would return this if the timer has already been set:

  Next Christmas unixtime: 1766664000
  Next Christmas         : 12/25/25 07:00

  The unixtime is        : 1713920625
  Next week is unixtime  : 1714525425
  Next week is also      : 04/30/24 21:03
  Next week is also      : 04/30/24 21:03:45

  Current time is        : 04/23/24 21:03:45
  Mob timer is up at     : 04/23/24 22:48:01
  Remaining time on mob  : 01:44:16