diff --git a/game/engines/default/engine/Particles.lua b/game/engines/default/engine/Particles.lua index 574654b925a0fd1d853a3279b33de524a8256052..3843f506ac2d95f4a6b8b4d8a0ef3ab30da8920c 100644 --- a/game/engines/default/engine/Particles.lua +++ b/game/engines/default/engine/Particles.lua @@ -70,5 +70,10 @@ function _M:loaded() gl = self.__particles_gl[gl] self.update = fct - self.ps = core.particles.newEmitter(max or 1000, no_stop, config.settings.particles_density or 100, def, gl) + -- Make a gas cloud + if def.gas then + self.ps = core.gas.newEmitter(def.gas.w, def.gas.h, config.settings.particles_density or 100, def, gl) + else + self.ps = core.particles.newEmitter(max or 1000, no_stop, config.settings.particles_density or 100, def, gl) + end end diff --git a/game/engines/default/engine/dialogs/Chat.lua b/game/engines/default/engine/dialogs/Chat.lua index 9912a37e7076e7cc1d89ad0531cd7aeea7b92b4a..a595837300b6429db4d6e90348b338b782e7ffde 100644 --- a/game/engines/default/engine/dialogs/Chat.lua +++ b/game/engines/default/engine/dialogs/Chat.lua @@ -79,7 +79,7 @@ function _M:use(item, a) return end end - if a.jump then + if a.jump and not self.killed then self.cur_id = a.jump self:regen() else @@ -92,6 +92,7 @@ function _M:regen() local d = new(self.chat, self.cur_id) d.__showup = false game:replaceDialog(self, d) + self.next_dialog = d end function _M:resolveAuto() --[[ diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua index a149de4d7b9c1ade0df252cb0cc4dd1f6df100e5..e37c3a4452bdf96300971eec00d0472d8ef82b1f 100644 --- a/game/modules/tome/class/Game.lua +++ b/game/modules/tome/class/Game.lua @@ -641,6 +641,7 @@ function _M:setupCommands() end, [{"_g","ctrl"}] = function() if config.settings.tome.cheat then +--[[ local a = mod.class.NPC.new{} a:replaceWith(self.player:cloneFull()) mod.class.NPC.castAs(a) @@ -656,6 +657,8 @@ function _M:setupCommands() a.ai_state = {talent_in=1} a.faction = "enemies" self.zone:addEntity(self.level, a, "actor", self.player.x+1, self.player.y) +--]] + game.level.map:particleEmitter(self.player.x, self.player.y, 1, "breath_fire") end end, } diff --git a/game/modules/tome/data/chats/mage-apprentice-quest.lua b/game/modules/tome/data/chats/mage-apprentice-quest.lua index 44e8d29ffa588780afbe706cabce7d5fb50e3c2a..1bccfcade829bfaffbd7b22ebad675bf62eee018 100644 --- a/game/modules/tome/data/chats/mage-apprentice-quest.lua +++ b/game/modules/tome/data/chats/mage-apprentice-quest.lua @@ -25,7 +25,7 @@ Good day to you, fellow traveler!]], {"I have something for you!", jump="welcome", cond=function(npc, player) return player:hasQuest("mage-apprentice") and player:hasQuest("mage-apprentice"):can_offer(player) end, - action=function(npc, player, dialog) player:hasQuest("mage-apprentice"):collect_staff(player, dialog) end + action=function(npc, player, dialog) player:hasQuest("mage-apprentice"):collect_staff(npc, player, dialog) end }, {"I found this staff; it looks powerful. Maybe it would be enough?", jump="angmar_fall", diff --git a/game/modules/tome/data/gfx/particles/breath_fire.lua b/game/modules/tome/data/gfx/particles/breath_fire.lua new file mode 100644 index 0000000000000000000000000000000000000000..10b39656b6aae6fa7fd7439a8ce855bf91c600ff --- /dev/null +++ b/game/modules/tome/data/gfx/particles/breath_fire.lua @@ -0,0 +1,50 @@ +-- ToME - Tales of Middle-Earth +-- Copyright (C) 2009, 2010 Nicolas Casalini +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see <http://www.gnu.org/licenses/>. +-- +-- Nicolas Casalini "DarkGod" +-- darkgod@te4.org + +local nb = 0 + +return { gas = {w=60, h=60}, +generator = function() + if nb < 10 then + nb = nb + 1 + return { +--[[ + { sx = 3, sy = 29, dx = 3, dy = -3 }, + { sx = 3, sy = 30, dx = 3, dy = 0 }, + { sx = 3, sy = 31, dx = 3, dy = 3 }, + + { sx = 4, sy = 29, dx = 3, dy = -3 }, + { sx = 4, sy = 30, dx = 3, dy = 0 }, + { sx = 4, sy = 31, dx = 3, dy = 3 }, +]] + { sx = 29, sy = 29, dx = -3, dy = -3 }, + { sx = 31, sy = 29, dx = 3, dy = -3 }, + { sx = 29, sy = 31, dx = -3, dy = 3 }, + { sx = 31, sy = 31, dx = 3, dy = 3 }, + + { sx = 30, sy = 29, dx = 0, dy = -3 }, + { sx = 30, sy = 31, dx = 0, dy = 3 }, + { sx = 29, sy = 30, dx = -3, dy = 0 }, + { sx = 31, sy = 30, dx = 3, dy = 0 }, + } + else return {} + end +end, }, +function(self)end, +30*6 diff --git a/game/modules/tome/data/quests/mage-apprentice.lua b/game/modules/tome/data/quests/mage-apprentice.lua index bb8ca2dc1b647a3f412ef49de36569af634964ec..ec4969cddc9118c05a75b121db379b4caa653b21 100644 --- a/game/modules/tome/data/quests/mage-apprentice.lua +++ b/game/modules/tome/data/quests/mage-apprentice.lua @@ -41,7 +41,7 @@ on_status_change = function(self, who, status, sub) end end -collect_staff = function(self, who, dialog) +collect_staff = function(self, npc, who, dialog) who:showEquipInven("Offer which item?", function(o) return (o.type == "weapon" and o.subtype == "staff" and (not o.define_as or o.define_as ~= "STAFF_ANGMAR")) or (o.type == "jewelry" and o.subtype == "ring") or (o.type == "jewelry" and o.subtype == "amulet") end, function(o, inven, item) @@ -49,7 +49,8 @@ collect_staff = function(self, who, dialog) if o.define_as and o.define_as == "STAFF_ABSORPTION" then game.logPlayer(who, "#LIGHT_RED#As the apprentice touches the staff he begins to consume, flames bursting out of his mouth, life seems to be drained away from him and in an instant he collapses in a lifeless husk.") who:setQuestStatus(self, self.FAILED) - game:unregisterDialog(dialog) + game:unregisterDialog(dialog.next_dialog) + npc:die() return true end @@ -58,7 +59,7 @@ collect_staff = function(self, who, dialog) who:removeObject(who:getInven(inven), item) game.log("You have no more %s", o:getName{no_count=true, do_color=true}) who:sortInven(who:getInven(inven)) - dialog:regen() + dialog.next_dialog:regen() return true end ) diff --git a/game/modules/tome/data/talents/gifts/cold-drake.lua b/game/modules/tome/data/talents/gifts/cold-drake.lua index f99efcfdd00890bef8b509fa0b1095303c756e6f..6ef30cf79ab053d910ee31d5d7fd472e25ef0e24 100644 --- a/game/modules/tome/data/talents/gifts/cold-drake.lua +++ b/game/modules/tome/data/talents/gifts/cold-drake.lua @@ -96,7 +96,7 @@ newTalent{ display = '#', color=colors.LIGHT_BLUE, back_color=colors.BLUE, always_remember = true, can_pass = {pass_wall=1}, - does_block_move = true, + block_move = true, block_sight = false, temporary = 4 + self:getTalentLevel(t), x = x, y = y, diff --git a/game/modules/tome/dialogs/LevelupStatsDialog.lua b/game/modules/tome/dialogs/LevelupStatsDialog.lua index aaccd1b413e293eea5f2c8236d97a7115ff4467a..53079867da4337f9d9d2c6eeeddcd0807ba1b281 100644 --- a/game/modules/tome/dialogs/LevelupStatsDialog.lua +++ b/game/modules/tome/dialogs/LevelupStatsDialog.lua @@ -103,8 +103,8 @@ function _M:finish() end end for i, tid in ipairs(reset) do - self.actor:forceUseTalent(tid, {ignore_energy=true, ingore_cd=true}) - self.actor:forceUseTalent(tid, {ignore_energy=true, ingore_cd=true}) + self.actor:forceUseTalent(tid, {ignore_energy=true, ignore_cd=true}) + self.actor:forceUseTalent(tid, {ignore_energy=true, ignore_cd=true}) end end diff --git a/game/modules/tome/dialogs/LevelupTalentsDialog.lua b/game/modules/tome/dialogs/LevelupTalentsDialog.lua index 5bf2332966b52f9cfb4d52536731a8c8087ee495..3f114866716ebcbeef1ca900791852b44186edff 100644 --- a/game/modules/tome/dialogs/LevelupTalentsDialog.lua +++ b/game/modules/tome/dialogs/LevelupTalentsDialog.lua @@ -212,8 +212,8 @@ function _M:finish() end end for i, tid in ipairs(reset) do - self.actor:forceUseTalent(tid, {ignore_energy=true, ingore_cd=true}) - self.actor:forceUseTalent(tid, {ignore_energy=true, ingore_cd=true}) + self.actor:forceUseTalent(tid, {ignore_energy=true, ignore_cd=true}) + self.actor:forceUseTalent(tid, {ignore_energy=true, ignore_cd=true}) end end diff --git a/src/main.c b/src/main.c index 6555cfbcb782e6e91958e6b625ae8c4d4f6e5482..3d228789e48015e425d14cc065773dae1293f638 100644 --- a/src/main.c +++ b/src/main.c @@ -641,6 +641,7 @@ void boot_lua(int state, bool rebooting, int argc, char *argv[]) luaopen_lxp(L); luaopen_map(L); luaopen_particles(L); + luaopen_gas(L); luaopen_sound(L); luaopen_noise(L); luaopen_shaders(L); diff --git a/src/particles_gas.c b/src/particles_gas.c new file mode 100644 index 0000000000000000000000000000000000000000..125bd13075259d4588d8cf5f7d2249057d888338 --- /dev/null +++ b/src/particles_gas.c @@ -0,0 +1,419 @@ +/* + TE4 - T-Engine 4 + Copyright (C) 2009, 2010 Nicolas Casalini + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + + Nicolas Casalini "DarkGod" + darkgod@te4.org +*/ +#include "display.h" +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +#include "auxiliar.h" +#include "types.h" +#include "particles_gas.h" +#include "script.h" +#include <math.h> +#include "SFMT.h" + +#define rng(x, y) (x + rand_div(1 + y - x)) + +static void getinitfield(lua_State *L, const char *key, int *min, int *max) +{ + lua_pushstring(L, key); + lua_gettable(L, -2); + + lua_pushnumber(L, 1); + lua_gettable(L, -2); + *min = (int)lua_tonumber(L, -1); + lua_pop(L, 1); + + lua_pushnumber(L, 2); + lua_gettable(L, -2); + *max = (int)lua_tonumber(L, -1); + lua_pop(L, 1); + +// printf("%s :: %d %d\n", key, (int)*min, (int)*max); + + lua_pop(L, 1); +} + +static void getparticulefield(lua_State *L, const char *k, float *v) +{ + lua_pushstring(L, k); + lua_gettable(L, -2); + *v = (float)lua_tonumber(L, -1); +// printf("emit %s :: %f\n", k, *v); + lua_pop(L, 1); +} + +static int gas_new(lua_State *L) +{ + int w = luaL_checknumber(L, 1); + int h = luaL_checknumber(L, 2); + int density = luaL_checknumber(L, 3); + GLuint *t = (GLuint*)auxiliar_checkclass(L, "gl{texture}", 5); + int t_ref = luaL_ref(L, LUA_REGISTRYINDEX); + int p_ref = luaL_ref(L, LUA_REGISTRYINDEX); + + gaszone_type *gz = (gaszone_type*)lua_newuserdata(L, sizeof(gaszone_type)); + auxiliar_setclass(L, "core{gas}", -1); + + gz->last_tick = -1; + gz->w = w; + gz->h = h; + gz->n = (w*2 > h*2) ? w*2 : h*2; + gz->size = (gz->n + 2) * (gz->n + 2); + + gz->visc = 1E-4f; + gz->diff = 1E-5f; + gz->force = 20.0f; + gz->source = 3000.0f; + gz->stepDelay = 0.0f; + + gz->texture = *t; + gz->texture_ref = t_ref; + + gz->u = calloc(gz->size, sizeof(float)); + gz->v = calloc(gz->size, sizeof(float)); + gz->dens = calloc(gz->size, sizeof(float)); + gz->u_prev = calloc(gz->size, sizeof(float)); + gz->v_prev = calloc(gz->size, sizeof(float)); + gz->dens_prev = calloc(gz->size, sizeof(float)); + + int i; + for (i=0; i < gz->size; i++) + { + gz->u[i] = 0.0f; + gz->u_prev[i] = 0.0f; + gz->v[i] = 0.0f; + gz->v_prev[i] = 0.0f; + gz->dens[i] = 0.0f; + gz->dens_prev[i] = 0.0f; + } + + printf("Making gas emitter with size %dx%d\n", w, h); + + // Grab all parameters + lua_rawgeti(L, LUA_REGISTRYINDEX, p_ref); + + lua_pushstring(L, "generator"); + lua_gettable(L, -2); + if (lua_isnil(L, -1)) + { + lua_pop(L, 1); + gz->generator_ref = LUA_NOREF; + } + else + gz->generator_ref = luaL_ref(L, LUA_REGISTRYINDEX); + + if (gz->generator_ref == LUA_NOREF) + { + lua_pushstring(L, "Gas cloud created without a lua generator!"); + lua_error(L); + } + lua_pop(L, 1); + + luaL_unref(L, LUA_REGISTRYINDEX, p_ref); + + return 1; +} + +static int gas_free(lua_State *L) +{ + gaszone_type *gz = (gaszone_type*)auxiliar_checkclass(L, "core{gas}", 1); + + free(gz->u); + free(gz->v); + free(gz->dens); + free(gz->u_prev); + free(gz->v_prev); + free(gz->dens_prev); + + luaL_unref(L, LUA_REGISTRYINDEX, gz->texture_ref); + if (gz->generator_ref) luaL_unref(L, LUA_REGISTRYINDEX, gz->generator_ref); + + lua_pushnumber(L, 1); + return 1; +} + +#define IX(i,j) ((i)+(gz->n+2)*(j)) +#define SWAP(x0,x) {float *tmp=x0;x0=x;x=tmp;} + +// set boundary conditions +void set_bnd (gaszone_type *gz, int b, float * x ) { + int i; + for ( i=1 ; i<=gz->n ; i++ ) { + // west and east walls + x[IX(0,i)] = b == 1 ? -x[IX(1,i)] : x[IX(1,i)]; + x[IX(gz->n+1,i)] = b == 1 ? -x[IX(gz->n,i)] : x[IX(gz->n,i)]; + // boundary doesn't work on north and south walls... + // dunno why... + x[IX(i,0)] = b == 1 ? -x[IX(i,1)] : x[IX(i,1)]; + x[IX(i,gz->n+1)] = b == 1 ? -x[IX(i,gz->n)] : x[IX(i,gz->n)]; + } + // boundary conditions at corners + x[IX(0 ,0 )] = 0.5*(x[IX(1,0 )]+x[IX(0 ,1)]); + x[IX(0 ,gz->n+1)] = 0.5*(x[IX(1,gz->n+1)]+x[IX(0 ,gz->n )]); + x[IX(gz->n+1,0 )] = 0.5*(x[IX(gz->n,0 )]+x[IX(gz->n+1,1)]); + x[IX(gz->n+1,gz->n+1)] = 0.5*(x[IX(gz->n,gz->n+1)]+x[IX(gz->n+1,gz->n )]); +} + + +// update density map according to density sources +// x : density map +// s : density source map +// dt : elapsed time +void add_source(gaszone_type *gz, float *x, float *s, float dt) { + int i; + for (i=0; i < gz->size; i++) { + x[i] += dt*s[i]; + } +} + +// update density or velocity map for diffusion +// b : boundary width +// x : current density map +// x0 : previous density map +// diff : diffusion coef +// dt : elapsed time +void diffuse(gaszone_type *gz, int b, float *x, float *x0, float diff, float dt) { + float a = diff*dt*gz->n*gz->n; + int i, j, k; + for (k=0; k < 20; k++) { + for (i=1; i <= gz->n; i++ ) { + for (j=1; j<= gz->n; j++) { + x[IX(i,j)] = (x0[IX(i,j)] + a*(x[IX(i-1,j)]+x[IX(i+1,j)] + +x[IX(i,j-1)]+x[IX(i,j+1)]))/(1+4*a); + } + } + set_bnd(gz, b,x); + } +} + +// update density map according to velocity map +// b : boundary width +// d : current density map +// d0 : previous density map +// u,v : current velocity map +// dt : elapsed time +void advect (gaszone_type *gz, int b, float * d, float * d0, float * u, float * v, float dt ) { + int i0, j0, i1, j1; + float x, y, s0, t0, s1, t1, dt0; + + dt0 = dt*gz->n; + int i, j; + for (i=1 ; i<=gz->n ; i++ ) { + for (j=1 ; j<=gz->n ; j++ ) { + x = i-dt0*u[IX(i,j)]; + y = j-dt0*v[IX(i,j)]; + if (x<0.5) x=0.5; + if (x>gz->n+0.5) x=gz->n+ 0.5; + i0=(int)x; + i1=i0+1; + if (y<0.5) y=0.5; + if (y>gz->n+0.5) y=gz->n+ 0.5; + j0=(int)y; + j1=j0+1; + s1 = x-i0; + s0 = 1-s1; + t1 = y-j0; + t0 = 1-t1; + d[IX(i,j)] = s0*(t0*d0[IX(i0,j0)]+t1*d0[IX(i0,j1)])+ + s1*(t0*d0[IX(i1,j0)]+t1*d0[IX(i1,j1)]); + } + } + set_bnd (gz, b, d ); +} + +void project (gaszone_type *gz, float * u, float * v, float * p, float * div ) { + int i, j, k; + + float h = 1.0/gz->n; + for (i=1 ; i<=gz->n ; i++ ) { + for (j=1 ; j<=gz->n ; j++ ) { + div[IX(i,j)] = -0.5*h*(u[IX(i+1,j)]-u[IX(i-1,j)]+ + v[IX(i,j+1)]-v[IX(i,j-1)]); + p[IX(i,j)] = 0; + } + } + set_bnd (gz, 0, div ); set_bnd (gz, 0, p ); + + for (k=0 ; k<19 ; k++ ) { + for (i=1 ; i<=gz->n ; i++ ) { + for (j=1 ; j<=gz->n ; j++ ) { + p[IX(i,j)] = (div[IX(i,j)] + p[IX(i-1,j)] + p[IX(i+1,j)] + p[IX(i,j-1)] + p[IX(i,j+1)]) / 4; + } + } + set_bnd (gz, 0, p ); + } + + for (i=1 ; i<=gz->n ; i++ ) { + for (j=1 ; j<=gz->n ; j++ ) { + u[IX(i,j)] -= 0.5*(p[IX(i+1,j)]-p[IX(i-1,j)])/h; + v[IX(i,j)] -= 0.5*(p[IX(i,j+1)]-p[IX(i,j-1)])/h; + } + } + set_bnd (gz, 1, u ); set_bnd (gz, 2, v ); +} + +// do all three density steps +void update_density (gaszone_type *gz, float * x, float * x0, float * u, float * v, float diff, float dt ) { + add_source (gz, x, x0, dt ); + SWAP ( x0, x ); diffuse (gz, 0, x, x0, diff, dt ); + SWAP ( x0, x ); advect (gz, 0, x, x0, u, v, dt ); +} + +void update_velocity(gaszone_type *gz, float * u, float * v, float * u0, float * v0, float visc, float dt ) { + add_source (gz, u, u0, dt ); + add_source (gz, v, v0, dt ); + SWAP ( u0, u ); diffuse (gz, 1, u, u0, visc, dt ); + SWAP ( v0, v ); diffuse (gz, 2, v, v0, visc, dt ); + project (gz, u, v, u0, v0 ); + SWAP ( u0, u ); SWAP ( v0, v ); + advect (gz, 1, u, u0, u0, v0, dt ); advect (gz, 2, v, v0, u0, v0, dt ); + project (gz, u, v, u0, v0 ); +} + +void add_data (gaszone_type *gz, float * d, float * u, float * v, float elapsed) +{ + int i; + for ( i=0 ; i < gz->size; i++ ) + { + u[i] = v[i] = d[i] = 0.0f; + } + + int px; + int py; + float dx; + float dy; + + lua_rawgeti(L, LUA_REGISTRYINDEX, gz->generator_ref); + lua_call(L, 0, 1); + if (!lua_isnil(L, -1)) + { + int len = lua_objlen(L, -1); + for (i = 1; i <= len; i++) + { + lua_pushnumber(L, i); + lua_gettable(L, -2); + + float tmp; + getparticulefield(L, "sx", &tmp); px = tmp; + getparticulefield(L, "sy", &tmp); py = tmp; + getparticulefield(L, "dx", &dx); + getparticulefield(L, "dy", &dy); + float l = sqrt(dx*dx+dy*dy); + if (l > 0.0f) + { + l = 1.0f / l; + dx *= l; + dy *= l; + u[IX(px*2, py*2)] = gz->force * dx; + v[IX(px*2, py*2)] = gz->force * dy; + d[IX(px*2, py*2)] = gz->source; + } + + lua_pop(L, 1); + } + lua_pop(L, 1); + } +} + +void update(gaszone_type *gz, float elapsed) { + add_data(gz, gz->dens_prev, gz->u_prev, gz->v_prev, elapsed); + update_velocity(gz, gz->u, gz->v, gz->u_prev, gz->v_prev, gz->visc, elapsed); + update_density(gz, gz->dens, gz->dens_prev, gz->u, gz->v, gz->diff, elapsed); +} + +#define CLAMP(a, b, x) ((x) < (a) ? (a) : ((x) > (b) ? (b) : (x))) + +static int gas_emit(lua_State *L) +{ + gaszone_type *gz = (gaszone_type*)auxiliar_checkclass(L, "core{gas}", 1); + + return 0; +} + +static int gas_to_screen(lua_State *L) +{ + gaszone_type *gz = (gaszone_type*)auxiliar_checkclass(L, "core{gas}", 1); + int x = luaL_checknumber(L, 2); + int y = luaL_checknumber(L, 3); + bool show = lua_toboolean(L, 4); + float zoom = luaL_checknumber(L, 5); + int w = 0; + int i, j, dx, dy; + bool alive = FALSE; + + glBindTexture(GL_TEXTURE_2D, gz->texture); + + if (gz->last_tick == -1) gz->last_tick = ((float)SDL_GetTicks()) / 1000.0f - 1; + + float now = ((float)SDL_GetTicks()) / 1000.0f; + update(gz, now - gz->last_tick); + gz->last_tick = now; + + for (dx=0; dx <= gz->n; dx++) + { + for (dy = 0; dy <= gz->n; dy++) + { + float coef = (float)(gz->dens[IX(dx, dy)] / 128.0f); + coef = CLAMP(0.0f, 1.0f, coef); + if (coef > 0.1) + { + glColor4f(coef, 0, 0, coef); + + glBegin(GL_QUADS); + i = x + dx * 4; + j = y + dy * 4; + glTexCoord2f(0,0); glVertex3f(0 + i, 0 + j, -97); + glTexCoord2f(1,0); glVertex3f(10 + i, 0 + j, -97); + glTexCoord2f(1,1); glVertex3f(10 + i, 10 + j, -97); + glTexCoord2f(0,1); glVertex3f(0 + i, 10 + j, -97); + glEnd(); + } + } + } + + // Restore normal display + glColor4f(1, 1, 1, 1); + + lua_pushboolean(L, 1); + return 1; +} + +static const struct luaL_reg gaslib[] = +{ + {"newEmitter", gas_new}, + {NULL, NULL}, +}; + +static const struct luaL_reg gas_reg[] = +{ + {"__gc", gas_free}, + {"close", gas_free}, + {"emit", gas_emit}, + {"toScreen", gas_to_screen}, + {NULL, NULL}, +}; + +int luaopen_gas(lua_State *L) +{ + auxiliar_newclass(L, "core{gas}", gas_reg); + luaL_openlib(L, "core.gas", gaslib, 0); + return 1; +} diff --git a/src/particles_gas.h b/src/particles_gas.h new file mode 100644 index 0000000000000000000000000000000000000000..9529d5a689efcd8303336bc063e755b989f1062b --- /dev/null +++ b/src/particles_gas.h @@ -0,0 +1,50 @@ +/* + TE4 - T-Engine 4 + Copyright (C) 2009, 2010 Nicolas Casalini + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + + Nicolas Casalini "DarkGod" + darkgod@te4.org +*/ +#ifndef _PARTICLES_H_ +#define _PARTICLES_H_ + +#include "tgl.h" + +typedef struct { + GLuint texture; + int texture_ref; + int generator_ref; + + float last_tick; + + int w, h; + int size; + int n; + + // 2D velocity maps (current and previous) + float *u, *v, *u_prev, *v_prev; + + // density maps (current and previous) + float *dens, *dens_prev; + + float visc; + float diff; + float force; + float source; + float stepDelay; +} gaszone_type; + +#endif