Allow defining random-teleport exclusion zones in lua
Adds a new lua command
des.exclusion({ type = "teleport", region = { x1,y1, x2,y2 } });
which allows defining "exclusion zones" in the level, areas where
random teleports (or falling into the level) will never place the hero.
Does not prevent targeted teleportation into the area.
Breaks saves and bones.
This commit is contained in:
@@ -342,6 +342,7 @@ const struct instance_globals_e g_init_e = {
|
||||
/* mkmaze.c */
|
||||
UNDEFINED_PTR, /* ebubbles */
|
||||
/* new */
|
||||
NULL, /* exclusion_zones */
|
||||
0, /* early_raw_messages */
|
||||
TRUE, /* havestate*/
|
||||
IVMAGIC /* e_magic to validate that structure layout has been preserved */
|
||||
|
||||
@@ -2675,6 +2675,66 @@ donamelevel(void)
|
||||
return ECMD_OK;
|
||||
}
|
||||
|
||||
/* exclusion zones */
|
||||
void
|
||||
free_exclusions(void)
|
||||
{
|
||||
struct exclusion_zone *ez = ge.exclusion_zones;
|
||||
|
||||
while (ez) {
|
||||
struct exclusion_zone *nxtez = ez->next;
|
||||
|
||||
free(ez);
|
||||
ez = nxtez;
|
||||
}
|
||||
ge.exclusion_zones = (struct exclusion_zone *) 0;
|
||||
}
|
||||
|
||||
void
|
||||
save_exclusions(NHFILE *nhfp)
|
||||
{
|
||||
struct exclusion_zone *ez;
|
||||
int nez;
|
||||
|
||||
for (nez = 0, ez = ge.exclusion_zones; ez; ez = ez->next, ++nez) ;
|
||||
|
||||
if (nhfp->structlevel)
|
||||
bwrite(nhfp->fd, (genericptr_t) &nez, sizeof nez);
|
||||
|
||||
for (ez = ge.exclusion_zones; ez; ez = ez->next) {
|
||||
if (nhfp->structlevel) {
|
||||
bwrite(nhfp->fd, (genericptr_t) &ez->zonetype, sizeof ez->zonetype);
|
||||
bwrite(nhfp->fd, (genericptr_t) &ez->lx, sizeof ez->lx);
|
||||
bwrite(nhfp->fd, (genericptr_t) &ez->ly, sizeof ez->ly);
|
||||
bwrite(nhfp->fd, (genericptr_t) &ez->hx, sizeof ez->hx);
|
||||
bwrite(nhfp->fd, (genericptr_t) &ez->hy, sizeof ez->hy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
load_exclusions(NHFILE *nhfp)
|
||||
{
|
||||
struct exclusion_zone *ez;
|
||||
int nez = 0;
|
||||
|
||||
if (nhfp->structlevel)
|
||||
mread(nhfp->fd, (genericptr_t) &nez, sizeof nez);
|
||||
|
||||
while (nez-- > 0) {
|
||||
ez = (struct exclusion_zone *) alloc(sizeof *ez);
|
||||
if (nhfp->structlevel) {
|
||||
mread(nhfp->fd, (genericptr_t) &ez->zonetype, sizeof ez->zonetype);
|
||||
mread(nhfp->fd, (genericptr_t) &ez->lx, sizeof ez->lx);
|
||||
mread(nhfp->fd, (genericptr_t) &ez->ly, sizeof ez->ly);
|
||||
mread(nhfp->fd, (genericptr_t) &ez->hx, sizeof ez->hx);
|
||||
mread(nhfp->fd, (genericptr_t) &ez->hy, sizeof ez->hy);
|
||||
}
|
||||
ez->next = ge.exclusion_zones;
|
||||
ge.exclusion_zones = ez;
|
||||
}
|
||||
}
|
||||
|
||||
/* find the particular mapseen object in the chain; may return null */
|
||||
static mapseen *
|
||||
find_mapseen(d_level *lev)
|
||||
|
||||
@@ -822,6 +822,7 @@ clear_level_structures(void)
|
||||
stairway_free_all();
|
||||
gm.made_branch = FALSE;
|
||||
clear_regions();
|
||||
free_exclusions();
|
||||
reset_xystart_size();
|
||||
if (gl.lev_message) {
|
||||
free(gl.lev_message);
|
||||
|
||||
20
src/mkmaze.c
20
src/mkmaze.c
@@ -297,6 +297,22 @@ maze0xy(coord *cc)
|
||||
return;
|
||||
}
|
||||
|
||||
static boolean
|
||||
is_exclusion_zone(xint16 type, coordxy x, coordxy y)
|
||||
{
|
||||
struct exclusion_zone *ez = ge.exclusion_zones;
|
||||
|
||||
while (ez) {
|
||||
if (((type == LR_DOWNTELE && (ez->zonetype == LR_DOWNTELE || ez->zonetype == LR_TELE))
|
||||
|| (type == LR_UPTELE && (ez->zonetype == LR_UPTELE || ez->zonetype == LR_TELE))
|
||||
|| type == ez->zonetype)
|
||||
&& within_bounded_area(x, y, ez->lx, ez->ly, ez->hx, ez->hy))
|
||||
return TRUE;
|
||||
ez = ez->next;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Bad if:
|
||||
* pos is occupied OR
|
||||
@@ -375,7 +391,7 @@ put_lregion_here(
|
||||
{
|
||||
struct monst *mtmp;
|
||||
|
||||
if (bad_location(x, y, nlx, nly, nhx, nhy)) {
|
||||
if (bad_location(x, y, nlx, nly, nhx, nhy) || is_exclusion_zone(rtype, x, y)) {
|
||||
if (!oneshot) {
|
||||
return FALSE; /* caller should try again */
|
||||
} else {
|
||||
@@ -389,7 +405,7 @@ put_lregion_here(
|
||||
mtmp->mtrapped = 0;
|
||||
deltrap(t);
|
||||
}
|
||||
if (bad_location(x, y, nlx, nly, nhx, nhy))
|
||||
if (bad_location(x, y, nlx, nly, nhx, nhy) || is_exclusion_zone(rtype, x, y))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1141,6 +1141,7 @@ getlev(NHFILE *nhfp, int pid, xint8 lev)
|
||||
restdamage(nhfp);
|
||||
rest_regions(nhfp);
|
||||
rest_bubbles(nhfp); /* for water and air; empty marker on other levels */
|
||||
load_exclusions(nhfp);
|
||||
|
||||
if (ghostly) {
|
||||
stairway *stway = gs.stairs;
|
||||
|
||||
@@ -553,6 +553,7 @@ savelev_core(NHFILE *nhfp, xint8 lev)
|
||||
savedamage(nhfp); /* pending shop wall and/or floor repair */
|
||||
save_regions(nhfp);
|
||||
save_bubbles(nhfp, lev); /* for water and air */
|
||||
save_exclusions(nhfp);
|
||||
|
||||
if (nhfp->mode != FREEING) {
|
||||
if (nhfp->structlevel)
|
||||
|
||||
31
src/sp_lev.c
31
src/sp_lev.c
@@ -141,6 +141,7 @@ int lspo_ladder(lua_State *);
|
||||
int lspo_level_flags(lua_State *);
|
||||
int lspo_level_init(lua_State *);
|
||||
int lspo_levregion(lua_State *);
|
||||
int lspo_exclusion(lua_State *);
|
||||
int lspo_map(lua_State *);
|
||||
int lspo_mazewalk(lua_State *);
|
||||
int lspo_message(lua_State *);
|
||||
@@ -6073,6 +6074,35 @@ lspo_levregion(lua_State *L)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* exclusion({ type = "teleport", region = { x1,y1, x2,y2 } }); */
|
||||
int
|
||||
lspo_exclusion(lua_State *L)
|
||||
{
|
||||
static const char *const ez_types[] = {
|
||||
"teleport", "teleport-up", "teleport-down", NULL
|
||||
};
|
||||
static const int ez_types2i[] = {
|
||||
LR_TELE, LR_UPTELE, LR_DOWNTELE, 0
|
||||
};
|
||||
struct exclusion_zone *ez = (struct exclusion_zone *) alloc(sizeof *ez);
|
||||
lua_Integer x1,y1,x2,y2;
|
||||
|
||||
create_des_coder();
|
||||
lcheck_param_table(L);
|
||||
ez->zonetype = ez_types2i[get_table_option(L, "type", "teleport",
|
||||
ez_types)];
|
||||
get_table_region(L, "region", &x1, &y1, &x2, &y2, FALSE);
|
||||
ez->lx = x1;
|
||||
ez->ly = y1;
|
||||
ez->hx = x2;
|
||||
ez->hy = y2;
|
||||
cvt_to_abscoord(&ez->lx, &ez->ly);
|
||||
cvt_to_abscoord(&ez->hx, &ez->hy);
|
||||
ez->next = ge.exclusion_zones;
|
||||
ge.exclusion_zones = ez;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
sel_set_lit(coordxy x, coordxy y, genericptr_t arg)
|
||||
{
|
||||
@@ -6960,6 +6990,7 @@ static const struct luaL_Reg nhl_functions[] = {
|
||||
{ "drawbridge", lspo_drawbridge },
|
||||
{ "region", lspo_region },
|
||||
{ "levregion", lspo_levregion },
|
||||
{ "exclusion", lspo_exclusion },
|
||||
{ "wallify", lspo_wallify },
|
||||
{ "wall_property", lspo_wall_property },
|
||||
{ "non_diggable", lspo_non_diggable },
|
||||
|
||||
Reference in New Issue
Block a user