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); }
static char * liner_desc_char(int n) { char buf[LEN]; extern int show_combat_flag; char *s; int sk; strcpy(buf, box_name(n)); sk = subkind(n); if (sk == sub_ni) { int mk = noble_item(n); int num = has_item(n, mk) + 1; if (num == 1) strcat(buf, sout(", %s", plural_item_name(mk, num))); else strcat(buf, sout(", %s, number:~%s", plural_item_name(mk, num), comma_num(num))); } else if (sk) { if (sk == sub_temple) { if (is_temple(n)) { strcat(buf, sout(", Temple of %s", god_name(is_temple(n)))); } else { strcat(buf, sout(", undedicated temple")); }; } else if (sk == sub_guild) { strcat(buf, sout(", %s Guild", box_name(is_guild(n)))); } else { strcat(buf, sout(", %s", subkind_s[sk])); }; } strcat(buf, nation_s(n)); strcat(buf, deserted_s(n)); strcat(buf, rank_s(n)); strcat(buf, mage_s(n)); strcat(buf, priest_s(n)); #if 0 strcat(buf, wield_s(n)); #endif if (show_combat_flag) { if (char_behind(n)) strcat(buf, sout(", behind~%d%s", char_behind(n), combat_ally)); else strcat(buf, combat_ally); } else if (char_guard(n) && stack_leader(n) == n && subkind(n) != sub_garrison) strcat(buf, ", on guard"); #if 0 if (subkind(n) == 0) { /* only show lord for regular players */ int sp = lord(n); if (sp != indep_player && !cloak_lord(n)) strcat(buf, sout(", of~%s", box_code_less(sp))); } #endif if (show_display_string) { s = banner(n); if (s && *s) strcat(buf, sout(", \"%s\"", s)); } strcat(buf, with_inventory_string(n)); if (is_prisoner(n)) strcat(buf, ", prisoner"); return sout("%s", buf); }
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 ); }