Merge pull request #5469 from Mailaender/fort-lonestar-lua

Ported Fort Lonestar to Lua
This commit is contained in:
Paul Chote
2014-06-14 17:47:06 +12:00
9 changed files with 1540 additions and 413 deletions

View File

@@ -37,6 +37,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Common Lua scripts", "Commo
mods\common\lua\supportpowers.lua = mods\common\lua\supportpowers.lua mods\common\lua\supportpowers.lua = mods\common\lua\supportpowers.lua
mods\common\lua\team.lua = mods\common\lua\team.lua mods\common\lua\team.lua = mods\common\lua\team.lua
mods\common\lua\utils.lua = mods\common\lua\utils.lua mods\common\lua\utils.lua = mods\common\lua\utils.lua
mods\common\lua\facing.lua = mods\common\lua\facing.lua
mods\common\lua\production.lua = mods\common\lua\production.lua
EndProjectSection EndProjectSection
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tiberian Dawn Lua scripts", "Tiberian Dawn Lua scripts", "{62FCD0D0-6D24-435D-9DD8-3CCADCF7ECAB}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tiberian Dawn Lua scripts", "Tiberian Dawn Lua scripts", "{62FCD0D0-6D24-435D-9DD8-3CCADCF7ECAB}"
@@ -48,6 +50,24 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tiberian Dawn Lua scripts",
mods\cnc\maps\nod03a\nod03a.lua = mods\cnc\maps\nod03a\nod03a.lua mods\cnc\maps\nod03a\nod03a.lua = mods\cnc\maps\nod03a\nod03a.lua
mods\cnc\maps\nod03b\nod03b.lua = mods\cnc\maps\nod03b\nod03b.lua mods\cnc\maps\nod03b\nod03b.lua = mods\cnc\maps\nod03b\nod03b.lua
mods\cnc\maps\shellmap\shellmap.lua = mods\cnc\maps\shellmap\shellmap.lua mods\cnc\maps\shellmap\shellmap.lua = mods\cnc\maps\shellmap\shellmap.lua
mods\cnc\maps\gdi04a\gdi04a.lua = mods\cnc\maps\gdi04a\gdi04a.lua
mods\cnc\maps\gdi04b\gdi04b.lua = mods\cnc\maps\gdi04b\gdi04b.lua
mods\cnc\maps\gdi04c\gdi04c.lua = mods\cnc\maps\gdi04c\gdi04c.lua
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Red Alert Lua scripts", "Red Alert Lua scripts", "{B35D533F-BEB6-4674-A466-324EEFD97259}"
ProjectSection(SolutionItems) = preProject
mods\ra\maps\allies-01-classic\allies01.lua = mods\ra\maps\allies-01-classic\allies01.lua
mods\ra\maps\allies-02-classic\allies02.lua = mods\ra\maps\allies-02-classic\allies02.lua
mods\ra\maps\desert-shellmap\desert-shellmap.lua = mods\ra\maps\desert-shellmap\desert-shellmap.lua
mods\ra\maps\fort-lonestar\fort-lonestar.lua = mods\ra\maps\fort-lonestar\fort-lonestar.lua
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "System Lua scripts", "System Lua scripts", "{A4D6AEA4-8009-4256-903B-8D227E50452B}"
ProjectSection(SolutionItems) = preProject
lua\sandbox.lua = lua\sandbox.lua
lua\scriptwrapper.lua = lua\scriptwrapper.lua
lua\stacktraceplus.lua = lua\stacktraceplus.lua
EndProjectSection EndProjectSection
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenRA.CrashDialog", "OpenRA.CrashDialog\OpenRA.CrashDialog.csproj", "{47F1B0EE-EB35-47F2-93E4-273C70909157}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenRA.CrashDialog", "OpenRA.CrashDialog\OpenRA.CrashDialog.csproj", "{47F1B0EE-EB35-47F2-93E4-273C70909157}"

View File

