Ejemplo n.º 1
0
void change_room_name(struct room_data *rp, struct char_data *ch, char *arg,
                      int type) {
  if (type != ENTER_CHECK)
    if (!*arg || (*arg == '\n')) {
      ch->specials.edit = MAIN_MENU;
      update_room_menu(ch);
      return;
    }

  if (type != ENTER_CHECK) {
    if (rp->name)
      free(rp->name);
    rp->name = (char *)strdup(arg);
    ch->specials.edit = MAIN_MENU;
    update_room_menu(ch);
    return;
  }

  send_to_charf(ch, VT_HOMECLR);

  send_to_charf(ch, "Current Room Name: %s", rp->name);
  send_to_char("\n\r\n\rNew Room Name: ", ch);

  return;
}
Ejemplo n.º 2
0
// Added by SinaC 2001 so, people can teach skills/spells to other
void do_teach( CHAR_DATA *ch, const char *argument ) {
  CHAR_DATA *victim;
  char arg[MAX_INPUT_LENGTH];
  char arg2[MAX_INPUT_LENGTH];
  int sn;

  argument = one_argument( argument, arg );
  argument = one_argument( argument, arg2 );

  if ( IS_NPC(ch)
       && ( IS_AFFECTED( ch, AFF_CHARM ) 
	    || ch->master != NULL
	    || ch->leader != NULL ) ) {
    send_to_char("You can't teach anything.\n\r", ch );
    return;
  }

  if ( ( victim = get_char_room( ch, arg2 ) ) == NULL ) {
    send_to_char( "They aren't here.\n\r", ch );
    return;
  }

  if ( IS_NPC( victim ) ) {
    send_to_char("NPC's are dumb, they can't learn anything.\n\r", ch );
    return;
  }

  if ( ( sn = ability_lookup( arg ) ) <= 0 ) {
    send_to_char("That skill/spell doesn't exist!\n\r", ch );
    return;
  }

  if ( get_ability( ch, sn ) < 95 ) {
    send_to_charf( ch,
		   "You haven't practiced '%s' enough to teach it.\n\r", 
		   ability_table[sn].name );
    return;
  }

  // get_ability_simple cos' we don't want to take care of victim's level
  if ( get_ability_simple( victim, sn ) > 0 ) {
    act("$N already knows '$t'.", ch, ability_table[sn].name, victim, TO_CHAR );
    return;
  }

  victim->pcdata->ability_info[sn].learned = 1;
  victim->pcdata->ability_info[sn].casting_level = ability_table[sn].nb_casting_level > 0 ? 1 : 0;
  victim->pcdata->ability_info[sn].level = URANGE( 1, victim->level, 100 );

  act( "$n teachs '$t' to $N.",
       ch, ability_table[sn].name, victim, TO_NOTVICT );
  act( "You teach '$t' to $N.",
       ch, ability_table[sn].name, victim, TO_CHAR );
  act( "$N teachs you '$t'.",
       victim, ability_table[sn].name, ch, TO_CHAR );
}
Ejemplo n.º 3
0
/* checks for skill improvement */
void check_improve( CHAR_DATA *ch, int sn, bool success, int multiplier ) {
  int chance;
  char buf[100];

  if (IS_NPC(ch))
    return;

  // Modified by SinaC 2001
  if (ch->level < class_abilitylevel( /*ch->cstat(classes)*/ch, sn )
      // Modified by SinaC 2003
      ||  class_abilityrating( ch, sn, ch->pcdata->ability_info[sn].casting_level ) == 0
      ||  ch->pcdata->ability_info[sn].learned == 0
      ||  ch->pcdata->ability_info[sn].learned == 100)
    return;  /* skill is not known */

  /* check to see if the character has a chance to learn */
  chance = 10 * int_app[ch->cstat(INT)].learn;
  chance /= ( multiplier
	      *	class_abilityrating( ch, sn, ch->pcdata->ability_info[sn].casting_level )
	      *	4 );
  chance += ch->level;

  if (number_range(1,1000) > chance)
    return;

  /* now that the character has a CHANCE to learn, see if they really have */

  bool done = FALSE; // Added by SinaC 2003
  if (success) {
    chance = URANGE(5,100 - ch->pcdata->ability_info[sn].learned, 95);
    if (number_percent() < chance) {
      sprintf(buf,"You have become better at %s!\n\r",
	      ability_table[sn].name);
      send_to_char(buf,ch);
      ch->pcdata->ability_info[sn].learned++;
      gain_exp(ch,2 * class_abilityrating( ch, sn, ch->pcdata->ability_info[sn].casting_level), TRUE);
      done = TRUE;
    }
  }
  else {
    chance = URANGE(5,ch->pcdata->ability_info[sn].learned/2,30);
    if (number_percent() < chance) {
      sprintf(buf,
	      "You learn from your mistakes, and your %s skill improves.\n\r",
	      ability_table[sn].name);
      send_to_char(buf,ch);
      ch->pcdata->ability_info[sn].learned += number_range(1,3);
      ch->pcdata->ability_info[sn].learned = UMIN(ch->pcdata->ability_info[sn].learned,100);
      gain_exp(ch,2 * class_abilityrating( ch, sn, ch->pcdata->ability_info[sn].casting_level), TRUE);
      done = TRUE;
    }
  }
  if ( done && ch->pcdata->ability_info[sn].learned == 100 ) // Added by SinaC 2003
    send_to_charf(ch,"You are now master in '%s'.\n\r", ability_table[sn].name );
}
Ejemplo n.º 4
0
void change_room_desc(struct room_data *rp, struct char_data *ch,
                      char *UNUSED(arg), int type) {

  if (type != ENTER_CHECK) {
    ch->specials.edit = MAIN_MENU;
    update_room_menu(ch);
    return;
  }

  send_to_charf(ch, VT_HOMECLR);

  send_to_charf(ch, "Current Room Description:\n\r");
  send_to_char(rp->description, ch);
  send_to_char("\n\r\n\rNew Room Description:\n\r", ch);
  send_to_char("(Terminate with a @. Press <C/R> again to continue)\n\r", ch);
  free(rp->description);
  rp->description = NULL;
  ch->desc->str = &rp->description;
  ch->desc->max_str = MAX_STRING_LENGTH;
  return;
}
Ejemplo n.º 5
0
void change_room_flags(struct room_data *rp, struct char_data *ch, char *arg,
                       int type) {
  int i, row, update;

  if (type != ENTER_CHECK)
    if (!*arg || (*arg == '\n')) {
      ch->specials.edit = MAIN_MENU;
      update_room_menu(ch);
      return;
    }

  update = atoi(arg);
  update--;
  if (type != ENTER_CHECK) {
    if (update < 0 || update > 13)
      return;
    i = 1 << update;

    if (IS_SET(rp->room_flags, i))
      REMOVE_BIT(rp->room_flags, i);
    else
      SET_BIT(rp->room_flags, i);
  }

  send_to_charf(ch, VT_HOMECLR);
  send_to_charf(ch, "Room Flags:");

  row = 0;
  for (i = 0; i < 14; i++) {
    send_to_charf(ch, VT_CURSPOS, row + 4, ((i & 1) ? 45 : 5));
    if (i & 1)
      row++;
    send_to_charf(ch, "%-2d [%s] %s", i + 1,
                  ((rp->room_flags & (1 << i)) ? "X" : " "), room_bits[i]);
  }

  send_to_charf(ch, VT_CURSPOS, 20, 1);
  send_to_char
    ("Select the number to toggle, <C/R> to return to main menu.\n\r--> ", ch);
}
Ejemplo n.º 6
0
/*
 * Help categories are fairly static, and it would be a pain to execute another
 * query just to get them, so we've already read them in in db.c into an array,
 * and here we just loop them over.
 * Torgny Bjers, 2001-11-12
 */
