Skip to content
Snippets Groups Projects
Commit 34c14c90 authored by DarkGod's avatar DarkGod
Browse files
parents 27d9e8dd ee89c8b0
No related branches found
No related tags found
No related merge requests found
Showing
with 115 additions and 31 deletions
......@@ -28,6 +28,7 @@ Lore:
Graphics:
- Shockbolt (Raymond Gaustadnes) http://shockbolt.deviantart.com
- Rexorcorum (Assen Kanev)
- Suslik (Alex Sannikov) for his awesome shaders
Musics:
- "A lomos del dragón blanco" by Carlos Saura (http://www.jamendo.com/en/artist/carlosaura)
......@@ -39,6 +40,7 @@ Fonts:
- INSULA, USENET: http://www.dafont.com/fr/apostrophic-labs.d128
- SVBasicManual: http://www.dafont.com/fr/johan-winge.d757 // http://home.student.uu.se/j/jowi4905/fonts/
- FSEX300: http://www.fixedsysexcelsior.com/
- square: Wouter van Oortmerssen: http://strlen.com/square
Others:
- The good people at lua.org who made the world a better place
......
File added
......@@ -191,6 +191,7 @@ end
--- Removes a particles emitter following the entity
function _M:removeParticles(ps)
if not ps then return end
self.__particles[ps] = nil
ps:dieDisplay()
if self.x and self.y and game.level and game.level.map then
......@@ -682,7 +683,7 @@ function _M:addTemporaryValue(prop, v, noupdate)
end
elseif type(v) == "string" then
-- Only last works on strings
if method == "last" then
if true or method == "last" then
base["__tlast_"..prop] = base["__tlast_"..prop] or {[-1] = base[prop]}
local b = base["__tlast_"..prop]
b[id] = v
......@@ -780,7 +781,7 @@ function _M:removeTemporaryValue(prop, id, noupdate)
end
elseif type(v) == "string" then
-- Only last works on strings
if method == "last" then
if true or method == "last" then
base["__tlast_"..prop] = base["__tlast_"..prop] or {}
local b = base["__tlast_"..prop]
b[id] = nil
......
......@@ -21,6 +21,7 @@ require "engine.class"
require "engine.Mouse"
require "engine.DebugConsole"
require "engine.dialogs.ShowErrorStack"
local Shader = require "engine.Shader"
--- Represent a game
-- A module should subclass it and initialize anything it needs to play inside
......@@ -32,8 +33,6 @@ module(..., package.seeall, class.make)
function _M:init(keyhandler)
self.key = keyhandler
self.level = nil
self.log = function() end
self.logSeen = function() end
self.w, self.h, self.fullscreen = core.display.size()
self.dialogs = {}
self.save_name = ""
......@@ -49,6 +48,9 @@ function _M:init(keyhandler)
self:defaultMouseCursor()
end
function _M:log() end
function _M:logSeen() end
--- Default mouse cursor
function _M:defaultMouseCursor()
local UIBase = require "engine.ui.Base"
......@@ -239,6 +241,8 @@ function _M:tick()
end
end
Shader:cleanup()
if self.cleanSounds then self:cleanSounds() end
self:onTickEndExecute()
......
......@@ -90,7 +90,7 @@ end
--- Run tick on a level
function _M:tickLevel(level)
local i, e
local i, e = 1, nil
local arr = level.e_array
if level.last_iteration then
......@@ -105,7 +105,7 @@ function _M:tickLevel(level)
-- print("=====LEVEL", level.level, level.sublevel_id, "resuming tick loop at ", i, arr[i].name)
end
for i = 1, #arr do
for i = i, #arr do
e = arr[i]
if e and e.act and e.energy then
if e.actBase and e.energyBase then
......
......@@ -1007,6 +1007,7 @@ function _M:addEffect(src, x, y, duration, damtype, dam, radius, dir, angle, ove
table.insert(self.effects, e)
self.changed = true
return e
end
--- Display the overlay effects, called by self:display()
......@@ -1041,7 +1042,9 @@ function _M:processEffects()
elseif act and e.src and e.src.reactionToward and (e.src:reactionToward(act) >= 0) and not ((type(e.friendlyfire) == "number" and rng.percent(e.friendlyfire)) or (type(e.friendlyfire) ~= "number" and e.friendlyfire)) then
-- Otherwise hit
else
e.src.__project_source = e -- intermediate projector source
DamageType:get(e.damtype).projector(e.src, lx, ly, e.damtype, e.dam)
e.src.__project_source = nil
end
end
end
......
......@@ -60,6 +60,7 @@ function _M:loaded()
local _
setfenv(f, setmetatable(t, {__index=_G}))
_, _ , _, gl, _ = f()
setmetatable(t, nil)
if t.use_shader then self.shader = t.use_shader end
if t.alterscreen then islast = true end
......
......@@ -205,6 +205,7 @@ function _M:act()
if self.project then
local x, y, act, stop = self.src:projectDoMove(self.project.def.typ, self.project.def.x, self.project.def.y, self.x, self.y, self.project.def.start_x, self.project.def.start_y)
if x and y then self:move(x, y) end
if self.src then self.src.__project_source = self end -- intermediate projector source
if act then self.src:projectDoAct(self.project.def.typ, self.project.def.tg, self.project.def.damtype, self.project.def.dam, self.project.def.particles, self.x, self.y, self.tmp_proj) end
if stop then
local block, hit, hit_radius = false, true, true
......@@ -219,9 +220,11 @@ function _M:act()
end
self.src:projectDoStop(self.project.def.typ, self.project.def.tg, self.project.def.damtype, self.project.def.dam, self.project.def.particles, self.x, self.y, self.tmp_proj, radius_x, radius_y, self)
end
if self.src then self.src.__project_source = nil end -- intermediate projector source
elseif self.homing then
self:moveDirection(self.homing.target.x, self.homing.target.y)
self.homing.count = self.homing.count - 1
if self.src then self.src.__project_source = self end -- intermediate projector source
if (self.x == self.homing.target.x and self.y == self.homing.target.y) or self.homing.count <= 0 then
game.level:removeEntity(self, true)
self.dead = true
......@@ -229,18 +232,21 @@ function _M:act()
else
self.homing.on_move(self, self.src)
end
if self.src then self.src.__project_source = nil end -- intermediate projector source
end
end
return true
end
--- Something moved in the same spot as us, hit ?
function _M:on_move(x, y, target)
self.src.__project_source = self -- intermediate projector source
if self.project and self.project.def.typ.line then self.src:projectDoAct(self.project.def.typ, self.project.def.tg, self.project.def.damtype, self.project.def.dam, self.project.def.particles, self.x, self.y, self.tmp_proj) end
if self.project and self.project.def.typ.stop_block then
self.src:projectDoStop(self.project.def.typ, self.project.def.tg, self.project.def.damtype, self.project.def.dam, self.project.def.particles, self.x, self.y, self.tmp_proj, self.x, self.y, self)
end
self.src.__project_source = nil
end
--- Premature end
......@@ -255,7 +261,7 @@ function _M:makeProject(src, display, def, do_move, do_act, do_stop)
local name = def.tg.name
if def.tg.talent then
speed = src:getTalentProjectileSpeed(def.tg.talent) or speed
name = def.tg.talent.name
name = name or def.tg.talent.name
def.tg.talent_id = def.tg.talent.id
def.tg.talent = nil
end
......
......@@ -31,7 +31,16 @@ _M.progsreset = {}
loadNoDelay = true
function core.shader.allow(kind)
return config.settings['shaders_kind_'..kind]
return config.settings['shaders_kind_'..kind] and core.shader.active(4)
end
function _M:cleanup()
local time = os.time()
local todel = {}
for name, s in pairs(self.progs) do
if s.dieat < time then todel[name] = true end
end
for name, _ in pairs(todel) do self.progs[name] = nil end
end
--- Make a shader
......@@ -65,11 +74,14 @@ function _M:init(name, args)
end
end
function _M:makeTotalName()
function _M:makeTotalName(add)
local str = {}
for k, v in pairs(self.args) do
local args = self.args
if add then args = table.clone(add) table.merge(args, self.args) end
for k, v in pairs(args) do
if type(v) == "function" then v = v(self) end
if type(v) == "number" then
str[#str+1] = v
str[#str+1] = k.."="..tostring(v)
elseif type(v) == "table" then
if v.texture then
if v.is3d then str[#str+1] = k.."=tex3d("..v.texture..")"
......@@ -83,6 +95,7 @@ function _M:makeTotalName()
end
end
end
table.sort(str)
return self.name.."["..table.concat(str,",").."]"
end
......@@ -135,12 +148,12 @@ function _M:createProgram(def)
end
function _M:loaded()
if _M.progs[self.totalname] then
self.shad = _M.progs[self.totalname]
if _M.progs[self.totalname] and not _M.progsreset[self.totalname] then
-- print("[SHADER] using cached shader "..self.totalname)
self.shad = _M.progs[self.totalname]
self.shad = _M.progs[self.totalname].shad
_M.progs[self.totalname].dieat = os.time() + 120
else
print("[SHADER] Loading from /data/gfx/shaders/"..self.name..".lua")
-- print("[SHADER] Loading from /data/gfx/shaders/"..self.name..".lua")
local f, err = loadfile("/data/gfx/shaders/"..self.name..".lua")
if not f and err then error(err) end
setfenv(f, setmetatable(self.args or {}, {__index=_G}))
......@@ -153,10 +166,19 @@ function _M:loaded()
if not core.shader.allow(def.require_kind) then return end
end
_M.progs[self.totalname] = self:createProgram(def)
_M.progsreset[self.totalname] = def.resetargs
if def.resetargs then
self.totalname = self:makeTotalName(def.resetargs)
end
-- print("[SHADER] Loaded shader with totalname", self.totalname)
if not _M.progs[self.totalname] then
_M.progs[self.totalname] = {shad=self:createProgram(def), dieat=def.resetargs and (os.time() + 3) or (os.time() + 120)}
_M.progsreset[self.totalname] = def.resetargs
else
_M.progs[self.totalname].dieat = def.resetargs and (os.time() + 3) or (os.time() + 120)
end
self.shad = _M.progs[self.totalname]
self.shad = _M.progs[self.totalname].shad
if self.shad then
for k, v in pairs(def.args) do
self:setUniform(k, v)
......
......@@ -135,7 +135,9 @@ function _M:trigger(x, y, who)
game.logSeen(who, "%s", str)
end
local known, del = false, false
if self.summoner then self.summoner.__project_source = self end -- intermediate projector source
if self.triggered then known, del = self:triggered(x, y, who) end
if self.summoner then self.summoner.__project_source = nil end
if known then
self:setKnown(who, true)
game.level.map:updateMap(x, y)
......
......@@ -141,7 +141,7 @@ function _M:generateList()
end,}
local zone = Textzone.new{width=self.c_desc.w, height=self.c_desc.h, text=string.toTString"Activates volumetric shaders.\nThis option allows for volumetricion effects (like deep starfields). Enabling it will severely reduce performance when shaders are displayed.\n\n#LIGHT_RED#You must restart the game for it to take effect.#WHITE#"}
list[#list+1] = { zone=zone, name=string.toTString"#GOLD##{bold}#OpenGL Shaders: Volumetricions#WHITE##{normal}#", status=function(item)
list[#list+1] = { zone=zone, name=string.toTString"#GOLD##{bold}#OpenGL Shaders: Volumetric#WHITE##{normal}#", status=function(item)
return tostring(config.settings.shaders_kind_volumetric and "enabled" or "disabled")
end, fct=function(item)
config.settings.shaders_kind_volumetric = not config.settings.shaders_kind_volumetric
......
......@@ -194,7 +194,7 @@ function _M:project(t, x, y, damtype, dam, particles)
elseif act and self.reactionToward and (self:reactionToward(act) >= 0) and not ((type(typ.friendlyfire) == "number" and rng.percent(typ.friendlyfire)) or (type(typ.friendlyfire) ~= "number" and typ.friendlyfire)) then
-- Otherwise hit
else
if type(damtype) == "function" then if damtype(px, py, tg, self) then stop=true break end
if type(damtype) == "function" then if damtype(px, py, t, self) then stop=true break end
else DamageType:get(damtype).projector(self, px, py, damtype, dam, tmp, nil) end
if particles then
game.level.map:particleEmitter(px, py, 1, particles.type, particles.args)
......@@ -311,6 +311,7 @@ function _M:projectile(t, x, y, damtype, dam, particles)
game.zone:addEntity(game.level, proj, "projectile", typ.start_x, typ.start_y)
self:check("on_projectile_fired", proj, typ, x, y, damtype, dam, particles)
return proj
end
-- @param typ a target type table
......
......@@ -138,14 +138,15 @@ function _M:useTalent(id, who, force_level, ignore_cd, force_target, silent, no_
end
if not self:preUseTalent(ab, silent) then return end
local old_level
local old_target
local old_target, old_target_set = nil, false
if force_level then old_level = who.talents[id]; who.talents[id] = force_level end
if force_target then old_target = rawget(who, "getTarget"); who.getTarget = function(a) return force_target.x, force_target.y, not force_target.__no_self and force_target end end
if ab.onAIGetTarget and not who.player then old_target_set = true; old_target = rawget(who, "getTarget"); who.getTarget = function() return ab.onAIGetTarget(self, ab) end end
if force_target and not old_target then old_target_set = true; old_target = rawget(who, "getTarget"); who.getTarget = function(a) return force_target.x, force_target.y, not force_target.__no_self and force_target end end
self.__talent_running = ab
local ok, ret, special = xpcall(function() return ab.action(who, ab) end, debug.traceback)
self.__talent_running = nil
if force_target then who.getTarget = old_target end
if old_target_set then who.getTarget = old_target end
if force_level then who.talents[id] = old_level end
if not ok then error(ret) end
......@@ -186,7 +187,8 @@ function _M:useTalent(id, who, force_level, ignore_cd, force_target, silent, no_
local old_level
if force_level then old_level = who.talents[id]; who.talents[id] = force_level end
local ret = ab.activate(who, ab)
if ret == true then ret = {} end -- fix for badly coded talents
if not ret or ret == true then ret = {} end -- fix for badly coded talents
ret.name = ret.name or ab.name
if force_level then who.talents[id] = old_level end
if not self:postUseTalent(ab, ret) then return end
......
......@@ -73,9 +73,11 @@ function _M:timedEffects(filter)
todel[#todel+1] = eff
else
if def.on_timeout then
if p.src then p.src.__project_source = p end -- intermediate projector source
if def.on_timeout(self, p) then
todel[#todel+1] = eff
end
if p.src then p.src.__project_source = nil end
end
end
p.dur = p.dur - def.decrease
......@@ -103,6 +105,7 @@ function _M:setEffect(eff_id, dur, p, silent)
if not p[k] then p[k] = e end
end
p.dur = dur
p.effect_id = eff_id
self:check("on_set_temporary_effect", eff_id, _M.tempeffect_def[eff_id], p)
if p.dur <= 0 then return self:removeEffect(eff_id) end
......
......@@ -68,6 +68,25 @@ function _M:loadAchievements()
end
end
--[[
function _M:achievementsDumpCSV()
local f = fs.open("/achvs.csv", "w")
f:write('"id","name","desc","earned","unearned"\n')
for i, a in ipairs(self.achiev_defs) do
f:write(('"%s","%s","%s","earned_%s.jpg","unearned_%s.jpg"\n'):
format(
"TOME_"..a.id,
a.name:gsub('\\', '\\\\'):gsub('"', '\\"'),
a.desc:gsub('\\', '\\\\'):gsub('"', '\\"'),
a.id:lower(),
a.id:lower()
)
)
end
f:close()
end
]]
function _M:getAchievementFromId(id)
return self.achiev_defs[id]
end
......
......@@ -99,7 +99,7 @@ function _M:generate()
self.sel_j = util.bound(self.scroll + math.floor(by / (self.tile_h + self.padding)), 1, self.max)
self.sel_i = util.bound(1 + math.floor(bx / (self.tile_w + self.padding)), 1, self.nb_w)
if button == "left" and event == "button" then self:onUse(button) end
if (button == "left" or button == "right") and event == "button" then self:onUse(button) end
self:onSelect()
end)
self.key:addBinds{
......@@ -176,7 +176,7 @@ function _M:onUse(button, forcectrl)
if not (forcectrl == true or (forcectrl == nil and core.key.modState("ctrl"))) then self:clearSelection() end
item.selected = not item.selected
end
self.fct(item)
self.fct(item, button)
end
end
......
......@@ -90,6 +90,9 @@ function _M:generate()
end
function _M:setupInput()
self.prev_sel = 0
self.mouse_pos = { x = 0, y = 0 }
self.mouse:reset()
self.key:reset()
local colx = 0
......
......@@ -24,6 +24,16 @@ function math.decimals(v, nb)
return math.floor(v * nb) / nb
end
-- Rounds to nearest multiple
-- (round away from zero): math.round(4.65, 0.1)=4.7, math.round(-4.475, 0.01) = -4.48
-- num = rouding multiplier to compensate for numerical rounding (default 1000000 for 6 digits accuracy)
function math.round(v, mult, num)
mult = mult or 1
num = num or 1000000
v, mult = v*num, mult*num
return v >= 0 and math.floor((v + mult/2)/mult) * mult/num or math.ceil((v - mult/2)/mult) * mult/num
end
function lpeg.anywhere (p)
return lpeg.P{ p + 1 * lpeg.V(1) }
end
......@@ -336,12 +346,14 @@ end
function string.his_her(actor)
if actor.female then return "her"
elseif actor.neuter then return "it"
else return "his"
end
end
function string.his_her_self(actor)
if actor.female then return "herself"
elseif actor.neuter then return "itself"
else return "himself"
end
end
......@@ -722,6 +734,8 @@ function core.display.virtualImage(path, data)
virtualimages[path] = data
end
if not core.game.getFrameTime then core.game.getFrameTime = core.game.getTime end
local oldloadimage = core.display.loadImage
function core.display.loadImage(path)
if virtualimages[path] then return core.display.loadImageMemory(virtualimages[path]) end
......
......@@ -152,9 +152,9 @@ end
function string.unserialize(str)
local f, err = loadstring(str)
if not f then print("[UNSERIALIZE] error", err, str) return nil end
if not f then print("[UNSERIALIZE] error", err) return nil end
local t = {}
setfenv(f, setmetatable(t, {__index={_G=t}}))
local ok, err = pcall(f)
if ok then return setmetatable(t, nil) else print("[UNSERIALIZE] error", err, str) return nil end
if ok then return setmetatable(t, nil) else print("[UNSERIALIZE] error", err) return nil end
end
......@@ -43,7 +43,8 @@ newAI("escort_quest", function(self)
if not self.ai_state.fleeing_msg then
self.ai_state.fleeing_msg = true
local enemy = self.ai_target.actor
self:doEmote(("Help! %s to the %s!"):format(string.capitalize(enemy.name), game.level.map:compassDirection(enemy.x-self.x, enemy.y-self.y) or "???"))
local dir = game.level.map:compassDirection(enemy.x-self.x, enemy.y-self.y)
self:doEmote("Help!"..(dir and (" %s to the %s!"):format(self:canSee(enemy) and string.capitalize(enemy.name) or "Something", dir) or ""))
end
else
self:runAI("move_escort")
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment