Add in quit flag and fix quit logic

This commit is contained in:
kinther 2025-09-06 15:39:42 -07:00
parent 32919358e4
commit 21c66a16ae
8 changed files with 141 additions and 59 deletions

View file

@ -492,7 +492,7 @@ S
Draqoman Station~
This unfinished room was created by Kinther.
~
1 0 0 0 0 0
1 131072 0 0 0 0
D1
~
~
@ -530,7 +530,7 @@ S
The Golden Inix Inn~
This unfinished room was created by Kinther.
~
1 0 0 0 0 0
1 131072 0 0 0 0
D0
~
~

View file

@ -495,7 +495,7 @@ void look_at_room(struct char_data *ch, int ignore_brief)
if (!ch->desc)
return;
if (IS_DARK(IN_ROOM(ch)) && !CAN_SEE_IN_DARK(ch)){
if (IS_DARK(IN_ROOM(ch)) && !CAN_SEE_IN_DARK(ch)) {
send_to_char(ch, "It is pitch black...\r\n");
return;
}
@ -510,7 +510,12 @@ void look_at_room(struct char_data *ch, int ignore_brief)
sprintbitarray(ROOM_FLAGS(IN_ROOM(ch)), room_bits, RF_ARRAY_MAX, buf);
send_to_char(ch, "[%5d] ", GET_ROOM_VNUM(IN_ROOM(ch)));
send_to_char(ch, "%s[ %s][ %s ]", world[IN_ROOM(ch)].name, buf, sector_types[world[IN_ROOM(ch)].sector_type]);
send_to_char(ch, "%s[ %s][ %s ]",
world[IN_ROOM(ch)].name,
buf,
sector_types[world[IN_ROOM(ch)].sector_type]);
/* Do NOT append [Quit] here; QUITSAFE already shows in the flags list */
if (SCRIPT(rm)) {
send_to_char(ch, "[T");
@ -519,25 +524,28 @@ void look_at_room(struct char_data *ch, int ignore_brief)
send_to_char(ch, "]");
}
}
else
send_to_char(ch, "%s", world[IN_ROOM(ch)].name);
else {
/* For normal players (no PRF_SHOWVNUMS), append [Quit] to the title line */
send_to_char(ch, "%s%s",
world[IN_ROOM(ch)].name,
ROOM_FLAGGED(IN_ROOM(ch), ROOM_QUIT) ? " [Quit]" : "");
}
send_to_char(ch, "%s\r\n", CCNRM(ch, C_NRM));
if ((!IS_NPC(ch) && !PRF_FLAGGED(ch, PRF_BRIEF)) || ignore_brief ||
ROOM_FLAGGED(IN_ROOM(ch), ROOM_DEATH)) {
ROOM_FLAGGED(IN_ROOM(ch), ROOM_DEATH)) {
if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_AUTOMAP) && can_see_map(ch))
str_and_map(world[target_room].description, ch, target_room);
else
send_to_char(ch, "%s", world[IN_ROOM(ch)].description);
send_to_char(ch, "%s", world[IN_ROOM(ch)].description);
}
/*autoexits */
/* autoexits */
if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_AUTOEXIT))
do_auto_exits(ch);
/*now list characters &objects */
/* now list characters & objects */
list_obj_to_char(world[IN_ROOM(ch)].contents, ch, SHOW_OBJ_LONG, FALSE);
list_char_to_char(world[IN_ROOM(ch)].people, ch);
}

View file

