Player death and quits

Posted by Kal on Tue 06 May 2003 10:13 PM — 17 posts, 64,611 views.

#0
Ok, so I'm learning to code. Total newbie to it sadly, but hey...

I've downloaded SWR1.0 and got it compiled and running. However, the mud does not kick players upon death, nor does it delete their Pfiles in that eventuality.

What's wrong with it, and how do I make it all better?

USA #1
I don't know how "new" you are, but I'm new too, so my answer will be pretty basic just to get things started off on this thread.

It isn't a permadeath coded MUD. It is designed how you described. Along with that design, the things involved with handling player death is pretty deeply embedded in the code. I'm not able to give you a list of functions you'd need to look into without quite a bit of study myself. As I said, I'm new too. I do know, however, that there are substates to indicate victims are dead and several things that take place after they are found to be dead that'd you'd need to investigate being rid of were you to replace those actions with the permanent death.

I've seen discussions on smaug forums about that, and if I'm not mistaken there is a ROM snippet from the days of wayback that has instructions to do it on that codebase, it could possibly be ported depending on how "new" you actually are. Also, SMAUG codebase has a pretty solid player Delete port by Samson that I've found to be good, as far as the pfile deletion portion you may be able to learn some good pointers from looking at it since SWR is a smaug derivative.

In closing, I'd like to add, if you are coding the Mud for your own entertainment of course, my opinion is mute...but permadeath is pretty harsh! hehe

bye bye meanie :P
USA #2
I've been running my SWR based mud almost a year now and I just have to say that in SWR its more realistic with permanant death. Anyways, permanant death is in SWR (one of the big changes from SMAUG I believe) and it should be fairly easy to pin point the problem. Now, I'm no guru on coding, having just started in May of 2002, but I've got to say I learned a lot on these formus have helpped me a lot also. Anyways, lets see to your problem.

From what you describe it sounds like a problem with the raw_kill function. raw_kill is the code that deletes the players pfile along with disconnecting the player. Now, I don't know what yours looks like, so posting it would be good (if possible) or you can just post saying where you got the codebase and I'll go have a look for myself.

