diff --git a/Aquaria/Avatar.cpp b/Aquaria/Avatar.cpp index ea5856e..43d334c 100644 --- a/Aquaria/Avatar.cpp +++ b/Aquaria/Avatar.cpp @@ -3561,7 +3561,7 @@ void Avatar::lockToWall() while(0); } - if (dsq->game->getGrid(t)==OT_HURT && isDamageTarget(DT_WALLHURT)) + if (dsq->game->isObstructed(t, OT_HURT) && isDamageTarget(DT_WALLHURT)) { good = false; } @@ -3612,16 +3612,16 @@ void Avatar::lockToWall() Vector offdiff = t.worldVector() - position; if (!offdiff.isZero()) { - if (tileType != OT_INVISIBLEIN) + if (tileType & OT_INVISIBLEIN) { Vector adjust = offdiff; - adjust.setLength2D(TILE_SIZE*2); + adjust.setLength2D(TILE_SIZE/2); offdiff -= adjust; } else { Vector adjust = offdiff; - adjust.setLength2D(TILE_SIZE/2); + adjust.setLength2D(TILE_SIZE*2); offdiff -= adjust; } } diff --git a/Aquaria/Entity.cpp b/Aquaria/Entity.cpp index d89a13d..b34b0af 100644 --- a/Aquaria/Entity.cpp +++ b/Aquaria/Entity.cpp @@ -1509,13 +1509,13 @@ bool Entity::isSittingOnInvisibleIn() { for (int y = 0; y < 4; y++) { - if (dsq->game->getGrid(TileVector(t.x+x, t.y+y))==OT_INVISIBLEIN) + if (dsq->game->isObstructed(TileVector(t.x+x, t.y+y), OT_INVISIBLEIN)) return true; - if (dsq->game->getGrid(TileVector(t.x-x, t.y+y))==OT_INVISIBLEIN) + if (dsq->game->isObstructed(TileVector(t.x-x, t.y+y), OT_INVISIBLEIN)) return true; - if (dsq->game->getGrid(TileVector(t.x+x, t.y-y))==OT_INVISIBLEIN) + if (dsq->game->isObstructed(TileVector(t.x+x, t.y-y), OT_INVISIBLEIN)) return true; - if (dsq->game->getGrid(TileVector(t.x-x, t.y-y))==OT_INVISIBLEIN) + if (dsq->game->isObstructed(TileVector(t.x-x, t.y-y), OT_INVISIBLEIN)) return true; } } @@ -3055,6 +3055,7 @@ bool Entity::doCollisionAvoidance(float dt, int search, float mod, Vector *vp, i int minDist=-1; TileVector t(position); TileVector useTile; + const int blockObs = ~ignoreObs; float totalDist = sqrtf(float(sqr((search*2)*TILE_SIZE)+sqr((search*2)*TILE_SIZE))); for (int x = -search; x <= search; x++) @@ -3069,7 +3070,7 @@ bool Entity::doCollisionAvoidance(float dt, int search, float mod, Vector *vp, i } if (waterBlocked || dsq->game->isObstructed(checkT)) { - if (dsq->game->getGrid(checkT) != ignoreObs) + if (dsq->game->isObstructed(checkT, blockObs)) { Vector vtc(t.x+x, t.y+y); Vector vt(t.x, t.y); diff --git a/Aquaria/Game.cpp b/Aquaria/Game.cpp index ddd07e3..8d246b9 100644 --- a/Aquaria/Game.cpp +++ b/Aquaria/Game.cpp @@ -2075,8 +2075,8 @@ void Game::fillGridFromQuad(Quad *q, ObsType obsType, bool trim) //dsq->game->setGrid(TileVector(tpos.x+(w2*TILE_SIZE)+(x/TILE_SIZE), tpos.y+(h2*TILE_SIZE)+(y/TILE_SIZE)), obsType); TileVector tvec(tpos.x+w2+x, tpos.y+h2+y); - if (dsq->game->getGrid(tvec) == OT_EMPTY) - dsq->game->setGrid(tvec, obsType); + if (!dsq->game->isObstructed(tvec)) + dsq->game->addGrid(tvec, obsType); } glPopMatrix(); @@ -2103,7 +2103,7 @@ void Game::clearDynamicGrid(unsigned char maskbyte /* = OT_MASK_BLACK */) // otherwise there is a chance to write a few bytes over the end of the buffer -- FG compile_assert(sizeof(grid) % sizeof(uint32) == 0); - signed char *gridstart = &grid[0][0]; + unsigned char *gridstart = &grid[0][0]; uint32 *gridend = (uint32*)(gridstart + sizeof(grid)); uint32 *gridptr = (uint32*)gridstart; // mask out specific bytes @@ -2165,9 +2165,9 @@ void Game::trimGrid() // from beeing drawn. (The maps were designed with this mind...) for (int x = 0; x < MAX_GRID; x++) { - const signed char *curCol = dsq->game->getGridColumn(x); - const signed char *leftCol = dsq->game->getGridColumn(x-1); - const signed char *rightCol = dsq->game->getGridColumn(x+1); + const unsigned char *curCol = grid[x]; // safe + const unsigned char *leftCol = dsq->game->getGridColumn(x-1); // unsafe + const unsigned char *rightCol = dsq->game->getGridColumn(x+1); // unsafe for (int y = 0; y < MAX_GRID; y++) { if (curCol[y] & OT_MASK_BLACK) @@ -2179,6 +2179,66 @@ void Game::trimGrid() } } +void Game::dilateGrid(unsigned int radius, ObsType test, ObsType set, ObsType allowOverwrite) +{ + if(!radius) + return; + const int lim = MAX_GRID - radius; + const unsigned int denyOverwrite = ~allowOverwrite; + // Box dilation is separable, so we do a two-pass by axis + int dilate = 0; + + // dilate rows + for (int y = 0; y < MAX_GRID; ++y) + { + for (int x = radius; x < lim; ++x) + { + if (grid[x][y] & test) + { + dilate = 2 * radius; + goto doDilate1; + } + if(dilate) + { + --dilate; + doDilate1: + if((grid[x - radius][y] & denyOverwrite) == OT_EMPTY) + grid[x - radius][y] |= set; + } + } + assert(lim + dilate < MAX_GRID); + for(int x = 0; x < dilate; ++x) + if(!(grid[x][y - radius] & test)) + grid[x][y - radius] |= set; + } + + // dilate colums + dilate = 0; + for (int x = 0; x < MAX_GRID; ++x) + { + unsigned char * const curCol = grid[x]; + for (int y = radius; y < lim; ++y) + { + if (curCol[y] & test) + { + dilate = 2 * radius; + goto doDilate2; + } + if(dilate) + { + --dilate; + doDilate2: + if((curCol[y - radius] & denyOverwrite) == OT_EMPTY) + curCol[y - radius] |= set; + } + } + assert(lim + dilate < MAX_GRID); + for(int y = 0; y < dilate; ++y) + if(!(curCol[y - radius] & test)) + curCol[y - radius] |= set; + } +} + float Game::getCoverage(Vector pos, int sampleArea) { TileVector t(pos); @@ -6451,30 +6511,46 @@ void Game::applyState() addRenderObject(songLineRender, LR_HUD); gridRender = new GridRender(OT_INVISIBLE); + gridRender->color = Vector(1, 0, 0); addRenderObject(gridRender, LR_DEBUG_TEXT); gridRender->alpha = 0; gridRender2 = new GridRender(OT_HURT); + gridRender2->color = Vector(1, 1, 0); addRenderObject(gridRender2, LR_DEBUG_TEXT); gridRender2->alpha = 0; gridRender3 = new GridRender(OT_INVISIBLEIN); + gridRender3->color = Vector(1, 0.5f, 0); addRenderObject(gridRender3, LR_DEBUG_TEXT); gridRender3->alpha = 0; edgeRender = new GridRender(OT_BLACKINVIS); + edgeRender->color = Vector(0.3f, 0, 0.6f); addRenderObject(edgeRender, LR_DEBUG_TEXT); edgeRender->alpha = 0; gridRenderEnt = new GridRender(OT_INVISIBLEENT); + gridRenderEnt->color = Vector(0, 1, 0.5); addRenderObject(gridRenderEnt, LR_DEBUG_TEXT); gridRenderEnt->alpha = 0; + gridRenderUser1 = new GridRender(OT_USER1); + addRenderObject(gridRenderUser1, LR_DEBUG_TEXT); + gridRenderUser1->color = Vector(1, 0, 1); + gridRenderUser1->alpha = 0; + + gridRenderUser2 = new GridRender(OT_USER2); + addRenderObject(gridRenderUser2, LR_DEBUG_TEXT); + gridRenderUser2->color = Vector(1, 1, 1); + gridRenderUser2->alpha = 0; + waterSurfaceRender = new WaterSurfaceRender(); //waterSurfaceRender->setRenderPass(-1); addRenderObject(waterSurfaceRender, LR_WATERSURFACE); GridRender *blackRender = new GridRender(OT_BLACK); + blackRender->color = Vector(0, 0, 0); //blackRender->alpha = 0; blackRender->blendEnabled = false; addRenderObject(blackRender, LR_ELEMENTS4); @@ -8515,22 +8591,17 @@ void Game::toggleMiniMapRender(int v) void Game::toggleGridRender() { float t = 0; + float a = 0; if (gridRender->alpha == 0) - { - gridRender->alpha.interpolateTo(0.5, t); - gridRender2->alpha.interpolateTo(0.5, t); - gridRender3->alpha.interpolateTo(0.5, t); - edgeRender->alpha.interpolateTo(0.5, t); - gridRenderEnt->alpha.interpolateTo(0.5, t); - } - else if (gridRender->alpha == 0.5) - { - gridRender->alpha.interpolateTo(0, t); - gridRender2->alpha.interpolateTo(0, t); - gridRender3->alpha.interpolateTo(0, t); - edgeRender->alpha.interpolateTo(0, t); - gridRenderEnt->alpha.interpolateTo(0, t); - } + a = 0.5f; + + gridRender->alpha.interpolateTo(a, t); + gridRender2->alpha.interpolateTo(a, t); + gridRender3->alpha.interpolateTo(a, t); + edgeRender->alpha.interpolateTo(a, t); + gridRenderEnt->alpha.interpolateTo(a, t); + gridRenderUser1->alpha.interpolateTo(a, t); + gridRenderUser2->alpha.interpolateTo(a, t); } Vector Game::getCameraPositionFor(const Vector &pos) @@ -10624,7 +10695,7 @@ void Game::setGrid(ElementTemplate *et, Vector position, float rot360) } TileVector s(t.x+x, t.y+y); //Vector v = Vector(position.x+et->grid[i].x*TILE_SIZE, position.y+et->grid[i].y*TILE_SIZE); - setGrid(s, 1); + setGrid(s, OT_INVISIBLE); } } @@ -10752,6 +10823,12 @@ void Game::removeState() miniMapRender = 0; gridRender = 0; + gridRender2 = 0; + gridRender3 = 0; + edgeRender = 0; + gridRenderEnt = 0; + gridRenderUser1 = 0; + gridRenderUser2 = 0; worldMapRender = 0; //core->sound->stopStreamingOgg(); @@ -10922,44 +10999,6 @@ bool Game::collideCircleWithGrid(const Vector& position, float r) return false; } -bool Game::collideBoxWithGrid(const Vector& position, int hw, int hh) -{ - Vector tile = position; - TileVector t(tile); - tile.x = t.x; - tile.y = t.y; - - float hsz = TILE_SIZE/2; - int xrange=1,yrange=1; - xrange = (hw/TILE_SIZE)+1; - yrange = (hh/TILE_SIZE)+1; - for (int x = tile.x-xrange; x <= tile.x+xrange; x++) - { - for (int y = tile.y-yrange; y <= tile.y+yrange; y++) - { - int v = this->getGrid(TileVector(x, y)); - if (v == 1) - { - if (tile.x == x && tile.y == y) return true; - float rx = (x*TILE_SIZE)+TILE_SIZE/2; - float ry = (y*TILE_SIZE)+TILE_SIZE/2; - - - if (isBoxIn(position, Vector(hw, hh), Vector(rx, ry), Vector(hsz, hsz))) - { - return true; - } - if (isBoxIn(Vector(rx, ry), Vector(hsz, hsz), position, Vector(hw, hh))) - { - return true; - } - } - } - } - return false; -} - - void Game::learnedRecipe(Recipe *r, bool effects) { if (nocasecmp(dsq->getTopStateData()->name,"Game")==0 && !applyingState) diff --git a/Aquaria/Game.h b/Aquaria/Game.h index 5193014..caefa3c 100644 --- a/Aquaria/Game.h +++ b/Aquaria/Game.h @@ -587,6 +587,14 @@ enum ObsType // set by entities OT_INVISIBLEENT = 0x20, + + // mask for all bits that block + OT_BLOCKING = OT_MASK_BLACK | OT_INVISIBLE | OT_INVISIBLEIN | OT_HURT | OT_INVISIBLEENT, + + // free for use, not colliding by default + OT_USER1 = 0x40, + OT_USER2 = 0x80, + OT_USER_MASK = OT_USER1 | OT_USER2, }; struct EntitySaveData @@ -620,12 +628,14 @@ public: std::string getSelectedChoice() { return selectedChoice; } - int getGrid(const TileVector &tile) const; - int getGridRaw(unsigned int x, unsigned int y) const; - const signed char *getGridColumn(int tileX); - void setGrid(const TileVector &tile, int v); - bool isObstructed(const TileVector &tile, int t = -1) const; + ObsType getGrid(const TileVector &tile) const; + ObsType getGridRaw(const TileVector &tile) const; + unsigned char *getGridColumn(int tileX); + void setGrid(const TileVector &tile, ObsType v); + void addGrid(const TileVector &tile, ObsType v); + bool isObstructed(const TileVector &tile, int t = OT_BLOCKING) const; void trimGrid(); + void dilateGrid(unsigned int radius, ObsType test, ObsType set, ObsType allowOverwrite); void clearPointers(); @@ -655,7 +665,6 @@ public: void registerSporeDrop(const Vector &pos, int t); - bool collideBoxWithGrid(const Vector& position, int w, int h); bool collideCircleWithGrid(const Vector& position, float r); bool collideHairVsCircle(Entity *a, int num, const Vector &pos2, float radius, float perc=0, int *colSegment=0); @@ -959,7 +968,7 @@ public: void createGradient(); std::string saveMusic; - GridRender *gridRender, *gridRender2, *gridRender3, *edgeRender, *gridRenderEnt; + GridRender *gridRender, *gridRender2, *gridRender3, *edgeRender, *gridRenderEnt, *gridRenderUser1, *gridRenderUser2; void toggleGridRender(); ElementUpdateList elementUpdateList; ElementUpdateList elementInteractionList; @@ -1174,7 +1183,7 @@ protected: void toggleSceneEditor(); #endif - signed char grid[MAX_GRID][MAX_GRID]; + unsigned char grid[MAX_GRID][MAX_GRID]; Quad *bg, *bg2; @@ -1200,21 +1209,23 @@ extern Game *game; // INLINE FUNCTIONS inline -int Game::getGridRaw(unsigned int x, unsigned int y) const +ObsType Game::getGridRaw(const TileVector &tile) const { - return grid[x][y]; + return (unsigned(tile.x) < unsigned(MAX_GRID) && unsigned(tile.y) < unsigned(MAX_GRID)) + ? ObsType(grid[tile.x][tile.y]) + : OT_INVISIBLE; } inline -int Game::getGrid(const TileVector &tile) const +ObsType Game::getGrid(const TileVector &tile) const { - //if (tile.x < 0 || tile.x >= MAX_GRID || tile.y < 0 || tile.y >= MAX_GRID) return OT_INVISIBLE; - //return grid[tile.x][tile.y]; - return (unsigned(tile.x) < unsigned(MAX_GRID) && unsigned(tile.y) < unsigned(MAX_GRID)) ? grid[tile.x][tile.y] : OT_INVISIBLE; + return (unsigned(tile.x) < unsigned(MAX_GRID) && unsigned(tile.y) < unsigned(MAX_GRID)) + ? ObsType(grid[tile.x][tile.y] & OT_BLOCKING) + : OT_INVISIBLE; } inline -const signed char *Game::getGridColumn(int tileX) +unsigned char *Game::getGridColumn(int tileX) { if (tileX < 0) return grid[0]; @@ -1225,14 +1236,21 @@ const signed char *Game::getGridColumn(int tileX) } inline -void Game::setGrid(const TileVector &tile, int v) +void Game::setGrid(const TileVector &tile, ObsType v) { - if (tile.x < 0 || tile.x >= MAX_GRID || tile.y < 0 || tile.y >= MAX_GRID) return; - grid[tile.x][tile.y] = v; + if (unsigned(tile.x) < unsigned(MAX_GRID) && unsigned(tile.y) < unsigned(MAX_GRID)) + grid[tile.x][tile.y] = v; } inline -bool Game::isObstructed(const TileVector &tile, int t /* = -1 */) const +void Game::addGrid(const TileVector &tile, ObsType v) +{ + if (unsigned(tile.x) < unsigned(MAX_GRID) && unsigned(tile.y) < unsigned(MAX_GRID)) + grid[tile.x][tile.y] |= v; +} + +inline +bool Game::isObstructed(const TileVector &tile, int t /* = OT_BLOCKING */) const { return (getGrid(tile) & t); } diff --git a/Aquaria/GridRender.cpp b/Aquaria/GridRender.cpp index bbfd4a3..fa6c9cd 100644 --- a/Aquaria/GridRender.cpp +++ b/Aquaria/GridRender.cpp @@ -66,30 +66,6 @@ inline static void doRenderGrid(int x, int startCol, int endCol) void GridRender::onRender() { - switch(obsType) - { - case OT_INVISIBLE: - core->setColor(1, 0, 0, alpha.getValue()); - break; - case OT_INVISIBLEIN: - core->setColor(1, 0.5, 0, alpha.getValue()); - break; - case OT_INVISIBLEENT: - core->setColor(0, 1, 0.5, alpha.getValue()); - break; - case OT_BLACK: - core->setColor(0, 0, 0, 1); - break; - case OT_BLACKINVIS: - core->setColor(0.3, 0, 0.6, alpha.getValue()); - break; - case OT_HURT: - core->setColor(1, 1, 0, alpha.getValue()); - break; - default: - break; - } - const signed char obsType = this->obsType; Vector camPos = core->cameraPos; camPos.x -= core->getVirtualOffX() * (core->invGlobalScale); @@ -112,11 +88,11 @@ void GridRender::onRender() return; for (int x = startX; x <= endX; ++x) { - const signed char *gridColumn = dsq->game->getGridColumn(x); + const unsigned char *gridColumn = dsq->game->getGridColumn(x); int startCol = -1, y; // fast-forward to next drawable byte - if(const signed char *next = (const signed char*)memchr(gridColumn + startY, obsType, endY - startY + 1)) // find next byte with correct obs type + if(const unsigned char *next = (const unsigned char*)memchr(gridColumn + startY, obsType, endY - startY + 1)) // find next byte with correct obs type { y = next - gridColumn; // will get incremented right away, which is okay, because we alrady set startCol startCol = y; @@ -131,7 +107,7 @@ void GridRender::onRender() doRenderGrid(x, startCol, y - 1); // fast-forward to next drawable byte - if(const signed char *next = (const signed char*)memchr(gridColumn + y, obsType, endY - y)) // find next byte with correct obs type + if(const unsigned char *next = (const unsigned char*)memchr(gridColumn + y, obsType, endY - y)) // find next byte with correct obs type { y = next - gridColumn; // will get incremented right away, which is okay, because we alrady set startCol startCol = y; diff --git a/Aquaria/PathFinding.cpp b/Aquaria/PathFinding.cpp index f214f88..3a0f69e 100644 --- a/Aquaria/PathFinding.cpp +++ b/Aquaria/PathFinding.cpp @@ -24,16 +24,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "DSQ.h" #include "Game.h" -class SearchGrid +class SearchGridRaw { public: - SearchGrid() : game(dsq->game) {} + SearchGridRaw(ObsType blocking) : game(dsq->game), blockingObsBits(blocking) {} inline bool operator()(unsigned x, unsigned y) const { - return game->getGrid(TileVector(x, y)) == OT_EMPTY; + return (game->getGridRaw(TileVector(x, y)) & blockingObsBits) == OT_EMPTY; } private: + const ObsType blockingObsBits; const Game *game; }; @@ -157,7 +158,7 @@ void PathFinding::generatePath(RenderObject *ro, TileVector start, TileVector go VectorPath& vp = ro->position.data->path; vp.clear(); - SearchGrid grid; + SearchGridRaw grid(OT_BLOCKING); JPS::PathVector path; if(JPS::findPath(path, grid, start.x, start.y, goal.x, goal.y, 1)) { @@ -166,9 +167,12 @@ void PathFinding::generatePath(RenderObject *ro, TileVector start, TileVector go } } -bool PathFinding::generatePathSimple(VectorPath& path, const Vector& start, const Vector& end, unsigned int step /* = 0 */) +bool PathFinding::generatePathSimple(VectorPath& path, const Vector& start, const Vector& end, unsigned int step /* = 0 */, unsigned int obs /* = 0 */) { - SearchGrid grid; + if(obs == OT_EMPTY) + obs = OT_BLOCKING; + + SearchGridRaw grid((ObsType)obs); JPS::PathVector p; TileVector tstart(start); TileVector tend(end); diff --git a/Aquaria/PathFinding.h b/Aquaria/PathFinding.h index c0dc9c2..7920cbb 100644 --- a/Aquaria/PathFinding.h +++ b/Aquaria/PathFinding.h @@ -37,7 +37,7 @@ public: void molestPath(VectorPath &path); void generatePath(RenderObject *go, TileVector g1, TileVector g2, int offx=0, int offy=0); - bool generatePathSimple(VectorPath& path, const Vector& start, const Vector& end, unsigned int step = 0); + bool generatePathSimple(VectorPath& path, const Vector& start, const Vector& end, unsigned int step = 0, unsigned int obs = 0); }; #endif diff --git a/Aquaria/ScriptInterface.cpp b/Aquaria/ScriptInterface.cpp index efe7a40..07e49b8 100644 --- a/Aquaria/ScriptInterface.cpp +++ b/Aquaria/ScriptInterface.cpp @@ -2898,6 +2898,16 @@ luaFunc(reconstructEntityGrid) luaReturnNil(); } +luaFunc(dilateGrid) +{ + unsigned int radius = lua_tointeger(L, 1); + ObsType test = (ObsType)lua_tointeger(L, 2); + ObsType set = (ObsType)lua_tointeger(L, 3); + ObsType allowOverwrite = (ObsType)lua_tointeger(L, 4); + dsq->game->dilateGrid(radius, test, set, allowOverwrite); + luaReturnNil(); +} + luaFunc(entity_setCanLeaveWater) { Entity *e = entity(L); @@ -8347,6 +8357,11 @@ luaFunc(getObstruction) luaReturnInt(dsq->game->getGrid(TileVector(Vector(lua_tonumber(L, 1), lua_tonumber(L, 2))))); } +luaFunc(getGridRaw) +{ + luaReturnInt(dsq->game->getGridRaw(TileVector(Vector(lua_tonumber(L, 1), lua_tonumber(L, 2))))); +} + luaFunc(isObstructedBlock) { float x = lua_tonumber(L, 1); @@ -8568,13 +8583,14 @@ luaFunc(isShuttingDownGameState) luaReturnBool(dsq->game->isShuttingDownGameState()); } -// startx, starty, endx, endy [, step, xtab, ytab] +// startx, starty, endx, endy [, step, xtab, ytab, obsMask] luaFunc(findPath) { VectorPath path; Vector start(lua_tonumber(L, 1), lua_tonumber(L, 2)); Vector end(lua_tonumber(L, 3), lua_tonumber(L, 4)); - if(!dsq->pathFinding.generatePathSimple(path, start, end, lua_tointeger(L, 5))) + ObsType obs = ObsType(lua_tointeger(L, 8)); + if(!dsq->pathFinding.generatePathSimple(path, start, end, lua_tointeger(L, 5), obs)) luaReturnBool(false); const unsigned num = path.getNumPathNodes(); @@ -8964,6 +8980,7 @@ static const struct { luaRegister(reconstructGrid), luaRegister(reconstructEntityGrid), + luaRegister(dilateGrid), luaRegister(ing_hasIET), luaRegister(ing_getIngredientName), @@ -9463,6 +9480,7 @@ static const struct { luaRegister(isObstructed), luaRegister(isObstructedBlock), luaRegister(getObstruction), + luaRegister(getGridRaw), luaRegister(findPath), luaRegister(castLine), luaRegister(getUserInputString), @@ -10597,6 +10615,11 @@ static const struct { luaConstant(OT_INVISIBLEIN), luaConstant(OT_HURT), luaConstant(OT_INVISIBLEENT), + luaConstant(OT_USER1), + luaConstant(OT_USER2), + luaConstant(OT_MASK_BLACK), + luaConstant(OT_BLOCKING), + luaConstant(OT_USER_MASK), luaConstant(SEE_MAP_NEVER), luaConstant(SEE_MAP_DEFAULT),