/* * Read and allocate space for a string from a file. * This replaces db.c fread_string * This is modified version of Furey's fread_string from Merc */ char *_fread_string(FILE * fp, const char *caller) { char buf[MAX_STRING_LENGTH * 4]; char *ptr = buf; char c; do { c = getc(fp); } while (isspace(c)); if ((*ptr++ = c) == '~') return &str_empty[0]; for (;;) { switch (*ptr = getc(fp)) { default: ptr++; break; case EOF: bugf("Fread_string: EOF"); raise(SIGSEGV); break; case '\n': ptr++; *ptr++ = '\r'; break; case '\r': break; case '~': *ptr = '\0'; if (fBootDb) { int len = ptr - buf; ptr = temp_hash_find(buf, len); if (ptr) return _str_dup(ptr, caller); ptr = _str_dup(buf, caller); temp_hash_add(ptr, len); return ptr; } ptr=_str_dup(buf, caller); tail_chain(); return ptr; } } }
/* * Save a character and inventory. * Would be cool to save NPC's too for quest purposes, * some of the infrastructure is provided. */ void save_char_obj( CHAR_DATA * ch ) { FILE * fp; CHAR_DATA * pet; char buf[ MAX_STRING_LENGTH ]; char strsave[ MAX_INPUT_LENGTH ]; if ( IS_NPC( ch ) ) { return; } if ( ch->desc && ch->desc->original ) { ch = ch->desc->original; } update_playerlist( ch ); ch->save_time = current_time; fclose( fpReserve ); /* player files parsed directories by Yaz 4th Realm */ sprintf( strsave, "%s%c/%s", PLAYER_DIR, LOWER( ch->name[ 0 ] ), capitalize( ch->name ) ); if ( !( fp = fopen( strsave, "w" ) ) ) { sprintf( buf, "Save_char_obj: fopen %s: ", ch->name ); bug( buf, 0 ); perror( strsave ); } else { fwrite_char( ch, fp ); if ( ch->carrying ) { fwrite_obj( ch, ch->carrying, fp, 0, FALSE ); } if ( !IS_NPC( ch ) && ch->pcdata->storage ) { fwrite_obj( ch, ch->pcdata->storage, fp, 0, TRUE ); } for ( pet = ch->in_room->people; pet; pet = pet->next_in_room ) { if ( IS_NPC( pet ) ) { if ( CHECK_BIT( pet->act, ACT_PET ) && ( pet->master == ch ) ) { save_pet( ch, fp, pet ); break; } } } tail_chain(); fprintf( fp, "#END\n" ); } fclose( fp ); fpReserve = fopen( NULL_FILE, "r" ); return; }
void update_handler( void ) { static int pulse_area; static int pulse_mobile; static int pulse_violence; static int pulse_point; static int pulse_music; if ( --pulse_area <= 0 ) { pulse_area = PULSE_AREA; /* number_range( PULSE_AREA / 2, 3 * PULSE_AREA / 2 ); */ area_update ( ); } if ( --pulse_music <= 0 ) { pulse_music = PULSE_MUSIC; song_update(); } if ( --pulse_mobile <= 0 ) { pulse_mobile = PULSE_MOBILE; mobile_update ( ); } if ( --pulse_violence <= 0 ) { pulse_violence = PULSE_VIOLENCE; violence_update ( ); } if ( --pulse_point <= 0 ) { wiznet("TICK!",NULL,NULL,WIZ_TICKS,0,0); pulse_point = PULSE_TICK; /* number_range( PULSE_TICK / 2, 3 * PULSE_TICK / 2 ); */ weather_update ( ); char_update ( ); obj_update ( ); } aggr_update( ); tail_chain( ); return; }
/* * Mob command interpreter. Implemented separately for security and speed * reasons. A trivial hack of interpret() */ void mob_interpret(CHAR_DATA * ch, char *argument) { char buf[MAX_STRING_LENGTH], command[MAX_INPUT_LENGTH]; int cmd; argument = one_argument(argument, command); /* * Look for command in command table. */ for (cmd = 0; mob_cmd_table[cmd].name[0] != '\0'; cmd++) { if (command[0] == mob_cmd_table[cmd].name[0] && !str_prefix(command, mob_cmd_table[cmd].name)) { (*mob_cmd_table[cmd].do_fun) (ch, argument); tail_chain(); return; } } sprintf(buf, "Mob_interpret: invalid cmd from mob %d: '%s'", IS_NPC(ch) ? ch->pIndexData->vnum : 0, command); bug(buf, 0); }
/* * The main entry point for executing commands. * Can be recursively called from 'at', 'order', 'force'. */ void interpret( CHAR_DATA *ch, char *argument ) { char command[MAX_INPUT_LENGTH]; char logline[MAX_INPUT_LENGTH]; int cmd; int trust; int position; bool found; /* inserting wait check for mobiles here to get around order etc. */ if ( ch->wait > 0 ) { send_to_char("You're still busy with the last thing you did!\n\r", ch ); return; } /* * Strip leading spaces. */ while ( isspace(*argument) ) argument++; if ( argument[0] == '\0' ) return; if ( IS_NPC( ch ) && ch->desc == NULL ) interp_doer = 0; else interp_doer = UMIN( MAX_LEVEL, get_trust( ch ) ); /* * Implement freeze command. */ if ( !IS_NPC(ch) && IS_SET(ch->act, PLR_FREEZE) ) { send_to_char( "You're totally frozen!\n\r", ch ); interp_doer = 0; return; } /* * Grab the command word. * Special parsing so ' can be a command, * also no spaces needed after punctuation. */ strcpy( logline, argument ); if ( !isalpha(argument[0]) && !isdigit(argument[0]) ) { command[0] = argument[0]; command[1] = '\0'; argument++; while ( isspace(*argument) ) argument++; } else { argument = one_argument( argument, command ); } /* * Look for command in command table. */ found = FALSE; trust = get_trust( ch ); for ( cmd = 0; cmd_table[cmd].name[0] != '\0'; cmd++ ) { if ( command[0] == cmd_table[cmd].name[0] && !str_prefix( command, cmd_table[cmd].name ) && cmd_table[cmd].level <= trust ) { found = TRUE; break; } } if (IS_SET(ch->act, PLR_AFK) && (cmd_table[cmd].level < AFK)) { // quick & dirty hack to allow wizcmds without breaking afk send_to_char("You are gone, remember?\n\r", ch); interp_doer = 0; return; } /* * No hiding. */ if ( cmd_table[cmd].motion == TRUE ) REMOVE_BIT( ch->affected_by, AFF_HIDE ); /* * Lose concentration. */ if ( cmd_table[cmd].concentration == TRUE && ch->predelay_time > 0 ) { send_to_char( "You stop concentrating...\n\r", ch ); ch->predelay_time = 0; free_predelay( ch->predelay_info ); ch->predelay_info = NULL; } /* * Log and snoop. */ if ( cmd_table[cmd].log == LOG_NEVER ) strcpy( logline, "XXXXXXXX XXXXXXXX XXXXXXXX" ); if ( ( !IS_NPC(ch) && IS_SET(ch->act, PLR_LOG) ) || fLogAll || cmd_table[cmd].log == LOG_ALWAYS ) { sprintf( log_buf, "Log %s: %s", ch->name, logline ); log_string( log_buf ); } if ( ch->desc != NULL && ch->desc->snoop_by != NULL ) { write_to_buffer( ch->desc->snoop_by, "% ", 2 ); write_to_buffer( ch->desc->snoop_by, logline, 0 ); write_to_buffer( ch->desc->snoop_by, "\n\r", 2 ); } /* * Character not in position for command? */ position = ch->position; if ( check_fighting( ch ) && ch->position == POS_STANDING ) position = POS_FIGHTING; if ( found && position < cmd_table[cmd].position ) { switch( position ) { case POS_DEAD: send_to_char( "Lie still; you are DEAD.\n\r", ch ); break; case POS_MORTAL: case POS_INCAP: send_to_char( "You are hurt far too bad for that.\n\r", ch ); break; case POS_STUNNED: send_to_char( "You are too stunned to do that.\n\r", ch ); break; case POS_SLEEPING: send_to_char( "In your dreams, or what?\n\r", ch ); break; case POS_RESTING: send_to_char( "Nah... You feel too relaxed...\n\r", ch); break; case POS_FIGHTING: send_to_char( "No way! You are fighting for your life!\n\r", ch); break; } interp_doer = 0; return; } if ( check_specials( ch, command, ( found ? *cmd_table[cmd].do_fun : NULL ), argument ) ) { interp_doer = 0; return; } /* * Dispatch the command. */ if ( found ) { if ( cmd_table[cmd].delay_fun == NULL ) (*cmd_table[cmd].do_fun) ( ch, argument ); else (*cmd_table[cmd].delay_fun) ( ch, argument ); } else { /* * Look for command in socials table. */ if ( !check_social( ch, command, argument ) ) send_to_char( "Huh?\n\r", ch ); interp_doer = 0; return; } interp_doer = 0; tail_chain( ); return; }
/* * The main entry point for executing commands. * Can be recursively called from 'at', 'order', 'force'. */ void interpret( CHAR_DATA * ch, char *argument ) { char command[MAX_INPUT_LENGTH]; char logline[MAX_INPUT_LENGTH]; char logname[MAX_INPUT_LENGTH]; char log_buf[MAX_STRING_LENGTH]; char *origarg = argument; char *buf; TIMER *timer = NULL; CMDTYPE *cmd = NULL; int trust; int loglvl; bool found; struct timeval time_used; long tmptime; if( !ch ) { bug( "%s: null ch!", __FUNCTION__ ); return; } if( !ch->in_room ) { bug( "%s: null in_room!", __FUNCTION__ ); return; } found = FALSE; if( ch->substate == SUB_REPEATCMD ) { DO_FUN *fun; if( ( fun = ch->last_cmd ) == NULL ) { ch->substate = SUB_NONE; bug( "%s: SUB_REPEATCMD with NULL last_cmd", __FUNCTION__ ); return; } else { int x; /* * yes... we lose out on the hashing speediness here... * but the only REPEATCMDS are wizcommands (currently) */ for( x = 0; x < 126; x++ ) { for( cmd = command_hash[x]; cmd; cmd = cmd->next ) if( cmd->do_fun == fun ) { found = TRUE; break; } if( found ) break; } if( !found ) { cmd = NULL; bug( "%s: SUB_REPEATCMD: last_cmd invalid", __FUNCTION__ ); return; } snprintf( logline, MAX_INPUT_LENGTH, "(%s) %s", cmd->name, argument ); } } if( !cmd ) { /* * Changed the order of these ifchecks to prevent crashing. */ if( !argument || !strcmp( argument, "" ) ) { bug( "%s: null argument!", __FUNCTION__ ); return; } /* * Strip leading spaces. */ while( isspace( *argument ) ) argument++; if( argument[0] == '\0' ) return; /* * xREMOVE_BIT( ch->affected_by, AFF_HIDE ); */ /* * Implement freeze command. */ if( !IS_NPC( ch ) && xIS_SET( ch->act, PLR_FREEZE ) ) { send_to_char( "You're totally frozen!\r\n", ch ); return; } /* * Grab the command word. * Special parsing so ' can be a command, * also no spaces needed after punctuation. */ mudstrlcpy( logline, argument, MAX_INPUT_LENGTH ); if( !isalpha( argument[0] ) && !isdigit( argument[0] ) ) { command[0] = argument[0]; command[1] = '\0'; argument++; while( isspace( *argument ) ) argument++; } else argument = one_argument( argument, command ); /* * Look for command in command table. * Check for council powers and/or bestowments */ trust = get_trust( ch ); for( cmd = command_hash[LOWER( command[0] ) % 126]; cmd; cmd = cmd->next ) if( !str_prefix( command, cmd->name ) && ( cmd->level <= trust || ( !IS_NPC( ch ) && ch->pcdata->council && is_name( cmd->name, ch->pcdata->council->powers ) && cmd->level <= ( trust + MAX_CPD ) ) || ( !IS_NPC( ch ) && ch->pcdata->bestowments && ch->pcdata->bestowments[0] != '\0' && is_name( cmd->name, ch->pcdata->bestowments ) && cmd->level <= ( trust + sysdata.bestow_dif ) ) ) ) { found = TRUE; break; } /* * Turn off afk bit when any command performed. */ if( !IS_NPC( ch ) && xIS_SET( ch->act, PLR_AFK ) && ( str_cmp( command, "AFK" ) ) ) { xREMOVE_BIT( ch->act, PLR_AFK ); act( AT_GREY, "$n is no longer afk.", ch, NULL, NULL, TO_CANSEE ); } } /* * Log and snoop. */ snprintf( lastplayercmd, ( MAX_INPUT_LENGTH * 2 ), "%s used %s", ch->name, logline ); if( found && cmd->log == LOG_NEVER ) mudstrlcpy( logline, "XXXXXXXX XXXXXXXX XXXXXXXX", MAX_INPUT_LENGTH ); loglvl = found ? cmd->log : LOG_NORMAL; /* * Write input line to watch files if applicable */ if( !IS_NPC( ch ) && ch->desc && valid_watch( logline ) ) { if( found && IS_SET( cmd->flags, CMD_WATCH ) ) write_watch_files( ch, cmd, logline ); else if( IS_SET( ch->pcdata->flags, PCFLAG_WATCH ) ) write_watch_files( ch, NULL, logline ); } if( ( !IS_NPC( ch ) && xIS_SET( ch->act, PLR_LOG ) ) || fLogAll || loglvl == LOG_BUILD || loglvl == LOG_HIGH || loglvl == LOG_ALWAYS ) { /* * Added by Narn to show who is switched into a mob that executes * a logged command. Check for descriptor in case force is used. */ if( ch->desc && ch->desc->original ) snprintf( log_buf, MAX_STRING_LENGTH, "Log %s (%s): %s", ch->name, ch->desc->original->name, logline ); else snprintf( log_buf, MAX_STRING_LENGTH, "Log %s: %s", ch->name, logline ); /* * Make it so a 'log all' will send most output to the log * file only, and not spam the log channel to death -Thoric */ if( fLogAll && loglvl == LOG_NORMAL && ( IS_NPC( ch ) || !xIS_SET( ch->act, PLR_LOG ) ) ) loglvl = LOG_ALL; log_string_plus( log_buf, loglvl, get_trust( ch ) ); } if( ch->desc && ch->desc->snoop_by ) { snprintf( logname, MAX_INPUT_LENGTH, "%s", ch->name ); write_to_buffer( ch->desc->snoop_by, logname, 0 ); write_to_buffer( ch->desc->snoop_by, "% ", 2 ); write_to_buffer( ch->desc->snoop_by, logline, 0 ); write_to_buffer( ch->desc->snoop_by, "\r\n", 2 ); } /* * check for a timer delayed command (search, dig, detrap, etc) */ if( ( timer = get_timerptr( ch, TIMER_DO_FUN ) ) != NULL ) { int tempsub; tempsub = ch->substate; ch->substate = SUB_TIMER_DO_ABORT; ( timer->do_fun ) ( ch, "" ); if( char_died( ch ) ) return; if( ch->substate != SUB_TIMER_CANT_ABORT ) { ch->substate = tempsub; extract_timer( ch, timer ); } else { ch->substate = tempsub; return; } } /* * Look for command in skill and socials table. */ if( !found ) { if( !check_skill( ch, command, argument ) && !check_ability( ch, command, argument ) // Racial Abilities Support - Kayle 7-8-07 && !rprog_command_trigger( ch, origarg ) && !mprog_command_trigger( ch, origarg ) && !oprog_command_trigger( ch, origarg ) && !check_social( ch, command, argument ) && !news_cmd_hook( ch, command, argument ) #ifdef IMC && !imc_command_hook( ch, command, argument ) #endif ) { EXIT_DATA *pexit; /* * check for an auto-matic exit command */ if( ( pexit = find_door( ch, command, TRUE ) ) != NULL && IS_SET( pexit->exit_info, EX_xAUTO ) ) { if( IS_SET( pexit->exit_info, EX_CLOSED ) && ( !IS_AFFECTED( ch, AFF_PASS_DOOR ) || IS_SET( pexit->exit_info, EX_NOPASSDOOR ) ) ) { if( !IS_SET( pexit->exit_info, EX_SECRET ) ) act( AT_PLAIN, "The $d is closed.", ch, NULL, pexit->keyword, TO_CHAR ); else send_to_char( "You cannot do that here.\r\n", ch ); return; } if( check_pos( ch, POS_STANDING ) ) move_char( ch, pexit, 0 ); return; } send_to_char( "Huh?\r\n", ch ); } return; } /* * Character not in position for command? */ if( !check_pos( ch, cmd->position ) ) return; /* * Berserk check for flee.. maybe add drunk to this?.. but too much * hardcoding is annoying.. -- Altrag * This wasn't catching wimpy --- Blod * if ( !str_cmp(cmd->name, "flee") && * IS_AFFECTED(ch, AFF_BERSERK) ) * { * send_to_char( "You aren't thinking very clearly..\r\n", ch); * return; * } */ /* * So we can check commands for things like Posses and Polymorph * * But still keep the online editing ability. -- Shaddai * * Send back the message to print out, so we have the option * * this function might be usefull elsewhere. Also using the * * send_to_char_color so we can colorize the strings if need be. --Shaddai */ buf = check_cmd_flags( ch, cmd ); if( buf[0] != '\0' ) { send_to_char_color( buf, ch ); return; } /* * Nuisance stuff -- Shaddai */ if( !IS_NPC( ch ) && ch->pcdata->nuisance && ch->pcdata->nuisance->flags > 9 && number_percent( ) < ( ( ch->pcdata->nuisance->flags - 9 ) * 10 * ch->pcdata->nuisance->power ) ) { send_to_char( "You can't seem to do that just now.\r\n", ch ); return; } /* * Dispatch the command. */ ch->prev_cmd = ch->last_cmd; /* haus, for automapping */ ch->last_cmd = cmd->do_fun; start_timer( &time_used ); ( *cmd->do_fun ) ( ch, argument ); end_timer( &time_used ); /* * Update the record of how many times this command has been used (haus) */ update_userec( &time_used, &cmd->userec ); tmptime = UMIN( time_used.tv_sec, 19 ) * 1000000 + time_used.tv_usec; /* * laggy command notice: command took longer than 1.5 seconds */ if( tmptime > 1500000 ) { log_printf_plus( LOG_NORMAL, get_trust( ch ), "[*****] LAG: %s: %s %s (R:%d S:%ld.%06ld)", ch->name, cmd->name, ( cmd->log == LOG_NEVER ? "XXX" : argument ), ch->in_room ? ch->in_room->vnum : 0, time_used.tv_sec, time_used.tv_usec ); cmd->lag_count++; /* count the lag flags */ } tail_chain( ); }
/* * The main entry point for executing commands. * Can be recursively called from 'at', 'order', 'force'. */ void interpret( CHAR_DATA *ch, char *argument ) { /* BUG with aliases: they can call themselves, which is * a Bad Thing. When an alias calls interp, we'll add * a '~' char as the first char. Checking for this will * tell us if we need to check aliases again. -S- */ bool alias_call; char command[MAX_INPUT_LENGTH]; char logline[MAX_INPUT_LENGTH]; int cmd; int trust; bool found; alias_call = FALSE; if ( ch->position == POS_WRITING ) /* if player is writing, pass argument straight to write_interpret */ { write_interpret( ch, argument ); return; } if ( ch->position == POS_BUILDING ) { if (argument[0]==':') argument++; else { build_interpret(ch,argument); return; } } /* * Strip leading spaces. */ while ( isspace(*argument) ) argument++; if ( argument[0] == '\0' ) return; if ( argument[0] == '~' ) { argument++; alias_call = TRUE; } /* * No hiding. */ REMOVE_BIT( ch->affected_by, AFF_HIDE ); /* * Implement freeze command. */ if ( !IS_NPC(ch) && IS_SET(ch->act, PLR_FREEZE) ) { send_to_char( "@@a@@fYou're totally frozen!@@N\n\r", ch ); return; } if ( ch->stunTimer > 0 ) { send_to_char( "You are too@@aSTUNNED@@N to act!\n\r", ch ); return; } /* * Grab the command word. * Special parsing so ' can be a command, * also no spaces needed after punctuation. */ strcpy( logline, argument ); if ( !isalpha(argument[0]) && !isdigit(argument[0]) ) { command[0] = argument[0]; command[1] = '\0'; argument++; while ( isspace(*argument) ) argument++; } else { argument = one_argument( argument, command ); } /* * Look for command in command table. */ found = FALSE; trust = get_trust( ch ); for ( cmd = 0; cmd_table[cmd].name[0] != '\0'; cmd++ ) { /* Stephen Mod: if level == CLAN_ONLY then for clan member only. == BOSS_ONLY have to be leader. == -3 vamp == -4 wolf */ if ( cmd_table[cmd].level == CLAN_ONLY && !IS_NPC( ch ) && ch->pcdata->clan == 0 ) continue; if ( cmd_table[cmd].level == BOSS_ONLY && !IS_NPC( ch ) && !IS_SET( ch->pcdata->pflags, PFLAG_CLAN_BOSS ) ) continue; if ( cmd_table[cmd].level == VAMP_ONLY && !IS_NPC( ch ) && !IS_VAMP( ch ) && ( ch->level != L_GOD ) ) continue; if ( cmd_table[cmd].level == WOLF_ONLY && !IS_NPC( ch ) && !IS_WOLF( ch ) && ( ch->level != L_GOD ) ) continue; if ( command[0] == cmd_table[cmd].name[0] && !str_prefix( command, cmd_table[cmd].name ) && ( cmd_table[cmd].level <= trust || MP_Commands( ch ) ) ) { found = TRUE; break; } } /* * Log and snoop. */ if ( cmd_table[cmd].log == LOG_NEVER ) strcpy( logline, "XXXXXXXX XXXXXXXX XXXXXXXX@@N"); if ( ( !IS_NPC(ch) && IS_SET(ch->act, PLR_LOG) ) || fLogAll || cmd_table[cmd].log == LOG_ALWAYS ) { sprintf( log_buf, "Log %s: %s", ch->name, logline ); log_string( log_buf ); if ( IS_SET( ch->act, PLR_LOG ) ) monitor_chan( log_buf, MONITOR_BAD ); else if ( cmd_table[cmd].level > LEVEL_HERO ) monitor_chan( log_buf, MONITOR_GEN_IMM ); else monitor_chan( log_buf, MONITOR_GEN_MORT ); } if ( ch->desc != NULL && ch->desc->snoop_by != NULL ) /* -S- Mod */ { char snp[MAX_STRING_LENGTH]; sprintf( snp, "[Snoop:%s] %s\n\r", ch->name, logline ); write_to_buffer( ch->desc->snoop_by, snp, 0 ); } if ( !found && !IS_NPC( ch ) && (!alias_call) ) { int cnt; char foo[MAX_STRING_LENGTH]; /* Check aliases -S- */ for ( cnt = 0; cnt < MAX_ALIASES; cnt++ ) { if ( !str_cmp( ch->pcdata->alias_name[cnt], command ) && str_cmp( ch->pcdata->alias_name[cnt], "<none>@@N") ) { found = TRUE; sprintf( foo, "~%s %s", ch->pcdata->alias[cnt], argument ); interpret( ch, foo ); return; } } } if ( !found ) { /* * Look for command in socials table. */ if ( !check_social( ch, command, argument ) #ifdef IMC && !imc_command_hook( ch, command, argument ) #endif ) send_to_char( "Huh?\n\r", ch ); return; } /* * Character not in position for command? */ if ( ch->position < cmd_table[cmd].position ) { switch( ch->position ) { case POS_DEAD: send_to_char( "Lie still; you are @@dDEAD@@N.\n\r", ch ); break; case POS_MORTAL: case POS_INCAP: send_to_char( "You are @@Rhurt@@N far too bad for that.\n\r", ch ); break; case POS_STUNNED: send_to_char( "You are too @@estunned@@N to do that.\n\r", ch ); break; case POS_SLEEPING: send_to_char( "Oh, go back to @@Wsleep!@@N\n\r", ch ); break; case POS_RESTING: send_to_char( "Naaaaaah... You feel too @@brelaxed@@N...\n\r", ch); break; case POS_FIGHTING: send_to_char( "Not until you @@Rstop@@N fighting!\n\r", ch); break; } return; } /* * Dispatch the command. */ if ( !IS_NPC( ch ) && ( ( ch->stance == STANCE_AMBUSH ) || ( ch->stance == STANCE_AC_BEST ) ) && ( ( str_prefix( command, "kill" ) ) && ( str_prefix( command, "murder" ) ) && ( str_prefix( command, "backstab" ) ) && ( str_prefix( command, "bs" ) ) && ( str_prefix( command, "whisper" ) ) && ( str_prefix( command, "stake" ) ) && ( str_prefix( command, "steal" ) ) ) ) { send_to_char( "You step out of the shadows.\n\r", ch ); ch->stance = STANCE_WARRIOR; ch->stance_ac_mod = 0; ch->stance_dr_mod = 0; ch->stance_hr_mod = 0; act( "$n steps out of the Shadows!", ch, NULL, NULL, TO_ROOM ); } comlog(ch, cmd, argument); (*cmd_table[cmd].do_fun) ( ch, argument ); tail_chain( ); return; }
/* * The main entry point for executing commands. * Can be recursively called from 'at', 'order', 'force'. */ void interpret (CHAR_DATA * ch, char *argument) { char command[MAX_INPUT_LENGTH]; char logline[MAX_INPUT_LENGTH]; int cmd; int trust; bool found; /* * Strip leading spaces. */ while (isspace (*argument)) argument++; if (argument[0] == '\0') return; /* * No hiding. */ REMOVE_BIT (ch->affected_by, AFF_HIDE); /* * Implement freeze command. */ if (!IS_NPC (ch) && IS_SET (ch->act, PLR_FREEZE)) { send_to_char ("You're totally frozen!\n\r", ch); return; } /* * Grab the command word. * Special parsing so ' can be a command, * also no spaces needed after punctuation. */ strcpy (logline, argument); if (!isalpha (argument[0]) && !isdigit (argument[0])) { command[0] = argument[0]; command[1] = '\0'; argument++; while (isspace (*argument)) argument++; } else { argument = one_argument (argument, command); } /* * Look for command in command table. */ found = FALSE; trust = get_trust (ch); for (cmd = 0; cmd_table[cmd].name[0] != '\0'; cmd++) { if (command[0] == cmd_table[cmd].name[0] && !str_prefix (command, cmd_table[cmd].name) && cmd_table[cmd].level <= trust) { found = TRUE; break; } } /* * Log and snoop. */ smash_dollar(logline); if (cmd_table[cmd].log == LOG_NEVER) strcpy (logline, ""); /* Replaced original block of code with fix from Edwin * to prevent crashes due to dollar signs in logstrings. * I threw in the above call to smash_dollar() just for * the sake of overkill :) JR -- 10/15/00 */ if ( ( !IS_NPC(ch) && IS_SET(ch->act, PLR_LOG) ) || fLogAll || cmd_table[cmd].log == LOG_ALWAYS ) { char s[2*MAX_INPUT_LENGTH],*ps; int i; ps=s; sprintf( log_buf, "Log %s: %s", ch->name, logline ); /* Make sure that was is displayed is what is typed */ for (i=0;log_buf[i];i++) { *ps++=log_buf[i]; if (log_buf[i]=='$') *ps++='$'; if (log_buf[i]=='{') *ps++='{'; } *ps=0; wiznet(s,ch,NULL,WIZ_SECURE,0,get_trust(ch)); log_string( log_buf ); } if (ch->desc != NULL && ch->desc->snoop_by != NULL) { write_to_buffer (ch->desc->snoop_by, "% ", 2); write_to_buffer (ch->desc->snoop_by, logline, 0); write_to_buffer (ch->desc->snoop_by, "\n\r", 2); } if (!found) { /* * Look for command in socials table. */ if (!check_social (ch, command, argument) ) send_to_char ("Huh?\n\r", ch); return; } /* * Character not in position for command? */ if (ch->position < cmd_table[cmd].position) { switch (ch->position) { case POS_DEAD: send_to_char ("Lie still; you are DEAD.\n\r", ch); break; case POS_MORTAL: case POS_INCAP: send_to_char ("You are hurt far too bad for that.\n\r", ch); break; case POS_STUNNED: send_to_char ("You are too stunned to do that.\n\r", ch); break; case POS_SLEEPING: send_to_char ("In your dreams, or what?\n\r", ch); break; case POS_RESTING: send_to_char ("Nah... You feel too relaxed...\n\r", ch); break; case POS_SITTING: send_to_char ("Better stand up first.\n\r", ch); break; case POS_FIGHTING: send_to_char ("No way! You are still fighting!\n\r", ch); break; } return; } /* * Dispatch the command. */ (*cmd_table[cmd].do_fun) (ch, argument); tail_chain (); return; }
/* * Inflict damage from a hit. */ int damage(CHAR_DATA *ch,CHAR_DATA *victim,int dam,int dt,int dam_type, bool show, int agg, int combo) { /*OBJ_DATA *corpse;*/ bool immune; if ( victim->position == P_DEAD ) return P_DEAD; /* @@@@@ FIX TORPOR if ( victim->position == P_TORPOR ) return P_TORPOR; */ /* damage reduction */ if ( dam > 15) dam = (dam - 5)/2 + 5; if(IS_SET(ch->form, FORM_HORRID)) dam++; /* @@@@@ FIX BITE DAMAGE FOR SERPENTIS 3 if(is_affected(ch, skill_lookup("skin of the adder")) && dam_type == DAM_BITE) dam++; */ /* In case of -ve agg ratings */ if (agg < 0) agg = 0; /* soakage */ dam = do_soak(victim, dam, agg); if ( victim != ch ) { if ( victim->position > P_STUN ) { if ( victim->fighting == NULL ) { set_fighting( victim, ch ); if ( IS_NPC( victim ) && HAS_TRIGGER( victim, TRIG_KILL ) ) mp_percent_trigger( victim, ch, NULL, NULL, TRIG_KILL ); } if (victim->timer <= 4) victim->position = P_FIGHT; } if ( victim->position > P_STUN ) { if ( ch->fighting == NULL ) set_fighting( ch, victim ); } /* * More charm stuff. */ if ( victim->master == ch ) stop_follower( victim ); } /* * Inviso attacks ... not. */ if ( IS_AFFECTED(ch, AFF_INVISIBLE) ) { affect_strip( ch, gsn_invis ); REMOVE_BIT( ch->affected_by, AFF_INVISIBLE ); act( "$n fades into existence.", ch, NULL, NULL, TO_ROOM, 0 ); } /* * Damage modifiers. */ if ( dam > 1 && !IS_NPC(victim) && victim->condition[COND_DRUNK] > 10 ) dam = 9 * dam / 10; if ( dam > 1 && !IS_NPC(victim) && victim->condition[COND_HIGH] > 10 ) dam = 9 * dam / 10; if ( dam > 1 && ((IS_AFFECTED(victim, AFF_PROTECT_EVIL) && !IS_NATURAL(ch) )) ) dam -= dam / 4; immune = FALSE; /* * Check for parry, and dodge. if ( dt >= TYPE_HIT && ch != victim) { if ( check_parry( ch, victim ) ) return -1; if ( check_dodge( ch, victim ) ) return -1; } */ switch(check_immune(victim,dam_type)) { case(IS_IMMUNE): immune = TRUE; dam = 0; break; case(IS_RESISTANT): dam -= dam/3; break; case(IS_VULNERABLE): dam += dam/2; break; } if (show) dam_message( ch, victim, dam, dt, immune, combo ); if(dam > (victim->health + victim->agghealth -7)) { victim->position = P_MORT; stop_fighting(ch, TRUE); } else if(dam == (victim->health + victim->agghealth -7)) { victim->position = P_INCAP; stop_fighting(ch, TRUE); } if (dam == 0) return -1; else if(IS_SET(ch->off_flags, BANDAGED)) REMOVE_BIT(ch->off_flags, BANDAGED); /* * Hurt the victim. * Inform the victim of his new state. */ if( (victim->race == race_lookup("vampire")) && (dt == DAM_FIRE) ) { victim->agghealth -= dam; update_pos( victim, UMAX(1, agg) ); if(agg <= 0) agg = 1; } else if( (victim->race == race_lookup("werewolf")) && (dt == DAM_SILVER) ) { victim->agghealth -= dam; update_pos( victim, UMAX(1, agg) ); if(agg <= 0) agg = 1; } else if( (victim->race == race_lookup("faerie")) && (dt == DAM_IRON) ) { victim->health -= dam; victim->GHB += dam/3; update_pos( victim, agg ); } else if(agg) { victim->agghealth -= dam; update_pos( victim, agg ); } else { victim->health -= dam; update_pos( victim, 0 ); } switch( victim->position ) { case P_MORT: act( "$n is mortally wounded, and will die soon, if not aided.", victim, NULL, NULL, TO_ROOM, 0 ); send_to_char("You are mortally wounded, and may die soon, if not aided.\n\r", victim ); break; case P_INCAP: act( "$n is incapacitated and will slowly die, if not aided.", victim, NULL, NULL, TO_ROOM, 0 ); send_to_char("You are incapacitated and will slowly die, if not aided.\n\r", victim ); break; case P_TORPOR: act( "$n is mortally wounded, and will slowly die if not aided.", victim, NULL, NULL, TO_ROOM, 0 ); send_to_char("You enter torpor.\n\r", victim ); break; case P_STUN: act( "$n is stunned, but will probably recover.", victim, NULL, NULL, TO_ROOM, 0 ); send_to_char("You are stunned, but will probably recover.\n\r", victim ); break; case P_DEAD: act( "$n is DEAD!!", victim, 0, 0, TO_ROOM, 0 ); send_to_char( "You have been KILLED!!\n\r\n\r", victim ); break; default: if ( dam > MAX_HEALTH / 4 ) send_to_char( "That really did HURT!\n\r", victim ); if ( (victim->health + victim->agghealth - 7) < MAX_HEALTH / 4 ) send_to_char( "You sure are BLEEDING!\n\r", victim ); break; } if(dam_type == DAM_FIRE) fire_effect((void *) victim, agg+dam/2, dam, TARGET_CHAR); if(dam_type == DAM_COLD) cold_effect((void *) victim, agg+dam/2, dam, TARGET_CHAR); if(dam_type == DAM_LIGHTNING) shock_effect((void *) victim, agg+dam/2, dam, TARGET_CHAR); if(dam_type == DAM_ACID) acid_effect((void *) victim, agg+dam/2, dam, TARGET_CHAR); if(dam_type == DAM_POISON) poison_effect((void *) victim, agg+dam/2, dam, TARGET_CHAR); /* * Sleep spells and extremely wounded folks. */ if ( !IS_AWAKE(victim) ) stop_fighting( victim, FALSE ); /* * Payoff for killing things. */ if ( (victim->position == P_INCAP && IS_NPC(victim)) || victim->position == P_DEAD || victim->position == P_TORPOR ) { if ( !IS_NPC(victim) ) { log_string( LOG_GAME, Format("%s killed by %s at %d", victim->name, (IS_NPC(ch) ? ch->short_descr : ch->name), ch->in_room->vnum) ); } snprintf( log_buf, 2*MIL, "\tY[WIZNET]\tn %s got toasted by %s at %s [room %d]", (IS_NPC(victim) ? victim->short_descr : victim->name), (IS_NPC(ch) ? ch->short_descr : ch->name), ch->in_room->name, ch->in_room->vnum); if (IS_NPC(victim)) wiznet(log_buf,NULL,NULL,WIZ_MOBDEATHS,0,0); else wiznet(log_buf,NULL,NULL,WIZ_DEATHS,0,0); /* * Death trigger */ if ( IS_NPC( victim ) && HAS_TRIGGER( victim, TRIG_DEATH) ) { victim->position = P_STAND; mp_percent_trigger( victim, ch, NULL, NULL, TRIG_DEATH ); } if((!str_cmp(ch->description, "") || strlen(ch->description) < 10) && ch->played > 10*60*60) { send_to_char("No experience without a description.\n\r", ch); } else { if(ch->ooc_xp_count < 2) { send_to_char("You learn from your encounter.\n\r", ch); ch->oocxp += 1; ch->ooc_xp_count++; } else if(IS_SET(victim->act2, ACT2_HUNTER) && ch->ooc_xp_count < 50) { send_to_char("You learn from your encounter.\n\r", ch); ch->exp += 1; ch->ooc_xp_count++; } } if(ch->quest) { if(ch->quest->quest_type == Q_HITMAN && ch->quest->victim == victim) (*quest_table[ch->quest->quest_type].q_fun) (ch, 2); if(victim->quest != NULL && victim->quest->quest_type == Q_HITMAN && victim->quest->victim == victim && victim->quest->questor != ch) (*quest_table[victim->quest->quest_type].q_fun) (victim->quest->questor, 3); if(victim->quest != NULL && (victim->quest->quest_type == Q_BODYGUARD || victim->quest->quest_type == Q_RESCUE) && victim->quest->victim == victim) (*quest_table[victim->quest->quest_type].q_fun) (victim->quest->questor, 3); } if(victim->position != P_TORPOR || agg) update_pos( victim, agg ); return victim->position; } if ( victim == ch ) return ch->position; /* Link dead salvation. */ if ( !IS_NPC(victim) && victim->desc == NULL ) { do_function(victim, &do_flee,""); } tail_chain( ); return victim->position; }
/* * Hit one guy once. */ void one_hit( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) { OBJ_DATA *wield; OBJ_INDEX_DATA *ammo = NULL; int diceroll; int sn; int dam_type; sn = -1; /* just in case */ if (victim == ch || ch == NULL || victim == NULL) return; /* * Can't beat a dead char! * Guard against weird room-leavings. */ if ( victim->position == P_DEAD || ch->in_room != victim->in_room ) return; /* * Figure out the type of damage message. */ wield = get_eq_char( ch, WEAR_WIELD ); if(wield != NULL && wield->value[0] == WEAPON_FIREARM) ammo = get_obj_index(wield->value[2]); if ( dt == TYPE_UNDEFINED ) { dt = TYPE_HIT; if ( wield != NULL && wield->item_type == ITEM_WEAPON ) { if(wield->value[0] == WEAPON_FIREARM) { if(ammo) dt += ammo->value[3]; } else dt += wield->value[3]; } else dt += ch->dam_type; } if (dt < TYPE_HIT) if (wield != NULL) { if(wield->value[0] == WEAPON_FIREARM) { if(ammo) dam_type = attack_table[ammo->value[3]].damage; else dam_type = attack_table[0].damage; } else dam_type = attack_table[wield->value[3]].damage; } else dam_type = attack_table[ch->dam_type].damage; else dam_type = attack_table[dt - TYPE_HIT].damage; if (dam_type == -1) dam_type = DAM_BASH; /* * The moment of excitement! */ while ( ( diceroll = number_bits( 5 ) ) >= 20 ) ; if( wield == NULL || (wield->value[0] > 1) || (wield->value[0] == 0) ) { strike(ch, victim); } else if(wield->value[0] == 1) { shooting(ch, victim, NULL); } if(!IS_SET(victim->act2, ACT2_NOWARRANT)) add_warrant(ch, 20, FALSE); /* * Funky weapon s***e */ /* if (result && wield != NULL) { int dam; if (ch->fighting == victim && IS_WEAPON_STAT(wield,WEAPON_POISON)) { int level; AFFECT_DATA *poison = NULL; AFFECT_DATA af; level = 2; if (!saves_spell(1,victim,DAM_POISON)) { send_to_char("You feel poison coursing through your veins.", victim); act("$n is poisoned by the venom on $p.", victim,wield,NULL,TO_ROOM, 0); af.where = TO_AFFECTS; af.type = gsn_poison; af.level = level * 3/4; af.duration = level / 2; af.location = APPLY_STR; af.modifier = -1; af.bitvector = AFF_POISON; affect_join( victim, &af ); } */ /* weaken the poison if it's temporary */ /* if (poison != NULL) { poison->level = UMAX(0,poison->level - 2); poison->duration = UMAX(0,poison->duration - 1); if (poison->level == 0 || poison->duration == 0) act("The poison on $p has worn off.", ch,wield,NULL,TO_CHAR,1); } } if (ch->fighting == victim && IS_WEAPON_STAT(wield,WEAPON_VAMPIRIC)) { dam = number_range(1,2); act("$p draws life from $n.",victim,wield,NULL,TO_ROOM,0); act("You feel $p drawing your life away.", victim,wield,NULL,TO_CHAR,1); damage(ch,victim,dam,0,DAM_NEGATIVE,FALSE,1,-1); ch->RBPG += dam/2; } if (ch->fighting == victim && IS_WEAPON_STAT(wield,WEAPON_FLAMING)) { dam = number_range(1,2); act("$n is burned by $p.",victim,wield,NULL,TO_ROOM,0); act("$p sears your flesh.",victim,wield,NULL,TO_CHAR,1); fire_effect( (void *) victim,2,dam,TARGET_CHAR); damage(ch,victim,dam,0,DAM_FIRE,FALSE,1,-1); } if (ch->fighting == victim && IS_WEAPON_STAT(wield,WEAPON_FROST)) { dam = number_range(1, 2); act("$p freezes $n.",victim,wield,NULL,TO_ROOM,0); act("The cold touch of $p surrounds you with ice.", victim,wield,NULL,TO_CHAR,1); cold_effect(victim,2,dam,TARGET_CHAR); damage(ch,victim,dam,0,DAM_COLD,FALSE,0,-1); } if (ch->fighting == victim && IS_WEAPON_STAT(wield,WEAPON_SHOCKING)) { dam = number_range(1,2); act("$n is struck by lightning from $p.", victim,wield,NULL,TO_ROOM,0); act("You are shocked by $p.",victim,wield,NULL,TO_CHAR,1); shock_effect(victim,2,dam,TARGET_CHAR); damage(ch,victim,dam,0,DAM_LIGHTNING,FALSE,1,-1); } } */ tail_chain( ); return; }
/* * The main entry point for executing commands. * Can be recursively called from 'at', 'order', 'force'. */ void interpret(CHAR_DATA * ch, char *argument) { char command[MAX_INPUT_LENGTH]; char logline[MAX_INPUT_LENGTH]; int cmd; int trust; bool found; /* * Strip leading spaces. */ while(isspace(*argument)) { argument++; } if(argument[0] == '\0') { return; } /* * No hiding. */ REMOVE_BIT(ch->affected_by, AFF_HIDE); /* * Implement freeze command. */ if(!IS_NPC(ch) && IS_SET(ch->act, PLR_FREEZE)) { send_to_char("You're totally frozen!\r\n", ch); return; } /* * Grab the command word. * Special parsing so ' can be a command, * also no spaces needed after punctuation. */ strcpy(logline, argument); if(!isalpha(argument[0]) && !isdigit(argument[0])) { command[0] = argument[0]; command[1] = '\0'; argument++; while(isspace(*argument)) { argument++; } } else { argument = one_argument(argument, command); } /* * Look for command in command table. */ found = FALSE; trust = get_trust(ch); for(cmd = 0; cmd_table[cmd].name[0] != '\0'; cmd++) { if(command[0] == cmd_table[cmd].name[0] && !str_prefix(command, cmd_table[cmd].name) && (cmd_table[cmd].level <= trust || MP_Commands(ch))) { found = TRUE; break; } } /* * Log and snoop. */ if(cmd_table[cmd].log == LOG_NEVER) { strcpy(logline, "XXXXXXXX XXXXXXXX XXXXXXXX"); } if((!IS_NPC(ch) && IS_SET(ch->act, PLR_LOG)) || fLogAll || cmd_table[cmd].log == LOG_ALWAYS) { sprintf(log_buf, "Log %s: %s", ch->name, logline); log_string(log_buf); } if(ch->desc != NULL && ch->desc->snoop_by != NULL) { write_to_buffer(ch->desc->snoop_by, "% ", 2); write_to_buffer(ch->desc->snoop_by, logline, 0); write_to_buffer(ch->desc->snoop_by, "\r\n", 2); } if(!found) { /* * Look for command in socials table. */ if(!check_social(ch, command, argument) #ifdef IMC && !imc_command_hook(ch, command, argument) #endif ) { send_to_char("Huh?\r\n", ch); } return; } /* * Character not in position for command? */ if(ch->position < cmd_table[cmd].position) { switch(ch->position) { case POS_DEAD: send_to_char("Lie still; you are DEAD.\r\n", ch); break; case POS_MORTAL: case POS_INCAP: send_to_char("You are hurt far too bad for that.\r\n", ch); break; case POS_STUNNED: send_to_char("You are too stunned to do that.\r\n", ch); break; case POS_SLEEPING: send_to_char("In your dreams, or what?\r\n", ch); break; case POS_RESTING: send_to_char("Nah... You feel too relaxed...\r\n", ch); break; case POS_FIGHTING: send_to_char("No way! You are still fighting!\r\n", ch); break; } return; } /* * Dispatch the command. */ (*cmd_table[cmd].do_fun)(ch, argument); tail_chain(); return; }
/* * Write an object and its contents. */ void fwrite_obj( struct obj_data *obj, FILE *fp, int iNest ) { // struct affected_type * paf = NULL; struct extra_descr_data * ed = NULL; int i; /* * Slick recursion to write lists backwards, * so loading them will load in forwards order. */ if ( obj->next_content ) fwrite_obj( obj->next_content, fp, iNest ); /* * Castrate storage characters. */ if ( obj->obj_flags.type_flag == ITEM_KEY ) return; fprintf( fp, "#OBJECT\n" ); fprintf( fp, "Nest %d\n", iNest ); fprintf( fp, "Name %s~\n", obj->name ); fprintf( fp, "ShortDescr %s~\n", obj->short_description ); fprintf( fp, "Description %s~\n", obj->description ); fprintf( fp, "ActionDescr %s~\n", obj->action_description ? obj->action_description : "" ); fprintf( fp, "Vnum %ld\n", obj->item_number ); fprintf( fp, "ExtraFlags %ld\n", obj->obj_flags.extra_flags ); fprintf( fp, "WearFlags %d\n", obj->obj_flags.wear_flags ); fprintf( fp, "ItemType %d\n", obj->obj_flags.type_flag ); fprintf( fp, "Weight %d\n", obj->obj_flags.weight ); fprintf( fp, "Timer %d\n", obj->obj_flags.timer ); fprintf( fp, "Cost %d\n", obj->obj_flags.cost ); fprintf( fp, "Values %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", obj->obj_flags.value[0], obj->obj_flags.value[1], obj->obj_flags.value[2], obj->obj_flags.value[3], obj->obj_flags.value[4], obj->obj_flags.value[5], obj->obj_flags.value[6], obj->obj_flags.value[7], obj->obj_flags.value[8], obj->obj_flags.value[9] ); switch ( obj->obj_flags.type_flag ) { case ITEM_POTION: case ITEM_SCROLL: if ( obj->obj_flags.value[1] > 0 ) { fprintf( fp, "Spell 1 '%s'\n", skill_name( obj->obj_flags.value[1] ) ); } if ( obj->obj_flags.value[2] > 0 ) { fprintf( fp, "Spell 2 '%s'\n", skill_name( obj->obj_flags.value[2] ) ); } if ( obj->obj_flags.value[3] > 0 ) { fprintf( fp, "Spell 3 '%s'\n", skill_name( obj->obj_flags.value[3] ) ); } break; case ITEM_STAFF: case ITEM_WAND: if ( obj->obj_flags.value[3] > 0 ) { fprintf( fp, "Spell 3 '%s'\n", skill_name( obj->obj_flags.value[3] ) ); } break; default: /* ERROR */ break; } for ( i = 0; i < MAX_OBJ_AFFECT; i++ ) fprintf( fp, "Affect %d %d\n", obj->affected[ i ].location, obj->affected[ i ].modifier ); /* paf = obj->affected; for ( paf = obj->affected; paf; paf = paf->next ) { fprintf( fp, "Affect %d %d %d %d %ld\n", paf->type, paf->duration, paf->modifier, paf->location, paf->bitvector ); } */ for ( ed = obj->ex_description; ed; ed = ed->next ) { fprintf( fp, "ExtraDescr %s~ %s~\n", ed->keyword, ed->description ); } fprintf( fp, "End\n\n" ); if ( obj->contains ) fwrite_obj( obj->contains, fp, iNest + 1 ); tail_chain( ); return; }
/* * Write an object and its contents. */ void fwrite_obj( CHAR_DATA *ch, OBJ_DATA *obj, FILE *fp, int iNest ) { AFFECT_DATA *paf; EXTRA_DESCR_DATA *ed; /* * Slick recursion to write lists backwards, * so loading them will load in forwards order. */ if ( obj->next_content ) fwrite_obj( ch, obj->next_content, fp, iNest ); /* * Castrate storage characters. */ if ( ch->level < obj->level || obj->item_type == ITEM_KEY || obj->deleted ) return; fprintf( fp, "#OBJECT\n" ); fprintf( fp, "Nest %d\n", iNest ); fprintf( fp, "Name %s~\n", obj->name ); fprintf( fp, "ShortDescr %s~\n", obj->short_descr ); fprintf( fp, "Description %s~\n", obj->description ); fprintf( fp, "Vnum %d\n", obj->pIndexData->vnum ); fprintf( fp, "ExtraFlags %d\n", obj->extra_flags ); fprintf( fp, "WearFlags %d\n", obj->wear_flags ); fprintf( fp, "WearLoc %d\n", obj->wear_loc ); fprintf( fp, "ItemType %d\n", obj->item_type ); fprintf( fp, "Weight %d\n", obj->weight ); fprintf( fp, "Level %d\n", obj->level ); fprintf( fp, "Timer %d\n", obj->timer ); fprintf( fp, "Cost %d\n", obj->cost ); fprintf( fp, "Values %d %d %d %d\n", obj->value[0], obj->value[1], obj->value[2], obj->value[3] ); switch ( obj->item_type ) { case ITEM_POTION: case ITEM_SCROLL: if ( obj->value[1] > 0 ) { fprintf( fp, "Spell 1 '%s'\n", skill_table[obj->value[1]].name ); } if ( obj->value[2] > 0 ) { fprintf( fp, "Spell 2 '%s'\n", skill_table[obj->value[2]].name ); } if ( obj->value[3] > 0 ) { fprintf( fp, "Spell 3 '%s'\n", skill_table[obj->value[3]].name ); } break; case ITEM_PILL: case ITEM_STAFF: case ITEM_WAND: if ( obj->value[3] > 0 ) { fprintf( fp, "Spell 3 '%s'\n", skill_table[obj->value[3]].name ); } break; } for ( paf = obj->affected; paf; paf = paf->next ) { fprintf( fp, "Affect %d %d %d %d %d\n", paf->type, paf->duration, paf->modifier, paf->location, paf->bitvector ); } for ( ed = obj->extra_descr; ed; ed = ed->next ) { fprintf( fp, "ExtraDescr %s~ %s~\n", ed->keyword, ed->description ); } fprintf( fp, "End\n\n" ); if ( obj->contains ) fwrite_obj( ch, obj->contains, fp, iNest + 1 ); tail_chain(); return; }
/* * The main entry point for executing commands. * Can be recursively called from 'at', 'order', 'force'. */ void interpret( CHAR_DATA * ch, const char *argument ) { char command[MAX_INPUT_LENGTH]; char logline[MAX_INPUT_LENGTH]; char logname[MAX_INPUT_LENGTH]; TIMER *timer = NULL; CMDTYPE *cmd = NULL; int trust; int loglvl; bool found; struct timeval time_used; long tmptime; if( !ch ) { bug( "interpret: null ch!", 0 ); return; } found = FALSE; if( ch->substate == SUB_REPEATCMD ) { DO_FUN *fun; if( ( fun = ch->last_cmd ) == NULL ) { ch->substate = SUB_NONE; bug( "interpret: SUB_REPEATCMD with NULL last_cmd", 0 ); return; } else { int x; /* * yes... we lose out on the hashing speediness here... * but the only REPEATCMDS are wizcommands (currently) */ for( x = 0; x < 126; x++ ) { for( cmd = command_hash[x]; cmd; cmd = cmd->next ) if( cmd->do_fun == fun ) { found = TRUE; break; } if( found ) break; } if( !found ) { cmd = NULL; bug( "interpret: SUB_REPEATCMD: last_cmd invalid", 0 ); return; } sprintf( logline, "(%s) %s", cmd->name, argument ); } } if( !cmd ) { /* * Changed the order of these ifchecks to prevent crashing. */ if( !argument || !strcmp( argument, "" ) ) { bug( "interpret: null argument!", 0 ); return; } /* * Strip leading spaces. */ while( isspace( *argument ) ) argument++; if( argument[0] == '\0' ) return; timer = get_timerptr( ch, TIMER_DO_FUN ); /* * REMOVE_BIT( ch->affected_by, AFF_HIDE ); */ /* * Implement freeze command. */ if( !IS_NPC( ch ) && IS_SET( ch->act, PLR_FREEZE ) ) { send_to_char( "You're totally frozen!\r\n", ch ); return; } /* * Grab the command word. * Special parsing so ' can be a command, * also no spaces needed after punctuation. */ strcpy( logline, argument ); if( !isalpha( argument[0] ) && !isdigit( argument[0] ) ) { command[0] = argument[0]; command[1] = '\0'; argument++; while( isspace( *argument ) ) argument++; } else argument = one_argument( argument, command ); /* * Look for command in command table. * Check for council powers and/or bestowments */ trust = get_trust( ch ); for( cmd = command_hash[LOWER( command[0] ) % 126]; cmd; cmd = cmd->next ) if( !str_prefix( command, cmd->name ) && ( cmd->level <= trust || ( !IS_NPC( ch ) && ch->pcdata->bestowments && ch->pcdata->bestowments[0] != '\0' && is_name( cmd->name, ch->pcdata->bestowments ) && cmd->level <= ( trust + 5 ) ) ) ) { found = TRUE; break; } /* * Turn off afk bit when any command performed. */ if( !IS_NPC( ch ) && IS_SET( ch->act, PLR_AFK ) && ( str_cmp( command, "AFK" ) ) ) { REMOVE_BIT( ch->act, PLR_AFK ); act( AT_GREY, "$n is no longer afk.", ch, NULL, NULL, TO_ROOM ); } } /* * Log and snoop. */ sprintf( lastplayercmd, "** %s: %s", ch->name, logline ); if( found && cmd->log == LOG_NEVER ) strcpy( logline, "XXXXXXXX XXXXXXXX XXXXXXXX" ); loglvl = found ? cmd->log : LOG_NORMAL; if( ( !IS_NPC( ch ) && IS_SET( ch->act, PLR_LOG ) ) || fLogAll || loglvl == LOG_BUILD || loglvl == LOG_HIGH || loglvl == LOG_ALWAYS ) { /* * Added by Narn to show who is switched into a mob that executes * a logged command. Check for descriptor in case force is used. */ if( ch->desc && ch->desc->original ) sprintf( log_buf, "Log %s (%s): %s", ch->name, ch->desc->original->name, logline ); else sprintf( log_buf, "Log %s: %s", ch->name, logline ); /* * Make it so a 'log all' will send most output to the log * file only, and not spam the log channel to death -Thoric */ if( fLogAll && loglvl == LOG_NORMAL && ( IS_NPC( ch ) || !IS_SET( ch->act, PLR_LOG ) ) ) loglvl = LOG_ALL; /* * This is handled in get_trust already */ /* if ( ch->desc && ch->desc->original ) log_string_plus( log_buf, loglvl, ch->desc->original->level ); else*/ log_string_plus( log_buf, loglvl, get_trust( ch ) ); } if( ch->desc && ch->desc->snoop_by ) { sprintf( logname, "%s", ch->name ); write_to_buffer( ch->desc->snoop_by, logname, 0 ); write_to_buffer( ch->desc->snoop_by, "% ", 2 ); write_to_buffer( ch->desc->snoop_by, logline, 0 ); write_to_buffer( ch->desc->snoop_by, "\r\n", 2 ); } if( timer ) { int tempsub; tempsub = ch->substate; ch->substate = SUB_TIMER_DO_ABORT; ( timer->do_fun ) ( ch, "" ); if( char_died( ch ) ) return; if( ch->substate != SUB_TIMER_CANT_ABORT ) { ch->substate = tempsub; extract_timer( ch, timer ); } else { ch->substate = tempsub; return; } } /* * Look for command in skill and socials table. */ if( !found ) { if( !check_skill( ch, command, argument ) && !check_social( ch, command, argument ) #ifdef IMC && !imc_command_hook( ch, command, argument ) #endif ) { EXIT_DATA *pexit; /* * check for an auto-matic exit command */ if( ( pexit = find_door( ch, command, TRUE ) ) != NULL && IS_SET( pexit->exit_info, EX_xAUTO ) ) { if( IS_SET( pexit->exit_info, EX_CLOSED ) && ( !IS_AFFECTED( ch, AFF_PASS_DOOR ) || IS_SET( pexit->exit_info, EX_NOPASSDOOR ) ) ) { if( !IS_SET( pexit->exit_info, EX_SECRET ) ) act( AT_PLAIN, "The $d is closed.", ch, NULL, pexit->keyword, TO_CHAR ); else send_to_char( "You cannot do that here.\r\n", ch ); return; } move_char( ch, pexit, 0 ); return; } send_to_char( "Huh?\r\n", ch ); } return; } /* * Character not in position for command? */ if( !check_pos( ch, cmd->position ) ) return; /* * Berserk check for flee.. maybe add drunk to this?.. but too much * hardcoding is annoying.. -- Altrag */ if( !str_cmp( cmd->name, "flee" ) && IS_AFFECTED( ch, AFF_BERSERK ) ) { send_to_char( "You aren't thinking very clearly..\r\n", ch ); return; } /* * Dispatch the command. */ ch->prev_cmd = ch->last_cmd; /* haus, for automapping */ ch->last_cmd = cmd->do_fun; start_timer( &time_used ); ( *cmd->do_fun ) ( ch, argument ); end_timer( &time_used ); /* * Update the record of how many times this command has been used (haus) */ update_userec( &time_used, &cmd->userec ); tmptime = UMIN( time_used.tv_sec, 19 ) * 1000000 + time_used.tv_usec; /* * laggy command notice: command took longer than 1.5 seconds */ if( tmptime > 1500000 ) { sprintf( log_buf, "[*****] LAG: %s: %s %s (R:%d S:%d.%06d)", ch->name, cmd->name, ( cmd->log == LOG_NEVER ? "XXX" : argument ), ch->in_room ? ch->in_room->vnum : 0, ( int )( time_used.tv_sec ), ( int )( time_used.tv_usec ) ); log_string_plus( log_buf, LOG_NORMAL, get_trust( ch ) ); } tail_chain( ); }