Merge branch 'master' into very_experimental_input_stuff

This commit is contained in:
Sezz 2022-08-12 23:44:05 +10:00
commit c32be322ab
81 changed files with 1287 additions and 850 deletions

View file

@ -1,11 +1,81 @@
-----
--- Event sequence - a chain of functions to call at specified times, modeled after TRNG's organizers.
-- Example usage:
-- local EventSequence = require("EventSequence")
--
-- -- These will be called by the sequence
-- LevelFuncs.HealLara = function()
-- Lara:SetHP(Lara:GetHP()+10)
-- end
--
-- local nSpawned = 0
-- LevelFuncs.SpawnBaddy = function(baddy, name, pos)
-- local myBaddy = TEN.Objects.Moveable(baddy, name..nSpawned, pos, nil, 0)
-- myBaddy:Enable()
-- nSpawned = nSpawned + 1
-- end
--
-- -- This function triggers the sequence
-- LevelFuncs.TriggerSequence = function(obj)
-- local posSteve = TEN.Objects.GetMoveableByName("stevePosNullmesh"):GetPosition()
-- local posChris = TEN.Objects.GetMoveableByName("chrisPosNullmesh"):GetPosition()
-- local mySeq = EventSequence.Create("my_seq",
-- false, -- does not loop
-- {seconds = true, deciseconds = true}, -- timer format, see Timer for details
-- 6, -- seconds until call the function specified in next arg
-- "HealLara", -- first function to call. If we don't need to pass any arguments, we can just give the func name as a string
-- 2.1, -- seconds until the next function, after the previous one has been called
-- {"SpawnBaddy", TEN.Objects.ObjID.BADDY1, "steve", posSteve}, -- if we DO want to pass arguments to the function to be called, we give a table with the name of the function ("SpawnBaddy" in this case) followed by the args to pass to it
-- 0.5,
-- {"SpawnBaddy", TEN.Objects.ObjID.SAS_CAIRO, "chris", posChris},
-- 1,
-- "HealLara")
--
-- -- event sequences are inactive to begin with and so need to be started
-- mySeq:Start()
-- end
--
-- -- EventSequence runs on Timer, so this call is required
-- LevelFuncs.OnControlPhase = function(dt)
-- Timer.UpdateAll(dt)
-- end
--
-- @luautil EventSequence
local Timer = require("Timer")
local EventSequence
LevelVars.__TEN_eventSequence = {sequences = {}}
LevelFuncs.__TEN_eventSequence_callNext = function(sequenceName, nextTimerName, func, ...)
local thisES = LevelVars.__TEN_eventSequence.sequences[sequenceName]
LevelFuncs[func](...)
thisES.currentTimer = thisES.currentTimer + 1
if thisES.currentTimer <= #thisES.timers then
local theTimer = Timer.Get(nextTimerName)
theTimer:SetRemainingTime(theTimer:GetTotalTime())
theTimer:Start()
elseif thisES.loop then
local theTimer = Timer.Get(thisES.firstTimerName)
theTimer:SetRemainingTime(theTimer:GetTotalTime())
theTimer:Start()
thisES.currentTimer = 1
else
thisES.currentTimer = 1
end
end
EventSequence = {
Create = function(name, showString, ...)
--- Create (but do not start) a new event sequence.
--
-- @string name A label to give the sequence; used to retrieve the timer later as well as internally by TEN.
-- @bool loop if true, the sequence will start again from its first timer once its final function has been called
-- @tparam ?table|bool timerFormat same as in Timer. This is mainly for debugging. __This will not work properly if another sequence or timer is showing a countdown.__
-- @param[opt] ... a variable number of pairs of arguments - a time in seconds, followed by the function (must be defined in the LevelFuncs table) to call once the time has elapsed, followed by another duration in seconds, another function name, etc. You can specify a function either by its name as a string, or by a table with the function name as the first member, followed by its arguments (see above example).
-- @return The inactive sequence.
Create = function(name, loop, timerFormat, ...)
local obj = {}
local mt = {}
mt.__index = EventSequence
@ -13,10 +83,11 @@ EventSequence = {
obj.name = name
LevelVars.__TEN_eventSequence.sequences[name] ={}
LevelVars.__TEN_eventSequence.sequences[name] = {}
local thisES = LevelVars.__TEN_eventSequence.sequences[name]
thisES.name = name
thisES.timesFuncsAndArgs = {...}
thisES.loop = loop
local tfa = thisES.timesFuncsAndArgs
thisES.timers = {}
@ -35,6 +106,10 @@ EventSequence = {
local funcAndArgs = tfa[i+1]
local func
if i == 1 then
thisES.firstTimerName = timerName
end
if type(funcAndArgs) == "string" then
-- we only have a function
func = funcAndArgs
@ -44,29 +119,15 @@ EventSequence = {
func = table.remove(funcAndArgs, 1)
end
if nextTimer < #tfa then
-- This function must start next timer
-- AND do its function
LevelFuncs[funcName] = function(...)
LevelFuncs[func](...)
Timer.Get(nextTimerName):Start()
thisES.currentTimer = timerIndex + 1
end
else
-- final timer
LevelFuncs[funcName] = function(...)
LevelFuncs[func](...)
Timer.Get(timerName):Stop()
thisES.currentTimer = 1
end
end
local thisTimer = Timer.Create(timerName,
tfa[i], -- time
false,
showString,
funcName,
funcAndArgs -- now with func removed
timerFormat,
"__TEN_eventSequence_callNext",
name,
nextTimerName,
func,
table.unpack(funcAndArgs) -- now with func removed
)
thisES.timers[timerIndex] = timerName
@ -75,6 +136,9 @@ EventSequence = {
return obj
end;
--- Get an event sequence by its name.
-- @string name The label that was given to the sequence when it was created
-- @return The sequence
Get = function(name)
if LevelVars.__TEN_eventSequence.sequences[name] then
local obj = {}
@ -85,22 +149,45 @@ EventSequence = {
return obj
end
return nil
end,
end;
Pause = function(t)
--- Pause or unpause the sequence. If showing the remaining time on-screen, its color will be set to yellow (paused) or white (unpaused).
-- @function mySequence:SetPaused
-- @bool p if true, the sequence will be paused; if false, it will be unpaused
SetPaused = function(t, p)
local thisES = LevelVars.__TEN_eventSequence.sequences[t.name]
Timer.Get(thisES.timers[thisES.currentTimer]):Pause()
end,
Timer.Get(thisES.timers[thisES.currentTimer]):SetPaused(p)
end;
Stop = function(t)
--- Get whether or not the sequence is paused
-- @function mySequence:IsPaused
-- @return true if the timer is paused, false if otherwise
IsPaused = function(t)
local thisES = LevelVars.__TEN_eventSequence.sequences[t.name]
Timer.Get(thisES.timers[thisES.currentTimer]):Stop()
end,
return Timer.Get(thisES.timers[thisES.currentTimer]):IsPaused()
end;
--- Begin or unpause a sequence. If showing the remaining time on-screen, its color will be set to white.
-- @function mySequence:Start
Start = function(t)
local thisES = LevelVars.__TEN_eventSequence.sequences[t.name]
Timer.Get(thisES.timers[thisES.currentTimer]):Start()
end;
--- Stop the sequence.
--@function mySequence:Stop
Stop = function(t)
local thisES = LevelVars.__TEN_eventSequence.sequences[t.name]
Timer.Get(thisES.timers[thisES.currentTimer]):Stop()
end;
--- Get whether or not the sequence is active
-- @function mySequence:IsActive
-- @return true if the sequence is active, false if otherwise
IsActive = function(t)
local thisES = LevelVars.__TEN_eventSequence.sequences[t.name]
return Timer.Get(thisES.timers[thisES.currentTimer]):IsActive()
end;
}
return EventSequence

View file

@ -17,10 +17,6 @@ local ItemAction = Flow.ItemAction
Flow.SetIntroImagePath("Screens\\main.jpg")
Flow.SetTitleScreenImagePath("Screens\\main.jpg")
-- Flow.SetFarView sets global far view distance in blocks.
-- It will be overwritten by level.farView value, if it is specified.
Flow.SetFarView(20)
--------------------------------------------------
@ -71,7 +67,6 @@ test.objects = {
-1,
ItemAction.USE
),
myObj,
InventoryItem.new(
"tut1_ba_cartouche2",
InvID.PUZZLE_ITEM3_COMBO2,
@ -114,4 +109,4 @@ test.objects = {
)
}
Flow.AddLevel(test)
Flow.AddLevel(test)

View file

@ -1109,6 +1109,46 @@ local strings = {
"",
""
},
antialiasing = {
"Antialiasing",
"",
"",
"",
"",
"",
"",
""
},
low = {
"Low",
"",
"",
"",
"",
"",
"",
""
},
medium = {
"Medium",
"",
"",
"",
"",
"",
"",
""
},
high = {
"High",
"",
"",
"",
"",
"",
"",
""
},
waiting_for_key = {
"Waiting For Key",
"",

View file

@ -3,9 +3,17 @@
local Util = require("Util")
Util.ShortenTENCalls()
-- Called when entering a level, not called when loading from a save
LevelFuncs.OnStart = function() end
-- Called only when loading from a save
LevelFuncs.OnLoad = function() end
LevelFuncs.OnSave = function() end
LevelFuncs.OnControlPhase = function() end
-- dt stands for "delta time", and holds the time in seconds since the last call to OnControlPhase
LevelFuncs.OnControlPhase = function(dt) end
LevelFuncs.OnEnd = function() end
-- An example function which prints a string and leaves it on screen for 1 second.
@ -114,4 +122,4 @@ LevelFuncs.EmitHaloOnActionPush = function(Triggerer)
Effects.EmitParticle(pos, velocity, 2, 1, rot, Color.new(color * 0.5, color * 0.5, color), Color.new(color * 0.2, color * 0.1, color), 2, 16, 64, 1, false, false)
Effects.EmitLight(pos, Color.new(color * 0.5, color * 0.5, color), 7)
end
end

View file

@ -1,14 +1,23 @@
-----
--- Basic timer - after a specified number of seconds, the specified thing happens.
-- Usage:
-- Example usage:
-- local Timer = require("Timer")
--
-- -- This will be called when the timer runs out
-- LevelFuncs.FinishTimer = function(healthWhenStarted, victoryMessage)
-- -- Open a door, display a message, make an explosion... whatever you wish
-- DoSomething(healthWhenStarted, victoryMessage)
-- end
--
-- -- This function triggers the timer
-- LevelFuncs.TriggerTimer = function(obj)
-- local myTimer = Timer.Create("my_timer", 5.0, false, true, "FinishTimer", Lara:GetHP(), "Well done!")
-- local myTimer = Timer.Create("my_timer",
-- 5.0,
-- false,
-- {minutes = false, seconds = true, deciseconds = true},
-- "FinishTimer",
-- Lara:GetHP(),
-- "Well done!")
-- myTimer:Start()
-- end
--
@ -22,20 +31,42 @@ LevelVars.__TEN_timer = {timers = {}}
local Timer
local unpausedColor = Color(255, 255, 255)
local pausedColor = Color(255, 255, 0)
local unpausedColor = TEN.Color(255, 255, 255)
local pausedColor = TEN.Color(255, 255, 0)
local str = TEN.Strings.DisplayString("TIMER", 0, 0, unpausedColor, false, {TEN.Strings.DisplayStringOption.CENTER, TEN.Strings.DisplayStringOption.SHADOW} )
Timer = {
--- Create (but do not start) a new timer.
--
-- You have the option of displaying the remaining time on the clock. Timer format details:
--
-- -- deciseconds are 1/10th of a second
--
-- -- mins:secs
-- local myTimeFormat1 = {minutes = true, seconds = true, deciseconds = false}
--
-- -- also mins:secs
-- local myTimeFormat2 = {minutes = true, seconds = true}
--
-- -- secs:decisecs
-- local myTimeFormat3 = {seconds = true, deciseconds = true}
--
-- -- secs; also what is printed if you pass true instead of a table
-- local myTimeFormat4 = {seconds = true}
--
--__At any given time, only one timer can show its countdown__.
--
--Use this sparingly; in the classics, timed challenges did not have visible countdowns. For shorter timers, the gameplay benefit from showing the remaining time might not be necessary, and could interfere with the atmosphere of the level.
--
-- @string name A label to give this timer; used to retrieve the timer later
-- @number totalTime The duration of the timer, in seconds
-- @bool loop if true, the timer will start again immediately after the time has elapsed
-- @bool showString if true, the remaining time, rounded up, will show at the bottom of the screen. __At any given time, only one timer can show its remaining time__.
-- @string func The name of the LevelFunc member to call when the time is up
-- @param funcArgs the arguments with which the above function will be called
-- @tparam ?table|bool timerFormat If a table is given, the remaining time will be shown as a string, formatted according to the values in the table. If true, the remaining seconds, rounded up, will show at the bottom of the screen. If false, the remaining time will not be shown on screen.
-- @string func The name of the LevelFunc member to call when the time is upssss
-- @param[opt] ... a variable number of arguments with which the above function will be called
-- @return The timer in its paused state
Create = function(name, totalTime, loop, showString, func, ...)
--
Create = function(name, totalTime, loop, timerFormat, func, ...)
local obj = {}
local mt = {}
mt.__index = Timer
@ -45,7 +76,6 @@ Timer = {
LevelVars.__TEN_timer.timers[name] ={}
local thisTimer = LevelVars.__TEN_timer.timers[name]
thisTimer.name = name
thisTimer.showString = showString
thisTimer.totalTime = totalTime
thisTimer.remainingTime = totalTime
thisTimer.func = func
@ -53,6 +83,11 @@ Timer = {
thisTimer.loop = loop
thisTimer.active = false
thisTimer.paused = true
if type(timerFormat) == "table" then
thisTimer.timerFormat = timerFormat
elseif timerFormat then
thisTimer.timerFormat = {seconds = true}
end
return obj
end;
@ -69,92 +104,6 @@ Timer = {
return obj
end
return nil
end,
--- Give the timer a new function and args
-- @param t the timer in question
-- @string func The name of the LevelFunc member to call when the time is up
-- @param funcArgs the arguments with which the above function will be called
SetFunction = function(t, func, ...)
local thisTimer = LevelVars.__TEN_timer.timers[t.name]
thisTimer.func = func
thisTimer.funcArgs = {...}
end,
--- Begin or unpause a timer. If showing the remaining time on-screen, its color will be set to white.
-- @param t the timer in question
Start = function(t)
local thisTimer = LevelVars.__TEN_timer.timers[t.name]
if not thisTimer.active then
thisTimer.active = true
end
LevelVars.__TEN_timer.timers[t.name].paused = false
if thisTimer.showString then
str:SetColor(unpausedColor)
end
end;
--- Pause the timer. If showing the remaining time on-screen, its color will be set to yellow.
-- @param t the timer in question
Pause = function(t)
local thisTimer = LevelVars.__TEN_timer.timers[t.name]
thisTimer.paused = true
if thisTimer.showString then
str:SetColor(pausedColor)
end
end,
--- Stop the timer.
-- @param t the timer in question
Stop = function(t)
LevelVars.__TEN_timer.timers[t.name].active = false
end,
--- Get the remaining time for a timer.
-- @param t the timer in question
-- @return the time in seconds remaining on the clock
GetRemainingTime = function(t)
return LevelVars.__TEN_timer.timers[t.name].remainingTime
end,
--- Set the remaining time for a timer
-- @param t the timer in question
-- @number remainingTime the new time remaining for the timer
SetRemainingTime = function(t, remainingTime)
LevelVars.__TEN_timer.timers[t.name].remainingTime = remainingTime
end,
--- Get the total time for a timer.
-- This is the amount of time the timer will start with, as well as when starting a new loop
-- @param t the timer in question
-- @return the timer's total time
GetTotalTime = function(t)
return LevelVars.__TEN_timer.timers[t.name].totalTime
end,
--- Set the total time for a timer
-- @param t the timer in question
-- @number totalTime timer's new total time
SetTotalTime = function(t, totalTime)
LevelVars.__TEN_timer.timers[t.name].totalTime = totalTime
end,
--- Set whether or not the timer loops
-- @param t the timer in question
-- @bool looping whether or not the timer loops
SetLooping = function(t, looping)
LevelVars.__TEN_timer.timers[t.name].loop = looping
end,
--- Update all active timers.
-- Should be called in LevelFuncs.OnControlPhase
-- @number dt The time in seconds since the last frame
UpdateAll = function(dt)
for _, t in pairs(LevelVars.__TEN_timer.timers) do
Timer.Update(t, dt)
end
end;
Update = function(t, dt)
@ -173,17 +122,178 @@ Timer = {
end
end
if t.showString then
if t.timerFormat then
TEN.Strings.HideString(str)
str:SetKey(tostring(math.ceil(t.remainingTime)))
local fmt = ""
local remaining = math.max(t.remainingTime, 0)
local round = math.floor
local subSecond = remaining - math.floor(remaining)
local fmtBefore = false
-- deciseconds
if t.timerFormat.deciseconds then
fmt = math.floor(10*subSecond)
fmtBefore = true
end
-- seconds
if t.timerFormat.seconds then
if not fmtBefore then
round = math.ceil
else
round = math.floor
fmt = ":" .. fmt
end
local roundedSeconds = round(remaining)
local toBeDisplayed = roundedSeconds
if t.timerFormat.minutes then
toBeDisplayed = roundedSeconds % 60
end
fmt = string.format("%02d", toBeDisplayed) .. fmt
remaining = roundedSeconds
fmtBefore = true
end
-- minutes
if t.timerFormat.minutes then
if not fmtBefore then
round = math.ceil
else
round = math.floor
fmt = ":" .. fmt
end
local roundedMinutes = round(remaining/60)
local toBeDisplayed = roundedMinutes
fmt = string.format("%02d", toBeDisplayed) .. fmt
fmtBefore = true
end
str:SetKey(fmt)
local myX, myY = PercentToScreen(50, 90)
str:SetPosition(myX, myY)
-- Do this again in case the player has loaded while the timer was paused already
-- Need a better solution for this
if t.paused then
str:SetColor(pausedColor)
end
TEN.Strings.ShowString(str, 1)
end
end
end;
--- Update all active timers.
-- Should be called in LevelFuncs.OnControlPhase
-- @number dt The time in seconds since the last frame
UpdateAll = function(dt)
for _, t in pairs(LevelVars.__TEN_timer.timers) do
Timer.Update(t, dt)
end
end;
--- Give the timer a new function and args
-- @function myTimer:SetFunction
-- @string func The name of the LevelFunc member to call when the time is up
-- @param[opt] ... a variable number of arguments with which the above function will be called
SetFunction = function(t, func, ...)
local thisTimer = LevelVars.__TEN_timer.timers[t.name]
thisTimer.func = func
thisTimer.funcArgs = {...}
end;
--- Begin or unpause a timer. If showing the remaining time on-screen, its color will be set to white.
-- @function myTimer:Start
Start = function(t)
local thisTimer = LevelVars.__TEN_timer.timers[t.name]
if not thisTimer.active then
thisTimer.active = true
end
thisTimer.paused = false
if thisTimer.timerFormat then
str:SetColor(unpausedColor)
end
end;
--- Stop the timer.
-- @function myTimer:Stop
Stop = function(t)
LevelVars.__TEN_timer.timers[t.name].active = false
end;
--- Get whether or not the timer is active
-- @function myTimer:IsActive
-- @return true if the timer is active, false if otherwise
IsActive = function(t)
return LevelVars.__TEN_timer.timers[t.name].active
end;
--- Pause or unpause the timer. If showing the remaining time on-screen, its color will be set to yellow (paused) or white (unpaused).
-- @function myTimer:SetPaused
-- @bool p if true, the timer will be paused; if false, it would be unpaused
SetPaused = function(t, p)
local thisTimer = LevelVars.__TEN_timer.timers[t.name]
thisTimer.paused = p
if thisTimer.timerFormat then
if p then
str:SetColor(pausedColor)
else
str:SetColor(unpausedColor)
end
end
end;
--- Get whether or not the timer is paused
-- @function myTimer:IsPaused
-- @return true if the timer is paused, false if otherwise
IsPaused = function(t)
return LevelVars.__TEN_timer.timers[t.name].paused
end;
--- Get the remaining time for a timer.
-- @function myTimer:GetRemainingTime
-- @return the time in seconds remaining on the clock
GetRemainingTime = function(t)
return LevelVars.__TEN_timer.timers[t.name].remainingTime
end;
--- Set the remaining time for a timer
-- @function myTimer:SetRemainingTime
-- @number remainingTime the new time remaining for the timer
SetRemainingTime = function(t, remainingTime)
LevelVars.__TEN_timer.timers[t.name].remainingTime = remainingTime
end;
--- Get the total time for a timer.
-- This is the amount of time the timer will start with, as well as when starting a new loop
-- @function myTimer:GetRemainingTime
-- @return the timer's total time
GetTotalTime = function(t)
return LevelVars.__TEN_timer.timers[t.name].totalTime
end;
--- Set the total time for a timer
-- @function myTimer:SetTotalTime
-- @number totalTime timer's new total time
SetTotalTime = function(t, totalTime)
LevelVars.__TEN_timer.timers[t.name].totalTime = totalTime
end;
--- Set whether or not the timer loops
-- @function myTimer:SetLooping
-- @bool looping whether or not the timer loops
SetLooping = function(t, looping)
LevelVars.__TEN_timer.timers[t.name].loop = looping
end;
}
return Timer