/************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * Much time and thought has gone into this software and you are * * benefiting. We hope that you share your changes too. What goes * * around, comes around. * *************************************************************************** * ROM 2.4 is copyright 1993-1998 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@hypercube.org) * * Gabrielle Taylor (gtaylor@hypercube.org) * * Brian Moore (zump@rom.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Rom24/doc/rom.license * *************************************************************************** * 1stMud ROM Derivative (c) 2001-2004 by Markanth * * http://www.firstmud.com/ <markanth@firstmud.com> * * By using this code you have agreed to follow the term of * * the 1stMud license in ../doc/1stMud/LICENSE * ***************************************************************************/ #include "merc.h" #include "vnums.h" #include "interp.h" Do_Fun(do_remort) { Descriptor *d; CharData *mob; void send_race_info(Descriptor *); void send_class_info(Descriptor *); if (IsNPC(ch) || (d = ch->desc) == NULL) return; if (ch->in_room->guild == -1 || !is_class(ch, ch->in_room->guild)) { chprintlnf(ch, "You must be at your class%s guild to do that.", IsRemort(ch) ? "(s)" : ""); return; } for (mob = ch->in_room->person_first; mob; mob = mob->next_in_room) { if (IsNPC(mob) && IsSet(mob->act, ACT_TRAIN | ACT_GAIN)) break; } if (mob == NULL) { chprintln(ch, "You can't do that here."); return; } if (ch->level < calc_max_level(ch)) { chprintlnf(ch, "You must be a %s to remort.", high_level_name(calc_max_level(ch), true)); return; } if (ch->Class[CLASS_COUNT] == MAX_REMORT || ch->Class[CLASS_COUNT] == top_class) { chprintln(ch, "You can't remort any more!"); return; } if (IsQuester(ch) || Gquester(ch)) { chprintln(ch, "Don't you want to finish your quest first?"); return; } if (!check_worth(ch, 500000, VALUE_GOLD) || ch->pcdata->quest.points < 500) { chprintln(ch, "You need 500,000 gold and 500 quest points to remort."); return; } if (ch->pcdata->confirm_remort) { if (!NullStr(argument)) { chprintln(ch, "Remort status removed."); ch->pcdata->confirm_remort = false; return; } else { dwraplnf(ch->desc, "You have chosen to remort. You will now be dropped in at the %s" " selection section of character creation, and will be allowed recreate" " your character with an additional {Cclass{x%s and {Gbonuses{x." NEWLINE "In the unlikely event that you are disconnected or the Mud" " crashes while you are creating your character, log back on and write a" " note to an immortal who will retrieve your backup.", !ch->pcdata->stay_race ? "{BRACE{x" : "{CCLASS{x", !ch->pcdata->stay_race ? ", {brace{x" : ""); wiznet("$N has remorted.", ch, NULL, 0, true, 0); char_from_room(ch); char_to_room(ch, get_room_index(ROOM_VNUM_LIMBO)); UnLink(ch, char, next, prev); UnLink(ch, player, next_player, prev_player); chprintln(ch, NEWLINE "Now beginning the remorting process."); if (!ch->pcdata->stay_race) { send_race_info(ch->desc); chprint(ch, NEWLINE "What is your race (help for more information)?"); d->connected = CON_GET_NEW_RACE; } else { ch->pcdata->points = ch->race->points; send_class_info(ch->desc); chprintln(ch, "What is your next class? "); d->connected = CON_GET_NEW_CLASS; } return; } } if (!NullStr(argument)) { chprintln(ch, "Just type remort. No argument."); return; } dwraplnf(ch->desc, "{RTyping {Gremort{R with an argument will undo remort status." " Remorting is {Wnot reversable{R, make sure you read help REMORT" " and have an idea of what {Cclass%s{R you want to remort into." " Type {Gremort{R again to confirm this command.{x", !ch->pcdata->stay_race ? "and {Brace" : ""); ch->pcdata->confirm_remort = true; if (!ch->pcdata->stay_race) chprintln(ch, "{f{WWARNING{x{R: IF YOU CHOOSE A RACE DIFFERENT FROM YOUR RACE NOW YOU WILL BE THAT RACE {fFOREVER{x{R.{x"); wiznet("$N is contemplating remorting.", ch, NULL, 0, false, get_trust(ch)); } void finish_remort(CharData * ch) { int sn, b = lvl_bonus(ch); ObjData *obj, *obj_next; AffectData *af, *af_next; d_println(ch->desc, "Sucessful Remort!"); wiznet("Sucessful Remort! $N sighted.", ch, NULL, 0, false, 0); Link(ch, char, next, prev); Link(ch, player, next_player, prev_player); for (af = ch->affect_first; af != NULL; af = af_next) { af_next = af->next; affect_remove(ch, af); } for (obj = ch->carrying_first; obj != NULL; obj = obj_next) { obj_next = obj->next_content; if (obj->wear_loc != WEAR_NONE) { unequip_char(ch, obj); } } ch->trust = ch->level; ch->level = 1; ch->exp = 0; ch->pcdata->points = 0; deduct_cost(ch, 500000, VALUE_GOLD); ch->pcdata->quest.points -= 500; ch->max_hit = 100 * b; ch->max_mana = 100 * b; ch->max_move = 100 * b; ch->hit = ch->max_hit; ch->mana = ch->max_move; ch->move = ch->max_mana; ch->pcdata->perm_hit = ch->max_hit; ch->pcdata->perm_mana = ch->max_mana; ch->pcdata->perm_move = ch->max_move; ch->wimpy = ch->max_hit / 5; ch->train = 5 * b; ch->practice = 7 * b; ch->exp = exp_per_level(ch, ch->pcdata->points); reset_char(ch); if (ch->pet != NULL) { nuke_pets(ch); ch->pet = NULL; } for (sn = 0; sn < top_skill; sn++) { if (ch->pcdata->learned[sn] > 0 && ch->pcdata->learned[sn] < 100) { if (is_race_skill(ch, sn) && !ch->pcdata->stay_race) ch->pcdata->learned[sn] = 0; else ch->pcdata->learned[sn] = 1; } } char_from_room(ch); char_to_room(ch, get_room_index(ROOM_VNUM_SCHOOL)); ch->desc->connected = CON_PLAYING; act ("You are brought back to reality, and you feel quite different now...", ch, NULL, NULL, TO_CHAR); do_function(ch, &do_outfit, ""); save_char_obj(ch); mud_info.stats.remorts++; } bool can_use_skpell(CharData * ch, int sn) { int i; if (sn < 0 || sn >= top_skill) return false; if (IsNPC(ch)) return true; if (is_race_skill(ch, sn)) return true; if (is_deity_skill(ch, sn)) return true; for (i = 0; i < ch->Class[CLASS_COUNT]; i++) if (ch->level >= skill_table[sn].skill_level[ch->Class[i]]) return true; return false; } bool has_spells(CharData * ch) { int i; if (IsNPC(ch)) return false; for (i = 0; i < ch->Class[CLASS_COUNT]; i++) if (class_table[i].fMana) return true; return false; } bool is_class(CharData * ch, int Class) { int i; if (IsNPC(ch)) return false; for (i = 0; i < ch->Class[CLASS_COUNT]; i++) { if (ch->Class[i] == Class) return true; } return false; } bool is_same_class(CharData * ch, CharData * victim) { int i, jClass; if (IsNPC(ch) || IsNPC(victim)) return false; for (i = 0; i < ch->Class[CLASS_COUNT]; i++) { for (jClass = 0; victim->Class[jClass] != -1; jClass++) if (ch->Class[i] == victim->Class[jClass]) return true; } return false; } int prime_class(CharData * ch) { int slot = 0; if (!IsNPC(ch)) slot = Range(0, ch->pcdata->prime_class, ch->Class[CLASS_COUNT] - 1); return ch->Class[slot]; } int current_class(CharData * ch) { return ch->Class[ch->Class[CLASS_COUNT] - 1]; } int class_slot(CharData * ch, int pclass) { int iClass; if (IsNPC(ch)) return 0; for (iClass = 0; ch->Class[iClass] != -1; iClass++) { if (ch->Class[iClass] == pclass) return iClass; } return -1; } int number_classes(CharData * ch) { int i; if (IsNPC(ch)) return number_range(1, MAX_REMORT); for (i = 0; i < ch->Class[CLASS_COUNT]; i++) ; return i; } char *class_long(CharData * ch) { static char buf[512]; int i; buf[0] = '\0'; if (IsNPC(ch)) return "Mobile"; for (i = 0; i < ch->Class[CLASS_COUNT]; i++) { strcat(buf, "/"); strcat(buf, ClassName(ch, ch->Class[i])); } return buf + 1; } char *class_who(CharData * ch) { static char buf[512]; buf[0] = '\0'; if (IsNPC(ch)) return "Mob"; if (IsRemort(ch)) sprintf(buf, "%2.2s+%d", ClassName(ch, prime_class(ch)), ch->Class[CLASS_COUNT] - 1); else sprintf(buf, "%4.4s", ClassName(ch, prime_class(ch))); return buf; } char *class_short(CharData * ch) { static char buf[512]; int i; buf[0] = '\0'; if (IsNPC(ch)) return "Mob"; for (i = 0; i < ch->Class[CLASS_COUNT]; i++) { strcat(buf, "/"); sprintf(buf + strlen(buf), "%4.4s", ClassName(ch, ch->Class[i])); } return buf + 1; } char *class_numbers(CharData * ch) { static char buf[512]; char buf2[10]; int i; buf[0] = '\0'; if (IsNPC(ch)) return "0"; for (i = 0; i < MAX_MCLASS; i++) { strcat(buf, " "); sprintf(buf2, "%d", ch->Class[i]); strcat(buf, buf2); } return buf + 1; } int skill_level(CharData * ch, int sn) { int i; int tempskill = 999; if (sn < 0 || sn >= top_skill) return MAX_LEVEL + 1; if (is_race_skill(ch, sn)) return 1; if (is_deity_skill(ch, sn)) return 1; for (i = 0; i < ch->Class[CLASS_COUNT]; i++) tempskill = Min(tempskill, skill_table[sn].skill_level[ch->Class[i]]); return tempskill == 999 ? LEVEL_IMMORTAL : tempskill; } int skill_rating(CharData * ch, int sn) { int i; int temprate = 999; if (sn < 0 || sn >= top_skill) return 0; if (is_race_skill(ch, sn)) return 2; if (is_deity_skill(ch, sn)) return 2; for (i = 0; i < ch->Class[CLASS_COUNT]; i++) { if (skill_table[sn].rating[ch->Class[i]] < 1) continue; temprate = Min(temprate, skill_table[sn].rating[ch->Class[i]]); } return temprate == 999 ? 0 : temprate; } int group_rating(CharData * ch, int gn) { int i; int temprate = 999; if (gn < 0 || gn >= top_group) return 0; if (is_race_skill(ch, gn)) return 2; if (is_deity_skill(ch, gn)) return 2; for (i = 0; i < ch->Class[CLASS_COUNT]; i++) { if (group_table[gn].rating[ch->Class[i]] < 1) continue; temprate = Min(temprate, group_table[gn].rating[ch->Class[i]]); } return temprate == 999 ? 0 : temprate; } int get_hp_gain(CharData * ch) { int i = 0; int gain = 0; int count = 0; for (i = 0; i < ch->Class[CLASS_COUNT]; i++) { gain = Max(gain, number_range(class_table[ch->Class[i]].hp_min, class_table[ch->Class[i]].hp_max)); count++; } return number_range(gain, gain + count); } int hp_max(CharData * ch) { int i; int tmp = 0; for (i = 0; i < ch->Class[CLASS_COUNT]; i++) tmp = Max(tmp, class_table[ch->Class[i]].hp_max); return tmp; } bool is_prime_stat(CharData * ch, int stat) { int i = 0; if (IsNPC(ch)) return true; for (i = 0; i < ch->Class[CLASS_COUNT]; i++) { if (class_table[ch->Class[i]].attr_prime == stat) return true; } return false; } void add_default_groups(CharData * ch) { int i = 0; if (IsNPC(ch)) return; for (i = 0; i < ch->Class[CLASS_COUNT]; i++) if (class_table[ch->Class[i]].default_group != NULL) group_add(ch, class_table[ch->Class[i]].default_group, false); ch->pcdata->points += i > 0 ? 50 : 40; } void add_base_groups(CharData * ch) { int i = 0; if (IsNPC(ch)) return; for (i = 0; i < ch->Class[CLASS_COUNT]; i++) if (class_table[ch->Class[i]].base_group != NULL) group_add(ch, class_table[ch->Class[i]].base_group, false); } bool check_base_group(CharData * ch, int gn) { int i = 0; if (IsNPC(ch)) return false; if (gn < 0 || gn >= top_group) return false; for (i = 0; i < ch->Class[CLASS_COUNT]; i++) { if (class_table[ch->Class[i]].base_group == NULL) continue; if (group_lookup(class_table[ch->Class[i]].base_group) == gn) return true; } return false; } bool is_base_skill(CharData * ch, int sn) { int i = 0; int gn, x; if (IsNPC(ch)) return false; if (sn < 0 || sn >= top_skill) return false; for (i = 0; i < ch->Class[CLASS_COUNT]; i++) { if (class_table[ch->Class[i]].base_group == NULL) continue; if ((gn = group_lookup(class_table[ch->Class[i]].base_group)) != -1) { for (x = 0; x < MAX_IN_GROUP; x++) { if (group_table[gn].spells[x] == NULL) break; if (skill_lookup(group_table[gn].spells[x]) == sn) return true; } } } return false; } int get_thac00(CharData * ch) { int temp = 0, i = 0; if (IsNPC(ch)) return 0; for (i = 0; i < ch->Class[CLASS_COUNT]; i++) temp = Max(temp, class_table[ch->Class[i]].thac0_00); return temp; } int get_thac32(CharData * ch) { int temp = 999, i = 0; if (IsNPC(ch)) return 0; for (i = 0; i < ch->Class[CLASS_COUNT]; i++) temp = Min(temp, class_table[ch->Class[i]].thac0_32); return temp; } int class_mult(CharData * ch) { int temp = 999, i = 0; if (IsNPC(ch)) return 0; for (i = 0; i < ch->Class[CLASS_COUNT]; i++) temp = Min(temp, ch->race->class_mult[ch->Class[i]]); return temp; } int lvl_bonus(CharData * ch) { float adlev, inclev; int cntr; adlev = ch->Class[CLASS_COUNT]; inclev = .09; for (cntr = 1; cntr < ch->level; cntr++) { adlev += .9; adlev += inclev; inclev += .009; } return (int) (adlev + inclev); } bool is_race_skill(CharData * ch, int sn) { int i; if (sn < 0 || sn >= top_skill) return false; for (i = 0; i < MAX_RACE_SKILL; i++) { if (ch->race->skills[i] == NULL) continue; if (skill_lookup(ch->race->skills[i]) == sn) return true; if (group_lookup(ch->race->skills[i]) == sn) return true; } return false; } bool is_deity_skill(CharData * ch, int sn) { if (sn < 0 || sn >= top_skill) return false; if (ch->deity == NULL || IsNPC(ch)) return false; if (NullStr(ch->deity->skillname)) return false; if (skill_lookup(ch->deity->skillname) == sn) return true; if (group_lookup(ch->deity->skillname) == sn) return true; return false; } Do_Fun(do_prime) { int iClass, iSlot; if (NullStr(argument)) { cmd_syntax(ch, NULL, n_fun, "<class>", NULL); chprintln(ch, "It costs {R5{x trivia points to change your prime class."); } if ((iClass = class_lookup(argument)) == -1) { chprintln(ch, "No such class!"); return; } if ((iSlot = class_slot(ch, iClass)) == -1) { chprintlnf(ch, "You aren't part %s!", class_table[iClass].name); return; } if (iSlot == ch->pcdata->prime_class) { chprintlnf(ch, "Your prime class is already %s.", class_table[iClass].name); return; } if (ch->pcdata->trivia < 5) { chprintln(ch, "It costs {R5{x trivia points to change your prime class."); return; } ch->pcdata->prime_class = iSlot; ch->pcdata->trivia -= 5; chprintlnf(ch, "Your prime class is now %s, and are {R5{x trivia points lighter.", class_table[iClass].name); return; }