diff --git a/doc/lua.adoc b/doc/lua.adoc index e9962a174..0d63041ea 100644 --- a/doc/lua.adoc +++ b/doc/lua.adoc @@ -794,7 +794,8 @@ The hash parameter accepts the following keys: | ignorewater | boolean | ignore water when choosing location for the monster | countbirth | boolean | do we count this monster as generated | appear_as | string | monster can appear as object, monster, or terrain. Add "obj:", "mon:", or "ter:" prefix to the value. | -| inventory | function | objects generated in the function are given to the monster +| inventory | function | objects generated in the function are given to the monster (any random inventory it gets is discarded unless keep_default_invent is true) +| keep_default_invent | boolean | if inventory is specified and this is true, those items are in addition to random inventory for this species; if inventory is not specified and this is false, monster gets no starting inventory |=== Example: diff --git a/include/sp_lev.h b/include/sp_lev.h index 3a9a18d34..769c6a1c7 100644 --- a/include/sp_lev.h +++ b/include/sp_lev.h @@ -74,6 +74,11 @@ enum lvlinit_types { #define NO_LOC_WARN 0x20 /* no complaints and set x & y to -1, if no loc */ #define SPACELOC 0x40 /* like DRY, but accepts furniture too */ +/* has_invent flags */ +#define NO_INVENT 0 /* monster doesn't get any invent */ +#define CUSTOM_INVENT 0x01 /* monster gets items specified in lua */ +#define DEFAULT_INVENT 0x02 /* monster gets items from makemon() */ + #define SP_COORD_X(l) (l & 0xff) #define SP_COORD_Y(l) ((l >> 16) & 0xff) #define SP_COORD_PACK(x, y) (((x) & 0xff) + (((y) & 0xff) << 16)) diff --git a/src/sp_lev.c b/src/sp_lev.c index 16adaf345..f18f795e9 100644 --- a/src/sp_lev.c +++ b/src/sp_lev.c @@ -2165,8 +2165,14 @@ create_monster(monster *m, struct mkroom *croom) if (vampshifted(mtmp) && m->appear != M_AP_MONSTER) (void) newcham(mtmp, &mons[mtmp->cham], NO_NC_FLAGS); } - if (m->has_invent) { + if (!(m->has_invent & DEFAULT_INVENT)) { + /* guard against someone accidentally specifying e.g. quest nemesis + * with custom inventory that lacks Bell or quest artifact but + * forgetting to flag them as receiving their default inventory */ + mdrop_special_objs(mtmp); discard_minvent(mtmp, TRUE); + } + if (m->has_invent & CUSTOM_INVENT) { invent_carrying_monster = mtmp; } } @@ -3217,7 +3223,7 @@ lspo_monster(lua_State *L) tmpmons.stunned = 0; tmpmons.confused = 0; tmpmons.seentraps = 0; - tmpmons.has_invent = 0; + tmpmons.has_invent = DEFAULT_INVENT; tmpmons.waiting = 0; tmpmons.mm_flags = NO_MM_FLAGS; @@ -3265,6 +3271,7 @@ lspo_monster(lua_State *L) : (mgend == MALE) ? MALE : rn2(2); } } else { + int keep_default_invent = -1; /* -1 = unspecified */ lcheck_param_table(L); tmpmons.peaceful = get_table_boolean_opt(L, "peaceful", BOOL_RANDOM); @@ -3285,7 +3292,8 @@ lspo_monster(lua_State *L) tmpmons.confused = get_table_boolean_opt(L, "confused", FALSE); tmpmons.waiting = get_table_boolean_opt(L, "waiting", FALSE); tmpmons.seentraps = 0; /* TODO: list of trap names to bitfield */ - tmpmons.has_invent = 0; + keep_default_invent = + get_table_boolean_opt(L, "keep_default_invent", -1); if (!get_table_boolean_opt(L, "tail", TRUE)) tmpmons.mm_flags |= MM_NOTAIL; @@ -3334,7 +3342,19 @@ lspo_monster(lua_State *L) lua_getfield(L, 1, "inventory"); if (!lua_isnil(L, -1)) { - tmpmons.has_invent = 1; + /* overwrite DEFAULT_INVENT - most times inventory is specified, + * the monster should not get its species' default inventory. Only + * provide it if explicitly requested. */ + tmpmons.has_invent = CUSTOM_INVENT; + if (keep_default_invent == TRUE) + tmpmons.has_invent |= DEFAULT_INVENT; + } + else { + /* if keep_default_invent was not specified (-1), keep has_invent as + * DEFAULT_INVENT and provide the species' default inventory. + * But if it was explicitly set to false, provide *no* inventory. */ + if (keep_default_invent == FALSE) + tmpmons.has_invent = NO_INVENT; } } @@ -3348,7 +3368,8 @@ lspo_monster(lua_State *L) create_monster(&tmpmons, gc.coder->croom); - if (tmpmons.has_invent && lua_type(L, -1) == LUA_TFUNCTION) { + if ((tmpmons.has_invent & CUSTOM_INVENT) + && lua_type(L, -1) == LUA_TFUNCTION) { lua_remove(L, -2); nhl_pcall_handle(L, 0, 0, "lspo_monster", NHLpa_panic); spo_end_moninvent();