Skip to content
Snippets Groups Projects
Commit 6f411657 authored by dg's avatar dg
Browse files

traps!

git-svn-id: http://svn.net-core.org/repos/t-engine4@300 51575b47-30f0-44d4-a5cc-537603b46e54
parent c6d8fc1c
No related branches found
No related tags found
No related merge requests found
Showing
with 291 additions and 19 deletions
......@@ -57,6 +57,7 @@ function _M:move(x, y, force)
if y >= map.h then y = map.h - 1 end
self.x, self.y = x, y
map(x, y, Map.ACTOR, self)
map:checkAllEntities(x, y, "on_move", self)
game.level:idleProcessActor(self)
return true
......
......@@ -171,11 +171,14 @@ function _M:loadList(file, no_default, res)
if entities_load_functions[file] and entities_load_functions[file][no_default] then
print("Loading entities file from memory", file)
f = entities_load_functions[file][no_default]
else
elseif fs.exists(file) then
f, err = loadfile(file)
print("Loading entities file from file", file)
entities_load_functions[file] = entities_load_functions[file] or {}
entities_load_functions[file][no_default] = f
else
-- No data
f = function() end
end
if err then error(err) end
......
......@@ -9,15 +9,15 @@ module(..., package.seeall, class.make)
--- The place of a terrain entity in a map grid
TERRAIN = 1
--- The place of a terrain entity in a map grid
TRAP = 50
--- The place of an actor entity in a map grid
ACTOR = 100
--- The place of an object entity in a map grid
OBJECT = 1000
--- The order of display for grid seen
displayOrder = { ACTOR, OBJECT, TERRAIN }
--- The order of display for grids remembered
rememberDisplayOrder = { TERRAIN }
searchOrder = { TERRAIN, TRAP, OBJECT, ACTOR }
--- Sets the viewport size
-- Static
......@@ -128,7 +128,7 @@ function _M:loaded()
self._fov_lite = core.fov.new(_M.opaque, _M.applyLite, self)
self._fov_esp = core.fov.new(_M.opaqueESP, _M.applyESP, self)
self.changed = true
self.loaded = true
self.finished = true
self:redisplay()
end
......@@ -206,8 +206,17 @@ function _M:updateMap(x, y)
local g = self(x, y, TERRAIN)
local o = self(x, y, OBJECT)
local a = self(x, y, ACTOR)
local t = self(x, y, TRAP)
if g then g = self.tiles:get(g.display, g.color_r, g.color_g, g.color_b, g.color_br, g.color_bg, g.color_bb, g.image) end
if t then
-- Handles invisibility and telepathy and other such things
if not self.actor_player or t:knownBy(self.actor_player) then
t = self.tiles:get(t.display, t.color_r, t.color_g, t.color_b, t.color_br, t.color_bg, t.color_bb, t.image)
else
t = nil
end
end
if o then o = self.tiles:get(o.display, o.color_r, o.color_g, o.color_b, o.color_br, o.color_bg, o.color_bb, o.image) end
if a then
-- Handles invisibility and telepathy and other such things
......@@ -218,7 +227,7 @@ function _M:updateMap(x, y)
end
end
self._map:setGrid(x, y, g, o, a)
self._map:setGrid(x, y, g, t, o, a)
end
--- Sets/gets a value from the map
......
require "engine.class"
local Entity = require "engine.Entity"
--- Describes a trap
module(..., package.seeall, class.inherit(Entity))
function _M:init(t, no_default)
t = t or {}
assert(t.triggered, "no trap triggered action")
Entity.init(self, t, no_default)
if self.disarmable == nil then
self.disarmable = true
end
self.known_by = {}
self:loaded()
end
function _M:loaded()
-- known_by table is a weak table on keys, so taht it does not prevent garbage collection of actors
setmetatable(self.known_by, {__mode="k"})
end
--- Setup the trap
function _M:setup()
end
--- Set the known status for the given actor
function _M:setKnown(actor, v)
self.known_by[actor] = v
end
--- Get the known status for the given actor
function _M:knownBy(actor)
print("actor", actor.name, "knows", self.name)
return self.known_by[actor]
end
--- Try to disarm the trap
function _M:disarm(x, y, who)
if not self.disarmable then return false end
end
--- Trigger the trap
function _M:trigger(x, y, who)
if not self.message then
game.logSeen(who, "%s triggers a trap (%s)!", who.name:capitalize(), self.name)
else
local tname = who.name
local str =self.message
str = str:gsub("@target@", tname)
str = str:gsub("@Target@", tname:capitalize())
game.logSeen(who, "%s", str)
end
if self:triggered(x, y, who) then
self:knownBy(who, true)
game.level.map:updateMap(x, y)
end
end
--- When moving on a trap, trigger it
function _M:on_move(x, y, who)
self:trigger(x, y, who)
end
--[=[
require "engine.class"
local Entity = require "engine.Entity"
--- Describes a trap
module(..., package.seeall, class.inherit(Entity))
function _M:init(t, no_default)
t = t or {}
assert(t.triggered, "no trap triggered action")
Entity.init(self, t, no_default)
if self.disarmable == nil then
self.disarmable = true
end
self.known_by_list = {}
self:loaded()
end
function _M:loaded()
-- known_by table is a weak table on keys, so taht it does not prevent garbage collection of actors
self.known_by = {}
setmetatable(self.known_by, {__mode="k"})
setmetatable(self.known_by_list, {__mode="v"})
-- Restore
for i, a in ipairs(self.known_by_list) self.known_by[a] = true end
end
--- Setup the trap
function _M:setup()
end
--- Set the known status for the given actor
function _M:setKnown(actor)
print("actor", actor.name, "knows", self.name)
if not self.known_by[actor] then
self.known_by[actor] = true
table.insert(self.known_by_list, actor)
end
end
--- Get the known status for the given actor
function _M:knownBy(actor)
return self.known_by[actor]
end
--- Try to disarm the trap
function _M:disarm(x, y, who)
if not self.disarmable then return false end
end
--- Trigger the trap
function _M:trigger(x, y, who)
if not self.message then
game.logSeen(who, "%s triggers a trap (%s)!", who.name:capitalize(), self.name)
else
local tname = who.name
local str =self.message
str = str:gsub("@target@", tname)
str = str:gsub("@Target@", tname:capitalize())
game.logSeen(who, "%s", str)
end
if self:triggered(x, y, who) then
self.known_by[who.uid] = true
game.level.map:updateMap(x, y)
end
end
--- When moving on a trap, trigger it
function _M:on_move(x, y, who)
self:trigger(x, y, who)
end
--]=]
\ No newline at end of file
......@@ -16,6 +16,7 @@ function _M:setup(t)
self.level_class = require(t.level_class or "engine.Level")
self.npc_class = require(t.npc_class or "engine.Actor")
self.grid_class = require(t.grid_class or "engine.Grid")
self.trap_class = require(t.trap_class or "engine.Trap")
self.object_class = require(t.object_class or "engine.Object")
end
......@@ -32,6 +33,7 @@ function _M:init(short_name)
self.npc_list = self.npc_class:loadList("/data/zones/"..self.short_name.."/npcs.lua")
self.grid_list = self.grid_class:loadList("/data/zones/"..self.short_name.."/grids.lua")
self.object_list = self.object_class:loadList("/data/zones/"..self.short_name.."/objects.lua")
self.trap_list = self.trap_class:loadList("/data/zones/"..self.short_name.."/traps.lua")
-- Determine a zone base level
self.base_level = self.level_range[1]
......@@ -157,6 +159,7 @@ function _M:makeEntityByName(level, type, name)
if type == "actor" then e = self.npc_list[name]
elseif type == "object" then e = self.object_list[name]
elseif type == "grid" then e = self.grid_list[name]
elseif type == "trap" then e = self.trap_list[name]
end
if not e then return nil end
......@@ -303,6 +306,17 @@ function _M:newLevel(level_data, lev, old_lev, game)
generator:generate()
end
-- Generate traps
if level_data.generator.trap then
local generator = require(level_data.generator.trap.class).new(
self,
map,
level,
spots
)
generator:generate()
end
-- Generate actors
if level_data.generator.actor then
local generator = require(level_data.generator.actor.class).new(
......
......@@ -121,7 +121,13 @@ local function serialize_data(outf, name, value, saved, filter, allow, savefile,
for k,v in pairs(value) do -- save its fields
-- print(allow, k , filter[k])
if (not allow and not filter[k]) or (allow and filter[k]) then
local fieldname = string.format("%s[%s]", name, basicSerialize(k))
local fieldname
-- Special case to handle index by objects
if type(k) == "table" and k.__CLASSNAME then
fieldname = string.format("%s[loadObject('%s')]", name, savefile:getFileName(k))
else
fieldname = string.format("%s[%s]", name, basicSerialize(k))
end
serialize_data(outf, fieldname, v, saved, filter, allow, savefile, false)
end
end
......
require "engine.class"
local Map = require "engine.Map"
require "engine.Generator"
module(..., package.seeall, class.inherit(engine.Generator))
function _M:init(zone, map, level)
engine.Generator.init(self, zone, map)
self.level = level
local data = level.data.generator.trap
-- Setup the entities list
level:setEntitiesList("trap", zone:computeRarities("trap", zone.trap_list, level, nil))
self.filters = data.filters
self.nb_trap = data.nb_trap or {10, 20}
self.level_range = data.level_range or {level, level}
end
function _M:generate()
for i = 1, rng.range(self.nb_trap[1], self.nb_trap[2]) do
local f = nil
if self.filters then f = self.filters[rng.range(1, #self.filters)] end
local o = self.zone:makeEntity(self.level, "trap", f)
if o then
local x, y = rng.range(0, self.map.w), rng.range(0, self.map.h)
local tries = 0
while (self.map:checkEntity(x, y, Map.TERRAIN, "block_move") or self.map(x, y, Map.TRAP)) and tries < 100 do
x, y = rng.range(0, self.map.w-1), rng.range(0, self.map.h-1)
tries = tries + 1
end
if tries < 100 then
self.map(x, y, Map.TRAP, o)
o:added()
end
end
end
end
......@@ -9,7 +9,8 @@ local Target = require "engine.Target"
local Level = require "engine.Level"
local Birther = require "engine.Birther"
local Grid = require "engine.Grid"
local Trap = require "mod.class.Trap"
local Grid = require "mod.class.Grid"
local Actor = require "mod.class.Actor"
local ActorStats = require "engine.interface.ActorStats"
local ActorResource = require "engine.interface.ActorResource"
......@@ -98,7 +99,7 @@ end
function _M:loaded()
engine.GameTurnBased.loaded(self)
Zone:setup{npc_class="mod.class.NPC", grid_class="mod.class.Grid", object_class="mod.class.Object"}
Zone:setup{npc_class="mod.class.NPC", grid_class="mod.class.Grid", object_class="mod.class.Object", trap_class="mod.class.Trap"}
Map:setViewerActor(self.player)
Map:setViewPort(200, 20, self.w - 200, math.floor(self.h * 0.80) - 20, 32, 32, nil, 20, true)
self.key = engine.KeyBind.new()
......@@ -207,7 +208,7 @@ function _M:display()
self.hotkeys_display:display():toScreen(self.hotkeys_display.display_x, self.hotkeys_display.display_y)
-- Now the map, if any
if self.level and self.level.map and self.level.map.loaded then
if self.level and self.level.map and self.level.map.finished then
-- Display the map and compute FOV for the player if needed
if self.level.map.changed then
self.level.map:fovESP(self.player.x, self.player.y, self.player.esp.range or 10)
......@@ -224,7 +225,10 @@ function _M:display()
local ok = false
if game.player:attr("detect_actor") and game.level.map(lx, ly, game.level.map.ACTOR) then ok = true end
if game.player:attr("detect_object") and game.level.map(lx, ly, game.level.map.OBJECT) then ok = true end
-- if game.player:attr("detect_trap") and game.level.map(lx, ly, game.level.map.ACTOR) then ok = true end
if game.player:attr("detect_trap") and game.level.map(lx, ly, game.level.map.TRAP) then
game.level.map(lx, ly, game.level.map.TRAP):setKnown(self.player, true)
ok = true
end
if ok then
game.level.map.seens(lx, ly, true)
......@@ -241,7 +245,7 @@ function _M:display()
-- Display a tooltip if available
local mx, my = core.mouse.get()
local tmx, tmy = self.level.map:getMouseTile(mx, my)
local tt = self.level.map:checkEntity(tmx, tmy, Map.ACTOR, "tooltip") or self.level.map:checkEntity(tmx, tmy, Map.OBJECT, "tooltip") or self.level.map:checkEntity(tmx, tmy, Map.TERRAIN, "tooltip")
local tt = self.level.map:checkEntity(tmx, tmy, Map.ACTOR, "tooltip") or self.level.map:checkEntity(tmx, tmy, Map.OBJECT, "tooltip") or self.level.map:checkEntity(tmx, tmy, Map.TRAP, "tooltip") or self.level.map:checkEntity(tmx, tmy, Map.TERRAIN, "tooltip")
if tt and self.level.map.seens(tmx, tmy) then
self.tooltip:set("%s", tt)
local t = self.tooltip:display()
......
require "engine.class"
require "engine.Trap"
module(..., package.seeall, class.inherit(
engine.Trap
))
function _M:init(t, no_default)
engine.Trap.init(self, t, no_default)
end
--- Returns a tooltip for the trap
function _M:tooltip()
return self.name
end
......@@ -70,6 +70,7 @@ newBirthDescriptor{
[ActorTalents.T_MANATHRUST] = 1,
[ActorTalents.T_FLAME] = 1,
[ActorTalents.T_FREEZE] = 1,
[ActorTalents.T_SENSE] = 5,
},
}
......
......@@ -29,7 +29,6 @@ newEntity{ base = "BASE_NPC_SKELETON",
rarity = 4,
max_life = resolvers.rngavg(40,50),
combat_armor = 5, combat_def = 1,
talents = resolvers.talents{ [Talents.T_SUMMON]=1 },
}
newEntity{ base = "BASE_NPC_SKELETON",
......
......@@ -109,7 +109,11 @@ newEntity{ base = "BASE_SCROLL",
cost = 5,
use_simple = { name="detect enemies within a certain range", use = function(self, who)
who:detect(game.level.map.ACTOR, 20)
local rad = 15 + self:getMag(20)
self:setEffect(self.EFF_SENSE, 2, {
range = rad,
actor = 1,
})
game.logSeen(who, "%s reads a %s!", who.name:capitalize(), self:getName())
return "destroy", true
end}
......
......@@ -59,7 +59,7 @@ newTalent{
self.combat_spellpower = self.combat_spellpower - 5
end,
info = function(self, t)
return [[Your mastery of magic allows your to permanently increase your spellpower by 5.]]
return ([[Your mastery of magic allows your to permanently increase your spellpower by %d.]]):format(5 * self:getTalentLevelRaw(t))
end,
}
......
load("/data/general/traps/basic.lua")
......@@ -30,6 +30,10 @@ return {
nb_object = {6, 9},
filters = { {type="potion" }, {type="potion" }, {type="potion" }, {type="scroll" }, {}, {} }
},
trap = {
class = "engine.generator.trap.Random",
nb_trap = {60, 90},
},
},
levels =
{
......
......@@ -34,6 +34,7 @@ static int map_new(lua_State *L)
map->mheight = mheight;
map->grids_terrain = calloc(w, sizeof(GLuint*));
map->grids_actor = calloc(w, sizeof(GLuint*));
map->grids_trap = calloc(w, sizeof(GLuint*));
map->grids_object = calloc(w, sizeof(GLuint*));
map->grids_seens = calloc(w, sizeof(bool*));
map->grids_remembers = calloc(w, sizeof(bool*));
......@@ -46,6 +47,7 @@ static int map_new(lua_State *L)
map->grids_terrain[i] = calloc(h, sizeof(GLuint));
map->grids_actor[i] = calloc(h, sizeof(GLuint));
map->grids_object[i] = calloc(h, sizeof(GLuint));
map->grids_trap[i] = calloc(h, sizeof(GLuint));
map->grids_seens[i] = calloc(h, sizeof(bool));
map->grids_remembers[i] = calloc(h, sizeof(bool));
map->grids_lites[i] = calloc(h, sizeof(bool));
......@@ -77,6 +79,7 @@ static int map_free(lua_State *L)
{
free(map->grids_terrain[i]);
free(map->grids_actor[i]);
free(map->grids_trap[i]);
free(map->grids_object[i]);
free(map->grids_seens[i]);
free(map->grids_remembers[i]);
......@@ -85,6 +88,7 @@ static int map_free(lua_State *L)
free(map->grids_terrain);
free(map->grids_actor);
free(map->grids_object);
free(map->grids_trap);
free(map->grids_seens);
free(map->grids_remembers);
free(map->grids_lites);
......@@ -98,13 +102,16 @@ static int map_set_grid(lua_State *L)
map_type *map = (map_type*)auxiliar_checkclass(L, "core{map}", 1);
int x = luaL_checknumber(L, 2);
int y = luaL_checknumber(L, 3);
GLuint *t = lua_isnil(L, 4) ? NULL : (GLuint*)auxiliar_checkclass(L, "gl{texture}", 4);
GLuint *o = lua_isnil(L, 5) ? NULL : (GLuint*)auxiliar_checkclass(L, "gl{texture}", 5);
GLuint *a = lua_isnil(L, 6) ? NULL : (GLuint*)auxiliar_checkclass(L, "gl{texture}", 6);
GLuint *g = lua_isnil(L, 4) ? NULL : (GLuint*)auxiliar_checkclass(L, "gl{texture}", 4);
GLuint *t = lua_isnil(L, 5) ? NULL : (GLuint*)auxiliar_checkclass(L, "gl{texture}", 5);
GLuint *o = lua_isnil(L, 6) ? NULL : (GLuint*)auxiliar_checkclass(L, "gl{texture}", 6);
GLuint *a = lua_isnil(L, 7) ? NULL : (GLuint*)auxiliar_checkclass(L, "gl{texture}", 7);
map->grids_terrain[x][y] = t ? *t : 0;
map->grids_terrain[x][y] = g ? *g : 0;
map->grids_trap[x][y] = t ? *t : 0;
map->grids_actor[x][y] = a ? *a : 0;
map->grids_object[x][y] = o ? *o : 0;
return 0;
}
static int map_set_seen(lua_State *L)
......@@ -218,6 +225,16 @@ static int map_to_screen(lua_State *L)
glTexCoord2f(0,1); glVertex3f(0 +dx, map->tile_h +dy,-99);
glEnd();
}
if (map->grids_trap[i][j])
{
glBindTexture(GL_TEXTURE_2D, map->grids_trap[i][j]);
glBegin(GL_QUADS);
glTexCoord2f(0,0); glVertex3f(0 +dx, 0 +dy,-99);
glTexCoord2f(1,0); glVertex3f(map->tile_w +dx, 0 +dy,-99);
glTexCoord2f(1,1); glVertex3f(map->tile_w +dx, map->tile_h +dy,-99);
glTexCoord2f(0,1); glVertex3f(0 +dx, map->tile_h +dy,-99);
glEnd();
}
if (map->grids_object[i][j])
{
glBindTexture(GL_TEXTURE_2D, map->grids_object[i][j]);
......@@ -261,6 +278,16 @@ static int map_to_screen(lua_State *L)
glTexCoord2f(0,1); glVertex3f(0 +dx, map->tile_h +dy,-99);
glEnd();
}
else if (map->grids_trap[i][j])
{
glBindTexture(GL_TEXTURE_2D, map->grids_trap[i][j]);
glBegin(GL_QUADS);
glTexCoord2f(0,0); glVertex3f(0 +dx, 0 +dy,-99);
glTexCoord2f(1,0); glVertex3f(map->tile_w +dx, 0 +dy,-99);
glTexCoord2f(1,1); glVertex3f(map->tile_w +dx, map->tile_h +dy,-99);
glTexCoord2f(0,1); glVertex3f(0 +dx, map->tile_h +dy,-99);
glEnd();
}
else if (map->grids_terrain[i][j])
{
glBindTexture(GL_TEXTURE_2D, map->grids_terrain[i][j]);
......
......@@ -7,6 +7,7 @@ typedef struct {
GLuint **grids_terrain;
GLuint **grids_actor;
GLuint **grids_object;
GLuint **grids_trap;
bool **grids_seens;
bool **grids_remembers;
bool **grids_lites;
......
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