@@ -1,411 +1,411 @@
-- tables -- tables
local _G = _G local _G = _G
local string, io, debug, coroutine = string, io, debug, coroutine local string, io, debug, coroutine = string, io, debug, coroutine
-- functions -- functions
local tostring, print, require = tostring, print, require local tostring, print, require = tostring, print, require
local next, assert = next, assert local next, assert = next, assert
local pcall, type, pairs, ipairs = pcall, type, pairs, ipairs local pcall, type, pairs, ipairs = pcall, type, pairs, ipairs
local error = error local error = error
assert(debug, "debug table must be available at this point") assert(debug, "debug table must be available at this point")
local io_open = io.open local io_open = io.open
local string_gmatch = string.gmatch local string_gmatch = string.gmatch
local string_sub = string.sub local string_sub = string.sub
local table_concat = table.concat local table_concat = table.concat
local _M = { local _M = {
max_tb_output_len = 70 -- controls the maximum length of the 'stringified' table before cutting with ' (more...)' max_tb_output_len = 70 -- controls the maximum length of the 'stringified' table before cutting with ' (more...)'
} }
-- this tables should be weak so the elements in them won't become uncollectable -- this tables should be weak so the elements in them won't become uncollectable
local m_known_tables = { [_G] = "_G (global table)" } local m_known_tables = { [_G] = "_G (global table)" }
local function add_known_module(name, desc) local function add_known_module(name, desc)
local ok, mod = pcall(require, name) local ok, mod = pcall(require, name)
if ok then if ok then
m_known_tables[mod] = desc m_known_tables[mod] = desc
end end
end end
add_known_module("string", "string module") add_known_module("string", "string module")
add_known_module("io", "io module") add_known_module("io", "io module")
add_known_module("os", "os module") add_known_module("os", "os module")
add_known_module("table", "table module") add_known_module("table", "table module")
add_known_module("math", "math module") add_known_module("math", "math module")
add_known_module("package", "package module") add_known_module("package", "package module")
add_known_module("debug", "debug module") add_known_module("debug", "debug module")
add_known_module("coroutine", "coroutine module") add_known_module("coroutine", "coroutine module")
-- lua5.2 -- lua5.2
add_known_module("bit32", "bit32 module") add_known_module("bit32", "bit32 module")
-- luajit -- luajit
add_known_module("bit", "bit module") add_known_module("bit", "bit module")
add_known_module("jit", "jit module") add_known_module("jit", "jit module")
local m_user_known_tables = {} local m_user_known_tables = {}
local m_known_functions = {} local m_known_functions = {}
for _, name in ipairs{ for _, name in ipairs{
-- Lua 5.2, 5.1 -- Lua 5.2, 5.1
"assert", "assert",
"collectgarbage", "collectgarbage",
"dofile", "dofile",
"error", "error",
"getmetatable", "getmetatable",
"ipairs", "ipairs",
"load", "load",
"loadfile", "loadfile",
"next", "next",
"pairs", "pairs",
"pcall", "pcall",
"print", "print",
"rawequal", "rawequal",
"rawget", "rawget",
"rawlen", "rawlen",
"rawset", "rawset",
"require", "require",
"select", "select",
"setmetatable", "setmetatable",
"tonumber", "tonumber",
"tostring", "tostring",
"type", "type",
"xpcall", "xpcall",
-- Lua 5.1 -- Lua 5.1
"gcinfo", "gcinfo",
"getfenv", "getfenv",
"loadstring", "loadstring",
"module", "module",
"newproxy", "newproxy",
"setfenv", "setfenv",
"unpack", "unpack",
-- TODO: add table.* etc functions -- TODO: add table.* etc functions
} do } do
if _G[name] then if _G[name] then
m_known_functions[_G[name]] = name m_known_functions[_G[name]] = name
end end
end end
local m_user_known_functions = {} local m_user_known_functions = {}
local function safe_tostring (value) local function safe_tostring (value)
local ok, err = pcall(tostring, value) local ok, err = pcall(tostring, value)
if ok then return err else return ("<failed to get printable value>: '%s'"):format(err) end if ok then return err else return ("<failed to get printable value>: '%s'"):format(err) end
end end
-- Private: -- Private:
-- Parses a line, looking for possible function definitions (in a very na<6E>ve way) -- Parses a line, looking for possible function definitions (in a very na<6E>ve way)
-- Returns '(anonymous)' if no function name was found in the line -- Returns '(anonymous)' if no function name was found in the line
local function ParseLine(line) local function ParseLine(line)
assert(type(line) == "string") assert(type(line) == "string")
--print(line) --print(line)
local match = line:match("^%s*function%s+(%w+)") local match = line:match("^%s*function%s+(%w+)")
if match then if match then
--print("+++++++++++++function", match) --print("+++++++++++++function", match)
return match return match
end end
match = line:match("^%s*local%s+function%s+(%w+)") match = line:match("^%s*local%s+function%s+(%w+)")
if match then if match then
--print("++++++++++++local", match) --print("++++++++++++local", match)
return match return match
end end
match = line:match("^%s*local%s+(%w+)%s+=%s+function") match = line:match("^%s*local%s+(%w+)%s+=%s+function")
if match then if match then
--print("++++++++++++local func", match) --print("++++++++++++local func", match)
return match return match
end end
match = line:match("%s*function%s*%(") -- this is an anonymous function match = line:match("%s*function%s*%(") -- this is an anonymous function
if match then if match then
--print("+++++++++++++function2", match) --print("+++++++++++++function2", match)
return "(anonymous)" return "(anonymous)"
end end
return "(anonymous)" return "(anonymous)"
end end
-- Private: -- Private:
-- Tries to guess a function's name when the debug info structure does not have it. -- Tries to guess a function's name when the debug info structure does not have it.
-- It parses either the file or the string where the function is defined. -- It parses either the file or the string where the function is defined.
-- Returns '?' if the line where the function is defined is not found -- Returns '?' if the line where the function is defined is not found
local function GuessFunctionName(info) local function GuessFunctionName(info)
--print("guessing function name") --print("guessing function name")
if type(info.source) == "string" and info.source:sub(1,1) == "@" then if type(info.source) == "string" and info.source:sub(1,1) == "@" then
local file, err = io_open(info.source:sub(2), "r") local file, err = io_open(info.source:sub(2), "r")
if not file then if not file then
print("file not found: "..tostring(err)) -- whoops! print("file not found: "..tostring(err)) -- whoops!
return "?" return "?"
end end
local line local line
for i = 1, info.linedefined do for i = 1, info.linedefined do
line = file:read("*l") line = file:read("*l")
end end
if not line then if not line then
print("line not found") -- whoops! print("line not found") -- whoops!
return "?" return "?"
end end
return ParseLine(line) return ParseLine(line)
else else
local line local line
local lineNumber = 0 local lineNumber = 0
for l in string_gmatch(info.source, "([^\n]+)\n-") do for l in string_gmatch(info.source, "([^\n]+)\n-") do
lineNumber = lineNumber + 1 lineNumber = lineNumber + 1
if lineNumber == info.linedefined then if lineNumber == info.linedefined then
line = l line = l
break break
end end
end end
if not line then if not line then
print("line not found") -- whoops! print("line not found") -- whoops!
return "?" return "?"
end end
return ParseLine(line) return ParseLine(line)
end end
end end
--- ---
-- Dumper instances are used to analyze stacks and collect its information. -- Dumper instances are used to analyze stacks and collect its information.
-- --
local Dumper = {} local Dumper = {}
Dumper.new = function(thread) Dumper.new = function(thread)
local t = { lines = {} } local t = { lines = {} }
for k,v in pairs(Dumper) do t[k] = v end for k,v in pairs(Dumper) do t[k] = v end
t.dumping_same_thread = (thread == coroutine.running()) t.dumping_same_thread = (thread == coroutine.running())
-- if a thread was supplied, bind it to debug.info and debug.get -- if a thread was supplied, bind it to debug.info and debug.get
-- we also need to skip this additional level we are introducing in the callstack (only if we are running -- we also need to skip this additional level we are introducing in the callstack (only if we are running
-- in the same thread we're inspecting) -- in the same thread we're inspecting)
if type(thread) == "thread" then if type(thread) == "thread" then
t.getinfo = function(level, what) t.getinfo = function(level, what)
if t.dumping_same_thread and type(level) == "number" then if t.dumping_same_thread and type(level) == "number" then
level = level + 1 level = level + 1
end end
return debug.getinfo(thread, level, what) return debug.getinfo(thread, level, what)
end end
t.getlocal = function(level, loc) t.getlocal = function(level, loc)
if t.dumping_same_thread then if t.dumping_same_thread then
level = level + 1 level = level + 1
end end
return debug.getlocal(thread, level, loc) return debug.getlocal(thread, level, loc)
end end
else else
t.getinfo = debug.getinfo t.getinfo = debug.getinfo
t.getlocal = debug.getlocal t.getlocal = debug.getlocal
end end
return t return t
end end
-- helpers for collecting strings to be used when assembling the final trace -- helpers for collecting strings to be used when assembling the final trace
function Dumper:add (text) function Dumper:add (text)
self.lines[#self.lines + 1] = text self.lines[#self.lines + 1] = text
end end
function Dumper:add_f (fmt, ...) function Dumper:add_f (fmt, ...)
self:add(fmt:format(...)) self:add(fmt:format(...))
end end
function Dumper:concat_lines () function Dumper:concat_lines ()
return table_concat(self.lines) return table_concat(self.lines)
end end
--- ---
-- Private: -- Private:
-- Iterates over the local variables of a given function. -- Iterates over the local variables of a given function.
-- --
-- @param level The stack level where the function is. -- @param level The stack level where the function is.
-- --
function Dumper:DumpLocals (level) function Dumper:DumpLocals (level)
local prefix = "\t " local prefix = "\t "
local i = 1 local i = 1
if self.dumping_same_thread then if self.dumping_same_thread then
level = level + 1 level = level + 1
end end
local name, value = self.getlocal(level, i) local name, value = self.getlocal(level, i)
if not name then if not name then
return return
end end
self:add("\tLocal variables:\r\n") self:add("\tLocal variables:\r\n")
while name do while name do
if type(value) == "number" then if type(value) == "number" then
self:add_f("%s%s = number: %g\r\n", prefix, name, value) self:add_f("%s%s = number: %g\r\n", prefix, name, value)
elseif type(value) == "boolean" then elseif type(value) == "boolean" then
self:add_f("%s%s = boolean: %s\r\n", prefix, name, tostring(value)) self:add_f("%s%s = boolean: %s\r\n", prefix, name, tostring(value))
elseif type(value) == "string" then elseif type(value) == "string" then
self:add_f("%s%s = string: %q\r\n", prefix, name, value) self:add_f("%s%s = string: %q\r\n", prefix, name, value)
elseif type(value) == "userdata" then elseif type(value) == "userdata" then
self:add_f("%s%s = %s\r\n", prefix, name, safe_tostring(value)) self:add_f("%s%s = %s\r\n", prefix, name, safe_tostring(value))
elseif type(value) == "nil" then elseif type(value) == "nil" then
self:add_f("%s%s = nil\r\n", prefix, name) self:add_f("%s%s = nil\r\n", prefix, name)
elseif type(value) == "table" then elseif type(value) == "table" then
if m_known_tables[value] then if m_known_tables[value] then
self:add_f("%s%s = %s\r\n", prefix, name, m_known_tables[value]) self:add_f("%s%s = %s\r\n", prefix, name, m_known_tables[value])
elseif m_user_known_tables[value] then elseif m_user_known_tables[value] then
self:add_f("%s%s = %s\r\n", prefix, name, m_user_known_tables[value]) self:add_f("%s%s = %s\r\n", prefix, name, m_user_known_tables[value])
else else
local txt = "{" local txt = "{"
for k,v in pairs(value) do for k,v in pairs(value) do
txt = txt..safe_tostring(k)..":"..safe_tostring(v) txt = txt..safe_tostring(k)..":"..safe_tostring(v)
if #txt > _M.max_tb_output_len then if #txt > _M.max_tb_output_len then
txt = txt.." (more...)" txt = txt.." (more...)"
break break
end end
if next(value, k) then txt = txt..", " end if next(value, k) then txt = txt..", " end
end end
self:add_f("%s%s = %s %s\r\n", prefix, name, safe_tostring(value), txt.."}") self:add_f("%s%s = %s %s\r\n", prefix, name, safe_tostring(value), txt.."}")
end end
elseif type(value) == "function" then elseif type(value) == "function" then
local info = self.getinfo(value, "nS") local info = self.getinfo(value, "nS")
local fun_name = info.name or m_known_functions[value] or m_user_known_functions[value] local fun_name = info.name or m_known_functions[value] or m_user_known_functions[value]
if info.what == "C" then if info.what == "C" then
self:add_f("%s%s = C %s\r\n", prefix, name, (fun_name and ("function: " .. fun_name) or tostring(value))) self:add_f("%s%s = C %s\r\n", prefix, name, (fun_name and ("function: " .. fun_name) or tostring(value)))
else else
local source = info.short_src local source = info.short_src
if source:sub(2,7) == "string" then if source:sub(2,7) == "string" then
source = source:sub(9) source = source:sub(9)
end end
--for k,v in pairs(info) do print(k,v) end --for k,v in pairs(info) do print(k,v) end
fun_name = fun_name or GuessFunctionName(info) fun_name = fun_name or GuessFunctionName(info)
self:add_f("%s%s = Lua function '%s' (defined at line %d of chunk %s)\r\n", prefix, name, fun_name, info.linedefined, source) self:add_f("%s%s = Lua function '%s' (defined at line %d of chunk %s)\r\n", prefix, name, fun_name, info.linedefined, source)
end end
elseif type(value) == "thread" then elseif type(value) == "thread" then
self:add_f("%sthread %q = %s\r\n", prefix, name, tostring(value)) self:add_f("%sthread %q = %s\r\n", prefix, name, tostring(value))
end end
i = i + 1 i = i + 1
name, value = self.getlocal(level, i) name, value = self.getlocal(level, i)
end end
end end
--- ---
-- Public: -- Public:
-- Collects a detailed stack trace, dumping locals, resolving function names when they're not available, etc. -- Collects a detailed stack trace, dumping locals, resolving function names when they're not available, etc.
-- This function is suitable to be used as an error handler with pcall or xpcall -- This function is suitable to be used as an error handler with pcall or xpcall
-- --
-- @param thread An optional thread whose stack is to be inspected (defaul is the current thread) -- @param thread An optional thread whose stack is to be inspected (defaul is the current thread)
-- @param message An optional error string or object. -- @param message An optional error string or object.
-- @param level An optional number telling at which level to start the traceback (default is 1) -- @param level An optional number telling at which level to start the traceback (default is 1)
-- --
-- Returns a string with the stack trace and a string with the original error. -- Returns a string with the stack trace and a string with the original error.
-- --
function _M.stacktrace(thread, message, level) function _M.stacktrace(thread, message, level)
if type(thread) ~= "thread" then if type(thread) ~= "thread" then
-- shift parameters left -- shift parameters left
thread, message, level = nil, thread, message thread, message, level = nil, thread, message
end end
thread = thread or coroutine.running() thread = thread or coroutine.running()
level = level or 1 level = level or 1
local dumper = Dumper.new(thread) local dumper = Dumper.new(thread)
local original_error local original_error
if type(message) == "table" then if type(message) == "table" then
dumper:add("an error object {\r\n") dumper:add("an error object {\r\n")
local first = true local first = true
for k,v in pairs(message) do for k,v in pairs(message) do
if first then if first then
dumper:add(" ") dumper:add(" ")
first = false first = false
else else
dumper:add(",\r\n ") dumper:add(",\r\n ")
end end
dumper:add(safe_tostring(k)) dumper:add(safe_tostring(k))
dumper:add(": ") dumper:add(": ")
dumper:add(safe_tostring(v)) dumper:add(safe_tostring(v))
end end
dumper:add("\r\n}") dumper:add("\r\n}")
original_error = dumper:concat_lines() original_error = dumper:concat_lines()
elseif type(message) == "string" then elseif type(message) == "string" then
dumper:add(message) dumper:add(message)
original_error = message original_error = message
end end
dumper:add("\r\n") dumper:add("\r\n")
dumper:add[[ dumper:add[[
Stack Traceback Stack Traceback
=============== ===============
]] ]]
--print(error_message) --print(error_message)
local level_to_show = level local level_to_show = level
if dumper.dumping_same_thread then level = level + 1 end if dumper.dumping_same_thread then level = level + 1 end
local info = dumper.getinfo(level, "nSlf") local info = dumper.getinfo(level, "nSlf")
while info do while info do
if info.what == "main" then if info.what == "main" then
if string_sub(info.source, 1, 1) == "@" then if string_sub(info.source, 1, 1) == "@" then
dumper:add_f("(%d) main chunk of file '%s' at line %d\r\n", level_to_show, string_sub(info.source, 2), info.currentline) dumper:add_f("(%d) main chunk of file '%s' at line %d\r\n", level_to_show, string_sub(info.source, 2), info.currentline)
else else
dumper:add_f("(%d) main chunk of %s at line %d\r\n", level_to_show, info.short_src, info.currentline) dumper:add_f("(%d) main chunk of %s at line %d\r\n", level_to_show, info.short_src, info.currentline)
end end
elseif info.what == "C" then elseif info.what == "C" then
--print(info.namewhat, info.name) --print(info.namewhat, info.name)
--for k,v in pairs(info) do print(k,v, type(v)) end --for k,v in pairs(info) do print(k,v, type(v)) end
local function_name = m_user_known_functions[info.func] or m_known_functions[info.func] or info.name or tostring(info.func) local function_name = m_user_known_functions[info.func] or m_known_functions[info.func] or info.name or tostring(info.func)
dumper:add_f("(%d) %s C function '%s'\r\n", level_to_show, info.namewhat, function_name) dumper:add_f("(%d) %s C function '%s'\r\n", level_to_show, info.namewhat, function_name)
--dumper:add_f("%s%s = C %s\r\n", prefix, name, (m_known_functions[value] and ("function: " .. m_known_functions[value]) or tostring(value))) --dumper:add_f("%s%s = C %s\r\n", prefix, name, (m_known_functions[value] and ("function: " .. m_known_functions[value]) or tostring(value)))
elseif info.what == "tail" then elseif info.what == "tail" then
--print("tail") --print("tail")
--for k,v in pairs(info) do print(k,v, type(v)) end--print(info.namewhat, info.name) --for k,v in pairs(info) do print(k,v, type(v)) end--print(info.namewhat, info.name)
dumper:add_f("(%d) tail call\r\n", level_to_show) dumper:add_f("(%d) tail call\r\n", level_to_show)
dumper:DumpLocals(level) dumper:DumpLocals(level)
elseif info.what == "Lua" then elseif info.what == "Lua" then
local source = info.short_src local source = info.short_src
local function_name = m_user_known_functions[info.func] or m_known_functions[info.func] or info.name local function_name = m_user_known_functions[info.func] or m_known_functions[info.func] or info.name
if source:sub(2, 7) == "string" then if source:sub(2, 7) == "string" then
source = source:sub(9) source = source:sub(9)
end end
local was_guessed = false local was_guessed = false
if not function_name or function_name == "?" then if not function_name or function_name == "?" then
--for k,v in pairs(info) do print(k,v, type(v)) end --for k,v in pairs(info) do print(k,v, type(v)) end
function_name = GuessFunctionName(info) function_name = GuessFunctionName(info)
was_guessed = true was_guessed = true
end end
-- test if we have a file name -- test if we have a file name
local function_type = (info.namewhat == "") and "function" or info.namewhat local function_type = (info.namewhat == "") and "function" or info.namewhat
if info.source and info.source:sub(1, 1) == "@" then if info.source and info.source:sub(1, 1) == "@" then
dumper:add_f("(%d) Lua %s '%s' at file '%s:%d'%s\r\n", level_to_show, function_type, function_name, info.source:sub(2), info.currentline, was_guessed and " (best guess)" or "") dumper:add_f("(%d) Lua %s '%s' at file '%s:%d'%s\r\n", level_to_show, function_type, function_name, info.source:sub(2), info.currentline, was_guessed and " (best guess)" or "")
elseif info.source and info.source:sub(1,1) == '#' then elseif info.source and info.source:sub(1,1) == '#' then
dumper:add_f("(%d) Lua %s '%s' at template '%s:%d'%s\r\n", level_to_show, function_type, function_name, info.source:sub(2), info.currentline, was_guessed and " (best guess)" or "") dumper:add_f("(%d) Lua %s '%s' at template '%s:%d'%s\r\n", level_to_show, function_type, function_name, info.source:sub(2), info.currentline, was_guessed and " (best guess)" or "")
else else
dumper:add_f("(%d) Lua %s '%s' at line %d of chunk '%s'\r\n", level_to_show, function_type, function_name, info.currentline, source) dumper:add_f("(%d) Lua %s '%s' at line %d of chunk '%s'\r\n", level_to_show, function_type, function_name, info.currentline, source)
end end
dumper:DumpLocals(level) dumper:DumpLocals(level)
else else
dumper:add_f("(%d) unknown frame %s\r\n", level_to_show, info.what) dumper:add_f("(%d) unknown frame %s\r\n", level_to_show, info.what)
end end
level = level + 1 level = level + 1
level_to_show = level_to_show + 1 level_to_show = level_to_show + 1
info = dumper.getinfo(level, "nSlf") info = dumper.getinfo(level, "nSlf")
end end
return dumper:concat_lines(), original_error return dumper:concat_lines(), original_error
end end
-- --
-- Adds a table to the list of known tables -- Adds a table to the list of known tables
function _M.add_known_table(tab, description) function _M.add_known_table(tab, description)
if m_known_tables[tab] then if m_known_tables[tab] then
error("Cannot override an already known table") error("Cannot override an already known table")
end end
m_user_known_tables[tab] = description m_user_known_tables[tab] = description
end end
-- --
-- Adds a function to the list of known functions -- Adds a function to the list of known functions
function _M.add_known_function(fun, description) function _M.add_known_function(fun, description)
if m_known_functions[fun] then if m_known_functions[fun] then
error("Cannot override an already known function") error("Cannot override an already known function")
end end
m_user_known_functions[fun] = description m_user_known_functions[fun] = description
end end
return _M return _M

View File

@@ -579,7 +579,7 @@ Rules:
-SpawnMPUnits: -SpawnMPUnits:
-MPStartLocations: -MPStartLocations:
LuaScriptInterface: LuaScriptInterface:
LuaScripts: mission.lua LuaScripts: allies01.lua
TRAN.Extraction: TRAN.Extraction:
Inherits: TRAN Inherits: TRAN
RenderUnit: RenderUnit:

View File

@@ -874,7 +874,7 @@ Rules:
-SpawnMPUnits: -SpawnMPUnits:
-MPStartLocations: -MPStartLocations:
LuaScriptInterface: LuaScriptInterface:
LuaScripts: mission.lua LuaScripts: allies02.lua
^Infantry: ^Infantry:
MustBeDestroyed: MustBeDestroyed:
^Tank: ^Tank:

View File

@@ -0,0 +1,148 @@
Patrol = { "e1", "e2", "e1" }
Infantry = { "e4", "e1", "e1", "e2", "e1", "e2" }
Vehicles = { "arty", "ftrk", "ftrk", "apc", "apc" }
Tank = { "3tnk" }
LongRange = { "v2rl" }
Boss = { "4tnk" }
SovietEntryPoints = { Entry1, Entry2, Entry3, Entry4, Entry5, Entry6, Entry7, Entry8 }
PatrolWaypoints = { Patrol1, Patrol2, Patrol3, Patrol4 }
ParadropWaypoints = { Paradrop1, Paradrop2, Paradrop3, Paradrop4 }
OilDerricks = { OilDerrick1, OilDerrick2, OilDerrick3, OilDerrick4 }
SpawnPoints = { Spawn1, Spawn2, Spawn3, Spawn4 }
Snipers = { Sniper1, Sniper2, Sniper3, Sniper4, Sniper5, Sniper6, Sniper7, Sniper8, Sniper9, Sniper10, Sniper11, Sniper12 }
Wave = 0
Waves =
{
{ 500, SovietEntryPoints, Infantry, SpawnPoints },
{ 750, PatrolWaypoints, Patrol, ParadropWaypoints },
{ 750, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Vehicles, SpawnPoints },
{ 1500, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1500, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Vehicles, SpawnPoints },
{ 1500, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Tank, SpawnPoints },
{ 1, SovietEntryPoints, Vehicles, SpawnPoints },
{ 1500, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Tank, SpawnPoints },
{ 1, SovietEntryPoints, Tank, SpawnPoints },
{ 1500, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, LongRange, SpawnPoints },
{ 1500, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, LongRange, SpawnPoints },
{ 1, SovietEntryPoints, Tank, SpawnPoints },
{ 1, SovietEntryPoints, LongRange, SpawnPoints },
{ 1500, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, LongRange, SpawnPoints },
{ 1, SovietEntryPoints, LongRange, SpawnPoints },
{ 1, SovietEntryPoints, Tank, SpawnPoints },
{ 1, SovietEntryPoints, Tank, SpawnPoints },
{ 1, SovietEntryPoints, Vehicles, SpawnPoints },
{ 1500, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Infantry, SpawnPoints },
{ 1, SovietEntryPoints, Boss, SpawnPoints }
}
SendUnits = function(entryCell, unitTypes, interval, targetCell)
local i = 0
Utils.Do(unitTypes, function(type)
local a = Actor.Create(type, false, { Owner = soviets, Location = entryCell })
Trigger.OnIdle(a, function(a) a.AttackMove(targetCell) end)
Trigger.AfterDelay(i * interval, function() a.IsInWorld = true end)
i = i + 1
end)
if (Wave < #Waves) then
SendWave()
else
Trigger.AfterDelay(3000, SovietsRetreating)
end
end
SendWave = function()
Wave = Wave + 1
local wave = Waves[Wave]
local delay = wave[1]
local entry = Utils.Random(wave[2]).Location
local units = wave[3]
local target = Utils.Random(wave[4]).Location
print(string.format("Sending wave %i in %i.", Wave, delay))
Trigger.AfterDelay(delay, function() SendUnits(entry, units, 40, target) end)
end
SovietsRetreating = function()
Utils.Do(Snipers, function(a)
if not a.IsDead and a.Owner == soviets then
a.Destroy()
end
end)
end
WorldLoaded = function()
soviets = Player.GetPlayer("Soviets")
Utils.Do(Snipers, function(a)
if a.Owner == soviets then
a.Invulnerable = true
end
end)
SendWave()
end

Binary file not shown.

View File

@@ -0,0 +1,959 @@
Selectable: True
MapFormat: 6
RequiresMod: ra
Title: Fort Lonestar
Description: Survive multiple waves of attacking enemies.
Author: Nuke'm Bro.
Tileset: TEMPERAT
MapSize: 96,96
Bounds: 8,8,48,48
UseAsShellmap: False
Type: Minigame
Options:
Fog: True
Shroud: True
AllyBuildRadius: False
FragileAlliances: False
StartingCash: 50
ConfigurableStartingUnits: False
Players:
PlayerReference@Neutral:
Name: Neutral
OwnsWorld: True
NonCombatant: True
Race: allies
PlayerReference@Multi0:
Name: Multi0
Playable: True
AllowBots: False
LockTeam: True
Allies: Multi1,Multi2,Multi3
Enemies: Soviets
PlayerReference@Multi1:
Name: Multi1
Playable: True
AllowBots: False
LockTeam: True
Allies: Multi0,Multi2,Multi3
Enemies: Soviets
PlayerReference@Multi2:
Name: Multi2
Playable: True
AllowBots: False
LockTeam: True
Allies: Multi0,Multi1,Multi3
Enemies: Soviets
PlayerReference@Multi3:
Name: Multi3
Playable: True
AllowBots: False
LockTeam: True
Allies: Multi0,Multi1,Multi2
Enemies: Soviets
PlayerReference@Soviets:
Name: Soviets
Race: soviet
ColorRamp: 0,255,128
Enemies: Multi0,Multi1,Multi2,Multi3
Actors:
Actor76: t11
Location: 47,27
Owner: Neutral
Actor47: t12
Location: 55,24
Owner: Neutral
Actor25: tc03
Location: 54,49
Owner: Neutral
Actor14: tc04
Location: 24,7
Owner: Neutral
Actor10: tc04
Location: 38,53
Owner: Neutral
Actor0: t14
Location: 32,16
Owner: Neutral
Actor75: tc04
Location: 45,25
Owner: Neutral
Actor72: tc01
Location: 49,16
Owner: Neutral
Actor58: t10
Location: 22,54
Owner: Neutral
Actor26: tc01
Location: 54,41
Owner: Neutral
Actor37: tc01
Location: 54,21
Owner: Neutral
Actor60: tc05
Location: 7,16
Owner: Neutral
Actor69: t17
Location: 23,8
Owner: Neutral
Actor4: tc04
Location: 29,45
Owner: Neutral
Actor6: t17
Location: 33,43
Owner: Neutral
Actor16: tc04
Location: 53,16
Owner: Neutral
Actor21: tc03
Location: 8,14
Owner: Neutral
Actor8: t14
Location: 49,37
Owner: Neutral
Actor29: tc01
Location: 8,42
Owner: Neutral
Actor49: t15
Location: 54,47
Owner: Neutral
Actor62: tc05
Location: 6,43
Owner: Neutral
Actor73: tc05
Location: 16,34
Owner: Neutral
Actor30: barr
Location: 36,26
Owner: Multi0
Actor84: brik
Location: 35,25
Owner: Neutral
Actor32: tc01
Location: 8,24
Owner: Neutral
Actor59: tc05
Location: 7,39
Owner: Neutral
Actor5: tc01
Location: 44,44
Owner: Neutral
Actor67: brik
Location: 29,25
Owner: Neutral
Actor41: brik
Location: 25,25
Owner: Neutral
Actor56: brik
Location: 26,25
Owner: Neutral
Actor85: brik
Location: 39,26
Owner: Neutral
Actor81: brik
Location: 38,25
Owner: Neutral
Actor65: brik
Location: 27,25
Owner: Neutral
Actor66: brik
Location: 28,25
Owner: Neutral
Actor51: t08
Location: 55,46
Owner: Neutral
Actor57: t12
Location: 19,54
Owner: Neutral
Actor54: t11
Location: 26,54
Owner: Neutral
Actor33: tc01
Location: 21,7
Owner: Neutral
Actor27: tc01
Location: 42,54
Owner: Neutral
Actor23: tc03
Location: 16,54
Owner: Neutral
Actor15: tc04
Location: 38,8
Owner: Neutral
Actor19: tc03
Location: 18,7
Owner: Neutral
Actor17: tc03
Location: 54,26
Owner: Neutral
Actor83: brik
Location: 36,25
Owner: Neutral
Actor197: brik
Location: 39,37
Owner: Neutral
Actor11: tc04
Location: 20,53
Owner: Neutral
Actor9: tc04
Location: 53,37
Owner: Neutral
Actor7: tc02
Location: 44,36
Owner: Neutral
Actor3: t15
Location: 19,25
Owner: Neutral
Actor1: t05
Location: 29,16
Owner: Neutral
Actor82: brik
Location: 37,25
Owner: Neutral
Actor86: brik
Location: 39,27
Owner: Neutral
Actor80: brik
Location: 39,25
Owner: Neutral
Actor71: tc02
Location: 15,40
Owner: Neutral
Actor64: t06
Location: 18,16
Owner: Neutral
Actor63: t14
Location: 8,22
Owner: Neutral
Actor53: t08
Location: 41,55
Owner: Neutral
Actor61: tc05
Location: 54,39
Owner: Neutral
Actor48: t01
Location: 54,23
Owner: Neutral
Actor50: t17
Location: 54,44
Owner: Neutral
Actor36: tc01
Location: 42,8
Owner: Neutral
Actor52: t12
Location: 44,53
Owner: Neutral
Actor87: brik
Location: 39,28
Owner: Neutral
Actor91: brik
Location: 37,39
Owner: Neutral
Actor196: brik
Location: 39,38
Owner: Neutral
Actor195: brik
Location: 39,39
Owner: Neutral
Actor45: brik
Location: 25,28
Owner: Neutral
Actor92: brik
Location: 39,29
Owner: Neutral
Actor194: brik
Location: 38,39
Owner: Neutral
Actor55: brik
Location: 25,39
Owner: Neutral
Actor200: brik
Location: 28,39
Owner: Neutral
Actor233: brik
Location: 29,39
Owner: Neutral
Actor240: brik
Location: 39,35
Owner: Neutral
Actor199: brik
Location: 27,39
Owner: Neutral
Spawn1: mpspawn
Location: 36,28
Owner: Neutral
Actor28: tc01
Location: 24,54
Owner: Neutral
Actor22: tc03
Location: 7,46
Owner: Neutral
Actor24: tc03
Location: 45,54
Owner: Neutral
Actor18: tc03
Location: 45,8
Owner: Neutral
Actor12: tc04
Location: 7,37
Owner: Neutral
Actor13: tc04
Location: 8,19
Owner: Neutral
Actor2: tc04
Location: 14,23
Owner: Neutral
Actor74: t06
Location: 19,36
Owner: Neutral
Actor46: t11
Location: 54,19
Owner: Neutral
Actor42: t16
Location: 53,19
Owner: Neutral
Actor68: tc05
Location: 35,7
Owner: Neutral
Actor239: brik
Location: 39,36
Owner: Neutral
Actor89: brik
Location: 35,39
Owner: Neutral
Actor90: brik
Location: 36,39
Owner: Neutral
OilDerrick1: oilb
Location: 32,30
Owner: Multi0
Actor237: brik
Location: 25,35
Owner: Neutral
Actor236: brik
Location: 25,36
Owner: Neutral
Actor235: brik
Location: 25,37
Owner: Neutral
Actor234: brik
Location: 25,38
Owner: Neutral
Actor44: brik
Location: 25,27
Owner: Neutral
Actor43: brik
Location: 25,26
Owner: Neutral
Actor198: brik
Location: 26,39
Owner: Neutral
Actor88: brik
Location: 25,29
Owner: Neutral
Entry1: waypoint
Location: 8,8
Owner: Neutral
Entry2: waypoint
Location: 31,8
Owner: Neutral
Entry3: waypoint
Location: 55,8
Owner: Neutral
Entry4: waypoint
Location: 55,32
Owner: Neutral
Entry5: waypoint
Location: 55,55
Owner: Neutral
Entry6: waypoint
Location: 32,55
Owner: Neutral
Entry7: waypoint
Location: 8,55
Owner: Neutral
Entry8: waypoint
Location: 8,32
Owner: Neutral
Paradrop1: waypoint
Location: 32,28
Owner: Neutral
Paradrop2: waypoint
Location: 27,32
Owner: Neutral
Paradrop3: waypoint
Location: 32,36
Owner: Neutral
Paradrop4: waypoint
Location: 36,32
Owner: Neutral
Patrol3: waypoint
Location: 32,46
Owner: Neutral
Patrol4: waypoint
Location: 46,32
Owner: Neutral
Patrol2: waypoint
Location: 17,32
Owner: Neutral
Patrol1: waypoint
Location: 32,18
Owner: Neutral
Sniper1: sniper
Location: 9,26
Owner: Soviets
Sniper2: sniper
Location: 10,21
Owner: Soviets
Sniper3: sniper
Location: 26,9
Owner: Soviets
Sniper4: sniper
Location: 40,10
Owner: Soviets
Sniper5: sniper
Location: 53,21
Owner: Soviets
Sniper6: sniper
Location: 54,25
Owner: Soviets
Sniper7: sniper
Location: 53,40
Owner: Soviets
Sniper8: sniper
Location: 54,43
Owner: Soviets
Sniper9: sniper
Location: 54,46
Owner: Soviets
Sniper10: sniper
Location: 43,53
Owner: Soviets
Sniper11: sniper
Location: 8,36
Owner: Soviets
Sniper12: sniper
Location: 28,55
Owner: Soviets
Actor100: barr
Location: 27,26
Owner: Multi3
Actor99: barr
Location: 27,36
Owner: Multi2
Actor31: barr
Location: 36,36
Owner: Multi1
OilDerrick2: oilb
Location: 32,32
Owner: Multi1
OilDerrick3: oilb
Location: 30,32
Owner: Multi2
OilDerrick4: oilb
Location: 30,30
Owner: Multi3
Spawn2: mpspawn
Location: 27,28
Owner: Neutral
Spawn3: mpspawn
Location: 27,38
Owner: Neutral
Spawn4: mpspawn
Location: 36,38
Owner: Neutral
Smudges:
Rules:
World:
CrateSpawner:
Maximum: 1
SpawnInterval: 100
-SpawnMPUnits:
-MPStartLocations:
LuaScript:
Scripts: fort-lonestar.lua
CRATE:
-LevelUpCrateAction:
-GiveMcvCrateAction:
-RevealMapCrateAction:
-HideMapCrateAction:
-ExplodeCrateAction@nuke:
-ExplodeCrateAction@boom:
-ExplodeCrateAction@fire:
-GiveUnitCrateAction@jeep:
-GiveUnitCrateAction@arty:
-GiveUnitCrateAction@v2rl:
-GiveUnitCrateAction@1tnk:
-GiveUnitCrateAction@2tnk:
-GiveUnitCrateAction@3tnk:
-GiveUnitCrateAction@4tnk:
SupportPowerCrateAction@parabombs:
SelectionShares: 30
HealUnitsCrateAction:
SelectionShares: 30
GiveCashCrateAction:
Amount: 400
UseCashTick: yes
SelectionShares: 30
GiveUnitCrateAction@e7:
Unit: e7
SelectionShares: 10
Player:
PlayerResources:
InitialCash: 50
ClassicProductionQueue@Infantry:
Type: Infantry
BuildSpeed: 1
LowPowerSlowdown: 3
ClassicProductionQueue@Defense:
Type: Defense
BuildSpeed: .4
LowPowerSlowdown: 3
^Infantry:
MustBeDestroyed:
^Vehicle:
MustBeDestroyed:
^Tank:
MustBeDestroyed:
OILB:
Health:
HP: 3000
Armor:
Type: Wood
Bib:
RevealsShroud:
Range: 3c0
CashTrickler:
Period: 250
Amount: 50
BARR:
Buildable:
Owner: allies,soviet
Building:
Power: 0
Health:
HP: 1000
Production:
Produces: Defense,Infantry
-Sellable:
BaseProvider:
Range: 12
FTUR:
Building:
Power: 0
Valued:
Cost: 400
PBOX:
Building:
Power: 0
Buildable:
Prerequisites: barr,oilb
Valued:
Cost: 400
Health:
HP: 200
Armor:
Type: Heavy
HBOX:
Building:
Power: 0
GUN:
Buildable:
Owner: None
SAM:
Buildable:
Owner: None
SBAG:
Buildable:
Owner: None
FENC:
Buildable:
Owner: None
MSLO:
Buildable:
Owner: None
GAP:
Buildable:
Owner: None
IRON:
Buildable:
Owner: None
PDOX:
Buildable:
Owner: None
AGUN:
Buildable:
Owner: None
TSLA:
Buildable:
Owner: None
DOG:
Buildable:
Owner: soviet,allies
Prerequisites: barr,oilb
Valued:
Cost: 20
E1:
Buildable:
Owner: soviet,allies
Prerequisites: barr,oilb
Valued:
Cost: 20
E2:
Buildable:
Owner: soviet,allies
Prerequisites: barr,oilb
Valued:
Cost: 40
Explodes:
Weapon: UnitExplodeSmall
Chance: 20
E3:
Buildable:
Owner: soviet,allies
Prerequisites: barr,oilb
Valued:
Cost: 60
E4:
Buildable:
Owner: soviet,allies
Prerequisites: barr,oilb
Valued:
Cost: 100
E6:
Buildable:
Owner: soviet,allies
Prerequisites: barr
Valued:
Cost: 100
E7:
Buildable:
Owner: soviet,allies
Prerequisites: barr,oilb
Valued:
Cost: 750
3TNK:
Inherits: ^Tank
Armament:
Weapon: TankNapalm
Recoil: 200
RecoilRecovery: 38
LocalOffset: 0,85,0, 0,-85,0
MECH:
Buildable:
Owner: None
HIJACKER:
Buildable:
Owner: None
MEDI:
Buildable:
Owner: soviet,allies
Prerequisites: barr,oilb
Valued:
Cost: 100
SHOK:
Buildable:
Owner: soviet,allies
Prerequisites: barr,oilb
Valued:
Cost: 150
SNIPER:
Valued:
Cost: 200
Buildable:
Owner: soviet, allies
Prerequisites: barr,oilb
Health:
HP: 200
AutoTarget:
InitialStance: Defend
ScriptInvulnerable:
SPY:
Inherits: ^Infantry
Buildable:
Queue: Infantry
BuildPaletteOrder: 60
Prerequisites: barr,oilb
Owner: allies, soviet
Valued:
Cost: 300
ARTY:
Inherits: ^Tank
Valued:
Cost: 600
Health:
HP: 75
RevealsShroud:
Range: 7c0
V2RL:
Health:
HP: 100
4TNK:
Health:
HP: 2500
Armor:
Type: Heavy
Mobile:
Speed: 56
RevealsShroud:
Range: 14c0
Turreted:
ROT: 1
AttackTurreted:
PrimaryWeapon: 120mm
SecondaryWeapon: MammothTusk
PrimaryLocalOffset: -4,-5,0,0,0, 4,-5,0,0,0
SecondaryLocalOffset: -7,2,0,0,25, 7,2,0,0,-25
PrimaryRecoil: 8
PrimaryRecoilRecovery: 0.7
SecondaryRecoil: 2
Explodes:
Weapon: napalm
EmptyWeapon: napalm
SelfHealing:
Step: 2
Ticks: 1
HealIfBelow: 40%
DamageCooldown: 150
BRIK:
Buildable:
Owner: None
BADR.Bomber:
Inherits: ^Plane
AttackBomber:
Armament:
Weapon: ParaBomb
Health:
HP: 60
Armor:
Type: Light
Plane:
ROT: 5
Speed: 280
LimitedAmmo:
Ammo: 30
RenderUnit:
Image: mig
WithShadow:
-Selectable:
-GainsExperience:
Tooltip:
Name: Mig Bomber
-EjectOnDeath:
Sequences:
VoxelSequences:
Weapons:
120mm:
ROF: 150
Range: 10c0
Report: CANNON1.AUD
Burst: 6
Projectile: Bullet
Speed: 204
High: true
Inaccuracy: 1c682
Image: 120MM
ContrailLength: 50
Warhead:
Spread: 256
Versus:
None: 75%
Wood: 75%
Light: 75%
Concrete: 100%
Explosion: self_destruct
WaterExplosion: self_destruct
InfDeath: 4
SmudgeType: Crater
Damage: 150
MammothTusk:
ROF: 300
Range: 10c0
Report: MISSILE6.AUD
Burst: 2
ValidTargets: Ground, Air
Projectile: Missile
Speed: 128
Arm: 2
High: true
Shadow: false
Proximity: true
Trail: smokey
ContrailLength: 150
Inaccuracy: 853
Image: DRAGON
ROT: 10
RangeLimit: 80
Warhead:
Spread: 640
Versus:
None: 125%
Wood: 110%
Light: 110%
Heavy: 100%
Concrete: 200%
Explosion: nuke
WaterExplosion: nuke
InfDeath: 3
SmudgeType: Crater
Damage: 250
TankNapalm:
ROF: 40
Range: 8c0
Report: AACANON3.AUD
ValidTargets: Ground
Burst: 6
BurstDelay: 1
Projectile: Bullet
Speed: 426
Image: 120MM
Inaccuracy: 2c512
Trail: smokey
ContrailLength: 2
Warhead:
Spread: 341
Versus:
None: 90%
Wood: 170%
Light: 100%
Heavy: 100%
Concrete: 100%
Explosion: small_explosion
WaterExplosion: small_explosion
InfDeath: 4
SmudgeType: Scorch
ImpactSound: firebl3.aud
Damage: 15
ParaBomb:
ROF: 5
Range: 5c0
Report: CHUTE1.AUD
Projectile: GravityBomb
Image: BOMBLET
Warhead:
Spread: 426
Versus:
None: 125%
Wood: 100%
Light: 60%
Concrete: 25%
Explosion: napalm
ImpactSound: firebl3.aud
WaterExplosion: napalm
InfDeath: 5
SmudgeType: Crater
Damage: 200
155mm:
ROF: 10
Range: 7c5
Burst: 20
MinRange: 3c0
-Report:
Projectile: Bullet
Speed: 170
Trail: fb4
Image: fb3
High: true
Angle: 30
Inaccuracy: 1c682
ContrailLength: 2
Warhead:
Spread: 426
Versus:
None: 80%
Wood: 100%
Light: 60%
Heavy: 75%
Concrete: 35%
Explosion: small_napalm
WaterExplosion: small_napalm
InfDeath: 5
SmudgeType: Scorch
ImpactSound: firebl3.aud
Damage: 10
FLAK-23:
ROF: 10
Range: 8c0
Report: AACANON3.AUD
ValidTargets: Air,Ground
Projectile: Bullet
Speed: 1c682
High: true
Warhead:
Spread: 213
Versus:
None: 35%
Wood: 30%
Light: 30%
Heavy: 40%
Concrete: 30%
Explosion: med_explosion
Damage: 25
SCUD:
ROF: 280
Range: 7c0
MinRange: 3c0
Report: MISSILE1.AUD
Projectile: Bullet
Speed: 170
Arm: 10
High: true
Shadow: false
Proximity: true
Trail: smokey
Inaccuracy: 426
Image: V2
Angle: 216
Warhead:
Spread: 853
Versus:
None: 100%
Wood: 90%
Light: 80%
Heavy: 70%
Explosion: nuke
WaterExplosion: large_splash
InfDeath: 3
SmudgeType: Crater
Damage: 500
ImpactSound: kaboom1.aud
WaterImpactSound: kaboom1.aud
SilencedPPK:
ROF: 80
Range: 25c0
Report: silppk.aud
Projectile: Bullet
Speed: 1c682
Warhead:
Spread: 128
Versus:
Wood: 0%
Light: 0%
Heavy: 50%
Concrete: 0%
Explosion: piffs
InfDeath: 2
Damage: 150
Voices:
Notifications:
Translations: