Lua: Allow creating gas clouds

Use the gas clouds in the Clouds themeroom.
Use the existing visible_region_at() in the vision code.
This commit is contained in:
Pasi Kallinen
2024-01-19 17:54:19 +02:00
parent da4bf5a87e
commit 2212cf27ec
6 changed files with 102 additions and 10 deletions

View File

@@ -43,10 +43,10 @@ themeroom_fills = {
-- Cloud room
function(rm)
local fog = selection.room();
des.terrain(fog, "C");
for i = 1, (fog:numpoints() / 4) do
des.monster({ id = "fog cloud", asleep = true });
end
des.gas_cloud({ selection = fog });
end,
-- Boulder room

View File

@@ -569,6 +569,21 @@ Example:
des.finalize_level();
=== gas_cloud
Create a gas cloud.
The `damage` and `ttl` fields are optional.
Defaults to non-poisonous and infinite lifetime.
Example:
des.gas_cloud({ x = XX, y = YY });
des.gas_cloud({ coord = { XX, YY } });
des.gas_cloud({ selection = SEL });
des.gas_cloud({ selection = SEL, damage = 5 });
des.gas_cloud({ selection = SEL, damage = 5, ttl = 200 });
=== gold
Create a pile of gold.

View File

@@ -2560,6 +2560,7 @@ extern void save_regions(NHFILE *) NONNULLARG1;
extern void rest_regions(NHFILE *) NONNULLARG1;
extern void region_stats(const char *, char *, long *, long *) NONNULLPTRS;
extern NhRegion *create_gas_cloud(coordxy, coordxy, int, int);
extern NhRegion *create_gas_cloud_selection(struct selectionvar *, int);
extern boolean region_danger(void);
extern void region_safety(void);

View File

@@ -1189,6 +1189,44 @@ create_gas_cloud(coordxy x, coordxy y, int cloudsize, int damage)
return cloud;
}
/* create a single gas cloud from selection */
NhRegion *
create_gas_cloud_selection(struct selectionvar *sel, int damage)
{
NhRegion *cloud;
NhRect tmprect;
coordxy x, y;
NhRect r;
boolean inside_cloud = is_hero_inside_gas_cloud();
selection_getbounds(sel, &r);
cloud = create_region((NhRect *) 0, 0);
for (x = r.lx; x <= r.hx; x++)
for (y = r.ly; y <= r.hy; y++)
if (selection_getpoint(x, y, sel)) {
tmprect.lx = tmprect.hx = x;
tmprect.ly = tmprect.hy = y;
add_rect_to_reg(cloud, &tmprect);
}
if (!gi.in_mklev && !gc.context.mon_moving)
set_heros_fault(cloud); /* assume player has created it */
cloud->inside_f = INSIDE_GAS_CLOUD;
cloud->expire_f = EXPIRE_GAS_CLOUD;
cloud->arg = cg.zeroany;
cloud->arg.a_int = damage;
cloud->visible = TRUE;
cloud->glyph = cmap_to_glyph(damage ? S_poisoncloud : S_cloud);
add_region(cloud);
if (!gi.in_mklev && !inside_cloud && is_hero_inside_gas_cloud())
You("are enveloped in a cloud of %s!",
damage ? "noxious gas" : "steam");
return cloud;
}
/* for checking troubles during prayer; is hero at risk? */
boolean
region_danger(void)

View File

@@ -159,6 +159,7 @@ int lspo_finalize_level(lua_State *);
int lspo_room(lua_State *);
int lspo_stair(lua_State *);
int lspo_teleport_region(lua_State *);
int lspo_gas_cloud(lua_State *);
int lspo_terrain(lua_State *);
int lspo_trap(lua_State *);
int lspo_wall_property(lua_State *);
@@ -5545,6 +5546,49 @@ lspo_feature(lua_State *L)
return 0;
}
/* gas_cloud({ selection=SELECTION }); */
/* gas_cloud({ selection=SELECTION, damage=N }); */
/* gas_cloud({ selection=SELECTION, damage=N, ttl=N }); */
int
lspo_gas_cloud(lua_State *L)
{
coordxy x = 0, y = 0;
struct selectionvar *sel = NULL;
int argc = lua_gettop(L);
int damage = 0;
int ttl = -2;
create_des_coder();
if (argc == 1 && lua_type(L, 1) == LUA_TTABLE) {
lua_Integer tx, ty;
NhRegion *reg;
lcheck_param_table(L);
get_table_xy_or_coord(L, &tx, &ty);
x = tx, y = ty;
if (tx == -1 && ty == -1) {
lua_getfield(L, 1, "selection");
sel = l_selection_check(L, -1);
lua_pop(L, 1);
}
damage = get_table_int_opt(L, "damage", 0);
ttl = get_table_int_opt(L, "ttl", -2);
if (!sel) {
reg = create_gas_cloud(x, y, 1, damage);
} else
reg = create_gas_cloud_selection(sel, damage);
if (ttl > -2)
reg->ttl = ttl;
} else {
nhl_error(L, "wrong parameters");
}
return 0;
}
/*
* [lit_state: 1 On, 0 Off, -1 random, -2 leave as-is]
* terrain({ x=NN, y=NN, typ=MAPCHAR, lit=lit_state });
@@ -6995,6 +7039,7 @@ static const struct luaL_Reg nhl_functions[] = {
{ "teleport_region", lspo_teleport_region },
{ "reset_level", lspo_reset_level },
{ "finalize_level", lspo_finalize_level },
{ "gas_cloud", lspo_gas_cloud },
/* TODO: { "branch", lspo_branch }, */
/* TODO: { "portal", lspo_portal }, */
{ NULL, NULL }

View File

@@ -141,7 +141,6 @@ does_block(int x, int y, struct rm *lev)
{
struct obj *obj;
struct monst *mon;
int i;
#ifdef DEBUG
/* set DEBUGFILES=seethru in environment to see through bubbles */
@@ -181,14 +180,8 @@ does_block(int x, int y, struct rm *lev)
if (gs.seethru != 1) {
#endif
/* Clouds (poisonous or not) block light. */
for (i = 0; i < gn.n_regions; i++) {
/* Ignore regions with ttl == 0 - expire_gas_cloud must unblock its
* points prior to being removed itself. */
if (gr.regions[i]->ttl > 0 && gr.regions[i]->visible
&& inside_region(gr.regions[i], x, y)) {
return 1;
}
}
if (visible_region_at(x, y))
return 1;
#ifdef DEBUG
} /* gs.seethru */
#endif