From 07fc781c3accf18d2f9e7f6926b4ec3d14649893 Mon Sep 17 00:00:00 2001 From: dg <dg@51575b47-30f0-44d4-a5cc-537603b46e54> Date: Sun, 13 Feb 2011 12:55:23 +0000 Subject: [PATCH] New smooth FOV shading (aka fog of war). Instead of being squares it will smooth transitions between seens and unseen tiles (only works with opengl framebuffers enabled) git-svn-id: http://svn.net-core.org/repos/t-engine4@2715 51575b47-30f0-44d4-a5cc-537603b46e54 --- game/engines/default/engine/Map.lua | 11 +- game/modules/tome/class/Game.lua | 26 +-- game/modules/tome/class/Player.lua | 1 + .../tome/data/gfx/shaders/main_fbo.frag | 36 +++- .../tome/data/gfx/shaders/main_fbo.lua | 1 + .../gfx/shockbolt/trap/poison_vines01.png | Bin 7969 -> 10320 bytes game/modules/tome/data/talents/misc/npcs.lua | 3 +- src/core_lua.c | 2 +- src/map.c | 166 +++++++++++++++--- src/map.h | 8 +- 10 files changed, 202 insertions(+), 52 deletions(-) diff --git a/game/engines/default/engine/Map.lua b/game/engines/default/engine/Map.lua index 8ddb87af03..3dc3841d93 100644 --- a/game/engines/default/engine/Map.lua +++ b/game/engines/default/engine/Map.lua @@ -444,14 +444,17 @@ function _M:minimapDisplay(dx, dy, x, y, w, h, transp) self._map:toScreenMiniMap(dx, dy, x, y, w, h, transp or 0.6) end ---- Displays the map on a surface --- @return a surface containing the drawn map -function _M:display(x, y, nb_keyframe) +--- Displays the map on screen +-- @param x the coord where to start drawing, if null it uses self.display_x +-- @param y the coord where to start drawing, if null it uses self.display_y +-- @param nb_keyframes the number of keyframes elapsed since last draw +-- @param always_show tell the map code to force display unseed entities as remembered (used for smooth FOV shading) +function _M:display(x, y, nb_keyframe, always_show) nb_keyframes = nb_keyframes or 1 local ox, oy = self.display_x, self.display_y self.display_x, self.display_y = x or self.display_x, y or self.display_y - self._map:toScreen(self.display_x, self.display_y, nb_keyframe) + self._map:toScreen(self.display_x, self.display_y, nb_keyframe, always_show) -- Tactical display if self.view_faction then diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua index df762e958b..2625f73bfa 100644 --- a/game/modules/tome/class/Game.lua +++ b/game/modules/tome/class/Game.lua @@ -338,6 +338,14 @@ function _M:setupDisplayMode(reboot, mode) if gfx.tiles == "ascii" then Map.tiles.use_images = false Map.tiles.force_back_color = {r=0, g=0, b=0, a=255} end if gfx.tiles == "ascii_full" then Map.tiles.use_images = false end if gfx.tiles == "shockbolt" then Map.tiles.nicer_tiles = true end + + -- Create the framebuffer + self.fbo = core.display.newFBO(Map.viewport.width, Map.viewport.height) + if self.fbo then + self.fbo_shader = Shader.new("main_fbo") + if not self.fbo_shader.shad then self.fbo = nil self.fbo_shader = nil end + end + if self.player then self.player:updateMainShader() end end if not mode or mode == "postinit" then @@ -347,14 +355,6 @@ function _M:setupDisplayMode(reboot, mode) self.level.map:moveViewSurround(self.player.x, self.player.y, 8, 8) end self:setupMiniMap() - - -- Create the framebuffer - self.fbo = core.display.newFBO(Map.viewport.width, Map.viewport.height) - if self.fbo then - self.fbo_shader = Shader.new("main_fbo") - if not self.fbo_shader.shad then self.fbo = nil self.fbo_shader = nil end - end - if self.player then self.player:updateMainShader() end end end @@ -729,7 +729,8 @@ function _M:display(nb_keyframes) -- Now the map, if any 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 + local changed = self.level.map.changed + if changed then self.player:playerFOV() end @@ -738,18 +739,21 @@ function _M:display(nb_keyframes) self.fbo:use(true) if self.level.data.background then self.level.data.background(self.level, 0, 0, nb_keyframes) end - self.level.map:display(0, 0, nb_keyframes) - self.target:display(0, 0) + self.level.map:display(0, 0, nb_keyframes, true) -- Display at the base of the FBO and make sure to display everything as the shader will do smooth FOV over it if self.level.data.foreground then self.level.data.foreground(self.level, 0, 0, nb_keyframes) end if self.level.data.weather_particle then self.state:displayWeather(self.level, self.level.data.weather_particle, nb_keyframes) end self.fbo:use(false) _2DNoise:bind(1, false) + if changed then self.level.map._map:updateSeensTexture() end + self.level.map._map:bindSeensTexture(2) + self.fbo_shader:setUniform("seensinfo", {self.level.map._map:getSeensInfo()}) self.fbo:toScreen( self.level.map.display_x, self.level.map.display_y, self.level.map.viewport.width, self.level.map.viewport.height, self.fbo_shader.shad ) + self.target:display() -- Basic display else diff --git a/game/modules/tome/class/Player.lua b/game/modules/tome/class/Player.lua index a84ff27ac5..6d141ac749 100644 --- a/game/modules/tome/class/Player.lua +++ b/game/modules/tome/class/Player.lua @@ -731,6 +731,7 @@ function _M:playerUseItem(object, item, inven) if game.zone.wilderness then game.logPlayer(self, "You cannot use items on the world map.") return end local use_fct = function(o, inven, item) + if not o then return end local co = coroutine.create(function() self.changed = true diff --git a/game/modules/tome/data/gfx/shaders/main_fbo.frag b/game/modules/tome/data/gfx/shaders/main_fbo.frag index 013d4d9cba..5e68631fc9 100644 --- a/game/modules/tome/data/gfx/shaders/main_fbo.frag +++ b/game/modules/tome/data/gfx/shaders/main_fbo.frag @@ -5,11 +5,35 @@ uniform float tick; uniform sampler2D noisevol; uniform vec2 texSize; uniform sampler2D tex; +uniform sampler2D seens; +uniform vec4 seensinfo; uniform vec3 colorize; +// Return the given pixel, this allows things like blur to work even with smooth fov shading +vec4 get_pixel(vec2 coord) +{ + /* + * Few lines to do some tricky things + * The game provides use with a "seens" texture that is the computed FOV + * We use this to lookup the current tile and shadow it as needed + * seenscoords is arranged as this: (tile_w, tile_h, view_scene_w, view_scene_h) + * We offset by 1x1.25 tiles .. dont ask why, it just works :/ + */ + vec2 seenscoord = vec2((((coord.x + 64 / texSize.x) / seensinfo.r)) * texSize.x / seensinfo.b, (((coord.y + 80 / texSize.y) / seensinfo.g)) * texSize.y / seensinfo.a); + vec3 seen = texture2D(seens, seenscoord); + vec4 res = texture2D(tex, coord.xy); + res.r *= seen.r; + res.g *= seen.g; + res.b *= seen.b; + + // Now we got our shaded pixel, we can do otehr stuff with it +// res = texture2D(tex, coord.xy); // this is a non shading version + return res; +} + void main(void) { - gl_FragColor = texture2D(tex, gl_TexCoord[0].xy); + gl_FragColor = get_pixel(gl_TexCoord[0]); if (motionblur > 0.0) { @@ -34,7 +58,7 @@ void main(void) { for(int j = -blursize; j <= 0; j++) { - sample += texture2D(tex, vec2(gl_TexCoord[0].xy+vec2(float(i)*offset.x, float(j)*offset.y))); + sample += get_pixel(vec2(gl_TexCoord[0].xy+vec2(float(i)*offset.x, float(j)*offset.y))); } } } @@ -44,7 +68,7 @@ void main(void) { for(int j = 0; j <= blursize; j++) { - sample += texture2D(tex, vec2(gl_TexCoord[0].xy+vec2(float(i)*offset.x, float(j)*offset.y))); + sample += get_pixel(vec2(gl_TexCoord[0].xy+vec2(float(i)*offset.x, float(j)*offset.y))); } } } @@ -54,7 +78,7 @@ void main(void) { for(int j = -blursize; j <= 0; j++) { - sample += texture2D(tex, vec2(gl_TexCoord[0].xy+vec2(float(i)*offset.x, float(j)*offset.y))); + sample += get_pixel(vec2(gl_TexCoord[0].xy+vec2(float(i)*offset.x, float(j)*offset.y))); } } } @@ -64,7 +88,7 @@ void main(void) { for(int j = 0; j <= blursize; j++) { - sample += texture2D(tex, vec2(gl_TexCoord[0].xy+vec2(float(i)*offset.x, float(j)*offset.y))); + sample += get_pixel(vec2(gl_TexCoord[0].xy+vec2(float(i)*offset.x, float(j)*offset.y))); } } } @@ -86,7 +110,7 @@ void main(void) { for(int j = -blursize; j <= blursize; j++) { - sample += texture2D(tex, vec2(gl_TexCoord[0].xy+vec2(float(i)*offset.x, float(j)*offset.y))); + sample += get_pixel(vec2(gl_TexCoord[0].xy+vec2(float(i)*offset.x, float(j)*offset.y))); } } sample /= (blur*2.0) * (blur*2.0); diff --git a/game/modules/tome/data/gfx/shaders/main_fbo.lua b/game/modules/tome/data/gfx/shaders/main_fbo.lua index 9eadd16867..423e85468f 100644 --- a/game/modules/tome/data/gfx/shaders/main_fbo.lua +++ b/game/modules/tome/data/gfx/shaders/main_fbo.lua @@ -23,6 +23,7 @@ return { args = { tex = { texture = 0 }, noisevol = { texture = 1 }, + seens = { texture = 2 }, }, clone = false, } diff --git a/game/modules/tome/data/gfx/shockbolt/trap/poison_vines01.png b/game/modules/tome/data/gfx/shockbolt/trap/poison_vines01.png index e84fe111458c95d0156c93396b062a4ec06cc997..d073c63f575fba21148045b53381f90981bfd1df 100644 GIT binary patch delta 10291 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 FV1oG*C@=s3 delta 7921 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 bvj05*C97VGR&u}?00000NkvXXu0mjf1+KaA diff --git a/game/modules/tome/data/talents/misc/npcs.lua b/game/modules/tome/data/talents/misc/npcs.lua index 58d104ba4a..a54e967427 100644 --- a/game/modules/tome/data/talents/misc/npcs.lua +++ b/game/modules/tome/data/talents/misc/npcs.lua @@ -744,13 +744,14 @@ newTalent{ detect_power = 6 * self:getTalentLevel(t), disarm_power = 10 * self:getTalentLevel(t), level_range = {self.level, self.level}, message = "@Target@ is caught in a web!", + pin_dur = dur, canTrigger = function(self, x, y, who) if who.type == "spiderkin" then return false end return mod.class.Trap.canTrigger(self, x, y, who) end, triggered = function(self, x, y, who) if who:checkHit(self.disarm_power + 5, who:combatPhysicalResist(), 0, 95, 15) and who:canBe("stun") and who:canBe("pin") then - who:setEffect(who.EFF_PINNED, dur, {}) + who:setEffect(who.EFF_PINNED, self.pin_dur, {}) else game.logSeen(who, "%s resists!", who.name:capitalize()) end diff --git a/src/core_lua.c b/src/core_lua.c index a6e2cbc9dd..56ab81fcde 100644 --- a/src/core_lua.c +++ b/src/core_lua.c @@ -1373,7 +1373,7 @@ static int gl_fbo_toscreen(lua_State *L) if (lua_isuserdata(L, 6)) { shader_type *s = (shader_type*)auxiliar_checkclass(L, "gl{program}", 6); - useShader(s, 0, 0, w, h, r, g, b, a); + useShader(s, fbo->w, fbo->h, w, h, r, g, b, a); } glDisable(GL_BLEND); diff --git a/src/map.c b/src/map.c index 8771dd872b..b9e7fae71d 100644 --- a/src/map.c +++ b/src/map.c @@ -497,17 +497,25 @@ static int map_new(lua_State *L) map->mwidth = mwidth; map->mheight = mheight; map->grids = calloc(w, sizeof(map_object***)); - map->grids_seens = calloc(w, sizeof(float*)); + map->grids_seens = calloc(w * h, sizeof(float)); map->grids_remembers = calloc(w, sizeof(bool*)); map->grids_lites = calloc(w, sizeof(bool*)); map->minimap = calloc(w, sizeof(unsigned char*)); printf("C Map size %d:%d :: %d\n", mwidth, mheight,mwidth * mheight); + glGenTextures(1, &(map->seens_texture)); + tglBindTexture(GL_TEXTURE_2D, map->seens_texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, 4, map->mwidth + 3, map->mheight + 3, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL); + map->seens_map = calloc((map->mwidth + 3)*(map->mheight + 3)*4, sizeof(GLubyte)); + for (i = 0; i < w; i++) { map->grids[i] = calloc(h, sizeof(map_object**)); for (j = 0; j < h; j++) map->grids[i][j] = calloc(zdepth, sizeof(map_object*)); - map->grids_seens[i] = calloc(h, sizeof(float)); +// map->grids_seens[i] = calloc(h, sizeof(float)); map->grids_remembers[i] = calloc(h, sizeof(bool)); map->grids_lites[i] = calloc(h, sizeof(bool)); map->minimap[i] = calloc(h, sizeof(unsigned char)); @@ -525,7 +533,7 @@ static int map_free(lua_State *L) { for (j = 0; j < map->h; j++) free(map->grids[i][j]); free(map->grids[i]); - free(map->grids_seens[i]); +// free(map->grids_seens[i]); free(map->grids_remembers[i]); free(map->grids_lites[i]); free(map->minimap[i]); @@ -542,6 +550,9 @@ static int map_free(lua_State *L) luaL_unref(L, LUA_REGISTRYINDEX, map->mo_list_ref); + glDeleteTextures(1, &map->seens_texture); + free(map->seens_map); + lua_pushnumber(L, 1); return 1; } @@ -645,7 +656,7 @@ static int map_set_seen(lua_State *L) float v = lua_tonumber(L, 4); if (x < 0 || y < 0 || x >= map->w || y >= map->h) return 0; - map->grids_seens[x][y] = v; + map->grids_seens[y*map->w+x] = v; return 0; } @@ -680,7 +691,7 @@ static int map_clean_seen(lua_State *L) for (i = 0; i < map->w; i++) for (j = 0; j < map->h; j++) - map->grids_seens[i][j] = 0; + map->grids_seens[j*map->w+i] = 0; return 0; } @@ -706,6 +717,87 @@ static int map_clean_lite(lua_State *L) return 0; } +static int map_get_seensinfo(lua_State *L) +{ + map_type *map = (map_type*)auxiliar_checkclass(L, "core{map}", 1); + lua_pushnumber(L, map->tile_w); + lua_pushnumber(L, map->tile_h); + lua_pushnumber(L, map->seensinfo_w); + lua_pushnumber(L, map->seensinfo_h); + return 4; +} + +static int map_update_seen_texture(lua_State *L) +{ + map_type *map = (map_type*)auxiliar_checkclass(L, "core{map}", 1); + + tglBindTexture(GL_TEXTURE_2D, map->seens_texture); + + int mx = map->used_mx; + int my = map->used_my; + GLubyte *seens = map->seens_map; + int ptr = 0; + int ii, jj; + map->seensinfo_w = map->mwidth + 3; + map->seensinfo_h = map->mheight + 3; + + for (jj = map->mheight + 3 - 1; jj >= 0; jj--) + { + for (ii = 0; ii < map->mwidth + 3; ii++) + { + int i = mx - 1 + ii, j = my - 1 + jj; + if ((i < 0) || (j < 0) || (i >= map->w) || (j >= map->h)) + { + seens[ptr] = 0; + seens[ptr+1] = 0; + seens[ptr+2] = 0; + seens[ptr+3] = 255; + ptr += 4; + continue; + } + float v = map->grids_seens[j*map->w+i] * 255; + if (v) + { + if (v > 255) v = 255; + if (v < 0) v = 0; + seens[ptr] = (GLubyte)(map->shown_b * v); + seens[ptr+1] = (GLubyte)(map->shown_g * v); + seens[ptr+2] = (GLubyte)(map->shown_r * v); + } + else if (map->grids_remembers[i][j]) + { + seens[ptr] = (GLubyte)(map->obscure_b * 255); + seens[ptr+1] = (GLubyte)(map->obscure_g * 255); + seens[ptr+2] = (GLubyte)(map->obscure_r * 255); + } + else + { + seens[ptr] = 0; + seens[ptr+1] = 0; + seens[ptr+2] = 0; + } + seens[ptr+3] = 255; + ptr += 4; + } + } + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, map->mwidth + 3, map->mheight + 3, GL_BGRA, GL_UNSIGNED_BYTE, seens); + + return 0; +} + +static int map_bind_seen_texture(lua_State *L) +{ + map_type *map = (map_type*)auxiliar_checkclass(L, "core{map}", 1); + int unit = luaL_checknumber(L, 2); + if (unit > 0 && !multitexture_active) return 0; + + if (unit > 0) tglActiveTexture(GL_TEXTURE0+unit); + tglBindTexture(GL_TEXTURE_2D, map->seens_texture); + if (unit > 0) tglActiveTexture(GL_TEXTURE0); + + return 0; +} + static int map_set_scroll(lua_State *L) { map_type *map = (map_type*)auxiliar_checkclass(L, "core{map}", 1); @@ -800,8 +892,8 @@ static int map_get_scroll(lua_State *L) } \ } -inline void display_map_quad(GLuint *cur_tex, int *vert_idx, int *col_idx, map_type *map, int dx, int dy, float dz, map_object *m, int i, int j, float a, float seen, int nb_keyframes) ALWAYS_INLINE; -void display_map_quad(GLuint *cur_tex, int *vert_idx, int *col_idx, map_type *map, int dx, int dy, float dz, map_object *m, int i, int j, float a, float seen, int nb_keyframes) +inline void display_map_quad(GLuint *cur_tex, int *vert_idx, int *col_idx, map_type *map, int dx, int dy, float dz, map_object *m, int i, int j, float a, float seen, int nb_keyframes, bool always_show) ALWAYS_INLINE; +void display_map_quad(GLuint *cur_tex, int *vert_idx, int *col_idx, map_type *map, int dx, int dy, float dz, map_object *m, int i, int j, float a, float seen, int nb_keyframes, bool always_show) { float r, g, b; GLfloat *vertices = map->vertices; @@ -811,29 +903,40 @@ void display_map_quad(GLuint *cur_tex, int *vert_idx, int *col_idx, map_type *ma /******************************************************** ** Select the color to use ********************************************************/ - if (seen) + if (always_show) { - if (m->tint_r < 1 || m->tint_g < 1 || m->tint_b < 1) - { - r = (map->shown_r + m->tint_r)/2; g = (map->shown_g + m->tint_g)/2; b = (map->shown_b + m->tint_b)/2; - } - else - { - r = map->shown_r; g = map->shown_g; b = map->shown_b; - } - r *= seen; - g *= seen; - b *= seen; + // In smooth fov mode it's the shader that does FOV display + r = m->tint_r; g = m->tint_g; b = m->tint_b; + a = 1; } else { - if (m->tint_r < 1 || m->tint_g < 1 || m->tint_b < 1) + if (seen) { - r = (map->obscure_r + m->tint_r)/2; g = (map->obscure_g + m->tint_g)/2; b = (map->obscure_b + m->tint_b)/2; + if (m->tint_r < 1 || m->tint_g < 1 || m->tint_b < 1) + { + r = (map->shown_r + m->tint_r)/2; g = (map->shown_g + m->tint_g)/2; b = (map->shown_b + m->tint_b)/2; + } + else + { + r = map->shown_r; g = map->shown_g; b = map->shown_b; + } + r *= seen; + g *= seen; + b *= seen; + a = seen; } else { - r = map->obscure_r; g = map->obscure_g; b = map->obscure_b; + if (m->tint_r < 1 || m->tint_g < 1 || m->tint_b < 1) + { + r = (map->obscure_r + m->tint_r)/2; g = (map->obscure_g + m->tint_g)/2; b = (map->obscure_b + m->tint_b)/2; + } + else + { + r = map->obscure_r; g = map->obscure_g; b = map->obscure_b; + } + a = map->obscure_r; } } @@ -932,6 +1035,7 @@ static int map_to_screen(lua_State *L) int x = luaL_checknumber(L, 2); int y = luaL_checknumber(L, 3); int nb_keyframes = luaL_checknumber(L, 4); + bool always_show = lua_toboolean(L, 5); int i = 0, j = 0, z = 0; int vert_idx = 0; int col_idx = 0; @@ -952,6 +1056,9 @@ static int map_to_screen(lua_State *L) x -= animdx; y -= animdy; + map->used_mx = mx; + map->used_my = my; + // Always display some more of the map to make sure we always see it all for (z = 0; z < map->zdepth; z++) { @@ -966,15 +1073,15 @@ static int map_to_screen(lua_State *L) map_object *mo = map->grids[i][j][z]; if (!mo) continue; - if ((mo->on_seen && map->grids_seens[i][j]) || (mo->on_remember && map->grids_remembers[i][j]) || mo->on_unknown) + if ((mo->on_seen && map->grids_seens[j*map->w+i]) || (mo->on_remember && (always_show || map->grids_remembers[i][j])) || mo->on_unknown) { - if (map->grids_seens[i][j]) + if (map->grids_seens[j*map->w+i]) { - display_map_quad(&cur_tex, &vert_idx, &col_idx, map, dx, dy, z, mo, i, j, map->shown_a, map->grids_seens[i][j], nb_keyframes); + display_map_quad(&cur_tex, &vert_idx, &col_idx, map, dx, dy, z, mo, i, j, map->shown_a, map->grids_seens[j*map->w+i], nb_keyframes, always_show); } else { - display_map_quad(&cur_tex, &vert_idx, &col_idx, map, dx, dy, z, mo, i, j, map->obscure_a, 0, nb_keyframes); + display_map_quad(&cur_tex, &vert_idx, &col_idx, map, dx, dy, z, mo, i, j, map->obscure_a, 0, nb_keyframes, always_show); } } } @@ -1039,9 +1146,9 @@ static int minimap_to_screen(lua_State *L) map_object *mo = map->grids[i][j][z]; if (!mo || mo->mm_r < 0) continue; - if ((mo->on_seen && map->grids_seens[i][j]) || (mo->on_remember && map->grids_remembers[i][j]) || mo->on_unknown) + if ((mo->on_seen && map->grids_seens[j*map->w+i]) || (mo->on_remember && map->grids_remembers[i][j]) || mo->on_unknown) { - if (map->grids_seens[i][j]) + if (map->grids_seens[j*map->w+i]) { r = mo->mm_r; g = mo->mm_g; b = mo->mm_b; a = transp; colors[col_idx] = r; colors[col_idx+1] = g; colors[col_idx+2] = b; colors[col_idx+3] = (a); @@ -1097,6 +1204,8 @@ static const struct luaL_reg map_reg[] = { {"__gc", map_free}, {"close", map_free}, + {"updateSeensTexture", map_update_seen_texture}, + {"bindSeensTexture", map_bind_seen_texture}, {"setZoom", map_set_zoom}, {"setShown", map_set_shown}, {"setObscure", map_set_obscure}, @@ -1107,6 +1216,7 @@ static const struct luaL_reg map_reg[] = {"setSeen", map_set_seen}, {"setRemember", map_set_remember}, {"setLite", map_set_lite}, + {"getSeensInfo", map_get_seensinfo}, {"setScroll", map_set_scroll}, {"getScroll", map_get_scroll}, {"toScreen", map_to_screen}, diff --git a/src/map.h b/src/map.h index 08125680af..a885e8fb12 100644 --- a/src/map.h +++ b/src/map.h @@ -50,7 +50,7 @@ typedef struct { typedef struct { map_object* ***grids; - float **grids_seens; + float *grids_seens; bool **grids_remembers; bool **grids_lites; unsigned char **minimap; @@ -58,6 +58,9 @@ typedef struct { GLfloat *vertices; GLfloat *colors; GLfloat *texcoords; + GLubyte *seens_map; + + GLuint seens_texture; int mo_list_ref; @@ -78,6 +81,9 @@ typedef struct { int mx, my, mwidth, mheight; float oldmx, oldmy; int move_step, move_max; + float used_mx, used_my; + int seensinfo_w; + int seensinfo_h; } map_type; #endif -- GitLab