[ Doh, take 3, it was originally a 204-line patch. It's now missing the
handler.h prototype for e_p_c, and the #defines for {PLR,MOB}_NOTDEADYET. ]
Here's what I'm using for the 'extracting a dead character in the middle of
a loop' fix. Can anyone think of cases that this will either break or that
will break this? You have 16 hours. :)
Index: act.offensive.c
===================================================================
RCS file: /home/circledb/.cvs/circle/src/act.offensive.c,v
retrieving revision 1.23
diff -u -p -r1.23 act.offensive.c
--- act.offensive.c 2001/01/26 00:50:43 1.23
+++ act.offensive.c 2001/03/14 03:40:50
@@ -207,10 +207,6 @@ ACMD(do_backstab)
}
-/*
- * Ordering followers is crash-ridden due to character extraction during
- * the command execution. It's been disabled until it can be made safer.
- */
ACMD(do_order)
{
char name[MAX_INPUT_LENGTH], message[MAX_INPUT_LENGTH];
@@ -223,7 +219,7 @@ ACMD(do_order)
if (!*name || !*message)
send_to_char("Order who to do what?\r\n", ch);
- else if (!(vict = get_char_vis(ch, name, NULL, FIND_CHAR_ROOM)) /* && !is_abbrev(name, "followers") */)
+ else if (!(vict = get_char_vis(ch, name, NULL, FIND_CHAR_ROOM)) && !is_abbrev(name, "followers"))
send_to_char("That person isn't here.\r\n", ch);
else if (ch == vict)
send_to_char("You obviously suffer from skitzofrenia.\r\n", ch);
Index: comm.c
===================================================================
RCS file: /home/circledb/.cvs/circle/src/comm.c,v
retrieving revision 1.87
diff -u -p -r1.87 comm.c
--- comm.c 2001/03/07 09:41:46 1.87
+++ comm.c 2001/03/14 03:14:14
@@ -822,6 +822,9 @@ void heartbeat(int pulse)
}
if (!(pulse % PULSE_USAGE))
record_usage();
+
+ /* Every pulse! Don't want them to stink the place up... */
+ extract_pending_chars();
}
Index: fight.c
===================================================================
RCS file: /home/circledb/.cvs/circle/src/fight.c,v
retrieving revision 1.19
diff -u -p -r1.19 fight.c
--- fight.c 1999/05/10 00:05:46 1.19
+++ fight.c 2001/03/18 13:00:42
@@ -640,10 +640,14 @@ int skill_message(int dam, struct char_d
int damage(struct char_data * ch, struct char_data * victim, int dam, int attacktype)
{
if (GET_POS(victim) <= POS_DEAD) {
+ /* This is "normal"-ish now with delayed extraction. -gg 3/15/2001 */
+ if (PLR_FLAGGED(victim, PLR_NOTDEADYET) || MOB_FLAGGED(victim, MOB_NOTDEADYET))
+ return (-1);
+
log("SYSERR: Attempt to damage corpse '%s' in room #%d by '%s'.",
GET_NAME(victim), GET_ROOM_VNUM(IN_ROOM(victim)), GET_NAME(ch));
die(victim);
- return (0); /* -je, 7/7/92 */
+ return (-1); /* -je, 7/7/92 */
}
/* peaceful rooms */
Index: handler.c
===================================================================
RCS file: /home/circledb/.cvs/circle/src/handler.c,v
retrieving revision 1.25
diff -u -p -r1.25 handler.c
--- handler.c 2001/03/07 09:44:56 1.25
+++ handler.c 2001/03/18 13:07:36
@@ -20,6 +20,9 @@
#include "interpreter.h"
#include "spells.h"
+/* local vars */
+int extractions_pending = 0;
+
/* external vars */
extern struct char_data *combat_list;
extern struct room_data *world;
@@ -844,9 +847,8 @@ void update_char_objects(struct char_dat
}
-
/* Extract a ch completely from the world, and leave his stuff behind */
-void extract_char(struct char_data * ch)
+void extract_char_final(struct char_data *ch)
{
struct char_data *k, *temp;
struct descriptor_data *d;
@@ -854,7 +856,7 @@ void extract_char(struct char_data * ch)
int i;
if (ch->in_room == NOWHERE) {
- log("SYSERR: NOWHERE extracting char %s. (%s, extract_char)",
+ log("SYSERR: NOWHERE extracting char %s. (%s, extract_char_final)",
GET_NAME(ch), __FILE__);
exit(1);
}
@@ -945,6 +947,61 @@ void extract_char(struct char_data * ch)
}
}
+
+/*
+ * Q: Why do we do this?
+ * A: Because trying to iterate over the character
+ * list with 'ch = ch->next' does bad things if
+ * the current character happens to die. The
+ * trivial workaround of 'vict = next_vict'
+ * doesn't work if the _next_ person in the list
+ * gets killed, for example, by an area spell.
+ *
+ * Q: Why do we leave them on the character_list?
+ * A: Because code doing 'vict = vict->next' would
+ * get really confused otherwise.
+ */
+void extract_char(struct char_data *ch)
+{
+ if (IS_NPC(ch))
+ SET_BIT(MOB_FLAGS(ch), MOB_NOTDEADYET);
+ else
+ SET_BIT(PLR_FLAGS(ch), PLR_NOTDEADYET);
+
+ extractions_pending++;
+}
+
+
+/*
+ * I'm not particularly pleased with the MOB/PLR
+ * hoops that have to be jumped through but it
+ * hardly calls for a completely new variable.
+ * Ideally it would be its own list, but that
+ * would change the '->next' pointer, potentially
+ * confusing some code. Ugh. -gg 3/15/2001
+ */
+void extract_pending_chars(void)
+{
+ struct char_data *vict, *next_vict;
+
+ if (extractions_pending < 0)
+ log("SYSERR: Negative (%d) extractions pending.", extractions_pending);
+
+ for (vict = character_list; vict && extractions_pending; vict = next_vict) {
+ next_vict = vict->next;
+
+ if (MOB_FLAGGED(vict, MOB_NOTDEADYET))
+ REMOVE_BIT(MOB_FLAGS(vict), MOB_NOTDEADYET);
+ else if (PLR_FLAGGED(vict, PLR_NOTDEADYET))
+ REMOVE_BIT(PLR_FLAGS(vict), PLR_NOTDEADYET);
+ else
+ continue;
+
+ extract_char_final(vict);
+ extractions_pending--;
+ }
+ extractions_pending = 0;
+}
/* ***********************************************************************
--
+---------------------------------------------------------------+
| FAQ: http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html |
| Archives: http://post.queensu.ca/listserv/wwwarch/circle.html |
+---------------------------------------------------------------+
This archive was generated by hypermail 2b30 : 12/04/01 PST