#include "luastack.hpp" #include "cellgrid.hpp" #include "table.hpp" #include #include LuaDefine(cellgrid_initregistry, "a") { LuaVar grid; LuaStack LS(L, grid); LS.getfield(grid, LuaRegistry, "cellgrid_cells"); if (LS.isnil(grid)) { LS.newtable(grid); LS.setfield(LuaRegistry, "cellgrid_cells", grid); } return LS.result(); } LuaDefine(cellgrid_addplane, "c") { LuaArg grid, plane; LuaVar planegrid; LuaStack LS(L, grid, plane, planegrid); // Get the grid. if (LS.isnil(grid)) LS.getfield(grid, LuaRegistry, "cellgrid_cells"); LS.checktable(grid); // Check for the plane. If not present, add it. LS.checkstring(plane); LS.rawget(planegrid, grid, plane); if (LS.isnil(planegrid)) { LS.rawset(grid, plane, LuaNewTable); } return LS.result(); } #define CELL_SCALE 10.0 #define CELL_INVALID 0 LuaDefine(cellgrid_scale, "c") { LuaRet scale; LuaStack LS(L, scale); LS.set(scale, CELL_SCALE); return LS.result(); } lua_Number calc_cellid(lua_Number x, lua_Number y, lua_Number z) { lua_Number cellx = floor(x / CELL_SCALE); lua_Number celly = floor(y / CELL_SCALE); lua_Number cellz = floor(z / CELL_SCALE); if ((cellx > 32767)||(celly > 32767)||(cellz > 32767)) { return CELL_INVALID; } if ((cellx < -32767)||(celly < -32767)||(cellz < -32767)) { return CELL_INVALID; } int64_t icellx = int64_t(cellx) & 0xFFFF; int64_t icelly = int64_t(celly) & 0xFFFF; int64_t icellz = int64_t(cellz) & 0xFFFF; return lua_Number(0x0001000000000000 | (icellx << 32) | (icelly << 16) | (icellz << 0)); } LuaDefine(cellgrid_cellid, "c") { LuaArg x, y, z; LuaRet cellid; LuaStack LS(L, x, y, z, cellid); lua_Number nx = LS.cknumber(x); lua_Number ny = LS.cknumber(y); lua_Number nz = LS.cknumber(z); LS.set(cellid, calc_cellid(nx, ny, nz)); return LS.result(); } LuaDefine(cellgrid_setpos, "c") { LuaArg grid, sprite, x, y, z, nplane; LuaVar smt, oplane, planegrid, cell; LuaStack LS(L, grid, sprite, x, y, z, nplane, smt, oplane, planegrid, cell); // Get the grid. if (LS.isnil(grid)) LS.getfield(grid, LuaRegistry, "cellgrid_cells"); LS.checktable(grid); // Calculate the new plane and cell ID. lua_Number nx, ny, nz; nx = LS.cknumber(x); ny = LS.cknumber(y); nz = LS.cknumber(z); if (!LS.isnil(nplane)) LS.checkstring(nplane); lua_Number ncellid = calc_cellid(nx, ny, nz); // Check that the new plane is an existing plane. LS.rawget(planegrid, grid, nplane); if (!LS.istable(planegrid)) { luaL_error(L, "invalid plane"); } // Get the sprite metatable. LS.checktable(sprite); LS.getmetatable(smt, sprite); LS.checktable(smt); // Get the sprite's old plane and cell ID. lua_Number ox, oy, oz; LS.getfield(LuaAcceptNil(ox), smt, "x"); LS.getfield(LuaAcceptNil(oy), smt, "y"); LS.getfield(LuaAcceptNil(oz), smt, "z"); LS.getfield(oplane, smt, "plane"); lua_Number ocellid = calc_cellid(ox, oy, oz); // The sprite 'moved' if it's in a new cell. bool moved = (!LS.equal(nplane, oplane)) || (ncellid != ocellid); // Change the sprite position. LS.rawset(smt, "x", x); LS.rawset(smt, "y", y); LS.rawset(smt, "z", z); LS.rawset(smt, "plane", nplane); // Remove sprite from the old cell. if (moved && LS.isstring(oplane) && (ocellid != CELL_INVALID)) { LS.rawget(planegrid, grid, oplane); if (LS.istable(planegrid)) { LS.rawget(cell, planegrid, ocellid); if (LS.istable(cell)) { LS.call(LuaDiscard, table_findremove, cell, sprite); if (LS.isemptytable(cell)) { LS.rawset(planegrid, ocellid, LuaNil); } } } } // Insert sprite into the new cell if (moved && LS.isstring(nplane) && (ncellid != CELL_INVALID)) { LS.rawget(planegrid, grid, nplane); if (LS.istable(planegrid)) { LS.rawget(cell, planegrid, ncellid); if (!LS.istable(cell)) { LS.newtable(cell); LS.rawset(planegrid, ncellid, cell); } LS.call(table_append, cell, sprite); } } return LS.result(); } int cellgrid_scanradius(lua_State *L); int cellgrid_scanregion(lua_State *L);