@ -37,19 +37,74 @@ static void display_group_list(struct char_data * ch);
ACMD(do_quit)
{
char first[MAX_INPUT_LENGTH];
char *rest;
if (IS_NPC(ch) || !ch->desc)
return;
if (subcmd != SCMD_QUIT && GET_LEVEL(ch) < LVL_IMMORT)
/* Parse optional "ooc" sub-arg: quit ooc <message> */
rest = (char *)argument;
skip_spaces(&rest);
rest = one_argument(rest, first);
bool quit_ooc = (*first && is_abbrev(first, "ooc")) ? TRUE : FALSE;
/* Keep original safety controls */
if (!quit_ooc && subcmd != SCMD_QUIT && GET_LEVEL(ch) < LVL_IMMORT)
send_to_char(ch, "You have to type quit--no less, to quit!\r\n");
else if (GET_POS(ch) == POS_FIGHTING)
send_to_char(ch, "No way! You're fighting for your life!\r\n");
else if (GET_POS(ch) < POS_STUNNED) {
send_to_char(ch, "You die before your time...\r\n");
die(ch, NULL);
} else {
}
/* New: normal quit must be in a QUIT room (mortals only). */
else if (!quit_ooc && GET_LEVEL(ch) < LVL_IMMORT &&
!ROOM_FLAGGED(IN_ROOM(ch), ROOM_QUIT)) {
send_to_char(ch, "You cannot quit here. Find a room marked [Quit].\r\n");
}
/* For quit ooc, require a message for staff context. */
else if (quit_ooc) {
skip_spaces(&rest);
if (!*rest) {
send_to_char(ch, "Usage must include a reason to quit ooc: quit ooc <message>\r\n");
return;
}
act("$n has left the game.", TRUE, ch, 0, 0, TO_ROOM);
mudlog(NRM, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE, "%s has quit the game.", GET_NAME(ch));
mudlog(CMP, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE,
"%s used QUIT OOC in room %d: %s",
GET_NAME(ch), GET_ROOM_VNUM(IN_ROOM(ch)), rest);
if (GET_QUEST_TIME(ch) != -1)
quest_timeout(ch);
send_to_char(ch, "You step out-of-character and leave the world...\r\n");
/* We used to check here for duping attempts, but we may as well do it right
* in extract_char(), since there is no check if a player rents out and it
* can leave them in an equally screwy situation. */
if (CONFIG_FREE_RENT)
Crash_rentsave(ch, 0);
/* Requirement: respawn in the same (possibly non-QUIT) room. */
GET_LOADROOM(ch) = GET_ROOM_VNUM(IN_ROOM(ch));
/* Stop snooping so you can't see passwords during deletion or change. */
if (ch->desc->snoop_by) {
write_to_output(ch->desc->snoop_by, "Your victim is no longer among us.\r\n");
ch->desc->snoop_by->snooping = NULL;
ch->desc->snoop_by = NULL;
}
extract_char(ch); /* Char is saved before extracting. */
}
else {
/* Normal quit (in a QUIT room, or immortal bypass) */
act("$n has left the game.", TRUE, ch, 0, 0, TO_ROOM);
mudlog(NRM, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE,
"%s has quit the game.", GET_NAME(ch));
if (GET_QUEST_TIME(ch) != -1)
quest_timeout(ch);
@ -63,6 +118,7 @@ ACMD(do_quit)
if (CONFIG_FREE_RENT)
Crash_rentsave(ch, 0);
/* Requirement: respawn in the same QUIT room they logged out in. */
GET_LOADROOM(ch) = GET_ROOM_VNUM(IN_ROOM(ch));
/* Stop snooping so you can't see passwords during deletion or change. */
@ -72,7 +128,7 @@ ACMD(do_quit)
ch->desc->snoop_by = NULL;
}
extract_char(ch); /* Char is saved before extracting. */
extract_char(ch); /* Char is saved before extracting. */
}
}
@ -82,11 +138,16 @@ ACMD(do_save)
return;
send_to_char(ch, "Saving %s.\r\n", GET_NAME(ch));
/* Stamp the spawn room first so it's included in this save. */
if (IN_ROOM(ch) != NOWHERE)
GET_LOADROOM(ch) = GET_ROOM_VNUM(IN_ROOM(ch));
save_char(ch);
Crash_crashsave(ch);
if (ROOM_FLAGGED(IN_ROOM(ch), ROOM_HOUSE_CRASH))
House_crashsave(GET_ROOM_VNUM(IN_ROOM(ch)));
GET_LOADROOM(ch) = GET_ROOM_VNUM(IN_ROOM(ch));
}
/* Generic function for commands which are normally overridden by special

View file

@ -477,10 +477,6 @@ void copyover_recover()
enter_player_game(d);
/* Clear their load room if it's not persistant. */
if (!PLR_FLAGGED(d->character, PLR_LOADROOM))
GET_LOADROOM(d->character) = NOWHERE;
d->connected = CON_PLAYING;
look_at_room(d->character, 0);

View file

@ -83,6 +83,7 @@ const char *room_bits[] = {
"OLC",
"*", /* The BFS Mark. */
"WORLDMAP",
"QUIT",
"\n"
};

View file

