On Aug 4, David Klasinc wrote
>
> Ok, I've done, what Sammy and George were suggesting and the result is,
> that still, nothing is working.. *grumble*
> Then I have this in my check_fall() where I check if ch is falling and
> since it's called every 2 seconds I've also put in few room spells that
> are supposed to take hp from char...
>
> void check_fall(void)
> {
> int fall_dmg;
> struct char_data *ch, *next_ch;
> for (ch = character_list; ch; ch = next_ch) {
> next_ch = ch->next;
>
> if (ROOM_AFFECTED(IN_ROOM(ch), RAFF_ACID_RAIN))
> gen_damage(ch, GET_MAX_HIT(ch) * 10 / 100, SPELL_ACID_RAIN);
>
> if (ch && ((SECT(IN_ROOM(ch)) == SECT_FLYING)) && (!AFF_FLAGGED(ch, AFF_FLY
> !(IS_NPC(ch) && MOB_FLAGGED(ch, MOB_WINGS)) &&
> !(IS_NPC(ch) && MOB_FLAGGED(ch, MOB_NOACT)) &&
> !(GET_LEVEL(ch) > LVL_IMMORT)) {
>
> .... etc etc etc ...
> Then there are usual checks, for the falling... as goes... first we check
> if ch is there... remember, we got in a syslog, that ch was set to NULL
> and that everything should work... Then we check if there is air in the
> room, if ch is maybe affected by flying, is this a mob with wings? and no
> act mobs (these are my dummy mobs, that just sit there with mobprogs
> hooked on them) and if ch is maybe immortal... Ok.. and mud crashes
> here...
Your FREE() macro is doing nothing for you here, because its another
level of the stack you're freeing at.
void check_fail(...)
{
...
/* ch = 0x807ee85 */
gen_damage(0x807ee85, ...);
Now, in gen_damage(), you have...
gen_damage(ch, ...)
{
...
/* ch = 0x807ee85 */
free(ch);
ch = NULL;
/* ch = 0x0 */
...
}
(The actual free() and ch = NULL probably occur within a function called
by gen_damage(), but the effects are still the same.)
But now you return to the previous stack level, so ch is still the same
as before the gen_damage() call.
/* ch = 0x807ee85 */
if (ch && ((SECT(IN_ROOM(ch)) == SECT_FLYING)) && ...
And the game crashes.
If you still don't see why this is happening, consider a simpiler program
which does the same thing:
void foo(int i)
{
i = 0;
}
void main()
{
int j = 10;
foo(j);
printf("%d\n", j);
}
which should be obvious that it will print 10, because j is passed by value,
not by reference.
To fix your problem, you could have gen_damage() return a special value
indicating that the character has been freed. In check_fall(), you would
test the return value, and return from check_fall() if the player died.
if (ROOM_AFFECTED(IN_ROOM(ch), RAFF_ACID_RAIN))
if (gen_damage(ch, GET_MAX_HIT(ch) * 10 / 100, SPELL_ACID_RAIN) < 0)
return;
if (ch && ((SECT(IN_ROOM(ch)) == SECT_FLYING)) && ...
Other solutions are throwing an exception in extract_char(), so the rest of
that function would be skipped, or moving extracted chars to a storage room
and freeing at the game_loop() level of the game.
Eric
+------------------------------------------------------------+
| Ensure that you have read the CircleMUD Mailing List FAQ: |
| http://democracy.queensu.ca/~fletcher/Circle/list-faq.html |
+------------------------------------------------------------+
This archive was generated by hypermail 2b30 : 12/08/00 PST