103 lines
3.1 KiB
Text
103 lines
3.1 KiB
Text
-- Forge milestone 2, genre one: the rail shooter. A camera on a rail that stops at encounters,
|
|
-- zombies that spawn there and walk to it, a gun whose ray says which part it hit, ragdolls, and
|
|
-- the rail moving on when the stop is clear. The pointer is aimed at each zombie's head through
|
|
-- sceneProject, which is what a light gun would do with a person behind it.
|
|
dofile("Forge/AuthorCompile.singe")
|
|
|
|
local font = fontLoad("Singe/FreeSansBold.ttf", 18)
|
|
|
|
fontSelect(font)
|
|
fontQuality(FONT_QUALITY_BLENDED)
|
|
|
|
dofile(authorBuild("testScripts/author/railshooter.game", singeGetDataPath() .. "railshooter.singe"))
|
|
|
|
local gameUpdate = onOverlayUpdate
|
|
local frames = 0
|
|
local shots = 0
|
|
local hits = 0
|
|
local heads = 0
|
|
local kills = 0
|
|
local stopped = 0
|
|
local ended = false
|
|
local lastShot = 0
|
|
local GIVE_UP = 60
|
|
|
|
local realEvent = authorEvent
|
|
function authorEvent(name, event)
|
|
if name == "hit" then
|
|
hits = hits + 1
|
|
if event.part == "head" then
|
|
heads = heads + 1
|
|
end
|
|
elseif name == "death" then
|
|
kills = kills + 1
|
|
elseif name == "stopped" then
|
|
stopped = stopped + 1
|
|
elseif name == "railEnd" then
|
|
ended = true
|
|
end
|
|
return realEvent(name, event)
|
|
end
|
|
|
|
|
|
local function fire(x, y, on)
|
|
authorSetPointer(1, x, y, on)
|
|
authorSwitchDown(SWITCH_BUTTON3)
|
|
authorSwitchUp(SWITCH_BUTTON3)
|
|
end
|
|
|
|
|
|
function onOverlayUpdate()
|
|
local t = authorTime()
|
|
local gun = authorEntity("gun1")
|
|
|
|
frames = frames + 1
|
|
-- Aim at the nearest living zombie's head and fire, no faster than a person would; reload
|
|
-- off the picture when empty.
|
|
if gun and (t - lastShot > 0.25) then
|
|
local nearest, best = nil, math.huge
|
|
|
|
for _, zombie in ipairs(authorEach("zombie")) do
|
|
if zombie.vars.state ~= "dead" then
|
|
local far = authorDistance(zombie, authorEntity("camera"))
|
|
|
|
if far < best then
|
|
nearest, best = zombie, far
|
|
end
|
|
end
|
|
end
|
|
if gun.vars.ammo <= 0 then
|
|
fire(-10, -10, false)
|
|
lastShot = t
|
|
elseif nearest then
|
|
local head = nodeFind("b_Head_05", nearest.model)
|
|
local hx, hy, hz = nodeGetWorldPosition(head)
|
|
local sx, sy, _, inFront = sceneProject(hx, hy, hz)
|
|
|
|
if inFront then
|
|
fire(sx, sy, true)
|
|
lastShot = t
|
|
end
|
|
end
|
|
end
|
|
|
|
local r = gameUpdate()
|
|
|
|
colorForeground(255, 255, 255, 255)
|
|
fontPrint(12, 450, string.format("authored rail shooter, %.1fs, zombies %d, kills %d, heads %d, stops %d", t, authorCount("zombie"), kills, heads, stopped))
|
|
if (shots == 0 and t > 5) or (shots == 1 and kills > 0) or (shots == 2 and stopped == 2) or (shots == 3 and ended) then
|
|
shots = shots + 1
|
|
singeScreenshot()
|
|
end
|
|
if (ended and t > 1) or (t > GIVE_UP) then
|
|
debugPrint(string.format("RAIL RESULT score=%d health=%d bites=%d stops=%d kills=%d hits=%d heads=%d ended=%s after=%.1fs",
|
|
AUTHOR_VARS.score, AUTHOR_VARS.health, AUTHOR_VARS.bites, stopped, kills, hits, heads, tostring(ended), t))
|
|
if stopped < 2 then debugPrint("RAIL FAIL the rail did not reach both stops") end
|
|
if kills < 7 then debugPrint("RAIL FAIL not every zombie was killed") end
|
|
if heads == 0 then debugPrint("RAIL FAIL no shot was reported on the head") end
|
|
if not ended then debugPrint("RAIL FAIL the rail never ended") end
|
|
singeQuit()
|
|
end
|
|
|
|
return r
|
|
end
|