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: ...@@ -28,6 +28,7 @@ Lore:
Graphics: Graphics:
- Shockbolt (Raymond Gaustadnes) http://shockbolt.deviantart.com - Shockbolt (Raymond Gaustadnes) http://shockbolt.deviantart.com
- Rexorcorum (Assen Kanev) - Rexorcorum (Assen Kanev)
- Suslik (Alex Sannikov) for his awesome shaders
Musics: Musics:
- "A lomos del dragón blanco" by Carlos Saura (http://www.jamendo.com/en/artist/carlosaura) - "A lomos del dragón blanco" by Carlos Saura (http://www.jamendo.com/en/artist/carlosaura)
...@@ -39,6 +40,7 @@ Fonts: ...@@ -39,6 +40,7 @@ Fonts:
- INSULA, USENET: http://www.dafont.com/fr/apostrophic-labs.d128 - 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/ - SVBasicManual: http://www.dafont.com/fr/johan-winge.d757 // http://home.student.uu.se/j/jowi4905/fonts/
- FSEX300: http://www.fixedsysexcelsior.com/ - FSEX300: http://www.fixedsysexcelsior.com/
- square: Wouter van Oortmerssen: http://strlen.com/square
Others: Others:
- The good people at lua.org who made the world a better place - The good people at lua.org who made the world a better place
......
File added
...@@ -191,6 +191,7 @@ end ...@@ -191,6 +191,7 @@ end
--- Removes a particles emitter following the entity --- Removes a particles emitter following the entity
function _M:removeParticles(ps) function _M:removeParticles(ps)
if not ps then return end
self.__particles[ps] = nil self.__particles[ps] = nil
ps:dieDisplay() ps:dieDisplay()
if self.x and self.y and game.level and game.level.map then if self.x and self.y and game.level and game.level.map then
...@@ -682,7 +683,7 @@ function _M:addTemporaryValue(prop, v, noupdate) ...@@ -682,7 +683,7 @@ function _M:addTemporaryValue(prop, v, noupdate)
end end
elseif type(v) == "string" then elseif type(v) == "string" then
-- Only last works on strings -- 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]} base["__tlast_"..prop] = base["__tlast_"..prop] or {[-1] = base[prop]}
local b = base["__tlast_"..prop] local b = base["__tlast_"..prop]
b[id] = v b[id] = v
...@@ -780,7 +781,7 @@ function _M:removeTemporaryValue(prop, id, noupdate) ...@@ -780,7 +781,7 @@ function _M:removeTemporaryValue(prop, id, noupdate)
end end
elseif type(v) == "string" then elseif type(v) == "string" then
-- Only last works on strings -- Only last works on strings
if method == "last" then if true or method == "last" then
base["__tlast_"..prop] = base["__tlast_"..prop] or {} base["__tlast_"..prop] = base["__tlast_"..prop] or {}
local b = base["__tlast_"..prop] local b = base["__tlast_"..prop]
b[id] = nil b[id] = nil
......
...@@ -21,6 +21,7 @@ require "engine.class" ...@@ -21,6 +21,7 @@ require "engine.class"
require "engine.Mouse" require "engine.Mouse"
require "engine.DebugConsole" require "engine.DebugConsole"
require "engine.dialogs.ShowErrorStack" require "engine.dialogs.ShowErrorStack"
local Shader = require "engine.Shader"
--- Represent a game --- Represent a game
-- A module should subclass it and initialize anything it needs to play inside -- A module should subclass it and initialize anything it needs to play inside
...@@ -32,8 +33,6 @@ module(..., package.seeall, class.make) ...@@ -32,8 +33,6 @@ module(..., package.seeall, class.make)
function _M:init(keyhandler) function _M:init(keyhandler)
self.key = keyhandler self.key = keyhandler
self.level = nil self.level = nil
self.log = function() end
self.logSeen = function() end
self.w, self.h, self.fullscreen = core.display.size() self.w, self.h, self.fullscreen = core.display.size()
self.dialogs = {} self.dialogs = {}
self.save_name = "" self.save_name = ""
...@@ -49,6 +48,9 @@ function _M:init(keyhandler) ...@@ -49,6 +48,9 @@ function _M:init(keyhandler)
self:defaultMouseCursor() self:defaultMouseCursor()
end end
function _M:log() end
function _M:logSeen() end
--- Default mouse cursor --- Default mouse cursor
function _M:defaultMouseCursor() function _M:defaultMouseCursor()
local UIBase = require "engine.ui.Base" local UIBase = require "engine.ui.Base"
...@@ -239,6 +241,8 @@ function _M:tick() ...@@ -239,6 +241,8 @@ function _M:tick()
end end
end end
Shader:cleanup()
if self.cleanSounds then self:cleanSounds() end if self.cleanSounds then self:cleanSounds() end
self:onTickEndExecute() self:onTickEndExecute()
......
...@@ -90,7 +90,7 @@ end ...@@ -90,7 +90,7 @@ end
--- Run tick on a level --- Run tick on a level
function _M:tickLevel(level) function _M:tickLevel(level)
local i, e local i, e = 1, nil
local arr = level.e_array local arr = level.e_array
if level.last_iteration then if level.last_iteration then
...@@ -105,7 +105,7 @@ function _M:tickLevel(level) ...@@ -105,7 +105,7 @@ function _M:tickLevel(level)
-- print("=====LEVEL", level.level, level.sublevel_id, "resuming tick loop at ", i, arr[i].name) -- print("=====LEVEL", level.level, level.sublevel_id, "resuming tick loop at ", i, arr[i].name)
end end
for i = 1, #arr do for i = i, #arr do
e = arr[i] e = arr[i]
if e and e.act and e.energy then if e and e.act and e.energy then
if e.actBase and e.energyBase 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 ...@@ -1007,6 +1007,7 @@ function _M:addEffect(src, x, y, duration, damtype, dam, radius, dir, angle, ove
table.insert(self.effects, e) table.insert(self.effects, e)
self.changed = true self.changed = true
return e
end end
--- Display the overlay effects, called by self:display() --- Display the overlay effects, called by self:display()
...@@ -1041,7 +1042,9 @@ function _M:processEffects() ...@@ -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 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 -- Otherwise hit
else else
e.src.__project_source = e -- intermediate projector source
DamageType:get(e.damtype).projector(e.src, lx, ly, e.damtype, e.dam) DamageType:get(e.damtype).projector(e.src, lx, ly, e.damtype, e.dam)
e.src.__project_source = nil
end end
end end
end end
......
...@@ -60,6 +60,7 @@ function _M:loaded() ...@@ -60,6 +60,7 @@ function _M:loaded()
local _ local _
setfenv(f, setmetatable(t, {__index=_G})) setfenv(f, setmetatable(t, {__index=_G}))
_, _ , _, gl, _ = f() _, _ , _, gl, _ = f()
setmetatable(t, nil)
if t.use_shader then self.shader = t.use_shader end if t.use_shader then self.shader = t.use_shader end
if t.alterscreen then islast = true end if t.alterscreen then islast = true end
......
...@@ -205,6 +205,7 @@ function _M:act() ...@@ -205,6 +205,7 @@ function _M:act()
if self.project then 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) 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 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 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 if stop then
local block, hit, hit_radius = false, true, true local block, hit, hit_radius = false, true, true
...@@ -219,9 +220,11 @@ function _M:act() ...@@ -219,9 +220,11 @@ function _M:act()
end 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) 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 end
if self.src then self.src.__project_source = nil end -- intermediate projector source
elseif self.homing then elseif self.homing then
self:moveDirection(self.homing.target.x, self.homing.target.y) self:moveDirection(self.homing.target.x, self.homing.target.y)
self.homing.count = self.homing.count - 1 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 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) game.level:removeEntity(self, true)
self.dead = true self.dead = true
...@@ -229,18 +232,21 @@ function _M:act() ...@@ -229,18 +232,21 @@ function _M:act()
else else
self.homing.on_move(self, self.src) self.homing.on_move(self, self.src)
end end
if self.src then self.src.__project_source = nil end -- intermediate projector source
end end
end end
return true return true
end end
--- Something moved in the same spot as us, hit ? --- Something moved in the same spot as us, hit ?
function _M:on_move(x, y, target) 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.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 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) 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 end
self.src.__project_source = nil
end end
--- Premature end --- Premature end
...@@ -255,7 +261,7 @@ function _M:makeProject(src, display, def, do_move, do_act, do_stop) ...@@ -255,7 +261,7 @@ function _M:makeProject(src, display, def, do_move, do_act, do_stop)
local name = def.tg.name local name = def.tg.name
if def.tg.talent then if def.tg.talent then
speed = src:getTalentProjectileSpeed(def.tg.talent) or speed 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_id = def.tg.talent.id
def.tg.talent = nil def.tg.talent = nil
end end
......
...@@ -31,7 +31,16 @@ _M.progsreset = {} ...@@ -31,7 +31,16 @@ _M.progsreset = {}
loadNoDelay = true loadNoDelay = true
function core.shader.allow(kind) 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 end
--- Make a shader --- Make a shader
...@@ -65,11 +74,14 @@ function _M:init(name, args) ...@@ -65,11 +74,14 @@ function _M:init(name, args)
end end
end end
function _M:makeTotalName() function _M:makeTotalName(add)
local str = {} 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 if type(v) == "number" then
str[#str+1] = v str[#str+1] = k.."="..tostring(v)
elseif type(v) == "table" then elseif type(v) == "table" then
if v.texture then if v.texture then
if v.is3d then str[#str+1] = k.."=tex3d("..v.texture..")" if v.is3d then str[#str+1] = k.."=tex3d("..v.texture..")"
...@@ -83,6 +95,7 @@ function _M:makeTotalName() ...@@ -83,6 +95,7 @@ function _M:makeTotalName()
end end
end end
end end
table.sort(str)
return self.name.."["..table.concat(str,",").."]" return self.name.."["..table.concat(str,",").."]"
end end
...@@ -135,12 +148,12 @@ function _M:createProgram(def) ...@@ -135,12 +148,12 @@ function _M:createProgram(def)
end end
function _M:loaded() function _M:loaded()
if _M.progs[self.totalname] then if _M.progs[self.totalname] and not _M.progsreset[self.totalname] then
self.shad = _M.progs[self.totalname]
-- print("[SHADER] using cached shader "..self.totalname) -- 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 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") local f, err = loadfile("/data/gfx/shaders/"..self.name..".lua")
if not f and err then error(err) end if not f and err then error(err) end
setfenv(f, setmetatable(self.args or {}, {__index=_G})) setfenv(f, setmetatable(self.args or {}, {__index=_G}))
...@@ -153,10 +166,19 @@ function _M:loaded() ...@@ -153,10 +166,19 @@ function _M:loaded()
if not core.shader.allow(def.require_kind) then return end if not core.shader.allow(def.require_kind) then return end
end end
_M.progs[self.totalname] = self:createProgram(def) if def.resetargs then
_M.progsreset[self.totalname] = def.resetargs 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 if self.shad then
for k, v in pairs(def.args) do for k, v in pairs(def.args) do
self:setUniform(k, v) self:setUniform(k, v)
......
...@@ -135,7 +135,9 @@ function _M:trigger(x, y, who) ...@@ -135,7 +135,9 @@ function _M:trigger(x, y, who)
game.logSeen(who, "%s", str) game.logSeen(who, "%s", str)
end end
local known, del = false, false 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.triggered then known, del = self:triggered(x, y, who) end
if self.summoner then self.summoner.__project_source = nil end
if known then if known then
self:setKnown(who, true) self:setKnown(who, true)
game.level.map:updateMap(x, y) game.level.map:updateMap(x, y)
......
...@@ -141,7 +141,7 @@ function _M:generateList() ...@@ -141,7 +141,7 @@ function _M:generateList()
end,} 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#"} 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") return tostring(config.settings.shaders_kind_volumetric and "enabled" or "disabled")
end, fct=function(item) end, fct=function(item)
config.settings.shaders_kind_volumetric = not config.settings.shaders_kind_volumetric config.settings.shaders_kind_volumetric = not config.settings.shaders_kind_volumetric
......
...@@ -194,7 +194,7 @@ function _M:project(t, x, y, damtype, dam, particles) ...@@ -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 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 -- Otherwise hit
else 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 else DamageType:get(damtype).projector(self, px, py, damtype, dam, tmp, nil) end
if particles then if particles then
game.level.map:particleEmitter(px, py, 1, particles.type, particles.args) game.level.map:particleEmitter(px, py, 1, particles.type, particles.args)
...@@ -311,6 +311,7 @@ function _M:projectile(t, x, y, damtype, dam, particles) ...@@ -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) 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) self:check("on_projectile_fired", proj, typ, x, y, damtype, dam, particles)
return proj
end end
-- @param typ a target type table -- @param typ a target type table
......
...@@ -138,14 +138,15 @@ function _M:useTalent(id, who, force_level, ignore_cd, force_target, silent, no_ ...@@ -138,14 +138,15 @@ function _M:useTalent(id, who, force_level, ignore_cd, force_target, silent, no_
end end
if not self:preUseTalent(ab, silent) then return end if not self:preUseTalent(ab, silent) then return end
local old_level 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_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 self.__talent_running = ab
local ok, ret, special = xpcall(function() return ab.action(who, ab) end, debug.traceback) local ok, ret, special = xpcall(function() return ab.action(who, ab) end, debug.traceback)
self.__talent_running = nil 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 force_level then who.talents[id] = old_level end
if not ok then error(ret) 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_ ...@@ -186,7 +187,8 @@ function _M:useTalent(id, who, force_level, ignore_cd, force_target, silent, no_
local old_level local old_level
if force_level then old_level = who.talents[id]; who.talents[id] = force_level end if force_level then old_level = who.talents[id]; who.talents[id] = force_level end
local ret = ab.activate(who, ab) 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 force_level then who.talents[id] = old_level end
if not self:postUseTalent(ab, ret) then return end if not self:postUseTalent(ab, ret) then return end
......
...@@ -73,9 +73,11 @@ function _M:timedEffects(filter) ...@@ -73,9 +73,11 @@ function _M:timedEffects(filter)
todel[#todel+1] = eff todel[#todel+1] = eff
else else
if def.on_timeout then 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 if def.on_timeout(self, p) then
todel[#todel+1] = eff todel[#todel+1] = eff
end end
if p.src then p.src.__project_source = nil end
end end
end end
p.dur = p.dur - def.decrease p.dur = p.dur - def.decrease
...@@ -103,6 +105,7 @@ function _M:setEffect(eff_id, dur, p, silent) ...@@ -103,6 +105,7 @@ function _M:setEffect(eff_id, dur, p, silent)
if not p[k] then p[k] = e end if not p[k] then p[k] = e end
end end
p.dur = dur p.dur = dur
p.effect_id = eff_id
self:check("on_set_temporary_effect", eff_id, _M.tempeffect_def[eff_id], p) 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 if p.dur <= 0 then return self:removeEffect(eff_id) end
......
...@@ -68,6 +68,25 @@ function _M:loadAchievements() ...@@ -68,6 +68,25 @@ function _M:loadAchievements()
end end
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) function _M:getAchievementFromId(id)
return self.achiev_defs[id] return self.achiev_defs[id]
end end
......
...@@ -99,7 +99,7 @@ function _M:generate() ...@@ -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_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) 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() self:onSelect()
end) end)
self.key:addBinds{ self.key:addBinds{
...@@ -176,7 +176,7 @@ function _M:onUse(button, forcectrl) ...@@ -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 if not (forcectrl == true or (forcectrl == nil and core.key.modState("ctrl"))) then self:clearSelection() end
item.selected = not item.selected item.selected = not item.selected
end end
self.fct(item) self.fct(item, button)
end end
end end
......
...@@ -90,6 +90,9 @@ function _M:generate() ...@@ -90,6 +90,9 @@ function _M:generate()
end end
function _M:setupInput() function _M:setupInput()
self.prev_sel = 0
self.mouse_pos = { x = 0, y = 0 }
self.mouse:reset() self.mouse:reset()
self.key:reset() self.key:reset()
local colx = 0 local colx = 0
......
...@@ -24,6 +24,16 @@ function math.decimals(v, nb) ...@@ -24,6 +24,16 @@ function math.decimals(v, nb)
return math.floor(v * nb) / nb return math.floor(v * nb) / nb
end 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) function lpeg.anywhere (p)
return lpeg.P{ p + 1 * lpeg.V(1) } return lpeg.P{ p + 1 * lpeg.V(1) }
end end
...@@ -336,12 +346,14 @@ end ...@@ -336,12 +346,14 @@ end
function string.his_her(actor) function string.his_her(actor)
if actor.female then return "her" if actor.female then return "her"
elseif actor.neuter then return "it"
else return "his" else return "his"
end end
end end
function string.his_her_self(actor) function string.his_her_self(actor)
if actor.female then return "herself" if actor.female then return "herself"
elseif actor.neuter then return "itself"
else return "himself" else return "himself"
end end
end end
...@@ -722,6 +734,8 @@ function core.display.virtualImage(path, data) ...@@ -722,6 +734,8 @@ function core.display.virtualImage(path, data)
virtualimages[path] = data virtualimages[path] = data
end end
if not core.game.getFrameTime then core.game.getFrameTime = core.game.getTime end
local oldloadimage = core.display.loadImage local oldloadimage = core.display.loadImage
function core.display.loadImage(path) function core.display.loadImage(path)
if virtualimages[path] then return core.display.loadImageMemory(virtualimages[path]) end if virtualimages[path] then return core.display.loadImageMemory(virtualimages[path]) end
......
...@@ -152,9 +152,9 @@ end ...@@ -152,9 +152,9 @@ end
function string.unserialize(str) function string.unserialize(str)
local f, err = loadstring(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 = {} local t = {}
setfenv(f, setmetatable(t, {__index={_G=t}})) setfenv(f, setmetatable(t, {__index={_G=t}}))
local ok, err = pcall(f) 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 end
...@@ -43,7 +43,8 @@ newAI("escort_quest", function(self) ...@@ -43,7 +43,8 @@ newAI("escort_quest", function(self)
if not self.ai_state.fleeing_msg then if not self.ai_state.fleeing_msg then
self.ai_state.fleeing_msg = true self.ai_state.fleeing_msg = true
local enemy = self.ai_target.actor 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 end
else else
self:runAI("move_escort") 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