Bug: Numerous problems with the switch command
Danger: Varies, but usually High to Critical due to crash potential.
Found by: Valcados
Fixed by: Valcados
---
act_wiz.c, do_balzhur
Locate:
set_char_color( AT_WHITE, ch );
send_to_char( "You summon the demon Balzhur to wreak your wrath!\r\n", ch );
send_to_char( "Balzhur sneers at you evilly, then vanishes in a puff of smoke.\r\n", ch );
set_char_color( AT_IMMORT, victim );
send_to_char( "You hear an ungodly sound in the distance that makes your blood run cold!\r\n", victim );
sprintf( buf, "Balzhur screams, 'You are MINE %s!!!'", victim->name );
echo_to_all( AT_IMMORT, buf, ECHOTAR_ALL );
victim->top_level = 1;
victim->trust = 0;
Change to:
victim->top_level = 1;
victim->trust = 0;
check_switch( victim, TRUE );
set_char_color( AT_WHITE, ch );
send_to_char( "You summon the demon Balzhur to wreak your wrath!\r\n", ch );
send_to_char( "Balzhur sneers at you evilly, then vanishes in a puff of smoke.\r\n", ch );
set_char_color( AT_IMMORT, victim );
send_to_char( "You hear an ungodly sound in the distance that makes your blood run cold!\r\n", victim );
snprintf( buf, MAX_STRING_LENGTH, "Balzhur screams, 'You are MINE %s!!!'", victim->name );
echo_to_all( AT_IMMORT, buf, ECHOTAR_ALL );
act_wiz.c, do_freeze
Locate:
if( get_trust( victim ) >= get_trust( ch ) )
{
send_to_char( "You failed.\r\n", ch );
return;
}
if( IS_SET( victim->act, PLR_FREEZE ) )
{
REMOVE_BIT( victim->act, PLR_FREEZE );
send_to_char( "You can play again.\r\n", victim );
send_to_char( "FREEZE removed.\r\n", ch );
}
else
{
SET_BIT( victim->act, PLR_FREEZE );
send_to_char( "You can't do ANYthing!\r\n", victim );
send_to_char( "FREEZE set.\r\n", ch );
}
Change to:
if( get_trust( victim ) >= get_trust( ch ) )
{
send_to_char( "You failed.\r\n", ch );
return;
}
if( victim->desc && victim->desc->original && get_trust(victim->desc->original) >= get_trust(ch) )
{
send_to_char( "For some inexplicable reason, you failed.\r\n", ch );
return;
}
if( IS_SET( victim->act, PLR_FREEZE ) )
{
REMOVE_BIT( victim->act, PLR_FREEZE );
send_to_char( "Your frozen form suddenly thaws.\r\n", victim );
ch_printf( ch, "%s is now unfrozen.\r\n", victim->name );
}
else
{
if( victim->switched )
{
do_return( victim->switched, "" );
set_char_color( AT_LBLUE, victim );
}
SET_BIT( victim->act, PLR_FREEZE );
send_to_char( "A godly force turns your body to ice!\r\n", victim );
ch_printf( ch, "You have frozen %s.\r\n", victim->name );
}
act_wiz.c, do_bestow
Locate:
ch_printf( victim, "%s has removed your bestowed commands.\r\n", ch->name );
Below that, add:
check_switch( victim, FALSE );
act_wiz.c, do_cedit
Locate:
if( !str_cmp( arg2, "level" ) )
{
int level = atoi( argument );
if( level < 0 || level > get_trust( ch ) )
{
send_to_char( "Level out of range.\r\n", ch );
return;
}
command->level = level;
send_to_char( "Done.\r\n", ch );
return;
}
Change to:
if( !str_cmp( arg2, "level" ) )
{
int level = atoi( argument );
if( ( level < 0 || level > get_trust( ch ) ) )
{
send_to_char( "Level out of range.\r\n", ch );
return;
}
if ( level > command->level && command->do_fun == do_switch )
{
command->level = level;
check_switches(FALSE);
}
else
command->level = level;
send_to_char( "Done.\r\n", ch );
return;
}
handler.c, extract_char
Locate:
if( ch->desc && ch->desc->original )
do_return( ch, "" );
Below it, add:
if( ch->switched && ch->switched->desc )
do_return( ch->switched, "" );
At the end of handler.c, add the following new functions:
void check_switches( bool possess )
{
CHAR_DATA *ch;
for( ch = first_char; ch; ch = ch->next )
check_switch( ch, possess );
}
void check_switch( CHAR_DATA *ch, bool possess )
{
AFFECT_DATA *paf;
CMDTYPE *cmd;
int hash, trust = get_trust(ch);
if( !ch->switched )
return;
if( !possess )
{
for( paf = ch->switched->first_affect; paf; paf = paf->next )
{
if( paf->duration == -1 )
continue;
if( paf->type != -1 && skill_table[paf->type]->spell_fun == spell_possess )
return;
}
}
for( hash = 0; hash < 126; hash++ )
{
for( cmd = command_hash[hash]; cmd; cmd = cmd->next )
{
if( cmd->do_fun != do_switch )
continue;
if( cmd->level <= trust )
return;
if( !IS_NPC(ch) && ch->pcdata->bestowments && is_name( cmd->name, ch->pcdata->bestowments )
&& cmd->level <= trust )
return;
}
}
if( !possess )
{
set_char_color( AT_BLUE, ch->switched );
send_to_char( "You suddenly forfeit the power to switch!\n\r", ch->switched );
}
do_return( ch->switched, "" );
}
mud.h
Locate:
int times_killed args( ( CHAR_DATA * ch, CHAR_DATA * mob ) );
Below it, add:
void check_switches( bool possess );
void check_switch( CHAR_DATA *ch, bool possess );
The switch command can be a very useful tool for imms who like to roleplay with the players, or just surprise them once in awhile with a mob that's more intelligent than usual. The problem with this is that there are a lot of game functions which don't even consider that the imm's body which is hanging around shouldn't be messed with.
This list of fixes is most likely not the end of this either. There are likely to be other bugs found with switch.