mirror of
https://github.com/tbamud/tbamud.git
synced 2026-03-19 10:46:33 +01:00
Update set commands, add exdescs to npc's
This commit is contained in:
parent
1a1767b97a
commit
b15702aa53
6 changed files with 777 additions and 1316 deletions
123
README.md
123
README.md
|
|
@ -2,122 +2,13 @@
|
|||
|
||||
Cataclysm MUD is a continuation of tbaMUD/CircleMUD, which is built on DIKU MUD.
|
||||
Due to licensing issues with tbaMUD, all licensing attributions should remain the
|
||||
same and not changed from the original, pre-LGPL license model.
|
||||
same and not changed from the original, pre-LGPL license model. It strives to be
|
||||
open source and available to everyone just like DIKU/Circle/tba have been in the
|
||||
past. You're welcome to read the code, make your own changes in a fork, and re-use
|
||||
it as need be. Just follow the LICENSE.md file and you'll be fine.
|
||||
|
||||
|
||||
TO be clear: **this is not an LGPL licensed fork**.
|
||||
|
||||
Changes from stock tbaMUD 2025 to Cataclysm MUD v1.0.0-alpha:
|
||||
|
||||
* The city of Caleran is available for exploration
|
||||
* Experience points and levels are removed in favor of skill based progression
|
||||
* Initial skills/spells based partly on tbaMUD code and 5e conversion (to be cleaned up in later release)
|
||||
* Expanded emoting system for roleplay
|
||||
* Permanent character death
|
||||
* A hybrid "5e-like" system where:
|
||||
- [ ] Legacy THAC0 systems are removed in favor of the modern 5e system
|
||||
- [ ] Your skill level translates to a proficiency bonus on a per-skill level
|
||||
- [ ] Saving throws are based on 5e rules (if your class has them, you do)
|
||||
- [ ] Your spell save DC is 8 + skill profiency + ability mod for your class
|
||||
- [ ] AC and to hit d20 rolls typical of 5e, capped at +10 to hit and +8 to AC
|
||||
- [ ] Introduction of basic 5e skills which are used for multiple commands
|
||||
* QUIT room flags to designate a room safe to quit in, as well as quit ooc <message>
|
||||
* SAVE room flags for players to drop their loot in (such as an apartment or barracks)
|
||||
* NPC's can be equipped with items and their prototypes saved for quick future loading
|
||||
* Rooms can be saved with their objects and NPC's to be loaded on the next boot
|
||||
* Converted action descriptions to main descriptions for items
|
||||
* Mapping command now supports new terrain types
|
||||
* Players do not pay to keep their items when they log out
|
||||
* Furniture items now allow items to be placed on top of them (a mug on top of the bar)
|
||||
* Furniture items can now be stood at, sat on, rested on, and slept on
|
||||
* Furniture items in rooms can be reviewed with "look tables"
|
||||
* Think, feel, and OOC commands for roleplay purposes
|
||||
* Expanded say, talk, and whisper commands to allow for greater roleplay
|
||||
* Sneak/Hide have been updated and an opposed roll against observers occurs
|
||||
* Ability to stealthily put or get items from containers via Palm/Slip commands
|
||||
* Listening in on conversations nearby is possible
|
||||
* Modernized stat output for immortals
|
||||
* NPC's can now be assigned a class like a PC and inherit the relevant skills
|
||||
* PC's now use a short description for identification instead of name
|
||||
* Backgrounds are now available for PC's and NPC's
|
||||
* Account system for tracking players/characters over long periods of time
|
||||
|
||||
Changes in v1.1.0-alpha:
|
||||
|
||||
* Cleaned up legacy practice system code
|
||||
* Added skill caps for classes to limit ability of everyone to reach skill level 100 (and respective proficiency)
|
||||
* Race/species selection and stat ranges (elves have higher dex, dwarves have higher str, etc)
|
||||
* Renamed move to stamina in code to reflect how much energy is used for certain actions
|
||||
* Species have base hit/mana/stamina now, plus their class modifier rolls
|
||||
* Prioritized stats during character generation
|
||||
* Ability to change ldesc of PC/NPC's
|
||||
* Ability to look in certain directions to see what is 1-3 rooms away
|
||||
* PC's and NPC's can now have an age set between 18-65
|
||||
* "audit armor" and "audit melee" commands for immortals (formerly "acaudit") to check non-compliant items
|
||||
* Minor score output change to only show quest status while on a quest, PC/NPC name, sdesc, and current ldesc
|
||||
* Added ability to reroll initial stats if they are not to player's liking, and undo reroll if needed
|
||||
* Removed alignment from game - no more GOOD/EVIL flags or restrictions on shops
|
||||
* Removed ANTI_ flags related to class restrictions on what objects they can use
|
||||
* Mounts added to help with long trips, and ability to use them as pack animals
|
||||
* Introduced AGENTS.md file to ensure code quality
|
||||
* Migration away from OLC with new commands "rcreate" and "rset" for builders to modify rooms
|
||||
* Migration away from OLC with new commands "ocreate", "oset", and "osave" for builders to modify objects
|
||||
* Migration away from OLC with new command "mcreate" and for builders to modify NPC's
|
||||
* Fixed issue with msave not saving items in containers on NPC's
|
||||
|
||||
Changes in v1.2.0-alpha:
|
||||
* Replaced ASCII files in favor of TOML for ease of reading
|
||||
|
||||
Changes in v1.3.0-alpha:
|
||||
* Migration away from OLC with new command "mset" and for builders to update NPC's
|
||||
|
||||
Features that will be implemented in the next few releases:
|
||||
|
||||
* Height and weight normalized to species
|
||||
* Stables allow for purchasing of mounts
|
||||
* Stables will take mounts and provide tickets to get them out
|
||||
* Updated door code so that it can be closed/locked/saved with rsave code
|
||||
* SECTOR/ROOM type changes to make terrain movement easier or more difficult
|
||||
* Subclass selection to personalize character further
|
||||
* Combat is slowed down so it isn't over in < 15 seconds (unless you're far outmatched)
|
||||
* Wagons added to help with caravans
|
||||
* BUILDING object type created to allow enter/leave
|
||||
* Updated BUILDING object type so that it can be damaged and no longer enterable (but someone can leave at cost to health)
|
||||
* Plantlife introduced, allowing a plant object to produce fruit or herbs every few hours/days
|
||||
* Plantlife can be refreshed to spawn fruits/herbs more frequently by watering it
|
||||
* Updated lockpicking skill
|
||||
* Trap as a skill - one focused on city and one focused on desert
|
||||
* Poisons and antidotes
|
||||
* New alcohol and drugs/stimulants
|
||||
* Skimmers/ships to traverse difficult terrain
|
||||
* New elemental classes
|
||||
* Introduction of gathering mana/magic for sorceror class
|
||||
* Highly modified magic system
|
||||
* Ranged weapons and ammo
|
||||
* Components for some magical spells
|
||||
* Reading/writing limited to specific castes of society
|
||||
* Haggling and bartering system
|
||||
* New calendar and moon cycles
|
||||
* Heat based on time of day increases/decreases, changing hunger/thirst levels
|
||||
* Weather updates and sandstorms limiting visibility
|
||||
* Shaded rooms providing bonuses to regeneration
|
||||
* Criminal system for cities and jails
|
||||
* Basic Psionics
|
||||
* Basic crafting system
|
||||
* Apartment rentals for storing your loot
|
||||
* Enhanced quest system
|
||||
* Dialogue trees with NPC's
|
||||
* Additional zones/cities based on Miranthas world map
|
||||
* Resources on the world map can be claimed by different city-states or independent factions
|
||||
* Claimed resources improve quality of armor/weapons/food/prices available
|
||||
* Death from old age if you roll badly on your birthday after the expected lifespan of a species
|
||||
* Attacks hit different parts of the body and have different damage effects
|
||||
* Armor degradation based on damage taken per body part
|
||||
* Weapon degradation based on damage dealt - potentially shattering weapons
|
||||
|
||||
...and down the road:
|
||||
|
||||
* Replace DG Scripts with a Python abstraction layer for modern scripting support
|
||||
* Replace Oasis OLC with more modern interface for easing builder duties
|
||||
* Discord server integration for ticketing and community
|
||||
* Full documentation for admins and easy to follow improvement guides
|
||||
* ...suggestions from anyone who uses this game
|
||||
Cataclysm's focus is on building an RPI MUD that takes into account many of the
|
||||
failings of previous RPI games.
|
||||
25
src/db.c
25
src/db.c
|
|
@ -1731,6 +1731,31 @@ static void parse_mobile_toml(toml_table_t *mob_tab)
|
|||
!str_cmp(fname(mob_proto[i].player.short_descr), "the"))
|
||||
*mob_proto[i].player.short_descr = LOWER(*mob_proto[i].player.short_descr);
|
||||
|
||||
arr = toml_array_in(mob_tab, "extra_desc");
|
||||
if (arr) {
|
||||
int n = toml_array_nelem(arr);
|
||||
for (j = 0; j < n; j++) {
|
||||
toml_table_t *ed_tab = toml_table_at(arr, j);
|
||||
struct extra_descr_data *new_descr;
|
||||
char *keyword, *description;
|
||||
if (!ed_tab)
|
||||
continue;
|
||||
keyword = toml_get_string_dup(ed_tab, "keyword");
|
||||
description = toml_get_string_dup(ed_tab, "description");
|
||||
if (!keyword || !description) {
|
||||
if (keyword) free(keyword);
|
||||
if (description) free(description);
|
||||
continue;
|
||||
}
|
||||
CREATE(new_descr, struct extra_descr_data, 1);
|
||||
new_descr->keyword = keyword;
|
||||
new_descr->description = description;
|
||||
ensure_newline_terminated(new_descr);
|
||||
new_descr->next = mob_proto[i].mob_specials.ex_description;
|
||||
mob_proto[i].mob_specials.ex_description = new_descr;
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < AF_ARRAY_MAX; j++) {
|
||||
MOB_FLAGS(mob_proto + i)[j] = 0;
|
||||
AFF_FLAGS(mob_proto + i)[j] = 0;
|
||||
|
|
|
|||
32
src/genmob.c
32
src/genmob.c
|
|
@ -128,6 +128,11 @@ static void extract_mobile_all(mob_vnum vnum)
|
|||
if (ch->player.background && ch->player.background != mob_proto[i].player.background)
|
||||
free(ch->player.background);
|
||||
ch->player.background = NULL;
|
||||
|
||||
if (ch->mob_specials.ex_description &&
|
||||
ch->mob_specials.ex_description != mob_proto[i].mob_specials.ex_description)
|
||||
free_ex_descriptions(ch->mob_specials.ex_description);
|
||||
ch->mob_specials.ex_description = NULL;
|
||||
|
||||
/* free script proto list if it's not the prototype */
|
||||
if (ch->proto_script && ch->proto_script != mob_proto[i].proto_script)
|
||||
|
|
@ -208,6 +213,8 @@ int copy_mobile_strings(struct char_data *t, struct char_data *f)
|
|||
t->player.description = strdup(f->player.description);
|
||||
if (f->player.background)
|
||||
t->player.background = strdup(f->player.background);
|
||||
if (f->mob_specials.ex_description)
|
||||
copy_ex_descriptions(&t->mob_specials.ex_description, f->mob_specials.ex_description);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -223,6 +230,7 @@ int update_mobile_strings(struct char_data *t, struct char_data *f)
|
|||
t->player.description = f->player.description;
|
||||
if (f->player.background)
|
||||
t->player.background = f->player.background;
|
||||
t->mob_specials.ex_description = f->mob_specials.ex_description;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -238,6 +246,10 @@ int free_mobile_strings(struct char_data *mob)
|
|||
free(mob->player.description);
|
||||
if (mob->player.background)
|
||||
free(mob->player.background);
|
||||
if (mob->mob_specials.ex_description) {
|
||||
free_ex_descriptions(mob->mob_specials.ex_description);
|
||||
mob->mob_specials.ex_description = NULL;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -266,6 +278,9 @@ int free_mobile(struct char_data *mob)
|
|||
free(mob->player.description);
|
||||
if (mob->player.background && mob->player.background != mob_proto[i].player.background)
|
||||
free(mob->player.background);
|
||||
if (mob->mob_specials.ex_description &&
|
||||
mob->mob_specials.ex_description != mob_proto[i].mob_specials.ex_description)
|
||||
free_ex_descriptions(mob->mob_specials.ex_description);
|
||||
/* free script proto list if it's not the prototype */
|
||||
if (mob->proto_script && mob->proto_script != mob_proto[i].proto_script)
|
||||
free_proto_script(mob, MOB_TRIGGER);
|
||||
|
|
@ -407,6 +422,7 @@ int write_mobile_record(mob_vnum mvnum, struct char_data *mob, FILE *fd)
|
|||
char ldesc[MAX_STRING_LENGTH];
|
||||
char ddesc[MAX_STRING_LENGTH];
|
||||
char bdesc[MAX_STRING_LENGTH];
|
||||
char edesc_buf[MAX_STRING_LENGTH];
|
||||
int has_bdesc = 0;
|
||||
|
||||
ldesc[MAX_STRING_LENGTH - 1] = '\0';
|
||||
|
|
@ -438,6 +454,22 @@ int write_mobile_record(mob_vnum mvnum, struct char_data *mob, FILE *fd)
|
|||
if (has_bdesc)
|
||||
toml_write_kv_string_opt(fd, "background", bdesc);
|
||||
|
||||
if (mob->mob_specials.ex_description) {
|
||||
struct extra_descr_data *xdesc;
|
||||
for (xdesc = mob->mob_specials.ex_description; xdesc; xdesc = xdesc->next) {
|
||||
if (!xdesc->keyword || !xdesc->description || !*xdesc->keyword || !*xdesc->description) {
|
||||
mudlog(BRF, LVL_IMMORT, TRUE, "SYSERR: GenOLC: write_mobile_record: Corrupt ex_desc!");
|
||||
continue;
|
||||
}
|
||||
strncpy(edesc_buf, xdesc->description, sizeof(edesc_buf) - 1);
|
||||
edesc_buf[sizeof(edesc_buf) - 1] = '\0';
|
||||
strip_cr(edesc_buf);
|
||||
fprintf(fd, "\n[[mob.extra_desc]]\n");
|
||||
toml_write_kv_string(fd, "keyword", xdesc->keyword);
|
||||
toml_write_kv_string(fd, "description", edesc_buf);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(fd, "flags = [%d, %d, %d, %d]\n",
|
||||
MOB_FLAGS(mob)[0], MOB_FLAGS(mob)[1],
|
||||
MOB_FLAGS(mob)[2], MOB_FLAGS(mob)[3]);
|
||||
|
|
|
|||
597
src/set.c
597
src/set.c
|
|
@ -50,7 +50,9 @@ static void rset_show_usage(struct char_data *ch)
|
|||
" rset add sector <sector>\r\n"
|
||||
" rset add flags <flag> [flag ...]\r\n"
|
||||
" rset add exit <direction> <room number>\r\n"
|
||||
" rset add exitdesc <direction> <text>\r\n"
|
||||
" rset add door <direction> <name of door>\r\n"
|
||||
" rset add doorflags <direction> <flag> [flag ...]\r\n"
|
||||
" rset add key <direction> <key number>\r\n"
|
||||
" rset add hidden <direction>\r\n"
|
||||
" rset add forage <object vnum> <dc check>\r\n"
|
||||
|
|
@ -100,7 +102,9 @@ static void rset_show_add_usage(struct char_data *ch)
|
|||
" rset add sector <sector>\r\n"
|
||||
" rset add flags <flag> [flag ...]\r\n"
|
||||
" rset add exit <direction> <room number>\r\n"
|
||||
" rset add exitdesc <direction> <text>\r\n"
|
||||
" rset add door <direction> <name of door>\r\n"
|
||||
" rset add doorflags <direction> <flag> [flag ...]\r\n"
|
||||
" rset add key <direction> <key number>\r\n"
|
||||
" rset add hidden <direction>\r\n"
|
||||
" rset add forage <object vnum> <dc check>\r\n"
|
||||
|
|
@ -116,7 +120,9 @@ static void rset_show_del_usage(struct char_data *ch)
|
|||
"Usage:\r\n"
|
||||
" rset del flags <flag> [flag ...]\r\n"
|
||||
" rset del exit <direction>\r\n"
|
||||
" rset del exitdesc <direction>\r\n"
|
||||
" rset del door <direction>\r\n"
|
||||
" rset del doorflags <direction> <flag> [flag ...]\r\n"
|
||||
" rset del key <direction>\r\n"
|
||||
" rset del hidden <direction>\r\n"
|
||||
" rset del forage <object vnum>\r\n"
|
||||
|
|
@ -208,10 +214,22 @@ static void rset_show_add_exit_usage(struct char_data *ch)
|
|||
" rset add exit n 101\r\n");
|
||||
}
|
||||
|
||||
static void rset_show_add_exitdesc_usage(struct char_data *ch)
|
||||
{
|
||||
send_to_char(ch,
|
||||
"Adds a description to an existing exit.\r\n"
|
||||
"\r\n"
|
||||
"Usage:\r\n"
|
||||
" rset add exitdesc <direction> <text>\r\n"
|
||||
"\r\n"
|
||||
"Examples:\r\n"
|
||||
" rset add exitdesc n A narrow arch leads north.\r\n");
|
||||
}
|
||||
|
||||
static void rset_show_add_door_usage(struct char_data *ch)
|
||||
{
|
||||
send_to_char(ch,
|
||||
"Adds a door to an existing exit.\r\n"
|
||||
"Adds a door keyword to an existing exit.\r\n"
|
||||
"\r\n"
|
||||
"Usage:\r\n"
|
||||
" rset add door <direction> <name of door>\r\n"
|
||||
|
|
@ -220,6 +238,26 @@ static void rset_show_add_door_usage(struct char_data *ch)
|
|||
" rset add door n door\r\n");
|
||||
}
|
||||
|
||||
static void rset_show_add_doorflags_usage(struct char_data *ch)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
while (*exit_bits[count] != '\n')
|
||||
count++;
|
||||
|
||||
send_to_char(ch,
|
||||
"Adds door flags to an existing exit.\r\n"
|
||||
"\r\n"
|
||||
"Usage:\r\n"
|
||||
" rset add doorflags <direction> <flag> [flag ...]\r\n"
|
||||
"\r\n"
|
||||
"Examples:\r\n"
|
||||
" rset add doorflags n closed locked\r\n"
|
||||
"\r\n"
|
||||
"Flags:\r\n");
|
||||
column_list(ch, 0, exit_bits, count, FALSE);
|
||||
}
|
||||
|
||||
static void rset_show_add_key_usage(struct char_data *ch)
|
||||
{
|
||||
send_to_char(ch,
|
||||
|
|
@ -280,6 +318,18 @@ static void rset_show_del_exit_usage(struct char_data *ch)
|
|||
" rset del exit n\r\n");
|
||||
}
|
||||
|
||||
static void rset_show_del_exitdesc_usage(struct char_data *ch)
|
||||
{
|
||||
send_to_char(ch,
|
||||
"Deletes the description from an existing exit.\r\n"
|
||||
"\r\n"
|
||||
"Usage:\r\n"
|
||||
" rset del exitdesc <direction>\r\n"
|
||||
"\r\n"
|
||||
"Examples:\r\n"
|
||||
" rset del exitdesc n\r\n");
|
||||
}
|
||||
|
||||
static void rset_show_del_door_usage(struct char_data *ch)
|
||||
{
|
||||
send_to_char(ch,
|
||||
|
|
@ -292,6 +342,26 @@ static void rset_show_del_door_usage(struct char_data *ch)
|
|||
" rset del door n\r\n");
|
||||
}
|
||||
|
||||
static void rset_show_del_doorflags_usage(struct char_data *ch)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
while (*exit_bits[count] != '\n')
|
||||
count++;
|
||||
|
||||
send_to_char(ch,
|
||||
"Deletes door flags from an existing exit.\r\n"
|
||||
"\r\n"
|
||||
"Usage:\r\n"
|
||||
" rset del doorflags <direction> <flag> [flag ...]\r\n"
|
||||
"\r\n"
|
||||
"Examples:\r\n"
|
||||
" rset del doorflags n locked\r\n"
|
||||
"\r\n"
|
||||
"Flags:\r\n");
|
||||
column_list(ch, 0, exit_bits, count, FALSE);
|
||||
}
|
||||
|
||||
static void rset_show_del_key_usage(struct char_data *ch)
|
||||
{
|
||||
send_to_char(ch,
|
||||
|
|
@ -380,6 +450,17 @@ static int rset_find_dir(const char *arg)
|
|||
return dir;
|
||||
}
|
||||
|
||||
static int rset_find_exit_flag(const char *arg)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; *exit_bits[i] != '\n'; i++)
|
||||
if (is_abbrev(arg, exit_bits[i]))
|
||||
return (1 << i);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void rset_mark_room_modified(room_rnum rnum)
|
||||
{
|
||||
if (rnum == NOWHERE || rnum < 0 || rnum > top_of_world)
|
||||
|
|
@ -436,6 +517,8 @@ static void rset_show_room(struct char_data *ch, struct room_data *room)
|
|||
exit->keyword ? exit->keyword : "None",
|
||||
keybuf,
|
||||
buf);
|
||||
if (exit->general_description && *exit->general_description)
|
||||
send_to_char(ch, " desc: %s\r\n", exit->general_description);
|
||||
count++;
|
||||
}
|
||||
if (!count)
|
||||
|
|
@ -831,6 +914,39 @@ ACMD(do_rset)
|
|||
return;
|
||||
}
|
||||
|
||||
if (is_abbrev(arg2, "exitdesc")) {
|
||||
int dir;
|
||||
char *desc;
|
||||
|
||||
argument = one_argument(argument, arg3);
|
||||
skip_spaces(&argument);
|
||||
desc = argument;
|
||||
|
||||
if (!*arg3 || !*desc) {
|
||||
rset_show_add_exitdesc_usage(ch);
|
||||
return;
|
||||
}
|
||||
|
||||
dir = rset_find_dir(arg3);
|
||||
if (dir < 0) {
|
||||
send_to_char(ch, "Invalid direction.\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!room->dir_option[dir] || room->dir_option[dir]->to_room == NOWHERE) {
|
||||
send_to_char(ch, "That exit does not exist.\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
genolc_checkstring(ch->desc, desc);
|
||||
if (room->dir_option[dir]->general_description)
|
||||
free(room->dir_option[dir]->general_description);
|
||||
room->dir_option[dir]->general_description = str_udup(desc);
|
||||
rset_mark_room_modified(rnum);
|
||||
send_to_char(ch, "Exit description set for %s.\r\n", dirs[dir]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_abbrev(arg2, "door")) {
|
||||
int dir;
|
||||
char *door_name;
|
||||
|
|
@ -865,6 +981,56 @@ ACMD(do_rset)
|
|||
return;
|
||||
}
|
||||
|
||||
if (is_abbrev(arg2, "doorflags")) {
|
||||
int dir;
|
||||
bool any = FALSE;
|
||||
|
||||
argument = one_argument(argument, arg3);
|
||||
if (!*arg3) {
|
||||
rset_show_add_doorflags_usage(ch);
|
||||
return;
|
||||
}
|
||||
|
||||
dir = rset_find_dir(arg3);
|
||||
if (dir < 0) {
|
||||
send_to_char(ch, "Invalid direction.\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!room->dir_option[dir] || room->dir_option[dir]->to_room == NOWHERE) {
|
||||
send_to_char(ch, "That exit does not exist.\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!*argument) {
|
||||
rset_show_add_doorflags_usage(ch);
|
||||
return;
|
||||
}
|
||||
|
||||
while (*argument) {
|
||||
int flag;
|
||||
|
||||
argument = one_argument(argument, arg1);
|
||||
if (!*arg1)
|
||||
break;
|
||||
|
||||
flag = rset_find_exit_flag(arg1);
|
||||
if (flag < 0) {
|
||||
send_to_char(ch, "Unknown door flag: %s\r\n", arg1);
|
||||
continue;
|
||||
}
|
||||
|
||||
SET_BIT(room->dir_option[dir]->exit_info, flag);
|
||||
any = TRUE;
|
||||
}
|
||||
|
||||
if (any) {
|
||||
rset_mark_room_modified(rnum);
|
||||
send_to_char(ch, "Door flags updated on %s.\r\n", dirs[dir]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_abbrev(arg2, "key")) {
|
||||
int dir;
|
||||
int key_vnum;
|
||||
|
|
@ -1088,6 +1254,36 @@ ACMD(do_rset)
|
|||
return;
|
||||
}
|
||||
|
||||
if (is_abbrev(arg2, "exitdesc")) {
|
||||
int dir;
|
||||
|
||||
argument = one_argument(argument, arg3);
|
||||
if (!*arg3) {
|
||||
rset_show_del_exitdesc_usage(ch);
|
||||
return;
|
||||
}
|
||||
|
||||
dir = rset_find_dir(arg3);
|
||||
if (dir < 0) {
|
||||
send_to_char(ch, "Invalid direction.\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!room->dir_option[dir] || room->dir_option[dir]->to_room == NOWHERE) {
|
||||
send_to_char(ch, "That exit does not exist.\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (room->dir_option[dir]->general_description) {
|
||||
free(room->dir_option[dir]->general_description);
|
||||
room->dir_option[dir]->general_description = NULL;
|
||||
}
|
||||
|
||||
rset_mark_room_modified(rnum);
|
||||
send_to_char(ch, "Exit description removed from %s.\r\n", dirs[dir]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_abbrev(arg2, "door")) {
|
||||
int dir;
|
||||
|
||||
|
|
@ -1123,6 +1319,56 @@ ACMD(do_rset)
|
|||
return;
|
||||
}
|
||||
|
||||
if (is_abbrev(arg2, "doorflags")) {
|
||||
int dir;
|
||||
bool any = FALSE;
|
||||
|
||||
argument = one_argument(argument, arg3);
|
||||
if (!*arg3) {
|
||||
rset_show_del_doorflags_usage(ch);
|
||||
return;
|
||||
}
|
||||
|
||||
dir = rset_find_dir(arg3);
|
||||
if (dir < 0) {
|
||||
send_to_char(ch, "Invalid direction.\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!room->dir_option[dir] || room->dir_option[dir]->to_room == NOWHERE) {
|
||||
send_to_char(ch, "That exit does not exist.\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!*argument) {
|
||||
rset_show_del_doorflags_usage(ch);
|
||||
return;
|
||||
}
|
||||
|
||||
while (*argument) {
|
||||
int flag;
|
||||
|
||||
argument = one_argument(argument, arg1);
|
||||
if (!*arg1)
|
||||
break;
|
||||
|
||||
flag = rset_find_exit_flag(arg1);
|
||||
if (flag < 0) {
|
||||
send_to_char(ch, "Unknown door flag: %s\r\n", arg1);
|
||||
continue;
|
||||
}
|
||||
|
||||
REMOVE_BIT(room->dir_option[dir]->exit_info, flag);
|
||||
any = TRUE;
|
||||
}
|
||||
|
||||
if (any) {
|
||||
rset_mark_room_modified(rnum);
|
||||
send_to_char(ch, "Door flags updated on %s.\r\n", dirs[dir]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_abbrev(arg2, "key")) {
|
||||
int dir;
|
||||
|
||||
|
|
@ -1309,6 +1555,7 @@ static void oset_show_usage(struct char_data *ch)
|
|||
" oset add weight <obj> <value>\r\n"
|
||||
" oset add cost <obj> <value>\r\n"
|
||||
" oset add oval <obj> <oval number> <value>\r\n"
|
||||
" oset add edesc <obj> <keyword> <description>\r\n"
|
||||
" oset del <obj> <field>\r\n"
|
||||
" oset clear <obj> force\r\n"
|
||||
" oset validate <obj>\r\n");
|
||||
|
|
@ -1329,7 +1576,8 @@ static void oset_show_add_usage(struct char_data *ch)
|
|||
" oset add wear <obj> <wear type> [wear types]\r\n"
|
||||
" oset add weight <obj> <value>\r\n"
|
||||
" oset add cost <obj> <value>\r\n"
|
||||
" oset add oval <obj> <oval number> <value>\r\n");
|
||||
" oset add oval <obj> <oval number> <value>\r\n"
|
||||
" oset add edesc <obj> <keyword> <description>\r\n");
|
||||
}
|
||||
|
||||
static void oset_show_add_keywords_usage(struct char_data *ch)
|
||||
|
|
@ -1442,6 +1690,18 @@ static void oset_show_add_oval_usage(struct char_data *ch)
|
|||
" oset add oval sword weapon_type slashing (for weapons)\r\n");
|
||||
}
|
||||
|
||||
static void oset_show_add_edesc_usage(struct char_data *ch)
|
||||
{
|
||||
send_to_char(ch,
|
||||
"Adds an extra description to the object.\r\n"
|
||||
"\r\n"
|
||||
"Usage:\r\n"
|
||||
" oset add edesc <obj> <keyword> <description>\r\n"
|
||||
"\r\n"
|
||||
"Examples:\r\n"
|
||||
" oset add edesc sword rune A rune is etched along the blade.\r\n");
|
||||
}
|
||||
|
||||
static void oset_show_del_usage(struct char_data *ch)
|
||||
{
|
||||
send_to_char(ch,
|
||||
|
|
@ -1452,6 +1712,7 @@ static void oset_show_del_usage(struct char_data *ch)
|
|||
" oset del <obj> flags <flags> [flags]\r\n"
|
||||
" oset del <obj> wear <wear type> [wear types]\r\n"
|
||||
" oset del <obj> oval <oval number|oval name>\r\n"
|
||||
" oset del <obj> edesc <keyword>\r\n"
|
||||
"\r\n"
|
||||
"Examples:\r\n"
|
||||
" oset del sword keywords sword\r\n"
|
||||
|
|
@ -1502,6 +1763,18 @@ static void oset_show_clear_usage(struct char_data *ch)
|
|||
" oset clear sword force\r\n");
|
||||
}
|
||||
|
||||
static void oset_show_del_edesc_usage(struct char_data *ch)
|
||||
{
|
||||
send_to_char(ch,
|
||||
"Deletes an extra description from the object.\r\n"
|
||||
"\r\n"
|
||||
"Usage:\r\n"
|
||||
" oset del <obj> edesc <keyword>\r\n"
|
||||
"\r\n"
|
||||
"Examples:\r\n"
|
||||
" oset del sword edesc rune\r\n");
|
||||
}
|
||||
|
||||
static struct obj_data *oset_get_target_obj_keyword(struct char_data *ch, char *keyword)
|
||||
{
|
||||
struct obj_data *obj;
|
||||
|
|
@ -1718,6 +1991,15 @@ static void oset_show_object(struct char_data *ch, struct obj_data *obj)
|
|||
const char *label = labels ? labels[i] : "Value";
|
||||
send_to_char(ch, " [%d] %s: %d\r\n", i, label, GET_OBJ_VAL(obj, i));
|
||||
}
|
||||
|
||||
send_to_char(ch, "Extra Descs:\r\n");
|
||||
i = 0;
|
||||
for (struct extra_descr_data *desc = obj->ex_description; desc; desc = desc->next) {
|
||||
send_to_char(ch, " %s\r\n", desc->keyword ? desc->keyword : "<None>");
|
||||
i++;
|
||||
}
|
||||
if (!i)
|
||||
send_to_char(ch, " None.\r\n");
|
||||
}
|
||||
|
||||
static void oset_desc_edit(struct char_data *ch, struct obj_data *obj)
|
||||
|
|
@ -1759,7 +2041,7 @@ static void oset_clear_object(struct obj_data *obj)
|
|||
GET_OBJ_COST(obj) = 0;
|
||||
GET_OBJ_COST_PER_DAY(obj) = 0;
|
||||
GET_OBJ_TIMER(obj) = 0;
|
||||
GET_OBJ_LEVEL(obj) = 0;
|
||||
GET_OBJ_LEVEL(obj) = 1;
|
||||
|
||||
memset(obj->obj_flags.extra_flags, 0, sizeof(obj->obj_flags.extra_flags));
|
||||
memset(obj->obj_flags.wear_flags, 0, sizeof(obj->obj_flags.wear_flags));
|
||||
|
|
@ -1809,6 +2091,33 @@ static void oset_validate_object(struct char_data *ch, struct obj_data *obj)
|
|||
errors++;
|
||||
}
|
||||
|
||||
if (GET_OBJ_LEVEL(obj) != 1) {
|
||||
send_to_char(ch, "Error: object level must be 1.\r\n");
|
||||
errors++;
|
||||
}
|
||||
|
||||
if (GET_OBJ_TIMER(obj) != 0) {
|
||||
send_to_char(ch, "Error: object timer must be 0.\r\n");
|
||||
errors++;
|
||||
}
|
||||
|
||||
if (GET_OBJ_COST_PER_DAY(obj) != 0) {
|
||||
send_to_char(ch, "Error: cost per day must be 0.\r\n");
|
||||
errors++;
|
||||
}
|
||||
|
||||
for (struct extra_descr_data *desc = obj->ex_description; desc; desc = desc->next) {
|
||||
if (!desc->keyword || !*desc->keyword) {
|
||||
send_to_char(ch, "Error: extra description is missing a keyword.\r\n");
|
||||
errors++;
|
||||
}
|
||||
if (!desc->description || !*desc->description) {
|
||||
send_to_char(ch, "Error: extra description for %s is missing text.\r\n",
|
||||
desc->keyword ? desc->keyword : "<None>");
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!errors)
|
||||
send_to_char(ch, "Object validates cleanly.\r\n");
|
||||
else
|
||||
|
|
@ -2160,6 +2469,40 @@ ACMD(do_oset)
|
|||
return;
|
||||
}
|
||||
|
||||
if (is_abbrev(arg2, "edesc")) {
|
||||
struct extra_descr_data *desc;
|
||||
char *keyword;
|
||||
char *edesc;
|
||||
|
||||
argument = one_argument(argument, arg3);
|
||||
argument = one_argument(argument, arg4);
|
||||
skip_spaces(&argument);
|
||||
keyword = arg4;
|
||||
edesc = argument;
|
||||
|
||||
if (!*arg3 || !*keyword || !*edesc) {
|
||||
oset_show_add_edesc_usage(ch);
|
||||
return;
|
||||
}
|
||||
|
||||
obj = oset_get_target_obj_keyword(ch, arg3);
|
||||
if (!obj) {
|
||||
send_to_char(ch, "You don't seem to have %s %s.\r\n", AN(arg3), arg3);
|
||||
return;
|
||||
}
|
||||
|
||||
genolc_checkstring(ch->desc, edesc);
|
||||
genolc_checkstring(ch->desc, keyword);
|
||||
|
||||
CREATE(desc, struct extra_descr_data, 1);
|
||||
desc->keyword = str_udup(keyword);
|
||||
desc->description = str_udup(edesc);
|
||||
desc->next = obj->ex_description;
|
||||
obj->ex_description = desc;
|
||||
send_to_char(ch, "Extra description added.\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
oset_show_add_usage(ch);
|
||||
return;
|
||||
}
|
||||
|
|
@ -2289,6 +2632,46 @@ ACMD(do_oset)
|
|||
return;
|
||||
}
|
||||
|
||||
if (is_abbrev(arg3, "edesc")) {
|
||||
struct extra_descr_data *desc;
|
||||
struct extra_descr_data *prev = NULL;
|
||||
|
||||
argument = one_argument(argument, arg4);
|
||||
if (!*arg4) {
|
||||
oset_show_del_edesc_usage(ch);
|
||||
return;
|
||||
}
|
||||
obj = oset_get_target_obj_keyword(ch, arg2);
|
||||
if (!obj) {
|
||||
send_to_char(ch, "You don't seem to have %s %s.\r\n", AN(arg2), arg2);
|
||||
return;
|
||||
}
|
||||
|
||||
for (desc = obj->ex_description; desc; desc = desc->next) {
|
||||
if (desc->keyword && isname(arg4, desc->keyword))
|
||||
break;
|
||||
prev = desc;
|
||||
}
|
||||
|
||||
if (!desc) {
|
||||
send_to_char(ch, "No extra description found for %s.\r\n", arg4);
|
||||
return;
|
||||
}
|
||||
|
||||
if (prev)
|
||||
prev->next = desc->next;
|
||||
else
|
||||
obj->ex_description = desc->next;
|
||||
|
||||
if (desc->keyword)
|
||||
free(desc->keyword);
|
||||
if (desc->description)
|
||||
free(desc->description);
|
||||
free(desc);
|
||||
send_to_char(ch, "Extra description removed.\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
oset_show_del_usage(ch);
|
||||
return;
|
||||
}
|
||||
|
|
@ -2359,6 +2742,7 @@ static void mset_show_usage(struct char_data *ch)
|
|||
" mset add ldesc <npc> <text>\r\n"
|
||||
" mset add desc <npc> (enters editor)\r\n"
|
||||
" mset add background <npc> (enters editor)\r\n"
|
||||
" mset add edesc <npc> <keyword> <description>\r\n"
|
||||
" mset add attack <npc> <attack type>\r\n"
|
||||
" mset add sex <npc> <male/female/neutral>\r\n"
|
||||
" mset add species <npc> <species name>\r\n"
|
||||
|
|
@ -2441,6 +2825,18 @@ static void mset_show_add_background_usage(struct char_data *ch)
|
|||
" mset add background <npc>\r\n");
|
||||
}
|
||||
|
||||
static void mset_show_add_edesc_usage(struct char_data *ch)
|
||||
{
|
||||
send_to_char(ch,
|
||||
"Adds an extra description to the NPC.\r\n"
|
||||
"\r\n"
|
||||
"Usage:\r\n"
|
||||
" mset add edesc <npc> <keyword> <description>\r\n"
|
||||
"\r\n"
|
||||
"Examples:\r\n"
|
||||
" mset add edesc guard scar A jagged scar cuts across the cheek.\r\n");
|
||||
}
|
||||
|
||||
static void mset_show_add_attack_usage(struct char_data *ch)
|
||||
{
|
||||
const char *types[NUM_ATTACK_TYPES];
|
||||
|
|
@ -2597,6 +2993,7 @@ static void mset_show_del_usage(struct char_data *ch)
|
|||
" mset del <npc> ldesc\r\n"
|
||||
" mset del <npc> desc\r\n"
|
||||
" mset del <npc> background\r\n"
|
||||
" mset del <npc> edesc <keyword>\r\n"
|
||||
" mset del <npc> attack\r\n"
|
||||
" mset del <npc> sex\r\n"
|
||||
" mset del <npc> species\r\n"
|
||||
|
|
@ -2609,6 +3006,18 @@ static void mset_show_del_usage(struct char_data *ch)
|
|||
" mset del <npc> skinning <vnum>\r\n");
|
||||
}
|
||||
|
||||
static void mset_show_del_edesc_usage(struct char_data *ch)
|
||||
{
|
||||
send_to_char(ch,
|
||||
"Deletes an extra description from the NPC.\r\n"
|
||||
"\r\n"
|
||||
"Usage:\r\n"
|
||||
" mset del <npc> edesc <keyword>\r\n"
|
||||
"\r\n"
|
||||
"Examples:\r\n"
|
||||
" mset del guard edesc scar\r\n");
|
||||
}
|
||||
|
||||
static void mset_show_del_flags_usage(struct char_data *ch)
|
||||
{
|
||||
send_to_char(ch,
|
||||
|
|
@ -2754,6 +3163,19 @@ static void mset_update_proto_keywords(mob_rnum rnum, const char *value)
|
|||
free(old);
|
||||
}
|
||||
|
||||
static void mset_update_proto_edesc(mob_rnum rnum, struct extra_descr_data *old)
|
||||
{
|
||||
struct char_data *mob;
|
||||
|
||||
if (rnum < 0)
|
||||
return;
|
||||
|
||||
for (mob = character_list; mob; mob = mob->next) {
|
||||
if (GET_MOB_RNUM(mob) == rnum && mob->mob_specials.ex_description == old)
|
||||
mob->mob_specials.ex_description = mob_proto[rnum].mob_specials.ex_description;
|
||||
}
|
||||
}
|
||||
|
||||
static void mset_replace_string(struct char_data *mob, char **field, const char *value, const char *proto_field)
|
||||
{
|
||||
if (*field && (!proto_field || *field != proto_field))
|
||||
|
|
@ -2867,6 +3289,15 @@ static void mset_show_mob(struct char_data *ch, struct char_data *mob)
|
|||
} else {
|
||||
send_to_char(ch, " None.\r\n");
|
||||
}
|
||||
|
||||
send_to_char(ch, "Extra Descs:\r\n");
|
||||
i = 0;
|
||||
for (struct extra_descr_data *desc = mob->mob_specials.ex_description; desc; desc = desc->next) {
|
||||
send_to_char(ch, " %s\r\n", desc->keyword ? desc->keyword : "<None>");
|
||||
i++;
|
||||
}
|
||||
if (!i)
|
||||
send_to_char(ch, " None.\r\n");
|
||||
}
|
||||
|
||||
static void mset_desc_edit(struct char_data *ch, char **field, const char *label)
|
||||
|
|
@ -2933,6 +3364,33 @@ static void mset_validate_mob(struct char_data *ch, struct char_data *mob)
|
|||
errors++;
|
||||
}
|
||||
|
||||
for (struct extra_descr_data *desc = mob->mob_specials.ex_description; desc; desc = desc->next) {
|
||||
if (!desc->keyword || !*desc->keyword) {
|
||||
send_to_char(ch, "Error: extra description is missing a keyword.\r\n");
|
||||
errors++;
|
||||
}
|
||||
if (!desc->description || !*desc->description) {
|
||||
send_to_char(ch, "Error: extra description for %s is missing text.\r\n",
|
||||
desc->keyword ? desc->keyword : "<None>");
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
if (GET_LEVEL(mob) != 1) {
|
||||
send_to_char(ch, "Error: level must be 1.\r\n");
|
||||
errors++;
|
||||
}
|
||||
|
||||
if (GET_DEFAULT_POS(mob) != POS_STANDING) {
|
||||
send_to_char(ch, "Error: default position must be standing.\r\n");
|
||||
errors++;
|
||||
}
|
||||
|
||||
if (GET_EXP(mob) != 0) {
|
||||
send_to_char(ch, "Error: EXP must be 0.\r\n");
|
||||
errors++;
|
||||
}
|
||||
|
||||
if (!errors)
|
||||
send_to_char(ch, "NPC validates cleanly.\r\n");
|
||||
else
|
||||
|
|
@ -3165,6 +3623,46 @@ ACMD(do_mset)
|
|||
return;
|
||||
}
|
||||
|
||||
if (is_abbrev(arg2, "edesc")) {
|
||||
struct extra_descr_data *desc;
|
||||
struct extra_descr_data *old;
|
||||
char *keyword;
|
||||
char *edesc;
|
||||
|
||||
argument = one_argument(argument, arg1);
|
||||
skip_spaces(&argument);
|
||||
keyword = arg1;
|
||||
edesc = argument;
|
||||
|
||||
if (!*keyword || !*edesc) {
|
||||
mset_show_add_edesc_usage(ch);
|
||||
return;
|
||||
}
|
||||
|
||||
genolc_checkstring(ch->desc, edesc);
|
||||
genolc_checkstring(ch->desc, keyword);
|
||||
|
||||
if (rnum != NOBODY) {
|
||||
old = mob_proto[rnum].mob_specials.ex_description;
|
||||
CREATE(desc, struct extra_descr_data, 1);
|
||||
desc->keyword = str_udup(keyword);
|
||||
desc->description = str_udup(edesc);
|
||||
desc->next = mob_proto[rnum].mob_specials.ex_description;
|
||||
mob_proto[rnum].mob_specials.ex_description = desc;
|
||||
mset_update_proto_edesc(rnum, old);
|
||||
mset_mark_mob_modified(vnum);
|
||||
} else {
|
||||
CREATE(desc, struct extra_descr_data, 1);
|
||||
desc->keyword = str_udup(keyword);
|
||||
desc->description = str_udup(edesc);
|
||||
desc->next = mob->mob_specials.ex_description;
|
||||
mob->mob_specials.ex_description = desc;
|
||||
}
|
||||
|
||||
send_to_char(ch, "Extra description added.\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_abbrev(arg2, "attack")) {
|
||||
int atype;
|
||||
|
||||
|
|
@ -3663,6 +4161,74 @@ ACMD(do_mset)
|
|||
return;
|
||||
}
|
||||
|
||||
if (is_abbrev(arg3, "edesc")) {
|
||||
struct extra_descr_data *desc;
|
||||
struct extra_descr_data *prev = NULL;
|
||||
struct extra_descr_data *old;
|
||||
|
||||
argument = one_argument(argument, arg1);
|
||||
if (!*arg1) {
|
||||
mset_show_del_edesc_usage(ch);
|
||||
return;
|
||||
}
|
||||
|
||||
if (rnum != NOBODY) {
|
||||
old = mob_proto[rnum].mob_specials.ex_description;
|
||||
desc = mob_proto[rnum].mob_specials.ex_description;
|
||||
while (desc) {
|
||||
if (desc->keyword && isname(arg1, desc->keyword))
|
||||
break;
|
||||
prev = desc;
|
||||
desc = desc->next;
|
||||
}
|
||||
|
||||
if (!desc) {
|
||||
send_to_char(ch, "No extra description found for %s.\r\n", arg1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (prev)
|
||||
prev->next = desc->next;
|
||||
else
|
||||
mob_proto[rnum].mob_specials.ex_description = desc->next;
|
||||
|
||||
if (desc->keyword)
|
||||
free(desc->keyword);
|
||||
if (desc->description)
|
||||
free(desc->description);
|
||||
free(desc);
|
||||
mset_update_proto_edesc(rnum, old);
|
||||
mset_mark_mob_modified(vnum);
|
||||
} else {
|
||||
desc = mob->mob_specials.ex_description;
|
||||
while (desc) {
|
||||
if (desc->keyword && isname(arg1, desc->keyword))
|
||||
break;
|
||||
prev = desc;
|
||||
desc = desc->next;
|
||||
}
|
||||
|
||||
if (!desc) {
|
||||
send_to_char(ch, "No extra description found for %s.\r\n", arg1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (prev)
|
||||
prev->next = desc->next;
|
||||
else
|
||||
mob->mob_specials.ex_description = desc->next;
|
||||
|
||||
if (desc->keyword)
|
||||
free(desc->keyword);
|
||||
if (desc->description)
|
||||
free(desc->description);
|
||||
free(desc);
|
||||
}
|
||||
|
||||
send_to_char(ch, "Extra description removed.\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_abbrev(arg3, "attack")) {
|
||||
mob->mob_specials.attack_type = 0;
|
||||
if (rnum != NOBODY) {
|
||||
|
|
@ -3946,6 +4512,8 @@ ACMD(do_mset)
|
|||
}
|
||||
|
||||
if (rnum != NOBODY) {
|
||||
struct extra_descr_data *old_edesc = mob_proto[rnum].mob_specials.ex_description;
|
||||
|
||||
if (mob_proto[rnum].player.name)
|
||||
free(mob_proto[rnum].player.name);
|
||||
if (mob_proto[rnum].player.short_descr)
|
||||
|
|
@ -3956,17 +4524,25 @@ ACMD(do_mset)
|
|||
free(mob_proto[rnum].player.description);
|
||||
if (mob_proto[rnum].player.background)
|
||||
free(mob_proto[rnum].player.background);
|
||||
if (mob_proto[rnum].mob_specials.ex_description)
|
||||
free_ex_descriptions(mob_proto[rnum].mob_specials.ex_description);
|
||||
|
||||
mob_proto[rnum].player.name = strdup("An unfinished NPC");
|
||||
mob_proto[rnum].player.short_descr = strdup("the unfinished npc");
|
||||
mob_proto[rnum].player.long_descr = strdup("An unfinished npc stands here.\r\n");
|
||||
mob_proto[rnum].player.description = strdup("It looks unfinished.\r\n");
|
||||
mob_proto[rnum].player.background = strdup("No background has been recorded.\r\n");
|
||||
mob_proto[rnum].mob_specials.ex_description = NULL;
|
||||
mset_update_proto_edesc(rnum, old_edesc);
|
||||
|
||||
mob_proto[rnum].mob_specials.attack_type = 0;
|
||||
GET_SEX(&mob_proto[rnum]) = SEX_NEUTRAL;
|
||||
GET_CLASS(&mob_proto[rnum]) = CLASS_UNDEFINED;
|
||||
GET_SPECIES(&mob_proto[rnum]) = SPECIES_UNDEFINED;
|
||||
GET_LEVEL(&mob_proto[rnum]) = 1;
|
||||
GET_DEFAULT_POS(&mob_proto[rnum]) = POS_STANDING;
|
||||
GET_POS(&mob_proto[rnum]) = POS_STANDING;
|
||||
GET_EXP(&mob_proto[rnum]) = 0;
|
||||
|
||||
mset_set_stat_value(&mob_proto[rnum], ABIL_STR, 10, FALSE);
|
||||
mset_set_stat_value(&mob_proto[rnum], ABIL_DEX, 10, FALSE);
|
||||
|
|
@ -3997,11 +4573,19 @@ ACMD(do_mset)
|
|||
mset_replace_string(mob, &GET_LDESC(mob), "An unfinished npc stands here.\r\n", NULL);
|
||||
mset_replace_string(mob, &mob->player.description, "It looks unfinished.\r\n", NULL);
|
||||
mset_replace_string(mob, &mob->player.background, "No background has been recorded.\r\n", NULL);
|
||||
if (mob->mob_specials.ex_description) {
|
||||
free_ex_descriptions(mob->mob_specials.ex_description);
|
||||
mob->mob_specials.ex_description = NULL;
|
||||
}
|
||||
|
||||
mob->mob_specials.attack_type = 0;
|
||||
GET_SEX(mob) = SEX_NEUTRAL;
|
||||
GET_CLASS(mob) = CLASS_UNDEFINED;
|
||||
GET_SPECIES(mob) = SPECIES_UNDEFINED;
|
||||
GET_LEVEL(mob) = 1;
|
||||
GET_DEFAULT_POS(mob) = POS_STANDING;
|
||||
GET_POS(mob) = POS_STANDING;
|
||||
GET_EXP(mob) = 0;
|
||||
|
||||
mset_set_stat_value(mob, ABIL_STR, 10, TRUE);
|
||||
mset_set_stat_value(mob, ABIL_DEX, 10, TRUE);
|
||||
|
|
@ -4157,6 +4741,9 @@ ACMD(do_mcreate)
|
|||
init_mobile(newmob);
|
||||
|
||||
GET_LEVEL(newmob) = 1;
|
||||
GET_DEFAULT_POS(newmob) = POS_STANDING;
|
||||
GET_POS(newmob) = POS_STANDING;
|
||||
GET_EXP(newmob) = 0;
|
||||
|
||||
GET_NAME(newmob) = strdup("An unfinished NPC");
|
||||
GET_KEYWORDS(newmob) = strdup("unfinished npc");
|
||||
|
|
@ -4289,6 +4876,10 @@ ACMD(do_ocreate)
|
|||
CREATE(newobj, struct obj_data, 1);
|
||||
clear_object(newobj);
|
||||
|
||||
GET_OBJ_LEVEL(newobj) = 1;
|
||||
GET_OBJ_TIMER(newobj) = 0;
|
||||
GET_OBJ_COST_PER_DAY(newobj) = 0;
|
||||
|
||||
newobj->name = strdup("unfinished object");
|
||||
strlcpy(namebuf, GET_NAME(ch), sizeof(namebuf));
|
||||
snprintf(buf, sizeof(buf), "unfinished object made by %s", namebuf);
|
||||
|
|
|
|||
|
|
@ -1088,6 +1088,7 @@ struct mob_special_data
|
|||
byte attack_type; /**< The primary attack type (bite, sting, hit, etc.) */
|
||||
byte default_pos; /**< Default position (standing, sleeping, etc.) */
|
||||
byte skills[MAX_SKILLS]; /* NPC-specific skill proficiency (0-100) */
|
||||
struct extra_descr_data *ex_description; /**< Extra descriptions */
|
||||
};
|
||||
|
||||
/** An affect structure. */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue