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; }
// 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 ); }
/* 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 ); }
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; }
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); }
/* * 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)); }
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); }
/* 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; }
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; }
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); }
// 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 }
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); }
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 ); }