Page 1 of 1

start an action after a certin time

Posted: Sat Oct 03, 2015 5:56 pm
by bongobeat
Hey,

does someone know how to make a script, that check if, let's say, 24 hours have passed?
I need something like that to recall the player that he have to go back to an npc after a certain time.

Re: start an action after a certin time

Posted: Sun Oct 04, 2015 2:53 am
by Drakkan
what about using just regular timer ?

Re: start an action after a certin time

Posted: Sun Oct 04, 2015 4:56 pm
by bongobeat
Well, in log 1, the problem with the timer, if you change level, the timer does not count the time same way than the level where the party is. I don't know if this has been changed in log2?

Another thing, if you press the rest button, the timer seems not take in count the time elapsed during rest.

I think of something with game time, but don't know how to do it. If it is possible to do something of course.

Re: start an action after a certin time

Posted: Sun Oct 04, 2015 6:37 pm
by THOM
Maybe you can add a timer component to the party object?

Re: start an action after a certin time

Posted: Sun Oct 04, 2015 7:30 pm
by minmay
TimerComponents track "real" time elapsed on the level, which does not correspond to time of day at all. Time of day changes when the party moves, turns, and rests, rather than with real time. Here's one way you could track elapsed time of day. Add these components to the party object:

Code: Select all

{
  class = "Timer",
  name = "daytimer",
  timerInterval = 0.001,
  onActivate = function(self)
    self.go.dayscript.update()
  end,
},
{
  class = "Script",
  name = "dayscript",
  source = [[-- NOTE: This will not correctly track GameMode.advanceTime() with units of 1.0 or greater, and will treat GameMode.setTimeOfDay() as advancing time. This isn't really avoidable without overwriting those functions, which would be gross. Instead we provide our own that you can use in place of these which will be tracked correctly.
last = 0
connectors = {}

function update()
  -- track wrapping
  local elapsed = math.min(math.abs(GameMode.getTimeOfDay() - last),GameMode.getTimeOfDay())
  last = GameMode.getTimeOfDay()
  updateConnectors(elapsed)
end

function addDayConnector(time,target,action)
  if not type(time) == "number" then
    print(string.format("err: invalid argument 1 to addDayConnector (number expected, got %s",type(time)))
    return false
  end
  if not type(target) == "string" then
    print(string.format("err: invalid argument 2 to addDayConnector (string expected, got %s",type(target)))
    return false
  end
  if not type(action) == "string" then
    print(string.format("err: invalid argument 3 to addDayConnector (string expected, got %s",type(action)))
    return false
  end
  table.insert(connectors,{t=time,targ=target,act=action})
  return true
end

-- Like GameMode.setTimeOfDay(), but don't elapse any time for the purposes of this script.
function setTimeOfDay(time)
  GameMode.setTimeOfDay(time)
  last = time%2
end

-- Like GameMode.advanceTime(), but elapse the appopriate amount of time in this script, even if the value is over 1.
function advanceTime(amt)
  GameMode.advanceTime(amt)
  updateConnectors(amt)
  last = GameMode.getTimeOfDay()
end

function updateConnectors(elapsed)
  for index,c in ipairs(connectors) do
    c.t = c.t-elapsed
    if c.t <= 0 then
      local e = findEntity(c.targ)
      if e and e.controller then
        if e.controller[c.act] then
          e.controller[c.act](e.controller)
        else
          print(string.format("warning: invalid day connector action %s on entity %s",c.act,c.targ))
        end
      else
        print(string.format("warning: invalid day connector target %s",c.targ))
      end
      table.remove(connectors,index)
    end
  end
end]],
},
(dont have the time to test at the moment, so there may be some typos)

Then to trigger an event after some amount of elapsed time, you'd make a call like this (it acts like a connector, except the first parameter is the amount of day time to trigger it after; 2 is one day):

Code: Select all

party.dayscript.addDayConnector(2,"dungeon_portcullis_1","open")
Remember to replace any calls to GameMode.setTimeOfDay() or GameMode.advanceTime() with party.dayscript.setTimeOfDay() or party.dayscript.advanceTime().

Attaching a TimerComponent to the party object is the easiest and almost certainly the best way to track elapsed realtime or call something on every frame. The party object is certain to update every frame, since it will always be on the party's level. TimerComponents trigger a maximum of once per frame, which is very convenient (it's why we can use a 1ms interval and not care). The common thought of using an onDrawGui hook is not so good since that hook is not called while the party is free-looking, viewing the map, etc...

edit: fixed one of those typos

Re: start an action after a certin time

Posted: Sun Oct 04, 2015 8:33 pm
by cromcrom
Wow, great post, thanks Minmay.

Re: start an action after a certin time

Posted: Mon Oct 05, 2015 11:57 am
by bongobeat
great! thanks! Gonna try it!