void display_help_categories(struct char_data *ch)
{
    int qend, i;
    char *name, *help = get_buffer(MAX_STRING_LENGTH);
    MYSQL_RES *stats;
    MYSQL_ROW row;
    int numentries = 0;
    time_t modified;

    strcpy(help, "&CARCANE REALMS HELP TOPICS&n\r\n\r\nType 'HELP <topic>' for more information on a specific topic.\r\nYou can use HELP ? <search phrase> to issue a fulltext search.\r\n\r\n");

    for (qend = 0, i = 0; i <= top_of_help_categories; i++) {
        if (!GOT_RIGHTS(ch, help_categories[i].rights) && !GOT_RIGHTS(ch, RIGHTS_HELPFILES))
            continue;
        name = str_dup(help_categories[i].name);
        sprintf(help + strlen(help), "%s%-22.22s", ((qend % 3 == 0)?"    ":""), ALLCAP(name));
        release_buffer(name);
        if (qend++ % 3 == 2) {
            strcat(help, "\r\n");
            send_to_char(help, ch);
            *help = '\0';
        }
    }
    if (*help)
        send_to_char(help, ch);
    if (!(--qend % 3 == 2))
        send_to_char("\r\n", ch);
    *help = '\0';

    release_buffer(help);

    if (!(stats = mysqlGetResource(TABLE_HLP_INDEX, "SELECT COUNT(keyword) AS count, MAX(modified) AS modfied FROM %s ORDER BY modified;", TABLE_HLP_INDEX))) {
        send_to_char("&YA database error has occured.  Please notify an administrator.&n\r\n", ch);
        extended_mudlog(NRM, SYSL_BUGS, TRUE, "Error loading help statistics.");
        return;
    }
    mysql_free_result(stats);

    row = mysql_fetch_row(stats);
    modified = atoi(row[1]);
    numentries = atoi(row[0]);

    send_to_charf(ch, "\r\nThere are &W%d&n help entries, latest updated: &W%s&n", numentries, ctime(&modified));
}
Ejemplo n.º 7
0
void update_room_menu(struct char_data *ch) {
  struct room_data *rp;

  rp = real_roomp(ch->in_room);

  send_to_char(VT_HOMECLR, ch);
  send_to_charf(ch, VT_CURSPOS, 1, 1);
  send_to_charf(ch, "Room Name: %s", rp->name);
  send_to_charf(ch, VT_CURSPOS, 1, 40);
  send_to_charf(ch, "Number: %d", rp->number);
  send_to_charf(ch, VT_CURSPOS, 1, 60);
  send_to_charf(ch, "Sector Type: %s", sector_types[rp->sector_type]);
  send_to_charf(ch, VT_CURSPOS, 3, 1);
  send_to_char("Menu:\n\r", ch);
  send_to_char(edit_menu, ch);
  send_to_char("--> ", ch);
}
Ejemplo n.º 8
0
/* this procedure handles the input parsing for the skill generator */
bool parse_gen_groups(CHAR_DATA *ch,const char *argument) {
  char arg[MAX_INPUT_LENGTH];
  char buf[100];
  int gn,sn,i;

  if (argument[0] == '\0')
    return FALSE;

  argument = one_argument(argument,arg);

  if (!str_prefix(arg,"help")) {
    if (argument[0] == '\0') {
      do_help(ch,"group help");
      return TRUE;
    }
    
    do_help(ch,argument);
    return TRUE;
  }

  // Removed by SinaC 2001, replaced with help
  /*
  // Added by Sinac 1997
  if (!str_prefix(arg,"level")) {
    do_level(ch,argument);
    return TRUE;
  }
  */

  // Added by SinaC 2001, so spells can be gained one by one not only by group
  if (!str_prefix(arg,"spell")) {
    list_spell_costs(ch);
    return TRUE;
  }

  // Added by SinaC 2001, so powers can be gained one by one not only by group
  if (!str_prefix(arg,"power")) {
    list_power_costs(ch);
    return TRUE;
  }

  // Added by SinaC 2003
  if (!str_prefix(arg,"song")) {
    list_song_costs(ch);
    return TRUE;
  }

  if (!str_prefix(arg,"add")) {
    if (argument[0] == '\0') {
      send_to_char("You must provide a skill/spell or group name.\n\r",ch);
      return TRUE;
    }
    
    gn = group_lookup(argument);
    if (gn != -1) {
      if (ch->gen_data->group_chosen[gn]
	  ||  ch->pcdata->group_known[gn]) {
	send_to_char("You already know that group!\n\r",ch);
	return TRUE;
      }
      
      if (class_grouprating( ch->bstat(classes), gn ) <= 0
	  || god_grouprating( ch, gn ) <= 0 ) {
	send_to_char("That group is not available.\n\r",ch);
	return TRUE;
      }
    
      sprintf(buf,"{W%s group added.{x\n\r",group_table[gn].name);
      send_to_char(buf,ch);
      ch->gen_data->group_chosen[gn] = TRUE;
      ch->gen_data->points_chosen += class_grouprating( ch->bstat(classes), gn );
      gn_add(ch,gn);
      ch->pcdata->points += class_grouprating( ch->bstat(classes), gn );
      return TRUE;
    }
    
    sn = ability_lookup(argument);
    if (sn != -1) {
      // Modified by SinaC 2001 for god skill
      if (ch->gen_data->ability_chosen[sn]
	  || get_raceability( ch, sn )
	  || get_clanability( ch, sn )
	  /*|| get_godskill( ch, sn )  removed by SinaC 2003*/
	  ||  ch->pcdata->ability_info[sn].learned > 0) {
	send_to_char("You already know that skill/spell/power/song!\n\r",ch);
	return TRUE;
      }
      
      // Modified by SinaC 2003
      if (class_gainabilityrating(ch, sn, ch->pcdata->ability_info[sn].casting_level ) <= 0
	  // Removed by SinaC 2001 so spells can be gained one by one
	  //  not only by group
	  /*||  ability_table[sn].spell_fun != spell_null*/) {
	send_to_char("That skill/spell/power/song is not available.\n\r",ch);
	return TRUE;
      }

      // Added by SinaC 2001
      if ( !can_gain_creation( ch, sn ) ) {
 	send_to_charf( ch, "You don't fit the prereqs for %s.\n\r",
		       ability_table[sn].name);
	return TRUE;
      }


      sprintf(buf, "{W%s skill/spell/power/song added.{x\n\r",ability_table[sn].name);
      send_to_char(buf,ch);
      ch->gen_data->ability_chosen[sn] = TRUE;
      ch->gen_data->points_chosen += class_abilityrating( ch, sn, ch->pcdata->ability_info[sn].casting_level );
      //ch->pcdata->ability_info[sn].learned = 1;  SinaC 2003, casting level need to be set
      group_add( ch, ability_table[sn].name, FALSE );
      ch->pcdata->points += class_abilityrating( ch, sn, ch->pcdata->ability_info[sn].casting_level );
      return TRUE;
    }
    
    send_to_char("No skills/spells/powers/songs or groups by that name...\n\r",ch);
    return TRUE;
  }
  
  if (!str_cmp(arg,"drop")) {
    if (argument[0] == '\0') {
      send_to_char("You must provide a skill/spell/power/song or group to drop.\n\r",ch);
      return TRUE;
    }

    gn = group_lookup(argument);
    if (gn != -1 && ch->gen_data->group_chosen[gn]) {
      send_to_char("{WGroup dropped.{x\n\r",ch);
      ch->gen_data->group_chosen[gn] = FALSE;
      ch->gen_data->points_chosen -= class_grouprating( ch->bstat(classes), gn );
      gn_remove(ch,gn);
      for (i = 0; i < MAX_GROUP; i++) {
	if (ch->gen_data->group_chosen[gn])
	  gn_add(ch,gn);
      }
      ch->pcdata->points -= class_grouprating( ch->bstat(classes), gn );
      // To avoid losing basic abilities which would be included in the group we just removed
      //  we re-add basics
      group_add( ch, class_table[ class_firstclass( ch->bstat(classes) ) ].base_group, FALSE );
      return TRUE;
    }
    
    sn = ability_lookup(argument);
    if (sn != -1 && ch->gen_data->ability_chosen[sn]) {
      send_to_char("{WSkill/spell/power/song dropped.{x\n\r",ch);
      ch->gen_data->ability_chosen[sn] = FALSE;
      ch->gen_data->points_chosen -= class_abilityrating( ch, sn, ch->pcdata->ability_info[sn].casting_level );
      ch->pcdata->ability_info[sn].learned = 0;
      ch->pcdata->points -= class_abilityrating( ch, sn, ch->pcdata->ability_info[sn].casting_level );
      return TRUE;
    }
    
    send_to_char("You haven't bought any such skill/spell/power/song or group.\n\r",ch);
    return TRUE;
  }
  
  if (!str_prefix(arg,"premise")) {
    do_help(ch,"premise");
    return TRUE;
  }
  
  if (!str_prefix(arg,"list")) {
    list_group_costs(ch);
    return TRUE;
  }
  
  if (!str_prefix(arg,"learned")) {
    list_group_chosen(ch);
    return TRUE;
  }

  // Added by SinaC 2000
  if (!str_prefix(arg,"known")){
    list_group_known(ch);
  }
  
  if (!str_prefix(arg,"info")) {
    do_groups(ch,argument);
    return TRUE;
  }

  return FALSE;
}
Ejemplo n.º 9
0
void change_exit_dir(struct room_data *rp, struct char_data *ch, char *arg,
                     int type) {
  int update;

  if (type != ENTER_CHECK) {
    if (!*arg || (*arg == '\n')) {
      ch->specials.edit = MAIN_MENU;
      update_room_menu(ch);
      return;
    }

    update = atoi(arg) - 1;
    if (update == -1) {
      change_exit_dir(rp, ch, "", ENTER_CHECK);
      return;
    }

    switch (update) {
    case 0:
      ch->specials.edit = CHANGE_EXIT_NORTH;
      add_exit_to_room(rp, ch, "", ENTER_CHECK);
      return;
      break;
    case 1:
      ch->specials.edit = CHANGE_EXIT_EAST;
      add_exit_to_room(rp, ch, "", ENTER_CHECK);
      return;
      break;
    case 2:
      ch->specials.edit = CHANGE_EXIT_SOUTH;
      add_exit_to_room(rp, ch, "", ENTER_CHECK);
      return;
      break;
    case 3:
      ch->specials.edit = CHANGE_EXIT_WEST;
      add_exit_to_room(rp, ch, "", ENTER_CHECK);
      return;
      break;
    case 4:
      ch->specials.edit = CHANGE_EXIT_UP;
      add_exit_to_room(rp, ch, "", ENTER_CHECK);
      return;
      break;
    case 5:
      ch->specials.edit = CHANGE_EXIT_DOWN;
      add_exit_to_room(rp, ch, "", ENTER_CHECK);
      return;
      break;
    case 6:
      ch->specials.edit = CHANGE_EXIT_DELETE;
      delete_exit(rp, ch, "", ENTER_CHECK);
      return;
      break;
    default:
      change_exit_dir(rp, ch, "", ENTER_CHECK);
      return;
    }

  }


  send_to_char(VT_HOMECLR, ch);
  send_to_charf(ch, "Room Name: %s", rp->name);
  send_to_charf(ch, VT_CURSPOS, 1, 40);
  send_to_charf(ch, "Room Number: %d", rp->number);
  send_to_charf(ch, VT_CURSPOS, 4, 1);
  send_to_char(exit_menu, ch);
  send_to_char("--> ", ch);
  return;
}
Ejemplo n.º 10
0
void change_room_type(struct room_data *rp, struct char_data *ch, char *arg,
                      int type) {
  int i, row, update;

  if (type != ENTER_CHECK)
    if (!*arg || (*arg == '\n')) {
      ch->specials.edit = MAIN_MENU;
      update_room_menu(ch);
      return;
    }

  update = atoi(arg);
  update--;

  if (type != ENTER_CHECK) {
    switch (ch->specials.edit) {
    case CHANGE_TYPE:
      if (update < 0 || update > 11)
        return;
      else {
        rp->sector_type = update;
        if (rp->sector_type == SECT_WATER_NOSWIM) {
          send_to_char("\n\rRiver Speed: ", ch);
          ch->specials.edit = CHANGE_TYPE2;
        }
        else {
          ch->specials.edit = MAIN_MENU;
          update_room_menu(ch);
        }
        return;
      }
    case CHANGE_TYPE2:
      rp->river_speed = update;
      send_to_char("\n\rRiver Direction (0 - 5): ", ch);
      ch->specials.edit = CHANGE_TYPE3;
      return;
    case CHANGE_TYPE3:
      update++;
      if (update < 0 || update > 5) {
        send_to_char("Direction must be between 0 and 5.\n\r", ch);
        return;
      }
      rp->river_dir = update;
      ch->specials.edit = MAIN_MENU;
      update_room_menu(ch);
      return;
    }
  }

  send_to_charf(ch, VT_HOMECLR);
  send_to_charf(ch, "Sector Type: %s", sector_types[rp->sector_type]);

  row = 0;
  for (i = 0; i < 12; i++) {
    send_to_charf(ch, VT_CURSPOS, row + 4, ((i & 1) ? 45 : 5));
    if (i & 1)
      row++;
    send_to_charf(ch, "%-2d %s", i + 1, sector_types[i]);
  }

  send_to_charf(ch, VT_CURSPOS, 20, 1);
  send_to_char
    ("Select the number to set to, <C/R> to return to main menu.\n\r--> ", ch);
}
Ejemplo n.º 11
0
// Added by SinaC 2001 for player disabled commands 
void do_disable_plr(CHAR_DATA *ch, const char *argument) {
  int i;
  DISABLED_CMD_DATA *p,*q;
  char buf[100];
  char arg1[MAX_INPUT_LENGTH];
  char arg2[MAX_INPUT_LENGTH];
  CHAR_DATA *victim;
    
  argument = one_argument( argument, arg1 );
  argument = one_argument( argument, arg2 );

  if (IS_NPC(ch)) {
    send_to_char ("Mobiles can't use that command.\n\r",ch);
    return;
  }

  if ( !arg1[0] ) {
    send_to_char("You must specify a target player.\n\r", ch );
    return;
  }

  if ( ( victim = get_char_world( ch, arg1 ) ) == NULL ) {
    send_to_char("Invalid target.\n\r", ch );
    return;
  }

  if (IS_NPC(victim)) {
    send_to_char("You can't disable NPC commands.\n\r", ch );
    return;
  }
   
  if (!arg2[0]) {/* Nothing specified. Show disabled commands. */
    if (!victim->pcdata->disabled_cmd) {/* Any disabled at all ? */
      send_to_char ("That player have no commands disabled.\n\r",ch);
      return;
    }

    send_to_charf (ch,"Disabled commands for player %s:\n\r"
		  "Command         Disabled by\n\r",
		  NAME(victim));
		                
    for (p = victim->pcdata->disabled_cmd; p; p = p->next) {
      sprintf (buf, "%-12s    %-12s\n\r",p->cmd->name, p->disabled_by );
      send_to_char (buf,ch);
    }
    return;
  }
	
  /* command given */

  /* First check if it is one of the disabled commands */
  for (p = victim->pcdata->disabled_cmd; p ; p = p->next)
    if (!str_cmp(arg2, p->cmd->name))
      break;
			
  if (p) {/* this command is disabled */
    /* Remove */
		
    if (victim->pcdata->disabled_cmd == p)/* node to be removed == head ? */
      victim->pcdata->disabled_cmd = p->next;
    else {/* Find the node before this one */
      for (q = victim->pcdata->disabled_cmd; q->next != p; q = q->next); /* empty for */
      q->next = p->next;
    }
    
    send_to_char ("Command enabled.\n\r",ch);
  }
  else {/* not a disabled command, check if that command exists */
    /* IQ test */
    if (!str_cmp(arg2,"disableplr")) {
      send_to_char ("You cannot disable the disableplr command.\n\r",ch);
      return;
    }

    /* Search for the command */
    for (i = 0; cmd_table[i].name[0] != '\0'; i++)
      if (!str_cmp(cmd_table[i].name, arg2))
	break;

    /* Found? */				
    if (cmd_table[i].name[0] == '\0') {
      send_to_char ("No such command.\n\r",ch);
      return;
    }

    /* Can the imm use this command at all ? */				
    if (cmd_table[i].level > get_trust(ch))	{
      send_to_char ("You dot have access to that command; you cannot disable it.\n\r",ch);
      return;
    }
		
    /* Disable the command */

    if ( ( p = (DISABLED_CMD_DATA *) GC_MALLOC( sizeof( DISABLED_CMD_DATA ) ) ) == NULL ) {
      bug("Memory allocation error in disable_cmd_data\n\r");
      exit(-1);
    }
    p->cmd = &cmd_table[i];
    p->disabled_by = str_dup(ch->name); /* save name of disabler */
    p->next = victim->pcdata->disabled_cmd;
    victim->pcdata->disabled_cmd = p; /* add before the current first element */
		
    send_to_char ("Command disabled.\n\r",ch);
  }
  new_save_pFile( victim, FALSE ); // force pFile saving
}
Ejemplo n.º 12
0
void do_specialize( CHAR_DATA *ch, const char *argument ) {
  int iClass, iWeapon;
  //  char arg[MAX_INPUT_LENGTH];

  if (IS_NPC(ch)){
    send_to_char("Mobs can't specialize!\n\r",ch);
    return;
  }

  // find a practicer
  CHAR_DATA *practicer;
  for ( practicer = ch->in_room->people; practicer != NULL; practicer = practicer->next_in_room)
    if (IS_NPC(practicer) && IS_SET(practicer->act,ACT_PRACTICE))
      break;
  
  if (practicer == NULL || !can_see(ch,practicer)) {
    send_to_char("You can't do that here.\n\r",ch);
    return;
  }

  //  argument = one_argument(argument,arg);

  // No arg
  if (argument[0] == 0) {
    Value *v = get_extra_field( ch, "specialized_weapon" );
    if ( v != NULL ) { // extra field found
      int specialized = v->asInt();
      send_to_charf(ch, "You are specialized in %s.\n\r", flag_string(weapon_class,specialized));
    }
    else
      specialize_syntax( ch );
  }
  // List available classes
  else if ( !str_cmp( argument, "list" ) ) {
    bool found = FALSE;
    char buf[MAX_STRING_LENGTH];
    char buf2[MAX_STRING_LENGTH];
    buf[0] = '\0';
    for ( int i = 0; i < MAX_CLASS; i++ ) {
      if ( class_table[i].name == NULL ) continue;
      if ( (1 << i) & ch->bstat(classes) ) continue;                     // already has that class
      if ( class_table[i].parent_class == i ) continue;                  // not a sub-class
      if ( !check_class_god( i, ch->pcdata->god ) ) continue;            // god doesn't like that class
      if ( !check_class_race( ch, i ) ) continue;                        // race can't be that class
      if (class_table[i].parent_class != i                               // doesn't have parent class
	  && !((1<<class_table[i].parent_class) & ch->bstat(classes)) ) continue;
      if ( class_table[i].choosable == CLASS_CHOOSABLE_NEVER ) continue; // can't be picked
      if ( ch->isWildMagic                                               // can't get non-wild magic
	   && IS_SET( class_table[i].type, CLASS_MAGIC )                 //  class if wild mage
	   && !IS_SET( class_table[i].type, CLASS_WILDABLE ) ) continue;

      sprintf(buf2,"  %s\n\r", class_table[i].name );
      strcat(buf,buf2);
      found = TRUE;
    }
    
    if (found) {
      send_to_char("Available classes to specialize in:\n\r",ch);
      send_to_char(buf,ch);
    }
    else
      send_to_char("You can't specialize in a class.\n\r", ch );
  }
  // List weapon available weapon
  else if ( !str_cmp( argument, "weapon" ) ) {
    if ( get_ability( ch, gsn_specialization ) == 0 ) {
      send_to_char("You don't know how to specialize in a weapon type.\n\r", ch );
      return;
    }
    bool found = FALSE;
    char buf[MAX_STRING_LENGTH];
    char buf2[MAX_STRING_LENGTH];
    buf[0] = '\0';
    for (int type = 0; weapon_table[type].name != NULL; type++)
      if ( weapon_table[type].gsn != NULL 
	   && get_ability( ch, *(weapon_table[type].gsn) ) == 100 ) {
	found = TRUE;
	sprintf(buf2,"  %s\n\r", weapon_table[type].name );
	strcat(buf,buf2);
      }
    if ( found ) {
      send_to_char("Available weapons to specialize in:\n\r",ch);
      send_to_char(buf,ch);
    }
    else
      send_to_char("You are not proficient enough in any weapon type.\n\r", ch );
  }
  // Weapon
  else if ( ( iWeapon = weapon_lookup(argument) ) >= 0 ) {
    if ( get_ability( ch, gsn_specialization ) == 0 ) {
      send_to_char("You don't know how to specialize in a weapon type.\n\r", ch );
      return;
    }
    if ( weapon_table[iWeapon].gsn
	 && get_ability( ch, *(weapon_table[iWeapon].gsn) ) != 100 ) {
      send_to_charf(ch,"You are not proficient enough in %s.\n\r", weapon_table[iWeapon].name );
      return;
    }
    Value *sp = get_extra_field( ch, "specialized_weapon" );
    if ( sp != NULL ) {
      int w = sp->asInt();
      send_to_charf(ch,"You already specialized in %s.\n\r", w>=0?weapon_table[w].name:"Unknown" );
      return;
    }
    // Add an extra field storing in which weapon the player is specialized
    Value v = add_extra_field( ch, "specialized_weapon" );
    v.setValue( weapon_table[iWeapon].type );
    send_to_charf(ch,"You are now specialized in %s.\n\r", weapon_table[iWeapon].name );
  }
  // Class
  else if ( ( iClass = class_lookup(argument, TRUE) ) >= 0 ) {
    if ((1<<iClass) & ch->bstat(classes)) {
      send_to_char("Choose a class that you don't already have.\n\r",ch);
      return;
    }
    if ( class_table[iClass].parent_class == iClass ) {
      send_to_char("This is not a sub-class.\n\r", ch );
      return;
    }
    if ( !check_class_god( iClass, ch->pcdata->god ) ){
      send_to_charf(ch,
		    "%s doesn't allow that class.\n\r",
		    god_name(ch->pcdata->god));
      return;
    }
    if ( !check_class_race( ch, iClass ) ){
      send_to_char( "You can't choose that class because of your race.\n\r", ch );
      return;
    }
    if ( class_table[iClass].parent_class != iClass
	 && !((1<<class_table[iClass].parent_class) & ch->bstat(classes))) {
      send_to_char("You can't choose this sub-class because you don't have the parent class.\n\r", ch );
      return;
    }
    // Added by SinaC 2003 to determine if a class can be picked during creation/multiclass
    if ( class_table[iClass].choosable == CLASS_CHOOSABLE_NEVER ) {
      send_to_char("This class cannot be picked.\n\r", ch );
      return;
    }
    if ( ch->isWildMagic                                                 // can't get non-wild magic class
	 && IS_SET( class_table[iClass].type, CLASS_MAGIC )              //  if wild mage
	 && !IS_SET( class_table[iClass].type, CLASS_WILDABLE ) ) {
      send_to_charf(ch,"This class cannot be picked by a wild-mage.\n\r");
      return;
    }

    // Remove parent class
    REMOVE_BIT( ch->bstat(classes), 1<<class_table[iClass].parent_class );
    // Add sub-class
    SET_BIT( ch->bstat(classes), 1<<iClass );
    
    send_to_charf(ch,"You specialize yourself as %s.\n\r", class_table[iClass].name );
    recompute(ch);
  }
  else
    specialize_syntax(ch);
}
Ejemplo n.º 13
0
void do_multiclass(CHAR_DATA *ch, const char *argument) {
  int iClass;
  //  char arg[MAX_INPUT_LENGTH];

  ROOM_INDEX_DATA *pRoom;
  OBJ_DATA *obj;

  if (IS_NPC(ch)){
    send_to_char("Mobs can't multiclass!\n\r",ch);
    return;
  }

  if (IS_IMMORTAL(ch)) {
    send_to_char("Immortals are damned to be immortals.\n\r",ch);
    return;
  }

  //  argument = one_argument(argument,arg);

  if (argument[0] == 0) {
    send_to_char("You must provide a class name to add to your class list.\n\r",ch);
    return;
  }

  iClass = class_lookup(argument, TRUE );
  if (iClass == -1) {
    send_to_char("You must provide an existing class name to add to your class list.\n\r",ch);
    return;
  }

  if ((1<<iClass) & ch->bstat(classes)) {
    send_to_char("Choose a class that you don't already have.\n\r",ch);
    return;
  }

  // Added by SinaC 2001
  if ( !check_class_god( iClass, ch->pcdata->god ) ){
    send_to_charf(ch,
		  "%s doesn't allow that class.\n\r",
		  god_name(ch->pcdata->god));
    return;
  }
  if ( !check_class_race( ch, iClass ) ){
    send_to_char( "You can't choose that class because of your race.\n\r", ch );
    return;
  }
  // Added by SinaC 2003 for subclass system
  //  If trying to multiclass in a subclass without having the parent class
  //  Should be able to get only one sub-class for each parent-class
  //   Cannot be fire and water elementalist
  //   Cannot be enchanter and transmuter
  //   But can be assassin and fire elementalist
  if ( class_table[iClass].parent_class != iClass
       && !((1<<class_table[iClass].parent_class) & ch->bstat(classes))) {
    send_to_char("You can't choose this sub-class because you don't have the parent class.\n\r", ch );
    return;
  }
  // Added by SinaC 2003 to determine if a class can be picked during creation/multiclass
  if ( class_table[iClass].choosable != CLASS_CHOOSABLE_YES ) {
    send_to_char("This class cannot be picked.\n\r", ch );
    return;
  }

  // check wild-magic
  if ( ch->isWildMagic                                                    // can't get non-wild magic class
       && IS_SET( class_table[iClass].type, CLASS_MAGIC )                 //  if wild mage
       && !IS_SET( class_table[iClass].type, CLASS_WILDABLE ) ) {
    send_to_charf(ch,"This class cannot be picked by a wild-mage.\n\r");
    return;
  }

  // kill pet and charmies
  die_follower( ch );

  /* Test if fighting ? */
  stop_fighting( ch, TRUE );

  /* Go to donation room */

  pRoom = get_donation_room( ch );
  //pRoom = get_room_index( ROOM_VNUM_DONATION );
  if (pRoom==NULL) {
    bug("do_multiclass: donation room not found for player [%s] clan [%s] hometown [%s]!",
	NAME(ch), get_clan_table(ch->clan)->name,
	(IS_NPC(ch)||ch->pcdata->hometown<0)?"none":hometown_table[ch->pcdata->hometown].name);
    //bug("multiclass: donation room not found %d!",ROOM_VNUM_DONATION);
    return;
  }

  if (ch->in_room != pRoom) {
    act("$n disapears!",ch,NULL,NULL,TO_ROOM);
    char_from_room( ch );
    char_to_room( ch, pRoom );
    act( "$n appears in the donation room.", ch, NULL, NULL, TO_ROOM );
  }

  ch->level = 1;
  ch->bstat(classes) |= 1<<iClass;
  ch->hit = 20;        /* I should place constants instead of "hard code" */
  ch->bstat(max_hit) = 20;
  ch->mana = 100;
  ch->bstat(max_mana) = 100;
  // Added by SinaC 2001 for mental user
  ch->psp = 100;
  ch->bstat(max_psp) = 100;
  ch->move = 100;
  ch->bstat(max_move) = 100;
  ch->wimpy = 0;

  /* ch->pcdata->points = ? creation points*/
  ch->exp = exp_per_level(ch,ch->pcdata->points);

  /* Train - Pra ?*/

  /* Gain base group*/
  group_add(ch,class_table[iClass].base_group,FALSE);

  /*group_add(ch,class_table[iClass].default_group,TRUE);*/
  /* adding this would raise creation points too much*/

  /*group_add(ch,class_table[iClass].default_group,FALSE);*/
  /* adding this would be too easy for the player */

  /* gold & silver ?*/

  /* Dealing with equipment */
  // FIXME: item STAY_DEATH or owned equipement must be dropped ?
  while ( ch->carrying != NULL ) {
    /* Remove the obj if it is worn */
    obj = ch->carrying;
    if (obj->wear_loc != WEAR_NONE)
      unequip_char( ch, obj );

    obj_from_char( obj );
    obj_to_room( obj, pRoom );
    SET_OBJ_STAT( obj, ITEM_DONATED);
  }

  // Added by SinaC 2001
  recompute(ch); 
  // Added by SinaC 2001
  recomproom(pRoom);

  do_outfit(ch,"");

  send_to_char("You are now mortal again...\n\r",ch);
  send_to_char("You see all your possesions lying on the ground...\n\r",ch);
  send_to_char("Probably few things are still usable, you'd better\n\r"
	       "leave them here.\n\r",ch);

  char buf[MAX_INPUT_LENGTH];
  sprintf( buf, "$N has multiclassed in %s.", class_table[iClass].name );
  wiznet(buf, ch, NULL, WIZ_MULTICLASS, 0, 0 );
}