I think you may have downloaded it from Atrox (perhaps from kyndig.com ). Don't get me wrong, its a great codebase, with copyover already added, commands tweaked slightly to get maximum affect, but I remember hearing something about the raw_kill function being out of wack in that code. In fact, I remember it being on Atrox's web site. Anyways, post your raw_kill here or tell me where you downloaded it so I can have a look. I'm sure other people on the forum will be glad to help also..
#3
void raw_kill( CHAR_DATA *ch, CHAR_DATA *victim )
{

CHAR_DATA *victmp;

char buf[MAX_STRING_LENGTH];
char buf2[MAX_STRING_LENGTH];
char arg[MAX_STRING_LENGTH];
OBJ_DATA *obj, *obj_next;
SHIP_DATA *ship;

if ( !victim )
{
bug( "raw_kill: null victim!", 0 );
return;
}

strcpy( arg , victim->name );

stop_fighting( victim, TRUE );

if ( ch && !IS_NPC(ch) && !IS_NPC(victim) )
claim_disintigration( ch , victim );

/* Take care of polymorphed chars */
if(IS_NPC(victim) && IS_SET(victim->act, ACT_POLYMORPHED))
{
char_from_room(victim->desc->original);
char_to_room(victim->desc->original, victim->in_room);
victmp = victim->desc->original;
do_revert(victim, "");
raw_kill(ch, victmp);
return;
}

if ( victim->in_room && IS_NPC(victim) && victim->vip_flags != 0 && victim->in_room->area && victim->in_room->area->planet )
{
victim->in_room->area->planet->population--;
victim->in_room->area->planet->population = UMAX( victim->in_room->area->planet->population , 0 );
victim->in_room->area->planet->pop_support -= (float) ( 1 + 1 / (victim->in_room->area->planet->population + 1) );
if ( victim->in_room->area->planet->pop_support < -100 )
victim->in_room->area->planet->pop_support = -100;
}

if ( !IS_NPC(victim) || !IS_SET( victim->act, ACT_NOKILL ) )
mprog_death_trigger( ch, victim );
if ( char_died(victim) )
return;

if ( !IS_NPC(victim) || !IS_SET( victim->act, ACT_NOKILL ) )
rprog_death_trigger( ch, victim );
if ( char_died(victim) )
return;

if ( !IS_NPC(victim) || ( !IS_SET( victim->act, ACT_NOKILL ) && !IS_SET( victim->act, ACT_NOCORPSE ) ) )
make_corpse( victim, ch );
else
{
for ( obj = victim->last_carrying; obj; obj = obj_next )
{
obj_next = obj->prev_content;
obj_from_char( obj );
extract_obj( obj );
}
}

/* make_blood( victim ); */

if ( IS_NPC(victim) )
{
victim->pIndexData->killed++;
extract_char( victim, TRUE );
victim = NULL;
return;
}

set_char_color( AT_DIEMSG, victim );
do_help(victim, "_DIEMSG_" );


#4
Second half of code

/* swreality chnages begin here */


for ( ship = first_ship; ship; ship = ship->next )
{
if ( !str_cmp( ship->owner, victim->name ) )
{
STRFREE( ship->owner );
ship->owner = STRALLOC( "" );
STRFREE( ship->pilot );
ship->pilot = STRALLOC( "" );
STRFREE( ship->copilot );
ship->copilot = STRALLOC( "" );

save_ship( ship );
}

}


if ( victim->plr_home )
{
ROOM_INDEX_DATA *room = victim->plr_home;

STRFREE( room->name );
room->name = STRALLOC( "An Empty Apartment" );

REMOVE_BIT( room->room_flags , ROOM_PLR_HOME );
SET_BIT( room->room_flags , ROOM_EMPTY_HOME );

fold_area( room->area, room->area->filename, FALSE );
}

if ( victim->pcdata && victim->pcdata->clan )
{
if ( !str_cmp( victim->name, victim->pcdata->clan->leader ) )
{
STRFREE( victim->pcdata->clan->leader );
if ( victim->pcdata->clan->number1 )
{
victim->pcdata->clan->leader = STRALLOC( victim->pcdata->clan->number1 );
STRFREE( victim->pcdata->clan->number1 );
victim->pcdata->clan->number1 = STRALLOC( "" );
}
else if ( victim->pcdata->clan->number2 )
{
victim->pcdata->clan->leader = STRALLOC( victim->pcdata->clan->number2 );
STRFREE( victim->pcdata->clan->number2 );
victim->pcdata->clan->number2 = STRALLOC( "" );
}
else
victim->pcdata->clan->leader = STRALLOC( "" );
}

if ( !str_cmp( victim->name, victim->pcdata->clan->number1 ) )
{
STRFREE( victim->pcdata->clan->number1 );
if ( victim->pcdata->clan->number2 )
{
victim->pcdata->clan->number1 = STRALLOC( victim->pcdata->clan->number2 );
STRFREE( victim->pcdata->clan->number2 );
victim->pcdata->clan->number2 = STRALLOC( "" );
}
else
victim->pcdata->clan->number1 = STRALLOC( "" );
}

if ( !str_cmp( victim->name, victim->pcdata->clan->number2 ) )
{
STRFREE( victim->pcdata->clan->number2 );
victim->pcdata->clan->number1 = STRALLOC( "" );
}

victim->pcdata->clan->members--;
}

if ( !victim )
{
DESCRIPTOR_DATA *d;

/* Make sure they aren't halfway logged in. */
for ( d = first_descriptor; d; d = d->next )
if ( (victim = d->character) && !IS_NPC(victim) )
break;
if ( d )
close_socket( d, TRUE );
}
else
{
int x, y;

quitting_char = victim;
save_char_obj( victim );
saving_char = NULL;
extract_char( victim, TRUE );
for ( x = 0; x < MAX_WEAR; x++ )
for ( y = 0; y < MAX_LAYERS; y++ )
save_equipment[x][y] = NULL;
}

sprintf( buf, "%s%c/%s", PLAYER_DIR, tolower(arg[0]),
capitalize( arg ) );
sprintf( buf2, "%s%c/%s", BACKUP_DIR, tolower(arg[0]),
capitalize( arg ) );

rename( buf, buf2 );

sprintf( buf, "%s%c/%s.clone", PLAYER_DIR, tolower(arg[0]),
capitalize( arg ) );
sprintf( buf2, "%s%c/%s", PLAYER_DIR, tolower(arg[0]),
capitalize( arg ) );

rename( buf, buf2 );

return;


/* original player kill started here

extract_char( victim, FALSE );
if ( !victim )
{
bug( "oops! raw_kill: extract_char destroyed pc char", 0 );
return;
}
while ( victim->first_affect )
affect_remove( victim, victim->first_affect );
victim->affected_by = race_table[victim->race].affected;
victim->resistant = 0;
victim->susceptible = 0;
victim->immune = 0;
victim->carry_weight= 0;
victim->armor = 100;
victim->mod_str = 0;
victim->mod_dex = 0;
victim->mod_wis = 0;
victim->mod_int = 0;
victim->mod_con = 0;
victim->mod_cha = 0;
victim->mod_lck = 0;
victim->damroll = 0;
victim->hitroll = 0;
victim->mental_state = -10;
victim->alignment = URANGE( -1000, victim->alignment, 1000 );
victim->saving_spell_staff = 0;
victim->position = POS_RESTING;
victim->hit = UMAX( 1, victim->hit );
victim->mana = UMAX( 1, victim->mana );
victim->move = UMAX( 1, victim->move );

victim->pcdata->condition[COND_FULL] = 12;
victim->pcdata->condition[COND_THIRST] = 12;

if ( IS_SET( sysdata.save_flags, SV_DEATH ) )
save_char_obj( victim );
return;

*/
USA #5
After direct comparison with my code I found that nothing was differen't. This is kinda confusing now, but I'm sure theres an answer. Where did you download the source?
#6
My code was downloaded from here in parts. The first was the SWRsrc file from the ftp site, which was set up to run under Vis basic C++. The second was a standard uncompiled copy of swr1.0.tar.gz, also from this site.

Any idea?
USA #7
Hmm. Well, could you please recap clearly and exactly what are the problems? Like, are the characters no saving, not loading, not being killed when they should, not being disconnected upon death. This will help lead to a resolution.
Canada #8
Kal, are you running on Windows, i.e. Cygwin?
#9
Ok, in order to recap.

I'm running on windows, but not using cygwin. I'm using Visbasic C++. My mud was taken in part from the unix version (i.e, the folders, and some of the C files), and in part from the visbasic version (for the src files), both of which were downloaded from the FTP version of this site.

Ok, the problem. Players are loading, and saving ok, and no bugs register. However....

Upon death of a player it does not kick you from the server. It stops you entering any commands but you're still connected. Also, when you manually disconnect that player, and then restart, the characters pfile has not been deleted, and starts them from the point where they died, despite the fact it creates a corpse upon their death.

No bug is registered upon this act, so I assume that whatever is wrong is the code misinterpretating itself. Hence why I've posted the code for raw_death up here. I can't spot the flaw myself, can anyone else help, or am I looking in the wrong place?
Australia Forum Administrator #10
The partial disconnection problem has been around for a while, I would suggest searching the forum for posts on that.
#11
Ok, had a look around, and tried a couple of things. A little progress made.

The first time a player dies, it now moves their pfile onto a backup file. However, now it simply means that the problem occurs after they've died twice, as it doesn't ever delete the backup files. How do I make these delete themselves if a player by the same name dies?

Also, I tried adding a command to the end of the do_quit command to make it disconnect the server, and it crashed the mud. Can anyone give me an idea of what I should be writing. This is a copy of my do_quit


void do_qui( CHAR_DATA *ch, char *argument )
{
set_char_color( AT_RED, ch );
send_to_char( "If you want to QUIT, you have to spell it out.\n\r", ch );
return;
}

void do_quit( CHAR_DATA *ch, char *argument )
{
/* OBJ_DATA *obj; */ /* Unused */
int x, y;
int level;

if ( IS_NPC(ch) && IS_SET(ch->act, ACT_POLYMORPHED))
{
send_to_char("You can't quit while polymorphed.\n\r", ch);
return;
}

if ( IS_NPC(ch) )
return;

if ( ch->position == POS_FIGHTING )
{
set_char_color( AT_RED, ch );
send_to_char( "No way! You are fighting.\n\r", ch );
return;
}

if ( ch->position < POS_STUNNED )
{
set_char_color( AT_BLOOD, ch );
send_to_char( "You're not DEAD yet.\n\r", ch );
return;
}

if ( auction->item != NULL && ((ch == auction->buyer) || (ch == auction->seller) ) )
{
send_to_char("Wait until you have bought/sold the item on auction.\n\r", ch);
return;
}

if ( !IS_IMMORTAL(ch) && ch->in_room && !IS_SET( ch->in_room->room_flags , ROOM_HOTEL ) && !NOT_AUTHED(ch) )
{
send_to_char("You may not quit here.\n\r", ch);
send_to_char("You will have to find a safer resting place such as a hotel...\n\r", ch);
send_to_char("Maybe you could HAIL a speeder.\n\r", ch);
return;
}

set_char_color( AT_WHITE, ch );
send_to_char( "Your surroundings begin to fade as a mystical swirling vortex of colors\n\renvelops your body... When you come to, things are not as they were.\n\r\n\r", ch );
act( AT_SAY, "A strange voice says, 'We await your return, $n...'", ch, NULL, NULL, TO_CHAR );
act( AT_BYE, "$n has left the game.", ch, NULL, NULL, TO_ROOM );
set_char_color( AT_GREY, ch);

sprintf( log_buf, "%s has quit.", ch->name );
quitting_char = ch;
save_char_obj( ch );
save_home(ch);
saving_char = NULL;

level = get_trust(ch);
/*
* After extract_char the ch is no longer valid!
*/
extract_char( ch, TRUE );
for ( x = 0; x < MAX_WEAR; x++ )
for ( y = 0; y < MAX_LAYERS; y++ )
save_equipment[x][y] = NULL;

/* don't show who's logging off to leaving player */
/*
to_channel( log_buf, CHANNEL_MONITOR, "Monitor", level );
*/
log_string_plus( log_buf, LOG_COMM, level );
return;
}

USA #12
I think extract_char in handler.c might be the reason they don't disconnect. Maybe not, just a thought.
#13
Could you be more specific please? What about it is making them not disconnect and why? And how should i go about correcting the problem. Bearing in mind I'm kind of new at this, and still getting my bearings.

USA #14
Alright, well, there are only a few things I could try, but I would need access to your code to do it. I've never run a mud off of a windows machine, so I don't want to mess something up I shouldn't be messing with in the first place. I'll see if I can write a code that will delete their pfile in the backup file if it exists already and will put the most up to date one there. Anyways, if the disconnet problem is still there, I'll see what I can do about that also. Is it just when they die, or when they try to save and quit? Or both?
USA #15
With this code in raw_kill:

sprintf( buf, "%s%c/%s", PLAYER_DIR, tolower(arg[0]),
capitalize( arg ) );
sprintf( buf2, "%s%c/%s", BACKUP_DIR, tolower(arg[0]),
capitalize( arg ) );

rename( buf, buf2 );

It should automatically replace the old file in the backup directory with the new one, should it not?
#16
I believe the fix to this particular problem is that some of the necessary folders needed for SWR to run are not included in your downloaded version of the code. Simply add a folder named 'backup' in the directory containing the other folders (player, src, area...) and inside it put a folder for each letter of the alphabet just as the 'player' folder is. Also, there should be a folder named 'gods' added, which is not always there, which allows the wizlist and some other things to be cleared up.