@ -215,7 +215,6 @@ cpp_extern const struct command_info cmd_info[] = {
{ "open" , "o" , POS_SITTING , do_gen_door , 0, SCMD_OPEN },
{ "order" , "ord" , POS_RESTING , do_order , 1, 0 },
{ "offer" , "off" , POS_STANDING, do_not_here , 1, 0 },
{ "olc" , "olc" , POS_DEAD , do_show_save_list, LVL_BUILDER, 0 },
{ "olist" , "olist" , POS_DEAD , do_oasis_list, LVL_BUILDER, SCMD_OASIS_OLIST },
{ "oedit" , "oedit" , POS_DEAD , do_oasis_oedit, LVL_BUILDER, 0 },
@ -253,7 +252,6 @@ cpp_extern const struct command_info cmd_info[] = {
{ "receive" , "rece" , POS_STANDING, do_not_here , 1, 0 },
{ "recent" , "recent" , POS_DEAD , do_recent , LVL_IMMORT, 0 },
{ "remove" , "rem" , POS_RESTING , do_remove , 0, 0 },
{ "rent" , "rent" , POS_STANDING, do_not_here , 1, 0 },
{ "report" , "repo" , POS_RESTING , do_report , 0, 0 },
{ "reroll" , "rero" , POS_DEAD , do_wizutil , LVL_GRGOD, SCMD_REROLL },
{ "rescue" , "resc" , POS_FIGHTING, do_rescue , 1, 0 },
@ -1220,50 +1218,50 @@ static bool perform_new_char_dupe_check(struct descriptor_data *d)
int enter_player_game (struct descriptor_data *d)
{
int load_result;
room_vnum load_room;
room_vnum saved_vnum; /* cache pfile value BEFORE any mutations */
room_rnum start_r = NOWHERE;
if (!d || !d->character)
return 0;
/* Cache the pfile's saved load room FIRST. */
saved_vnum = GET_LOADROOM(d->character);
reset_char(d->character);
if (PLR_FLAGGED(d->character, PLR_INVSTART))
GET_INVIS_LEV(d->character) = GET_LEVEL(d->character);
/* We have to place the character in a room before equipping them
* or equip_char() will gripe about the person in NOWHERE. */
if ((load_room = GET_LOADROOM(d->character)) != NOWHERE)
load_room = real_room(load_room);
/* Resolve the room to enter (use cached vnum -> rnum). */
if (saved_vnum != NOWHERE)
start_r = real_room(saved_vnum);
/* If char was saved with NOWHERE, or real_room above failed... */
if (load_room == NOWHERE) {
if (GET_LEVEL(d->character) >= LVL_IMMORT)
load_room = r_immort_start_room;
/* Fallbacks if invalid/missing. */
if (start_r == NOWHERE) {
if (PLR_FLAGGED(d->character, PLR_FROZEN))
start_r = r_frozen_start_room;
else if (GET_LEVEL(d->character) >= LVL_IMMORT)
start_r = r_immort_start_room;
else
load_room = r_mortal_start_room;
start_r = r_mortal_start_room;
}
if (PLR_FLAGGED(d->character, PLR_FROZEN))
load_room = r_frozen_start_room;
/* copyover */
/* DG Scripts setup */
d->character->script_id = GET_IDNUM(d->character);
/* find_char helper */
add_to_lookup_table(d->character->script_id, (void *)d->character);
/* After moving saving of variables to the player file, this should only
* be called in case nothing was found in the pfile. If something was
* found, SCRIPT(ch) will be set. */
if (!SCRIPT(d->character))
read_saved_vars(d->character);
/* Link character and place before equipping. */
d->character->next = character_list;
character_list = d->character;
char_to_room(d->character, load_room);
load_result = Crash_load(d->character);
/* Save the character and their object file */
save_char(d->character);
Crash_crashsave(d->character);
char_to_room(d->character, start_r);
/* Check for a login trigger in the players' start room */
/* Load inventory/equipment */
load_result = Crash_load(d->character);
/* DO NOT save here — avoids clobbering Room with NOWHERE on login. */
/* login_wtrigger can remain. */
login_wtrigger(&world[IN_ROOM(d->character)], d->character);
return load_result;
@ -1649,9 +1647,6 @@ void nanny(struct descriptor_data *d, char *arg)
load_result = enter_player_game(d);
send_to_char(d->character, "%s", CONFIG_WELC_MESSG);
/* Clear their load room if it's not persistant. */
if (!PLR_FLAGGED(d->character, PLR_LOADROOM))
GET_LOADROOM(d->character) = NOWHERE;
save_char(d->character);
greet_mtrigger(d->character, -1);

View file

@ -963,14 +963,34 @@ SPECIAL(cryogenicist)
void Crash_save_all(void)
{
struct descriptor_data *d;
/* Respect config: if autosave is off, do nothing. */
if (!CONFIG_AUTO_SAVE)
return;
for (d = descriptor_list; d; d = d->next) {
if ((STATE(d) == CON_PLAYING) && !IS_NPC(d->character)) {
if (PLR_FLAGGED(d->character, PLR_CRASH)) {
Crash_crashsave(d->character);
save_char(d->character);
REMOVE_BIT_AR(PLR_FLAGS(d->character), PLR_CRASH);
}
}
if (STATE(d) != CON_PLAYING)
continue;
if (!d->character || IS_NPC(d->character))
continue;
/* Skip characters not fully placed yet (prevents clobbering Room to 65535). */
if (IN_ROOM(d->character) == NOWHERE)
continue;
/* Optional hardening: if spawn vnum is not yet established, skip this tick. */
if (GET_LOADROOM(d->character) == NOWHERE)
continue;
/* IMPORTANT: Do NOT modify GET_LOADROOM here.
Autosave should not change the player's spawn point. */
/* Persist character and object file. */
save_char(d->character);
Crash_crashsave(d->character);
if (PLR_FLAGGED(d->character, PLR_CRASH))
REMOVE_BIT_AR(PLR_FLAGS(d->character), PLR_CRASH);
}
}

View file

@ -88,8 +88,9 @@
#define ROOM_OLC 14 /**< (R) Modifyable/!compress */
#define ROOM_BFS_MARK 15 /**< (R) breath-first srch mrk */
#define ROOM_WORLDMAP 16 /**< World-map style maps here */
#define ROOM_QUIT 17 /**< Room allows players to quit in it */
/** The total number of Room Flags */
#define NUM_ROOM_FLAGS 17
#define NUM_ROOM_FLAGS 18
/* Zone info: Used in zone_data.zone_flags */
#define ZONE_CLOSED 0 /**< Zone is closed - players cannot enter */