From 7ff19a3ceb6c51dc824fc0ae9bb7287897d2aa7b Mon Sep 17 00:00:00 2001 From: GickerLDS Date: Tue, 22 Oct 2024 16:54:41 +0000 Subject: [PATCH] -Added the roomvnum command, allowing players to get the room vnum for the room they're in. -Changed autoblast command to assistblast, and added the autoblast toggle so that warlocks don't have to use the blast command to commence using their eldritch blast in place of regular attacks. -Added more prominent display for characters who are flagged non-roleplayers, when seen in room. This is to alert role players in that room that this person is not a role player. -Added background archtypes. Each archtype gives a bonus to two skills, and a new ability. The archtypes are: Acolyte, Charlatan, Criminal/Spy, Entertainer, Folk Hero, Gladiator, Hermit, Noble, Outlander, Pirate, Sage, Sailor, Soldier, Squire, Trader and Urchin. -Characters can now choose their character's age from the following list: adolescent, adult, middle-aged, old-aged, venerable. Age is no longer tracked mechanically as a number, but rather as the listed descriptions instead, and does not change except through role-playing. Each age has certain ability score modifiers, except adult, which is +0 at all ability scores. -Added the postcombatbrief toggle, which will reduce the amount of post-combat text to cut down on text-spam. -Turn undead, when used on players, will now deal damage instead of causing them to flee or being insta-killed with large level differentials between player and mob. -Fixed a bug with paladin mercies that would sometimes crash the game. -Blackguards now get a series of class abilities that improve the save DCs on their cruetly uses. They also now get a mount they can summon with the 'call mount' command. -Made adjustments to the skill list. Some skills were combined, some new ones added, and some were renamed. -Adjusted the lore command to perform a d20 roll and also use different lore skills depending on what is being identified (Arcana, Religion or Nature). -Removed Ascii art on copyover. -Scythes are now slashing weapons only. Previously they were slashing and piercing. -Added character age to a character's short description. -Swapped out Great Int for Great Charisma for Sorcerer epic class feats. -Added a new game menu for setting optional character details. Among these are: short description, detailed description, background story, background archtype, character goals, character personality, character ideals, character bonds, character flaws, character age, homeland, hometown, faction, and deity. -New characters will now be prompted to flag themselves as non role players or role players, or defer the decision to later (which can be done in the prefedit menu). -Reduced exp gained by summoners for damage dealt by their eidolons in combat. -Fixed Anti-Neutral object flag to no longer exclude NG and NE alignments. -Added background descriptions to the help system. -kill command is now just an alias for the hit command. -Added the 'rpsheet' command which will display information pertinent to role playing for that character. Staff members can view the rpsheets of other players. -Fixed a bug with the holy aura command that caused crashes sometimes. -Fixed a bug with 'see the unseen' warlock spell that prevented it from working correctly. -Players casting healing spells on undead group members will no longer damage them. -Fixed some bugs with extra descs on some items causing crashes when their owners enter the game. -Fixed cooldown on the summoner 'merge forms' ability. -Coded in the mob ability 'corruption' -Smite Evil/Good/Destruction will all offer bonuses regardless of alignment, with greater bonuses if used against the listed alignment. --- act.comm.c | 7 + act.h | 5 +- act.informative.c | 32 +- act.item.c | 74 +- act.movement.c | 13 +- act.offensive.c | 77 +- act.other.c | 88 ++- act.wizard.c | 26 +- assign_wpn_armor.c | 2 +- backgrounds.c | 346 ++++++++- backgrounds.h | 7 +- char_descs.c | 10 +- class.c | 11 +- constants.c | 180 ++++- constants.h | 8 +- db.c | 2 + deities.c | 5 +- depend | 23 +- feats.c | 33 +- fight.c | 136 +++- handler.c | 2 +- help.c | 11 + interpreter.c | 640 +++++++++++++---- interpreter.h | 16 + limits.c | 31 +- magic.c | 91 ++- modify.c | 68 +- objsave.c | 27 +- players.c | 83 ++- prefedit.c | 35 +- premadebuilds.c | 10 + roleplay.c | 1672 ++++++++++++++++++++++++++++++++++++++++++++ roleplay.h | 43 ++ spec_procs.c | 19 +- spell_parser.c | 25 +- spells.h | 37 +- structs.h | 62 +- study.c | 61 +- transport.c | 25 +- util/plrtoascii.c | 2 +- utils.c | 146 +++- utils.h | 16 + 42 files changed, 3751 insertions(+), 456 deletions(-) create mode 100644 roleplay.c create mode 100644 roleplay.h diff --git a/act.comm.c b/act.comm.c index f05389c5..4d258581 100755 --- a/act.comm.c +++ b/act.comm.c @@ -881,6 +881,13 @@ ACMDU(do_gen_comm) case CON_QALIGN: case CON_QRACE_HELP: case CON_PLR_BG: + case CON_CHARACTER_GOALS_ENTER: + case CON_CHARACTER_GOALS_IDEAS: + case CON_CHARACTER_PERSONALITY_ENTER: + case CON_CHARACTER_PERSONALITY_IDEAS: + case CON_CHAR_RP_MENU: + case CON_BACKGROUND_ARCHTYPE: + case CON_BACKGROUND_ARCHTYPE_CONFIRM: continue; } diff --git a/act.h b/act.h index f0fb4699..878e65a8 100755 --- a/act.h +++ b/act.h @@ -268,6 +268,7 @@ ACMD_DECL(do_slayer); ACMD_DECL(do_true_judgement); ACMD_DECL(do_flightlist); ACMD_DECL(do_kapak_saliva); +ACMD_DECL(do_roomvnum); int max_judgements_active(struct char_data *ch); int num_judgements_active(struct char_data *ch); @@ -485,7 +486,7 @@ ACMD_DECL(do_fire); ACMD_DECL(do_aura_of_vengeance); ACMD_DECL(do_aura_of_justice); ACMD_DECL(do_reload); -ACMD_DECL(do_autoblast); +ACMD_DECL(do_assistblast); ACMD_DECL(do_autofire); ACMD_DECL(do_collect); ACMD_DECL(do_hitall); @@ -753,6 +754,8 @@ ACMD_DECL(do_buildwalk); #define SCMD_AUTOSTORE 59 #define SCMD_AUTOGROUP 60 #define SCMD_CONTAIN_AOES 61 +#define SCMD_POST_COMBAT_BRIEF 62 +#define SCMD_AUTO_BLAST 63 /* do_quit */ ACMD_DECL(do_quit); diff --git a/act.informative.c b/act.informative.c index 874b7ddf..fc936d02 100755 --- a/act.informative.c +++ b/act.informative.c @@ -831,6 +831,8 @@ static void list_one_char(struct char_data *i, struct char_data *ch) else send_to_char(ch, "\ty%s\r\n", i->player.long_descr); + if (PRF_FLAGGED(i, PRF_NON_ROLEPLAYER)) + act("...$e is a non-roleplayer.", FALSE, i, 0, ch, TO_VICT); if (AFF_FLAGGED(i, AFF_SANCTUARY)) act("...$e glows with a bright light!", FALSE, i, 0, ch, TO_VICT); if (affected_by_spell(i, SPELL_BANISHING_BLADE)) @@ -887,6 +889,8 @@ static void list_one_char(struct char_data *i, struct char_data *ch) send_to_char(ch, "%s", i->player.long_descr); + if (PRF_FLAGGED(i, PRF_NON_ROLEPLAYER)) + act("...$e is a non-roleplayer.", FALSE, i, 0, ch, TO_VICT); if (AFF_FLAGGED(i, AFF_SANCTUARY)) act("...$e glows with a bright light!", FALSE, i, 0, ch, TO_VICT); if (affected_by_spell(i, SPELL_BANISHING_BLADE)) @@ -1044,10 +1048,12 @@ static void list_one_char(struct char_data *i, struct char_data *ch) /* CARRIER RETURN! */ send_to_char(ch, "\r\n"); + if (PRF_FLAGGED(i, PRF_NON_ROLEPLAYER)) + act("...$e is a non-roleplayer.", FALSE, i, 0, ch, TO_VICT); if (AFF_FLAGGED(i, AFF_SANCTUARY)) act("...$e glows with a bright light!", FALSE, i, 0, ch, TO_VICT); - if (affected_by_spell(i, SPELL_BANISHING_BLADE)) - act("...a green blade of pure energy dances at $s side!", FALSE, i, 0, ch, TO_VICT); + if (affected_by_spell(i, SPELL_BANISHING_BLADE)) + act("...a green blade of pure energy dances at $s side!", FALSE, i, 0, ch, TO_VICT); if (affected_by_spell(i, SPELL_GREATER_BLACK_TENTACLES)) act("...$e is being curshed by huge, black tentacles sprouting from the ground!", FALSE, i, 0, ch, TO_VICT); else if (affected_by_spell(i, SPELL_BLACK_TENTACLES)) @@ -2083,6 +2089,8 @@ void perform_cooldowns(struct char_data *ch, struct char_data *k) send_to_char(ch, "Aura of Terror Immunity - Duration: %d seconds\r\n", ch->char_specials.terror_cooldown * 6); if (GET_FORAGE_COOLDOWN(k) > 0) send_to_char(ch, "Forage - Duration: %d seconds\r\n", GET_FORAGE_COOLDOWN(k) * 6); + if (GET_RETAINER_COOLDOWN(k) > 0) + send_to_char(ch, "Call Retainer - Duration: %d seconds\r\n", GET_RETAINER_COOLDOWN(k) * 6); list_item_activate_ability_cooldowns(ch); @@ -2197,6 +2205,8 @@ void perform_resistances(struct char_data *ch, struct char_data *k) } } } + if (dr->max_damage > 0) + send_to_char(ch, " %d damage left", dr->max_damage); send_to_char(ch, "\r\n"); dr = dr->next; } @@ -3351,8 +3361,8 @@ ACMD(do_score) snprintf(dname, sizeof(dname), "%s", deity_list[GET_DEITY(ch)].name); send_to_char(ch, "\tcDeity: \tn%-20s ", CAP(dname)); send_to_char(ch, "\tcAlignment : \tn%s (%d)\r\n", get_align_by_num(GET_ALIGNMENT(ch)), GET_ALIGNMENT(ch)); - send_to_char(ch, "\tcAge : \tn%-3d \tcyrs / \tn%2d \tcmths \tcPlayed : \tn%d days / %d hrs\r\n", - age(ch)->year, age(ch)->month, playing_time.day, playing_time.hours); + send_to_char(ch, "\tcAge : \tn%-10s \tcPlayed : \tn%d days / %d hrs\r\n", + character_ages[GET_CH_AGE(ch)], playing_time.day, playing_time.hours); send_to_char(ch, "\tcSize : \tn%-20s \tcLoad : \tn%d\tc/\tn%d \tclbs \tcNum Items: \tn%d\tc/\tn%d \tn\r\n", size_names[GET_SIZE(ch)], IS_CARRYING_W(ch), CAN_CARRY_W(ch), IS_CARRYING_N(ch), CAN_CARRY_N(ch)); @@ -4335,6 +4345,8 @@ ACMD(do_who) send_to_char(ch, " (THIEF)"); if (PLR_FLAGGED(tch, PLR_KILLER)) send_to_char(ch, " (KILLER)"); + if (PRF_FLAGGED(tch, PRF_NON_ROLEPLAYER)) + send_to_char(ch, " (NoRP)"); send_to_char(ch, "\r\n"); } } @@ -7363,6 +7375,18 @@ void list_item_activate_ability_cooldowns(struct char_data *ch) } } +ACMD(do_roomvnum) +{ + if (IN_ROOM(ch) == NOWHERE) + { + send_to_char(ch, "Error. Please tell staff ERRVNUMROOM001\r\n"); + return; + } + + send_to_char(ch, "This room's vnum is %d.\r\n", world[IN_ROOM(ch)].number); + return; +} + #undef WPT_SIMPLE #undef WPT_MARTIAL #undef WPT_EXOTIC diff --git a/act.item.c b/act.item.c index 7e058cd0..44cf7bc6 100755 --- a/act.item.c +++ b/act.item.c @@ -2101,12 +2101,16 @@ static void get_check_money(struct char_data *ch, struct obj_data *obj) extract_obj(obj); + ch->char_specials.post_combat_gold = value; increase_gold(ch, value); - if (value == 1) - send_to_char(ch, "There was 1 coin.\r\n"); - else - send_to_char(ch, "There were %d coins.\r\n", value); + if (!ch->char_specials.post_combat_messages) + { + if (value == 1) + send_to_char(ch, "There was 1 coin.\r\n"); + else + send_to_char(ch, "There were %d coins.\r\n", value); + } } static void perform_get_from_container(struct char_data *ch, struct obj_data *obj, @@ -2115,6 +2119,7 @@ static void perform_get_from_container(struct char_data *ch, struct obj_data *ob bool is_corpse = FALSE, is_clan = FALSE; int ct = 0; char buf[MAX_INPUT_LENGTH] = {'\0'}; + struct char_data *tch; if ((GET_OBJ_BOUND_ID(cont) != NOBODY) && (GET_OBJ_BOUND_ID(cont) != GET_IDNUM(ch))) { @@ -2163,8 +2168,15 @@ static void perform_get_from_container(struct char_data *ch, struct obj_data *ob } } - act("You get $p from $P.", FALSE, ch, obj, cont, TO_CHAR); - act("$n gets $p from $P.", TRUE, ch, obj, cont, TO_ROOM); + if (!ch->char_specials.post_combat_messages || GET_OBJ_TYPE(obj) != ITEM_MONEY) + act("You get $p from $P.", FALSE, ch, obj, cont, TO_CHAR); + for (tch = world[IN_ROOM(ch)].people; tch; tch = tch->next_in_room) + { + if (tch == ch) continue; + if (tch->char_specials.post_combat_messages && GET_OBJ_TYPE(obj) == ITEM_MONEY) continue; + snprintf(buf, sizeof(buf), "$n gets $p from %s.", cont->short_description); + act(buf, TRUE, ch, obj, tch, TO_VICT); + } get_check_money(ch, obj); if (cont->carried_by != ch) { @@ -2233,8 +2245,11 @@ void get_from_container(struct char_data *ch, struct obj_data *cont, if (!found) { if (obj_dotmode == FIND_ALL) - act("$p seems to be empty.", FALSE, ch, cont, 0, TO_CHAR); - else + { + if (!ch->char_specials.post_combat_messages) + act("$p seems to be empty.", FALSE, ch, cont, 0, TO_CHAR); + } + else if (!ch->char_specials.post_combat_messages) { char buf[MAX_STRING_LENGTH] = {'\0'}; @@ -2316,7 +2331,7 @@ static void get_from_room(struct char_data *ch, char *arg, int howmany) { if (dotmode == FIND_ALL) send_to_char(ch, "There doesn't seem to be anything here.\r\n"); - else + else if (!ch->char_specials.post_combat_messages) send_to_char(ch, "You don't see any %ss here.\r\n", arg); } } @@ -4465,6 +4480,7 @@ ACMD(do_sac) { char arg[MAX_INPUT_LENGTH] = {'\0'}; struct obj_data *j, *jj, *next_thing2; + struct char_data *tch; one_argument(argument, arg, sizeof(arg)); @@ -4498,36 +4514,57 @@ ACMD(do_sac) return; } - act("$n sacrifices $p.", FALSE, ch, j, 0, TO_ROOM); + if (IN_ROOM(ch) != NOWHERE) + { + for (tch = world[IN_ROOM(ch)].people; tch; tch = tch->next_in_room) + { + if (tch == ch) continue; + if (tch->char_specials.post_combat_messages) continue; + act("$n sacrifices $p.", FALSE, ch, j, tch, TO_VICT); + } + } switch (rand_number(0, 5)) { case 0: - send_to_char(ch, "You sacrifice %s to the gods.\r\nYou receive one gold coin for your humility.\r\n", GET_OBJ_SHORT(j)); + if (!ch->char_specials.post_combat_messages) + send_to_char(ch, "You sacrifice %s to the gods.\r\nYou receive one gold coin for your humility.\r\n", GET_OBJ_SHORT(j)); + ch->char_specials.post_combat_gold += 1; increase_gold(ch, 1); break; case 1: - send_to_char(ch, "You sacrifice %s to the gods.\r\nThe gods ignore your sacrifice.\r\n", GET_OBJ_SHORT(j)); + if (!ch->char_specials.post_combat_messages) + send_to_char(ch, "You sacrifice %s to the gods.\r\nThe gods ignore your sacrifice.\r\n", GET_OBJ_SHORT(j)); break; case 2: - send_to_char(ch, "You sacrifice %s to the gods.\r\nThe gods give you %d experience points.\r\n", GET_OBJ_SHORT(j), (GET_OBJ_COST(j))); + if (!ch->char_specials.post_combat_messages) + send_to_char(ch, "You sacrifice %s to the gods.\r\nThe gods give you %d experience points.\r\n", GET_OBJ_SHORT(j), (GET_OBJ_COST(j))); + ch->char_specials.post_combat_exp += GET_OBJ_COST(j); GET_EXP(ch) += (GET_OBJ_COST(j)); break; case 3: - send_to_char(ch, "You sacrifice %s to the gods.\r\nYou receive %d experience points.\r\n", GET_OBJ_SHORT(j), GET_OBJ_COST(j) / 2); + if (!ch->char_specials.post_combat_messages) + send_to_char(ch, "You sacrifice %s to the gods.\r\nYou receive %d experience points.\r\n", GET_OBJ_SHORT(j), GET_OBJ_COST(j) / 2); + ch->char_specials.post_combat_exp += GET_OBJ_COST(j) / 2; GET_EXP(ch) += GET_OBJ_COST(j) / 2; break; case 4: - send_to_char(ch, "Your sacrifice to the gods is rewarded with %d gold coins.\r\n", GET_OBJ_COST(j) / 4); + if (!ch->char_specials.post_combat_messages) + send_to_char(ch, "Your sacrifice to the gods is rewarded with %d gold coins.\r\n", GET_OBJ_COST(j) / 4); + ch->char_specials.post_combat_exp += GET_OBJ_COST(j) / 4; increase_gold(ch, GET_OBJ_COST(j) / 4); break; case 5: - send_to_char(ch, "Your sacrifice to the gods is rewarded with %d gold coins\r\n", (GET_OBJ_COST(j) / 2)); + if (!ch->char_specials.post_combat_messages) + send_to_char(ch, "Your sacrifice to the gods is rewarded with %d gold coins\r\n", (GET_OBJ_COST(j) / 2)); increase_gold(ch, (GET_OBJ_COST(j) / 2)); + ch->char_specials.post_combat_gold += GET_OBJ_COST(j) / 2; break; default: /* should not get here */ - send_to_char(ch, "You sacrifice %s to the gods.\r\nYou receive one gold coin for your humility.\r\n", GET_OBJ_SHORT(j)); + if (!ch->char_specials.post_combat_messages) + send_to_char(ch, "You sacrifice %s to the gods.\r\nYou receive one gold coin for your humility.\r\n", GET_OBJ_SHORT(j)); increase_gold(ch, 1); + ch->char_specials.post_combat_gold += 1; break; } for (jj = j->contains; jj; jj = next_thing2) @@ -5816,8 +5853,7 @@ ACMD(do_store) found = true; continue; } - STORED_POTIONS(ch, GET_OBJ_VAL(obj, i)) - ++; + STORED_POTIONS(ch, GET_OBJ_VAL(obj, i))++; send_to_char(ch, "You have stored a potion of '%s'.\r\n", spell_info[GET_OBJ_VAL(obj, i)].name); GET_OBJ_VAL(obj, i) = 0; } diff --git a/act.movement.c b/act.movement.c index 0f276b82..6c9ceaf4 100755 --- a/act.movement.c +++ b/act.movement.c @@ -2510,7 +2510,7 @@ static void do_doorcmd(struct char_data *ch, struct obj_data *obj, int door, int int ok_pick(struct char_data *ch, obj_vnum keynum, int pickproof, int scmd, int door) { - int skill_lvl; + int skill_lvl, roll; int lock_dc = 10; // struct obj_data *tools = NULL; @@ -2558,10 +2558,7 @@ int ok_pick(struct char_data *ch, obj_vnum keynum, int pickproof, int scmd, int return (0); } - if (FIGHTING(ch)) - skill_lvl += d20(ch); - else - skill_lvl += MAX(20, d20(ch)); // take 20 + roll = d20(ch); /* thief tools */ /* @@ -2589,14 +2586,15 @@ int ok_pick(struct char_data *ch, obj_vnum keynum, int pickproof, int scmd, int { send_to_char(ch, "It resists your attempts to pick it.\r\n"); } - else if (lock_dc <= skill_lvl) + else if (lock_dc <= (skill_lvl + roll)) { - send_to_char(ch, "Success! [%d dc vs. %d skill]\r\n", lock_dc, skill_lvl); + send_to_char(ch, "Success! [%d dc vs. %d skill + %d roll]\r\n", lock_dc, skill_lvl, roll); USE_MOVE_ACTION(ch); return (1); } /* failed */ + send_to_char(ch, "Failure! [%d dc vs. %d skill + %d roll]\r\n", lock_dc, skill_lvl, roll); USE_MOVE_ACTION(ch); return (0); } @@ -2694,6 +2692,7 @@ ACMD(do_gen_door) do_doorcmd(ch, obj, door, subcmd); ch->char_specials.autodoor_message = true; extract_key(ch, keynum); + return; } } return; diff --git a/act.offensive.c b/act.offensive.c index 87b992e8..d5efddb0 100755 --- a/act.offensive.c +++ b/act.offensive.c @@ -1257,7 +1257,7 @@ void apply_paladin_mercies(struct char_data *ch, struct char_data *vict) if (!ch || !vict) return; - struct affected_type *af = NULL; + struct affected_type *af = NULL, *af_next = NULL; struct affected_type af2; bool found = false; @@ -1292,8 +1292,9 @@ void apply_paladin_mercies(struct char_data *ch, struct char_data *vict) if (KNOWS_MERCY(ch, PALADIN_MERCY_ENFEEBLED)) { - for (af = vict->affected; af; af = af->next) + for (af = vict->affected; af; af = af_next) { + af_next = af->next; if ((af->location == APPLY_STR || af->location == APPLY_CON) && af->modifier < 0) { send_to_char(vict, "Affect '%s' has been healed!\r\n", spell_info[af->spell].name); @@ -1377,9 +1378,15 @@ void apply_paladin_mercies(struct char_data *ch, struct char_data *vict) // don't have their usefuless reduced by the ensorcelled mercy if (KNOWS_MERCY(ch, PALADIN_MERCY_ENSORCELLED)) { - for (af = vict->affected; af; af = af->next) + int spell_num = 0; + for (af = vict->affected; af; af = af_next) { - if (spell_info[af->spell].violent && dice(1, 2) == 1 && !found) + spell_num = af->spell; + if (spell_num < 0 || spell_num >= TOP_SKILL_DEFINE) continue; + af_next = af->next; + if (spell_info[af->spell].violent && + dice(1, 2) == 1 && + !found) { found = true; send_to_char(vict, "Affect '%s' has been healed!\r\n", spell_info[af->spell].name); @@ -2177,6 +2184,9 @@ int perform_turnundead(struct char_data *ch, struct char_data *vict, int turn_le else if (turn_difference >= 6) turn_result = 2; + if (turn_result >= 1 && !IS_NPC(vict)) + turn_result = 3; + /* messaging! */ act("You raise your divine symbol toward $N declaring, 'BEGONE!'", FALSE, ch, 0, vict, TO_CHAR); act("$n raises $s divine symbol towards you declaring, 'BEGONE!'", FALSE, ch, 0, vict, TO_VICT); @@ -2210,6 +2220,12 @@ int perform_turnundead(struct char_data *ch, struct char_data *vict, int turn_le act("The mighty force of $N's faith blasts $n out of existence!", FALSE, vict, 0, ch, TO_NOTVICT); dam_killed_vict(ch, vict); break; + case 3: + act("The mighty force of your faith blasts $N!", FALSE, ch, 0, vict, TO_CHAR); + act("The mighty force of $N's faith blasts you!", FALSE, vict, 0, ch, TO_CHAR); + act("The mighty force of $N's faith blasts $n!", FALSE, vict, 0, ch, TO_NOTVICT); + damage(ch, vict, dice(GET_LEVEL(ch) / 2, 6), SPELL_GREATER_RUIN, DAM_HOLY, FALSE); + break; } return 1; @@ -7763,7 +7779,7 @@ ACMD(do_fire) /* primarily useful for those with eldritch blast, * auto-assists players by auto-casting eldritch blast * when possible */ -ACMD(do_autoblast) +ACMD(do_assistblast) { char arg[MAX_INPUT_LENGTH] = {'\0'}; struct char_data *vict = NULL, *tch = NULL; @@ -7777,13 +7793,7 @@ ACMD(do_autoblast) if (IN_ROOM(ch) == NOWHERE) return; - if (BLASTING(ch)) - { - send_to_char(ch, "You stop utilizing eldritch blast.\r\n"); - BLASTING(ch) = FALSE; - return; - } - else if (FIGHTING(ch) && GET_ELDRITCH_SHAPE(ch) == WARLOCK_ELDRITCH_SPEAR) + if (FIGHTING(ch) && GET_ELDRITCH_SHAPE(ch) == WARLOCK_ELDRITCH_SPEAR) { send_to_char(ch, "You are too busy fighting!\r\n"); return; @@ -8987,22 +8997,46 @@ void apply_blackguard_cruelty(struct char_data *ch, struct char_data *vict, char } break; case BLACKGUARD_CRUELTY_PARALYZED: + if (AFF_FLAGGED(vict, AFF_FREE_MOVEMENT)) + { + act("$E cannot be paralyzed!", FALSE, ch, 0, vict, TO_CHAR); + return; + } + if (vict->char_specials.eldritch_blast_cooldowns[ELDRITCH_BLAST_COOLDOWN_BINDING_BLAST] > 0) + { + act("The target is on an immunity cooldown for paralysis already.", FALSE, ch, 0, vict, TO_CHAR); + return; + } to_vict = "You are -paralyzed- from the cruelty inflicted upon you by the corrupting touch!"; to_room = "$n is -paralyzed- from the cruelty inflicted upon $M by the corrupting touch!"; + break; + case BLACKGUARD_CRUELTY_DAZED: if (AFF_FLAGGED(vict, AFF_FREE_MOVEMENT)) { - act("$E cannot be paralyzed!", FALSE, ch, 0, vict, TO_CHAR); + act("$E cannot be dazed!", FALSE, ch, 0, vict, TO_CHAR); + return; + } + if (vict->char_specials.eldritch_blast_cooldowns[ELDRITCH_BLAST_COOLDOWN_NOXIOUS_BLAST] > 0) + { + act("The target is on an immunity cooldown for being dazed already.", FALSE, ch, 0, vict, TO_CHAR); return; } + to_vict = "You are -dazed- from the cruelty inflicted upon you by the corrupting touch!"; + to_room = "$n is -dazed- from the cruelty inflicted upon $M by the corrupting touch!"; break; case BLACKGUARD_CRUELTY_STUNNED: - to_vict = "You are -stunned- from the cruelty inflicted upon you by the corrupting touch!"; - to_room = "$n is -stunned- from the cruelty inflicted upon $M by the corrupting touch!"; if (!can_stun(vict)) { act("$E cannot be stunned!", FALSE, ch, 0, vict, TO_CHAR); return; } + if (vict->char_specials.eldritch_blast_cooldowns[ELDRITCH_BLAST_COOLDOWN_NOXIOUS_BLAST] > 0) + { + act("The target is on an immunity cooldown for being stunned already.", FALSE, ch, 0, vict, TO_CHAR); + return; + } + to_vict = "You are -stunned- from the cruelty inflicted upon you by the corrupting touch!"; + to_room = "$n is -stunned- from the cruelty inflicted upon $M by the corrupting touch!"; break; } @@ -9011,6 +9045,7 @@ void apply_blackguard_cruelty(struct char_data *ch, struct char_data *vict, char { case BLACKGUARD_CRUELTY_DAZED: case BLACKGUARD_CRUELTY_PARALYZED: + case BLACKGUARD_CRUELTY_STUNNED: duration = 1; break; case BLACKGUARD_CRUELTY_STAGGERED: @@ -9020,14 +9055,20 @@ void apply_blackguard_cruelty(struct char_data *ch, struct char_data *vict, char case BLACKGUARD_CRUELTY_NAUSEATED: duration = CLASS_LEVEL(ch, CLASS_BLACKGUARD) / 3; break; - case BLACKGUARD_CRUELTY_STUNNED: - duration = CLASS_LEVEL(ch, CLASS_BLACKGUARD) / 4; - break; default: duration = CLASS_LEVEL(ch, CLASS_BLACKGUARD); break; } + if (HAS_FEAT(ch, FEAT_IMPROVED_CRUELTIES)) + save_mod -= 2; + if (HAS_FEAT(ch, FEAT_ADVANCED_CRUELTIES)) + save_mod -= 2; + if (HAS_FEAT(ch, FEAT_MASTER_CRUELTIES)) + save_mod -= 2; + if (HAS_FEAT(ch, FEAT_EPIC_CRUELTIES)) + save_mod -= 2; + if (mag_savingthrow(ch, vict, SAVING_FORT, save_mod, CAST_CRUELTY, CLASS_LEVEL(ch, CLASS_BLACKGUARD), NOSCHOOL)) { return; diff --git a/act.other.c b/act.other.c index 5b069475..34c23bc8 100755 --- a/act.other.c +++ b/act.other.c @@ -1770,27 +1770,44 @@ void perform_call(struct char_data *ch, int call_type, int level) break; case MOB_C_MOUNT: - /* for now just one selection for paladins, soon to be changed */ - if (HAS_FEAT(ch, FEAT_EPIC_MOUNT)) + + if (CLASS_LEVEL(ch, CLASS_PALADIN) > 0) { - if (GET_SIZE(ch) < SIZE_MEDIUM) - GET_MOUNT(ch) = MOB_EPIC_PALADIN_MOUNT_SMALL; + /* for now just one selection for paladins, soon to be changed */ + if (HAS_FEAT(ch, FEAT_EPIC_MOUNT)) + { + if (GET_SIZE(ch) < SIZE_MEDIUM) + GET_MOUNT(ch) = MOB_EPIC_PALADIN_MOUNT_SMALL; + else + GET_MOUNT(ch) = MOB_EPIC_PALADIN_MOUNT; + } else - GET_MOUNT(ch) = MOB_EPIC_PALADIN_MOUNT; + { + if (GET_SIZE(ch) < SIZE_MEDIUM) + GET_MOUNT(ch) = MOB_PALADIN_MOUNT_SMALL; + else + GET_MOUNT(ch) = MOB_PALADIN_MOUNT; + } } - else + else if (CLASS_LEVEL(ch, CLASS_BLACKGUARD) > 0) { - if (GET_SIZE(ch) < SIZE_MEDIUM) - GET_MOUNT(ch) = MOB_PALADIN_MOUNT_SMALL; + if (HAS_FEAT(ch, FEAT_EPIC_MOUNT)) + { + GET_MOUNT(ch) = MOB_EPIC_BLACKGUARD_MOUNT; + } else - GET_MOUNT(ch) = MOB_PALADIN_MOUNT; + { + if (CLASS_LEVEL(ch, CLASS_BLACKGUARD) >= 12) + GET_MOUNT(ch) = MOB_ADV_BLACKGUARD_MOUNT; + else + GET_MOUNT(ch) = MOB_BLACKGUARD_MOUNT; + } } /* do they even have a valid selection yet? */ if (GET_MOUNT(ch) <= 0) { - send_to_char(ch, "You have to select your companion via the 'study' " - "command.\r\n"); + send_to_char(ch, "You have to select your companion via the 'study' command.\r\n"); return; } @@ -1891,6 +1908,8 @@ void perform_call(struct char_data *ch, int call_type, int level) case MOB_C_MOUNT: if (mob_num == MOB_EPIC_PALADIN_MOUNT || mob_num == MOB_EPIC_PALADIN_MOUNT_SMALL) GET_LEVEL(mob) = MIN(27, level); + else if (mob_num == MOB_EPIC_BLACKGUARD_MOUNT || mob_num == MOB_ADV_BLACKGUARD_MOUNT || mob_num == MOB_BLACKGUARD_MOUNT) + GET_LEVEL(mob) = MIN(27, level); else GET_LEVEL(mob) = MIN(20, level); autoroll_mob(mob, true, true); @@ -2038,6 +2057,9 @@ ACMD(do_call) { level = CLASS_LEVEL(ch, CLASS_PALADIN); + if (level == 0) + level = CLASS_LEVEL(ch, CLASS_BLACKGUARD); + if (!HAS_FEAT(ch, FEAT_CALL_MOUNT)) { send_to_char(ch, "You do not have a mount that you can call.\r\n"); @@ -2551,6 +2573,7 @@ void respec_engine(struct char_data *ch, int class, char *arg, bool silent) SUBRACE(ch) = 0; IS_MORPHED(ch) = 0; GET_DISGUISE_RACE(ch) = -1; // 0 is human + GET_BACKGROUND(ch) = 0; if (affected_by_spell(ch, SKILL_WILDSHAPE)) { @@ -4508,10 +4531,10 @@ int can_lore_target(struct char_data *ch, struct char_data *target_ch, struct ob if (target_obj) { skill = (compute_ability(ch, lore_skill) + lore_bonus); - dc = GET_OBJ_LEVEL(target_obj) * 2; + dc = (int) (GET_OBJ_LEVEL(target_obj) * 1.5); send_to_char(ch, "Using '%s' skill with d20 roll of %d + %d ranks, for total of %d against dc %d.\r\n", ability_names[lore_skill], roll, skill, skill + roll, dc); - if (skill >= dc) + if ((skill + roll) >= dc) knowledge = TRUE; if (!knowledge) @@ -4537,10 +4560,10 @@ int can_lore_target(struct char_data *ch, struct char_data *target_ch, struct ob } lore_skill = get_knowledge_skill_from_creature_type(GET_RACE(target_ch)); skill = (compute_ability(ch, lore_skill) + lore_bonus); - dc = GET_LEVEL(target_ch) * 2; + dc = (int) (GET_LEVEL(target_ch) * 1.5); send_to_char(ch, "Using '%s' skill with d20 roll of %d + %d ranks, for total of %d against dc %d.\r\n", ability_names[lore_skill], roll, skill, skill + roll, dc); - if (skill >= dc) + if ((skill + roll) >= dc) knowledge = TRUE; if (!knowledge) { @@ -6406,31 +6429,35 @@ ACMD(do_split) } decrease_gold(ch, share * (num - 1)); + ch->char_specials.post_combat_gold = share; /* Abusing signed/unsigned to make sizeof work. */ - len = snprintf(buf, sizeof(buf), "%s splits %d coins; you receive %d.\r\n", - GET_NAME(ch), amount, share); + len = snprintf(buf, sizeof(buf), "%s splits %d coins; you receive %d.\r\n", GET_NAME(ch), amount, share); if (rest && len < sizeof(buf)) { - snprintf(buf + len, sizeof(buf) - len, - "%d coin%s %s not splitable, so %s keeps the money.\r\n", rest, + snprintf(buf + len, sizeof(buf) - len, "%d coin%s %s not splitable, so %s keeps the money.\r\n", rest, (rest == 1) ? "" : "s", (rest == 1) ? "was" : "were", GET_NAME(ch)); } while ((k = (struct char_data *)simple_list(GROUP(ch)->members)) != NULL) + { if (k != ch && IN_ROOM(ch) == IN_ROOM(k) && !IS_NPC(k)) { increase_gold(k, share); - send_to_char(k, "%s", buf); + k->char_specials.post_combat_gold = share; + if (!k->char_specials.post_combat_messages) + send_to_char(k, "%s", buf); } - send_to_char(ch, "You split %d coins among %d members -- %d coins each.\r\n", - amount, num, share); + } + if (!ch->char_specials.post_combat_messages) + send_to_char(ch, "You split %d coins among %d members -- %d coins each.\r\n", amount, num, share); if (rest) { - send_to_char(ch, "%d coin%s %s not splitable, so you keep the money.\r\n", - rest, (rest == 1) ? "" : "s", (rest == 1) ? "was" : "were"); + if (!ch->char_specials.post_combat_messages) + send_to_char(ch, "%d coin%s %s not splitable, so you keep the money.\r\n", rest, (rest == 1) ? "" : "s", (rest == 1) ? "was" : "were"); increase_gold(ch, rest); + ch->char_specials.post_combat_gold += rest; } } else @@ -7205,6 +7232,12 @@ ACMD(do_gen_tog) // 61 {"Contain AoEs disabled.\r\n", "Contain AoEs enabled.\r\n"}, + // 62 + {"Post combat text (exp, gold, etc.) is no longer reduced.\r\n", + "Post combat text (exp, gold, etc.) is now reduced.\r\n"}, + // 63 + {"You will no longer automatically use eldritrch blast in place of normal attacks.\r\n" + "You will now automatically use eldritrch blast in place of normal attacks.\r\n"}, }; if (IS_NPC(ch)) @@ -7275,6 +7308,9 @@ ACMD(do_gen_tog) case SCMD_AUTOSORT: result = PRF_TOG_CHK(ch, PRF_AUTO_SORT); break; + case SCMD_POST_COMBAT_BRIEF: + result = PRF_TOG_CHK(ch, PRF_POST_COMBAT_BRIEF); + break; case SCMD_AUTOGROUP: result = PRF_TOG_CHK(ch, PRF_AUTO_GROUP); break; @@ -7284,6 +7320,10 @@ ACMD(do_gen_tog) case SCMD_AUTOSTORE: result = PRF_TOG_CHK(ch, PRF_AUTO_STORE); break; + case SCMD_AUTO_BLAST: + result = PRF_TOG_CHK(ch, PRF_AUTOBLAST); + BLASTING(ch) = PRF_FLAGGED(ch, PRF_AUTOBLAST); + break; case SCMD_NORAGE: result = PRF_TOG_CHK(ch, PRF_NO_RAGE); break; diff --git a/act.wizard.c b/act.wizard.c index 14aebbd7..dbdb739b 100755 --- a/act.wizard.c +++ b/act.wizard.c @@ -56,6 +56,7 @@ #include "perfmon.h" #include "missions.h" #include "deities.h" +#include "backgrounds.h" /* local utility functions with file scope */ static int perform_set(struct char_data *ch, struct char_data *vict, int mode, char *val_arg); @@ -3845,7 +3846,8 @@ const struct set_struct {"homeland", LVL_STAFF, PC, NUMBER}, /* 102 */ {"region", LVL_STAFF, PC, NUMBER}, /* 103 */ {"shortdesc", LVL_STAFF, PC, MISC}, /* 104 */ - {"necromancer", LVL_IMPL, PC, NUMBER}, /* 105 */ + {"necromancer", LVL_IMPL, PC, NUMBER}, /* 105 */ + {"background", LVL_STAFF, PC, MISC}, /* 106 */ {"\n", 0, BOTH, MISC}, }; @@ -4684,6 +4686,24 @@ static int perform_set(struct char_data *ch, struct char_data *vict, int mode, c affect_total(vict); break; + case 106: + for (i = 0; i < NUM_BACKGROUNDS; i++) + { + if (is_abbrev(val_arg, background_list[i].name)) + { + break; + } + } + + if (i >= NUM_BACKGROUNDS) + { + send_to_char(ch, "That is not a valid background archtype.\r\n"); + return 0; + } + + GET_BACKGROUND(vict) = i; + break; + default: send_to_char(ch, "Can't set that!\r\n"); @@ -5867,7 +5887,7 @@ void perform_do_copyover() { write_to_descriptor(d->descriptor, "\n\r *** Time stops for a moment as space and time folds upon itself! ***\n\r"); - +#if !defined(CAMPAIGN_DL) && !defined(CAMPAIGN_FR) switch (rand_number(1, 3)) { @@ -5939,7 +5959,7 @@ void perform_do_copyover() ); break; } - +#endif write_to_descriptor(d->descriptor, "[The game will pause for about 30 seconds while new code is being imported, \r\n" "you will need to reform if you were grouped. There is no need to disconnect, \r\n" diff --git a/assign_wpn_armor.c b/assign_wpn_armor.c index 3299b285..12d3ae16 100644 --- a/assign_wpn_armor.c +++ b/assign_wpn_armor.c @@ -1133,7 +1133,7 @@ void load_weapons(void) MATERIAL_STEEL, HANDLE_TYPE_SHAFT, HEAD_TYPE_POINT, "Similar in appearance to a trident, a ranseur has a single spear at its tip, f lanked by a pair of short, curving blades."); setweapon(WEAPON_TYPE_SCYTHE, "scythe", 2, 4, 0, 4, WEAPON_FLAG_MARTIAL, 18, - DAMAGE_TYPE_SLASHING | DAMAGE_TYPE_PIERCING, 10, 0, WEAPON_FAMILY_POLEARM, SIZE_LARGE, + DAMAGE_TYPE_SLASHING, 10, 0, WEAPON_FAMILY_POLEARM, SIZE_LARGE, MATERIAL_STEEL, HANDLE_TYPE_SHAFT, HEAD_TYPE_BLADE, "This weapon consists of a long wooden shaft with protruding handles and a sharp curved blade set at a right angle. Derived from a farm tool used to mow down crops, a scythe requires two hands to use, and is unwieldy but capable of inflicting grievous wounds. Its connotations as a symbol of death make it an intimidating weapon."); setweapon(WEAPON_TYPE_LONG_BOW, "long bow", 1, 8, 0, 3, WEAPON_FLAG_MARTIAL | WEAPON_FLAG_RANGED, 75, DAMAGE_TYPE_PIERCING, 3, 100, WEAPON_FAMILY_BOW, SIZE_MEDIUM, diff --git a/backgrounds.c b/backgrounds.c index 3d39b796..459eaa46 100644 --- a/backgrounds.c +++ b/backgrounds.c @@ -16,10 +16,34 @@ #include "handler.h" #include "fight.h" #include "spec_procs.h" +#include "clan.h" +#include "dg_scripts.h" +#include "feats.h" int background_sort_info[NUM_BACKGROUNDS]; struct background_data background_list[NUM_BACKGROUNDS]; +int backgrounds_listed_alphabetically[NUM_BACKGROUNDS] = +{ + BACKGROUND_NONE, + BACKGROUND_ACOLYTE, + BACKGROUND_CHARLATAN, + BACKGROUND_CRIMINAL, + BACKGROUND_ENTERTAINER, + BACKGROUND_FOLK_HERO, + BACKGROUND_GLADIATOR, + BACKGROUND_HERMIT, + BACKGROUND_NOBLE, + BACKGROUND_OUTLANDER, + BACKGROUND_PIRATE, + BACKGROUND_SAGE, + BACKGROUND_SAILOR, + BACKGROUND_SOLDIER, + BACKGROUND_SQUIRE, + BACKGROUND_TRADER, + BACKGROUND_URCHIN +}; + int compare_backgrounds(const void *x, const void *y) { int a = *(const int *)x, @@ -56,7 +80,7 @@ void initialize_background_list(void) /* initialize the list of feats */ for (i = 0; i < NUM_BACKGROUNDS; i++) { - background_list[i].name = "Unused Background"; + background_list[i].name = "none"; background_list[i].desc = "Unused Background"; background_list[i].skills[0] = 0; background_list[i].skills[1] = 0; @@ -72,23 +96,23 @@ void assign_backgrounds(void) "You have spent your life in the service of a temple to a specific god or pantheon of gods. " "You act as an intermediary between the realm of the holy and the mortal world, performing " "sacred rites and offering sacrifices in order to conduct worshipers into the presence of " - "the divine. You are not necessarily a cleric—performing sacred rites is not the same thing " + "the divine. You are not necessarily a cleric-performing sacred rites is not the same thing " "as channeling divine power."); backgroundo(BACKGROUND_CHARLATAN, "charlatan", ABILITY_SLEIGHT_OF_HAND, ABILITY_BLUFF, FEAT_BG_CHARLATAN, "You have always had a way with people. You know what makes them tick, you can tease out their " - "hearts’ desires after a few minutes of conversation, and with a few leading questions you can " - "read them like they were children’s books. It’s a useful talent, and one that you’re perfectly " + "hearts' desires after a few minutes of conversation, and with a few leading questions you can " + "read them like they were children's books. It's a useful talent, and one that you're perfectly " "willing to use for your advantage. You know what people want and you deliver, or rather, you " "promise to deliver. Common sense should steer people away from things that sound too good to " - "be true, but common sense seems to be in short supply when you’re around. The bottle of pink-colored " - "liquid will surely cure that unseemly rash, this ointment — nothing more than a bit of fat with a " - "sprinkle of silver dust — can restore youth and vigor, and there’s a bridge in the city that just " + "be true, but common sense seems to be in short supply when you're around. The bottle of pink-colored " + "liquid will surely cure that unseemly rash, this ointment - nothing more than a bit of fat with a " + "sprinkle of silver dust - can restore youth and vigor, and there's a bridge in the city that just " "happens to be for sale. These marvels sound implausible, but you make them sound like the real deal."); - backgroundo(BACKGROUND_CRIMINAL, "criminal", ABILITY_BLUFF, ABILITY_STEALTH, FEAT_BG_CRIMINAL, + backgroundo(BACKGROUND_CRIMINAL, "criminal/spy", ABILITY_BLUFF, ABILITY_STEALTH, FEAT_BG_CRIMINAL, "You are an experienced criminal with a history of breaking the law. You have spent a lot of time " - "among other criminals and still have contacts within the criminal underworld. You’re far closer " + "among other criminals and still have contacts within the criminal underworld. You're far closer " "than most people to the world of murder, theft, and violence that pervades the underbelly of " "civilization, and you have survived up to this point by flouting the rules and regulations of society."); @@ -109,20 +133,20 @@ void assign_backgrounds(void) "though you might also have some skills as a tumbler or actor."); backgroundo(BACKGROUND_TRADER, "trader", ABILITY_SENSE_MOTIVE, ABILITY_DIPLOMACY, FEAT_BG_TRADER, - "You are a member of an artisan’s guild, skilled in a particular field and closely associated " + "You are a member of an artisan's guild, skilled in a particular field and closely associated " "with other artisans. You are a well-established part of the mercantile world, freed by talent " "and wealth from the constraints of a feudal social order. You learned your skills as an apprentice " "to a master artisan, under the sponsorship of your guild, until you became a master in your own right."); backgroundo(BACKGROUND_HERMIT, "hermit", ABILITY_HEAL, ABILITY_RELIGION, FEAT_BG_HERMIT, - "You lived in seclusion—either in a sheltered community such as a monastery, or entirely alone-for " + "You lived in seclusion-either in a sheltered community such as a monastery, or entirely alone-for " "a formative part of your life. In your time apart from the clamor of society, you found quiet, " "solitude, and perhaps some of the answers you were looking for."); backgroundo(BACKGROUND_SQUIRE, "squire", ABILITY_HISTORY, ABILITY_DIPLOMACY, FEAT_BG_SQUIRE, "You trained at the feet of a knight, maintaining their gear and supporting them at " "tourneys and in battle. Now you search for a challenge that will prove you worthy of " - "full knighthood, or you’ve spurned pomp and ceremony to test yourself in honest, albeit " + "full knighthood, or you've spurned pomp and ceremony to test yourself in honest, albeit " "less formal, combat."); backgroundo(BACKGROUND_NOBLE, "noble", ABILITY_HISTORY, ABILITY_DIPLOMACY, FEAT_BG_NOBLE, @@ -134,11 +158,11 @@ void assign_backgrounds(void) "and work on your land, keenly aware of your responsibility to them."); backgroundo(BACKGROUND_OUTLANDER, "outlander", ABILITY_ATHLETICS, ABILITY_SURVIVAL, FEAT_BG_OUTLANDER, - "You grew up in the wilds, far from the comforts of town and technology. You’ve witnessed the " + "You grew up in the wilds, far from the comforts of town and technology. You've witnessed the " "migration of herds larger than forests, survived weather more extreme than any city-dweller " "could comprehend, and enjoyed the solitude of being the only thinking creature for miles in " "any direction. The wilds are in your blood, whether you were a nomad, an explorer, a recluse, " - "a hunter-gatherer, or even a marauder. Even in places where you don’t know the specific features " + "a hunter-gatherer, or even a marauder. Even in places where you don't know the specific features " "of the terrain, you know the ways of the wild."); backgroundo(BACKGROUND_PIRATE, "pirate", ABILITY_ATHLETICS, ABILITY_PERCEPTION, FEAT_BG_PIRATE, @@ -167,7 +191,7 @@ void assign_backgrounds(void) "provide for you, so you learned to provide for yourself. You fought fiercely over food and kept " "a constant watch out for other desperate souls who might steal from you. You slept on rooftops " "and in alleyways, exposed to the elements, and endured sickness without the advantage of medicine " - "or a place to recuperate. You’ve survived despite all odds, and did so through cunning, strength, " + "or a place to recuperate. You've survived despite all odds, and did so through cunning, strength, " "speed, or some combination of each."); } @@ -853,6 +877,11 @@ ACMD(do_relay) return; } } + else + { + send_to_char(ch, "Your contacts can't find anyone by that name.\r\n"); + return; + } if (IS_NPC(recipient)) { @@ -888,8 +917,11 @@ ACMD(do_relay) if (ch->player_specials->forge_as_signature) free(ch->player_specials->forge_as_signature); - act("A street urchin runs up and gives you a rolled piece of paper.", FALSE, 0, 0, ch, TO_VICT); - act("A street urchin runs up and gives $n a rolled piece of paper.", FALSE, ch, 0, 0, TO_ROOM); + act("You hand $p to a street urchin, who runs off to find your contact.", FALSE, 0, obj, ch, TO_CHAR); + act("$n hands $p to a street urchin, who runs off.", FALSE, ch, obj, 0, TO_ROOM); + + act("A street urchin runs up and gives you a rolled piece of paper.", FALSE, 0, 0, recipient, TO_VICT); + act("A street urchin runs up and gives $n a rolled piece of paper.", FALSE, recipient, 0, 0, TO_ROOM); } ACMD(do_forage) @@ -996,4 +1028,284 @@ ACMD(do_forage) act("You forage for food and find $p!", TRUE, ch, obj, 0, TO_CHAR); act("$n forages for food and finds $p!", TRUE, ch, obj, 0, TO_ROOM); +} + +#define RETAINER_SYNTAX ("Proper syntax is:\r\n" \ + "-- retainer call\r\n" \ + "-- retainer sell\r\n" \ + "-- retainer recipient (mail recipient name)\r\n" \ + "-- retainer mail (message to send)\r\n" \ + "See HELP RETAINER for more information") + +ACMD(do_retainer) +{ + struct obj_data *obj = NULL, *next_obj = NULL; + int y = 0, gold = 0; + struct char_data *recipient = NULL, *retainer = NULL; + char arg1[200], arg2[LONG_STRING]; + char buf[MAX_INPUT_LENGTH*4]; + + if (!HAS_FEAT(ch, FEAT_BG_SQUIRE)) + { + send_to_char(ch, "Only those with the squire background can call their retainer.\r\n"); + return; + } + + half_chop_c(argument, arg1, sizeof(arg1), arg2, sizeof(arg2)); + + if (!*arg1) + { + send_to_char(ch, "%s", RETAINER_SYNTAX); + return; + } + else if (is_abbrev(arg1, "call")) + { + if (is_retainer_in_room(ch)) + { + send_to_char(ch, "Your retainer is already here.\r\n"); + return; + } + + if (GET_RETAINER_COOLDOWN(ch) > 0) + { + send_to_char(ch, "You cannot call your retainer yet.\r\n"); + return; + } + + retainer = read_mobile(RETAINER_MOB_VNUM, VIRTUAL); + + if (!retainer) + { + send_to_char(ch, "The system could not find the retainer mob. Please inform staff with code ERRRET001.\r\n"); + return; + } + SET_BIT_AR(AFF_FLAGS(retainer), AFF_CHARM); + char_to_room(retainer, IN_ROOM(ch)); + act("You call forth $N.", TRUE, ch, 0, retainer, TO_CHAR); + act("$n calls forth $N.", TRUE, ch, 0, retainer, TO_ROOM); + add_follower(retainer, ch); + GET_RETAINER_COOLDOWN(ch) = 100; + return; + } + else if (is_abbrev(arg1, "sell")) + { + if ((retainer = get_retainer_from_room(ch)) == NULL) + { + send_to_char(ch, "You need to call your retainer in order to sell items.\r\n"); + return; + } + + if ((obj = retainer->carrying) == NULL) + { + send_to_char(ch, "Your retainer isn't carrying anything. Give any items you wish to sell to your retainer and then type: retainer sell\r\n"); + return; + } + + for (obj = retainer->carrying; obj; obj = next_obj) + { + next_obj = obj->next_content; + gold += (int) (GET_OBJ_COST(obj) * (0.15)); + obj_from_char(obj); + extract_obj(obj); + } + + send_to_char(ch, "Your retainer gives you a bank note worth %d coins, and then departs to sell the items you gave them.\r\n", gold); + act("$N gives $n a slip of paper and then hurries off.", TRUE, ch, 0, retainer, TO_ROOM); + GET_GOLD(ch) += gold; + extract_char(retainer); + return; + } + else if (is_abbrev(arg1, "recipient")) + { + if (!*arg2) + { + send_to_char(ch, "Please specify your mail recipient's name.\r\n"); + return; + } + + GET_RETAINER_MAIL_RECIPIENT(ch) = strdup(arg2); + send_to_char(ch, "You've set your retainer mail recipient to '%s'.\r\n", arg2); + return; + } + else if (is_abbrev(arg1, "mail")) + { + + if ((retainer = get_retainer_from_room(ch)) == NULL) + { + send_to_char(ch, "You need to call your retainer in order to send a message. Use 'retainer call' to do so.\r\n"); + return; + } + + if (!*arg2) + { + send_to_char(ch, "What would you like your mssage to say?\r\n"); + return; + } + + if (GET_RETAINER_MAIL_RECIPIENT(ch) == NULL) + { + send_to_char(ch, "You need to specify your mail recipient first by typing: retainer recipient (recipient name).\r\n"); + return; + } + + if (!(recipient = get_char_vis(ch, GET_RETAINER_MAIL_RECIPIENT(ch), NULL, FIND_CHAR_WORLD))) + { + send_to_char(ch, "Your contacts can't find anyone by the name of '%s'.\r\n", GET_RETAINER_MAIL_RECIPIENT(ch)); + return; + } + + if (IN_ROOM(recipient) != NOWHERE) + { + if (are_clans_allied(zone_table[world[IN_ROOM(recipient)].zone].faction, GET_CLAN(ch))) + { + send_to_char(ch, "Your retainer can only send to recipients in allied zones. This means you must be clanned and both you and your recipient are in a clan allied zone.\r\n"); + return; + } + } + else + { + send_to_char(ch, "Your contacts can't find anyone by the name of '%s'.\r\n", GET_RETAINER_MAIL_RECIPIENT(ch)); + return; + } + + if (IS_NPC(recipient)) + { + send_to_char(ch, "That is an NPC. Please specify a player name. Try using 2.name, 3.name, etc.\r\n"); + return; + } + + snprintf(buf, sizeof(buf), "%s\n\nSigned by: %s\n", strfrmt((char *) arg2, 80, 1, FALSE, FALSE, FALSE), GET_NAME(ch)); + + obj = create_obj(); + obj->item_number = 1; + if (ch->player_specials->forge_check > 0) + { + GET_OBJ_VAL(obj, 0) = ch->player_specials->forge_check; + } + obj->name = strdup("rolled piece paper"); + obj->short_description = strdup("a rolled piece of paper"); + obj->description = strdup("A rolled piece of paper lies here."); + + GET_OBJ_TYPE(obj) = ITEM_NOTE; + for (y = 0; y < TW_ARRAY_MAX; y++) + obj->obj_flags.wear_flags[y] = 0; + SET_BIT_AR(GET_OBJ_WEAR(obj), ITEM_WEAR_TAKE); + GET_OBJ_WEIGHT(obj) = 1; + GET_OBJ_COST(obj) = 30; + GET_OBJ_RENT(obj) = 10; + obj->action_description = strdup(buf); + + obj_to_char(obj, recipient); + + act("You hand $p to youor retainer, who runs off to find your contact.", FALSE, 0, obj, ch, TO_VICT); + act("$n hands $p to $s retainer, who runs off.", FALSE, ch, obj, 0, TO_ROOM); + + act("A hired retainer runs up and gives you a rolled piece of paper.", FALSE, 0, 0, recipient, TO_VICT); + act("A hired retainer runs up and gives $n a rolled piece of paper.", FALSE, recipient, 0, 0, TO_ROOM); + + GET_RETAINER_MAIL_RECIPIENT(ch) = NULL; + extract_char(retainer); + + return; + } + else + { + send_to_char(ch, "%s", RETAINER_SYNTAX); + return; + } + +} +ACMD(do_shortcut) +{ + char arg1[200]; + room_vnum rvnum = 0; + room_rnum target_room = NOWHERE; + struct char_data *vict; + + one_argument(argument, arg1, sizeof(arg1)); + + if (!*arg1) + { + send_to_char(ch, "You must specify a player, mob or room vnum. Rooms vnum can " + "be found by typing roomvnum, which will display the vnum for the room you're in.\r\n"); + return; + } + + if (GET_HOMETOWN(ch) == CITY_NONE) + { + send_to_char(ch, "You do not have a hometown set. This is required to use this ability.\r\n" + "You can do so by quitting to the main game menu and selecting the option there.\r\n"); + return; + } + + if (atoi(arg1) > 0) + { + target_room = real_room(rvnum); + } + else + { + if (!(vict = get_char_vis(ch, arg1, NULL, FIND_CHAR_WORLD))) + { + send_to_char(ch, "You can't find anyone by that description.\r\n"); + return; + } + target_room = IN_ROOM(vict); + } + + if (target_room == NOWHERE) + { + send_to_char(ch, "You can't find a path to that target.\r\n"); + return; + } + + if (zone_table[world[target_room].zone].city != GET_HOMETOWN(ch)) + { + send_to_char(ch, "You can't find a path to that target.\r\n"); + return; + } + + act("You find a shortcut to you destination.", TRUE, ch, 0, 0, TO_CHAR); + act("$n leaves the area suddenly.", TRUE, ch, 0, 0, TO_ROOM); + char_from_room(ch); + char_to_room(ch, target_room); + act("$n arrives suddenly.", TRUE, ch, 0, 0, TO_ROOM); + look_at_room(ch, 0); + entry_memory_mtrigger(ch); + greet_mtrigger(ch, -1); + greet_memory_mtrigger(ch); +} + +void show_background_help(struct char_data *ch, int background) +{ + + char buf[500]; + int i = 0; + + if (background <= BACKGROUND_NONE || background >= NUM_BACKGROUNDS) + { + send_to_char(ch, "Background type is invalid.\r\n"); + return; + } + + snprintf(buf, sizeof(buf), "%s BACKGROUND", background_list[background].name); + + for (i = 0; i < strlen(buf); i++) + { + buf[i] = toupper(buf[i]); + } + + draw_line(ch, 80, '-', '-'); + text_line(ch, buf, 80, '-', '-'); + draw_line(ch, 80, '-', '-'); + + snprintf(buf, sizeof(buf), "%s", background_list[background].desc); + send_to_char(ch, "%s", strfrmt(buf, 80, 1, 0, 0, 0)); + draw_line(ch, 80, '-', '-'); + send_to_char(ch, "Skill Bonuses: +2 to %s, +2 to %s.\r\n", + ability_names[background_list[background].skills[0]], ability_names[background_list[background].skills[1]]); + draw_line(ch, 80, '-', '-'); + snprintf(buf, sizeof(buf), "Special Ability: %s", feat_list[background_list[background].feat].description); + send_to_char(ch, "%s", strfrmt(buf, 80, 1, 0, 0, 0)); + draw_line(ch, 80, '-', '-'); + } \ No newline at end of file diff --git a/backgrounds.h b/backgrounds.h index 55e56c7c..64df22a2 100644 --- a/backgrounds.h +++ b/backgrounds.h @@ -20,10 +20,12 @@ #define NUM_BACKGROUNDS 17 #define FORAGE_FOOD_ITEM_VNUM 13820 +#define RETAINER_MOB_VNUM 13824 void assign_backgrounds(void); void sort_backgrounds(void); bool has_acolyte_in_group(struct char_data *ch); +void show_background_help(struct char_data *ch, int background); ACMD_DECL(do_swindle); ACMD_DECL(do_entertain); ACMD_DECL(do_forgeas); @@ -31,6 +33,8 @@ ACMD_DECL(do_relay); ACMD_DECL(do_tribute); ACMD_DECL(do_forage); ACMD_DECL(do_extort); +ACMD_DECL(do_retainer); +ACMD_DECL(do_shortcut); struct background_data { @@ -41,4 +45,5 @@ struct background_data }; extern int background_sort_info[NUM_BACKGROUNDS]; -extern struct background_data background_list[NUM_BACKGROUNDS]; \ No newline at end of file +extern struct background_data background_list[NUM_BACKGROUNDS]; +extern int backgrounds_listed_alphabetically[NUM_BACKGROUNDS]; \ No newline at end of file diff --git a/char_descs.c b/char_descs.c index f78cb451..aa3de3c5 100644 --- a/char_descs.c +++ b/char_descs.c @@ -283,7 +283,7 @@ char *current_short_desc(struct char_data *ch) } */ - snprintf(desc, sizeof(desc), "a %s %s", genders[(int)sex], race_list[(int)race].name); + snprintf(desc, sizeof(desc), "%s %s %s %s", AN(character_ages[GET_CH_AGE(ch)]), character_ages[GET_CH_AGE(ch)], genders[(int)sex], race_list[(int)race].name); snprintf(adj1, sizeof(adj1), "\tn"); snprintf(adj2, sizeof(adj2), "\tn"); @@ -823,14 +823,14 @@ void HandleStateGenericDescsParseMenuChoice(struct descriptor_data *d, char *arg GET_PC_ADJECTIVE_1(d->character) = 0; GET_PC_DESCRIPTOR_2(d->character) = 0; GET_PC_ADJECTIVE_2(d->character) = 0; - changeStateTo = CON_MENU; + changeStateTo = CON_CHAR_RP_MENU; SEND_TO_Q("\tcCharacter short description setting cancelled.\r\n\tn", d); - write_to_output(d, "%s", CONFIG_MENU); + show_character_rp_menu(d); break; case 1: - changeStateTo = CON_MENU; + changeStateTo = CON_CHAR_RP_MENU; SEND_TO_Q("\tcYour character descriptions are complete.\r\n\tn", d); - write_to_output(d, "%s", CONFIG_MENU); + show_character_rp_menu(d); break; case 2: diff --git a/class.c b/class.c index b09491ab..43b452ac 100755 --- a/class.c +++ b/class.c @@ -5702,7 +5702,7 @@ void load_class_list(void) feat_assignment(CLASS_SORCERER, FEAT_HELLBALL, Y, NOASSIGN_FEAT, N); feat_assignment(CLASS_SORCERER, FEAT_EPIC_MAGE_ARMOR, Y, NOASSIGN_FEAT, N); feat_assignment(CLASS_SORCERER, FEAT_EPIC_WARDING, Y, NOASSIGN_FEAT, N); - feat_assignment(CLASS_SORCERER, FEAT_GREAT_INTELLIGENCE, Y, NOASSIGN_FEAT, N); + feat_assignment(CLASS_SORCERER, FEAT_GREAT_CHARISMA, Y, NOASSIGN_FEAT, N); feat_assignment(CLASS_SORCERER, FEAT_AUTOMATIC_QUICKEN_SPELL, Y, NOASSIGN_FEAT, N); feat_assignment(CLASS_SORCERER, FEAT_AUTOMATIC_STILL_SPELL, Y, NOASSIGN_FEAT, N); feat_assignment(CLASS_SORCERER, FEAT_AUTOMATIC_SILENT_SPELL, Y, NOASSIGN_FEAT, N); @@ -5956,9 +5956,12 @@ void load_class_list(void) feat_assignment(CLASS_BLACKGUARD, FEAT_FIENDISH_BOON, Y, 5, N); + feat_assignment(CLASS_BLACKGUARD, FEAT_IMPROVED_CRUELTIES, Y, 6, N); + // cruelty slot - 6 feat_assignment(CLASS_BLACKGUARD, FEAT_SMITE_GOOD, Y, 7, Y); + feat_assignment(CLASS_BLACKGUARD, FEAT_CALL_MOUNT, Y, 7, N); feat_assignment(CLASS_BLACKGUARD, FEAT_AURA_OF_DESPAIR, Y, 8, N); @@ -5974,10 +5977,13 @@ void load_class_list(void) feat_assignment(CLASS_BLACKGUARD, FEAT_AURA_OF_SIN, Y, 14, Y); + feat_assignment(CLASS_BLACKGUARD, FEAT_ADVANCED_CRUELTIES, Y, 14, N); + // cruelty slot - 15 feat_assignment(CLASS_BLACKGUARD, FEAT_SMITE_GOOD, Y, 16, Y); + feat_assignment(CLASS_BLACKGUARD, FEAT_AURA_OF_DEPRAVITY, Y, 14, Y); // cruelty slot - 18 @@ -5992,6 +5998,8 @@ void load_class_list(void) feat_assignment(CLASS_BLACKGUARD, FEAT_SMITE_GOOD, Y, 22, Y); + feat_assignment(CLASS_BLACKGUARD, FEAT_MASTER_CRUELTIES, Y, 23, N); + // cruelty slot - 24 feat_assignment(CLASS_BLACKGUARD, FEAT_SMITE_GOOD, Y, 25, Y); @@ -6002,6 +6010,7 @@ void load_class_list(void) // cruelty slot - 30 feat_assignment(CLASS_BLACKGUARD, FEAT_UNHOLY_CHAMPION, Y, 30, Y); + feat_assignment(CLASS_BLACKGUARD, FEAT_EPIC_CRUELTIES, Y, 30, N); /* spell circles */ feat_assignment(CLASS_BLACKGUARD, FEAT_BLACKGUARD_1ST_CIRCLE, Y, 6, N); diff --git a/constants.c b/constants.c index e01832ac..a0e38b9e 100755 --- a/constants.c +++ b/constants.c @@ -24,6 +24,8 @@ #include "domains_schools.h" #include "handler.h" #include "deities.h" +#include "constants.h" +#include "roleplay.h" #define CHECK_TABLE_SIZE(tbl, exp_sz) \ _Static_assert(sizeof((tbl)) / sizeof((tbl)[0]) == (exp_sz), #tbl " wrong number entries") @@ -1492,7 +1494,7 @@ const char *action_bits[] = { "Ungrappleable", // 25 "Animal-Companion", "Familiar", - "Paladin-Mount", + "Paladin/Blackguard-Mount", "Summoned-Elemental", "Animated-Dead", // 30 "Guard", @@ -1559,6 +1561,7 @@ const char *action_bits[] = { "Mob-Block-Good", "Mob-Geniekind", "Mob-Dragon-Mount", + "Retainer", "\n" }; CHECK_TABLE_SIZE(action_bits, NUM_MOB_FLAGS + 1); @@ -1640,9 +1643,32 @@ const char *preference_bits[] = { "Auto-Store", "Auto-Group", "Contain-AOE", + "Non-Roleplayer", + "Brief-Post-Combat-Text", + "Auto-Eldritch-Blast", "\n"}; CHECK_TABLE_SIZE(preference_bits, NUM_PRF_FLAGS + 1); +const char *character_ages[] = { + "adult", + "adolescent", + "middle-aged", + "old-aged", + "venerable", + "\n" +}; +CHECK_TABLE_SIZE(character_ages, NUM_CHARACTER_AGES + 1); + +const int character_age_attributes[][6] = +{ +// St Dx Co In Ws Ch + { 0, 0, 0, 0, 0, 0}, + {-1, 2, 0, 0,-1, 0}, + {-1,-1,-1, 1, 1, 1}, + {-2,-2,-2, 2, 2, 2}, + {-3,-3,-3, 3, 3, 3} +}; + const char *bagnames[] = { "weapons", "armor", @@ -2015,6 +2041,25 @@ const char *connected_types[] = { "Select Descriptions Menu Parse", "Enter Background Story", "Set Recommended Preferences", + "Character RP Options Menu", + "Select Background Archtype", + "Confirm Background Archtype", + "Generate Goal Ideas", + "Enter in Character Goals", + "Generate Personality Ideas", + "Enter in Character Personality", + "Generate Ideals Ideas", + "Enter in Character Ideals", + "Generate Bond Ideas", + "Enter in Character Bonds", + "Generate Flaw Ideas", + "Enter in Character Flaws", + "Select Character Age", + "Select Character Faction", + "Select Character Hometown", + "Select Characeter Deity", + "Confirm Character Deity", + "Select Role-Play Status", "\n" /* make sure this matches NUM_CON_STATES */ }; CHECK_TABLE_SIZE(connected_types, NUM_CON_STATES + 1); @@ -2944,27 +2989,26 @@ int spell_bonus[][NUM_CIRCLES + 1] = { {0, 5, 5, 5, 4, 4, 4, 4, 3, 3, 0}, // 48 {0, 5, 5, 5, 4, 4, 4, 4, 3, 3, 0}, // 49 {0, 5, 5, 5, 5, 4, 4, 4, 4, 3, 0}, // 50 - {0, 5, 5, 5, 5, 4, 4, 4, 4, 3, 0}, // 51 - {0, 5, 5, 5, 5, 4, 4, 4, 4, 4, 0}, // 52 - {0, 5, 5, 5, 5, 4, 4, 4, 4, 4, 0}, // 53 - {0, 5, 5, 5, 5, 5, 4, 4, 4, 4, 0}, // 54 - {0, 5, 5, 5, 5, 5, 4, 4, 4, 4, 0}, // 55 - {0, 5, 5, 5, 5, 5, 5, 4, 4, 4, 0}, // 56 - {0, 5, 5, 5, 5, 5, 5, 4, 4, 4, 0}, // 57 - {0, 5, 5, 5, 5, 5, 5, 5, 4, 4, 0}, // 58 - {0, 5, 5, 5, 5, 5, 5, 5, 4, 4, 0}, // 59 - {0, 5, 5, 5, 5, 5, 5, 5, 5, 4, 0}, // 60 - {0, 5, 5, 5, 5, 5, 5, 5, 5, 4, 0}, // 61 - {0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0}, // 62 - {0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0}, // 63 - {0, 6, 5, 5, 5, 5, 5, 5, 5, 5, 0}, // 64 - {0, 6, 5, 5, 5, 5, 5, 5, 5, 5, 0}, // 65 - {0, 6, 6, 5, 5, 5, 5, 5, 5, 5, 0}, // 65 - {0, 6, 6, 5, 5, 5, 5, 5, 5, 5, 0}, // 66 - {0, 6, 6, 6, 5, 5, 5, 5, 5, 5, 0}, // 67 - {0, 6, 6, 6, 5, 5, 5, 5, 5, 5, 0}, // 68 - {0, 6, 6, 6, 6, 5, 5, 5, 5, 5, 0}, // 69 - {0, 6, 6, 6, 6, 5, 5, 5, 5, 5, 0}, // 70 + {0, 5, 5, 5, 5, 4, 4, 4, 4, 3, 0}, + {0, 5, 5, 5, 5, 4, 4, 4, 4, 3, 0}, + {0, 5, 5, 5, 5, 4, 4, 4, 4, 3, 0}, + {0, 5, 5, 5, 5, 4, 4, 4, 4, 3, 0}, + {0, 5, 5, 5, 5, 4, 4, 4, 4, 3, 0}, + {0, 5, 5, 5, 5, 4, 4, 4, 4, 3, 0}, + {0, 5, 5, 5, 5, 4, 4, 4, 4, 3, 0}, + {0, 5, 5, 5, 5, 4, 4, 4, 4, 3, 0}, + {0, 5, 5, 5, 5, 4, 4, 4, 4, 3, 0}, + {0, 5, 5, 5, 5, 4, 4, 4, 4, 3, 0}, + {0, 5, 5, 5, 5, 4, 4, 4, 4, 3, 0}, + {0, 5, 5, 5, 5, 4, 4, 4, 4, 3, 0}, + {0, 5, 5, 5, 5, 4, 4, 4, 4, 3, 0}, + {0, 5, 5, 5, 5, 4, 4, 4, 4, 3, 0}, + {0, 5, 5, 5, 5, 4, 4, 4, 4, 3, 0}, + {0, 5, 5, 5, 5, 4, 4, 4, 4, 3, 0}, + {0, 5, 5, 5, 5, 4, 4, 4, 4, 3, 0}, + {0, 5, 5, 5, 5, 4, 4, 4, 4, 3, 0}, + {0, 5, 5, 5, 5, 4, 4, 4, 4, 3, 0}, + {0, 5, 5, 5, 5, 4, 4, 4, 4, 3, 0}, }; /** Strength attribute affects. @@ -3952,17 +3996,9 @@ const char *ability_names[] = { "trapmaking", "poisonmaking", "metalworking", - /*knowledge*/ - "arcana", - "engineering", - "dungeoneering", - "geography", - "history", - "local", - "nature", - "nobility", - "religion", - "planes", + "fishing", + "cooking", + "brewing", "\n"}; #if defined(CAMPAIGN_DL) @@ -5742,6 +5778,84 @@ const char * dragon_bond_types[] = { "" }; +const char *character_rp_goal_objectives[] = +{ + "", + "Win the heart of a certain person", + "Discover the identity of an important person", + "Return to your homeland", + "Slay a powerful monster", + "Defend a group or settlement from an impending attack", + "Discover the location of a fabled natural feature", + "Destroy a powerful magical artifact", + "Obtain a powerful magical artifact", + "Find and recover a kidnapped or missing friend or family member", + "Claim an ancestral birthright or fortune", + "Defend or mentor an important young person", + "Prove the existence of a certain phenomenon or being that is thought to be fictional", + "Forge a peace or alliance between two groups", + "Conceal a secret by destroying evidence or a person", + "Interrupt a ritual or spell that would cause a grand negative effect", + "Detroy or neutralize a certain powerful person", + "Reconnect with an important person you used to be close to", + "Discover your own true identity as an important person", + "Learn important knowledge that has been concealed or locked away", + "Foil the plans of a specific deity", + "\n" +}; + +const char *character_rp_goal_reasons[] = +{ + "", + "A deep-seated desire to be loved", + "A pathological need to be appreciated or admired", + "A genuine sense of concern for others", + "A promise to a dying family member or friend", + "Spite, plain and simple", + "A hunger for power", + "A quest of self improvement", + "The search for spiritual enlightenment", + "Everyone else was doing it", + "It just seemed like fun", + "A prophecy you heard and believe will happen", + "A prophecy you have never heard and/or believe, but which fate keeps pulling you toward", + "The pay was too good to turn down", + "Revenge", + "Prove yourself worthy of a love interest who does not return your feelings", + "Restore your family's good name", + "Get the attention of a potential patron", + "An inexplicable compulsion that's probably related to childhood somehow", + "Gain experience in a skill for a particular task", + "A deity told you to", + "\n" +}; + +const char *character_rp_goal_complications[] = +{ + "", + "It's all a big misunderstanding", + "A rival is interested in the same thing", + "Doing so would anger a local politician", + "It's really, really far away", + "Someone else has done it already, but they did it wrong", + "You're unknowingly missing a key piece of information", + "A location involved is very dangerous for you", + "You have sworn a vow that will make it much harder to do", + "There is a religious prohibition against doing it", + "An injury or health issue prevents you from doing so", + "A person integral to completing your goal is hostile to you", + "A persistant misconception means you are mistaken", + "Two other groups are involved in the same goal", + "The trail has gone cold", + "A classic switcheroo has confused similar people or items", + "Two factions or people who do not get along must cooperate to make this happen", + "An important person or object is accidentally destroyed before much progress has been made", + "Doing so would break an important treaty", + "It has literally never been done before", + "An involved deity's followers are powerful obstacles", + "\n" +}; + /* --- End of constants arrays. --- */ /* Various arrays we count so we can check the world files. These diff --git a/constants.h b/constants.h index d3772cef..78bc6bf6 100755 --- a/constants.h +++ b/constants.h @@ -23,6 +23,8 @@ extern const char *shape_to_room[MAX_PC_SUBRACES + 1]; extern const char *shape_to_char[MAX_PC_SUBRACES + 1]; extern const char *npc_race_menu; extern const char *bagnames[]; +extern const char *character_ages[]; +extern const int character_age_attributes[][6]; extern const char * dragon_bond_types[]; extern const int dragon_type_specab_types[]; extern const char *npc_subrace_types[NUM_SUB_RACES + 1]; @@ -101,7 +103,7 @@ extern const char *weekdays[]; extern const char *month_name[]; extern const char *spell_schools[]; extern const char *spell_schools_lower[]; -extern int spell_bonus[STAT_CAP + 1][NUM_CIRCLES + 1]; +extern int spell_bonus[][NUM_CIRCLES + 1]; extern const struct str_app_type str_app[]; extern const struct dex_skill_type dex_app_skill[]; extern const struct dex_app_type dex_app[]; @@ -188,6 +190,10 @@ extern const char *factions[]; extern const char *apply_type_food_names[]; extern const int apply_type_food_or_drink[]; +extern const char *character_rp_goal_objectives[]; +extern const char *character_rp_goal_reasons[]; +extern const char *character_rp_goal_complications[]; + /* NewCraft */ extern const char *craft_flags[]; extern const char *requirement_flags[]; diff --git a/db.c b/db.c index 8d99495e..c3af815e 100755 --- a/db.c +++ b/db.c @@ -5225,6 +5225,8 @@ void free_char(struct char_data *ch) free(ch->player_specials->saved.autocquest_desc); if (ch->player.background) free(ch->player.background); + if (ch->player.goals) + free(ch->player.goals); if (GET_HOST(ch)) free(GET_HOST(ch)); if (IS_NPC(ch)) diff --git a/deities.c b/deities.c index 77fd487f..ac14424f 100644 --- a/deities.c +++ b/deities.c @@ -1571,9 +1571,8 @@ void assign_deities(void) { #elif defined(CAMPAIGN_DL) add_deity(DEITY_NONE, "None", ETHOS_NEUTRAL, ALIGNMENT_NEUTRAL, DOMAIN_UNDEFINED, DOMAIN_UNDEFINED, DOMAIN_UNDEFINED, DOMAIN_UNDEFINED, DOMAIN_UNDEFINED, DOMAIN_UNDEFINED, WEAPON_TYPE_UNARMED, DEITY_PANTHEON_ALL, "The Faithless", - "Those who choose to worship no deity at all are known as the faithless. It is their\r\n" - "destiny to become part of the living wall in Kelemvor's domain when they die, to\r\n" - "ultimately have their very soul devoured and destroyed forever.\r\n"); + "Those who choose to worship no deity at all are known as the faithless. " + "Their souls belong to Chemosh, Lord of Death, when they die.\r\n"); add_deity(DEITY_PALADINE, "Paladine", ETHOS_LAWFUL, ALIGNMENT_GOOD, DOMAIN_UNDEFINED, DOMAIN_UNDEFINED, DOMAIN_UNDEFINED, DOMAIN_UNDEFINED, DOMAIN_UNDEFINED, DOMAIN_UNDEFINED, WEAPON_TYPE_LONG_SWORD, DEITY_PANTHEON_ALL, "Good Dragons, Guardians, Rulers", diff --git a/depend b/depend index 30f42d20..77da1051 100644 --- a/depend +++ b/depend @@ -30,7 +30,7 @@ act.item.o: act.item.c conf.h sysdep.h structs.h bool.h protocol.h \ act.h quest.h spec_procs.h clan.h mud_event.h dg_event.h hlquest.h \ fight.h mudlim.h actions.h traps.h assign_wpn_armor.h spec_abilities.h \ item.h feats.h alchemy.h mysql.h treasure.h crafts.h hunts.h class.h \ - spell_prep.h genobj.h + spell_prep.h genobj.h backgrounds.h act.movement.o: act.movement.c conf.h sysdep.h structs.h bool.h \ protocol.h lists.h campaign.h utils.h db.h helpers.h perfmon.h comm.h \ interpreter.h handler.h spells.h house.h constants.h dg_scripts.h act.h \ @@ -61,7 +61,7 @@ act.wizard.o: act.wizard.c conf.h sysdep.h structs.h bool.h protocol.h \ race.h fight.h modify.h quest.h ban.h mud_event.h dg_event.h clan.h \ craft.h hlquest.h mudlim.h spec_abilities.h wilderness.h feats.h \ assign_wpn_armor.h item.h domains_schools.h crafts.h account.h alchemy.h \ - premadebuilds.h missions.h deities.h kdtree.h + premadebuilds.h missions.h deities.h backgrounds.h kdtree.h aedit.o: aedit.c conf.h sysdep.h structs.h bool.h protocol.h lists.h \ campaign.h utils.h db.h helpers.h perfmon.h interpreter.h handler.h \ comm.h oasis.h help.h screen.h constants.h genolc.h act.h @@ -81,7 +81,8 @@ assign_wpn_armor.o: assign_wpn_armor.c conf.h sysdep.h structs.h bool.h \ handler.h spells.h backgrounds.o: backgrounds.c conf.h sysdep.h structs.h bool.h protocol.h \ lists.h campaign.h utils.h db.h helpers.h perfmon.h comm.h spells.h \ - handler.h interpreter.h constants.h backgrounds.h treasure.h fight.h + handler.h interpreter.h constants.h backgrounds.h treasure.h fight.h \ + spec_procs.h clan.h dg_scripts.h feats.h ban.o: ban.c conf.h sysdep.h structs.h bool.h protocol.h lists.h \ campaign.h utils.h db.h helpers.h perfmon.h comm.h interpreter.h \ handler.h ban.h @@ -110,7 +111,8 @@ class.o: class.c conf.h sysdep.h structs.h bool.h protocol.h lists.h \ campaign.h utils.h db.h helpers.h perfmon.h spells.h interpreter.h \ constants.h act.h handler.h comm.h mud_event.h dg_event.h mudlim.h \ feats.h class.h assign_wpn_armor.h pfdefaults.h domains_schools.h \ - modify.h spell_prep.h race.h alchemy.h premadebuilds.h evolutions.h + modify.h spell_prep.h race.h alchemy.h premadebuilds.h evolutions.h \ + backgrounds.h combat_modes.o: combat_modes.c conf.h sysdep.h structs.h bool.h \ protocol.h lists.h campaign.h utils.h db.h helpers.h perfmon.h feats.h \ comm.h interpreter.h handler.h spells.h class.h mud_event.h dg_event.h \ @@ -127,7 +129,8 @@ config.o: config.c conf.h sysdep.h structs.h bool.h protocol.h lists.h \ asciimap.h constants.o: constants.c conf.h sysdep.h structs.h bool.h protocol.h \ lists.h campaign.h utils.h db.h helpers.h perfmon.h interpreter.h \ - spells.h craft.h feats.h domains_schools.h handler.h deities.h + spells.h craft.h feats.h domains_schools.h handler.h deities.h \ + constants.h craft.o: craft.c conf.h sysdep.h structs.h bool.h protocol.h lists.h \ campaign.h mysql.h utils.h db.h helpers.h perfmon.h comm.h spells.h \ interpreter.h constants.h handler.h craft.h mud_event.h dg_event.h \ @@ -224,7 +227,7 @@ fight.o: fight.c conf.h sysdep.h structs.h bool.h protocol.h lists.h \ fight.h shop.h quest.h mud_event.h dg_event.h spec_procs.h clan.h \ treasure.h mudlim.h spec_abilities.h feats.h actions.h actionqueues.h \ craft.h assign_wpn_armor.h grapple.h alchemy.h missions.h hunts.h \ - domains_schools.h staff_events.h evolutions.h + domains_schools.h staff_events.h evolutions.h backgrounds.h gain.o: gain.c conf.h sysdep.h structs.h bool.h protocol.h lists.h \ campaign.h utils.h db.h helpers.h perfmon.h comm.h oasis.h help.h \ screen.h interpreter.h modify.h spells.h @@ -274,7 +277,7 @@ hedit.o: hedit.c conf.h sysdep.h structs.h bool.h protocol.h lists.h \ help.o: help.c conf.h sysdep.h structs.h bool.h protocol.h lists.h \ campaign.h utils.h db.h helpers.h perfmon.h modify.h comm.h \ interpreter.h mysql.h help.h feats.h spells.h class.h race.h alchemy.h \ - constants.h deities.h act.h evolutions.h + constants.h deities.h act.h evolutions.h backgrounds.h helpers.o: helpers.c helpers.h hlqedit.o: hlqedit.c conf.h sysdep.h structs.h bool.h protocol.h lists.h \ campaign.h comm.h utils.h db.h helpers.h perfmon.h boards.h handler.h \ @@ -312,7 +315,7 @@ interpreter.o: interpreter.c conf.h sysdep.h structs.h bool.h protocol.h \ domains_schools.h grapple.h assign_wpn_armor.h bardic_performance.h \ spell_prep.h crafts.h new_mail.h alchemy.h staff_events.h \ premadebuilds.h missions.h transport.h hunts.h fight.h char_descs.h \ - evolutions.h deities.h mudlim.h backgrounds.h + evolutions.h deities.h mudlim.h backgrounds.h roleplay.h kdtree.o: kdtree.c kdtree.h limits.o: limits.c conf.h sysdep.h structs.h bool.h protocol.h lists.h \ campaign.h utils.h db.h helpers.h perfmon.h spells.h comm.h handler.h \ @@ -443,6 +446,10 @@ redit.o: redit.c conf.h sysdep.h structs.h bool.h protocol.h lists.h \ campaign.h utils.h db.h helpers.h perfmon.h comm.h interpreter.h \ boards.h genolc.h genwld.h genzon.h oasis.h help.h improved-edit.h \ dg_olc.h dg_scripts.h constants.h modify.h wilderness.h trails.h +roleplay.o: roleplay.c conf.h sysdep.h structs.h bool.h protocol.h \ + lists.h campaign.h utils.h db.h helpers.h perfmon.h comm.h spells.h \ + handler.h interpreter.h constants.h backgrounds.h treasure.h fight.h \ + spec_procs.h clan.h dg_scripts.h feats.h improved-edit.h sedit.o: sedit.c conf.h sysdep.h structs.h bool.h protocol.h lists.h \ campaign.h utils.h db.h helpers.h perfmon.h comm.h interpreter.h shop.h \ genolc.h genshp.h genzon.h oasis.h help.h constants.h diff --git a/feats.c b/feats.c index e099532c..99c75fc5 100644 --- a/feats.c +++ b/feats.c @@ -5255,6 +5255,19 @@ feato(FEAT_MOON_ELF_RACIAL_ADJUSTMENT, "moon elf racial adjustment", TRUE, FALSE feat_prereq_ability(FEAT_AUTOMATIC_STILL_SPELL, ABILITY_SPELLCRAFT, 24); feat_prereq_feat(FEAT_AUTOMATIC_STILL_SPELL, FEAT_STILL_SPELL, 1); + feato(FEAT_IMPROVED_CRUELTIES, "improved cruelties", TRUE, FALSE, FALSE, FEAT_TYPE_CLASS_ABILITY, + "Improves saving throw DCs against blackguard cruelties by 2.", + "Improves saving throw DCs against blackguard cruelties by 2. Stacks with other save dc increases."); + feato(FEAT_ADVANCED_CRUELTIES, "advanced cruelties", TRUE, FALSE, FALSE, FEAT_TYPE_CLASS_ABILITY, + "Improves saving throw DCs against blackguard cruelties by 2.", + "Improves saving throw DCs against blackguard cruelties by 2. Stacks with other save dc increases."); + feato(FEAT_MASTER_CRUELTIES, "master cruelties", TRUE, FALSE, FALSE, FEAT_TYPE_CLASS_ABILITY, + "Improves saving throw DCs against blackguard cruelties by 2.", + "Improves saving throw DCs against blackguard cruelties by 2. Stacks with other save dc increases."); + feato(FEAT_EPIC_CRUELTIES, "epic cruelties", TRUE, FALSE, FALSE, FEAT_TYPE_CLASS_ABILITY, + "Improves saving throw DCs against blackguard cruelties by 2.", + "Improves saving throw DCs against blackguard cruelties by 2. Stacks with other save dc increases."); + // Backgrounds feato(FEAT_BG_ACOLYTE, "acolyte background", TRUE, FALSE, FALSE, FEAT_TYPE_BACKGROUND, @@ -5271,9 +5284,9 @@ feato(FEAT_MOON_ELF_RACIAL_ADJUSTMENT, "moon elf racial adjustment", TRUE, FALSE "Gain access to the 'entertain' command, allowing them to perform for gold and potentially a random item, as well as a buff to a few skills."); feato(FEAT_BG_FOLK_HERO, "folk hero background", TRUE, FALSE, FALSE, FEAT_TYPE_BACKGROUND, "Gain access to the 'tribute' command, allowing for a small reward of coins and potentially a random item, only usable in the" - "folk-hero's home town. Also gain +10%% when buying or selling in their home town.", + "folk-hero's home town. Also gain +10% when buying or selling in their home town.", "Gain access to the 'tribute' command, allowing for a small reward of coins and potentially a random item, only usable in the" - "folk-hero's home town. Also gain +10%% when buying or selling in their home town."); + "folk-hero's home town. Also gain +10% when buying or selling in their home town."); feato(FEAT_BG_GLADIATOR, "gladiator background", TRUE, FALSE, FALSE, FEAT_TYPE_BACKGROUND, "Gains +1 to attack and damage rolls when fighting in an allied area (must be clanned)", "Gains +1 to attack and damage rolls when fighting in an allied area (must be clanned)"); @@ -5281,8 +5294,8 @@ feato(FEAT_MOON_ELF_RACIAL_ADJUSTMENT, "moon elf racial adjustment", TRUE, FALSE "Gains +1 to all crafting skills.", "Gains +1 to all crafting skills."); feato(FEAT_BG_HERMIT, "hermit background", TRUE, FALSE, FALSE, FEAT_TYPE_BACKGROUND, - "+1 to damage and +5%% experience when fighting alone.", - "+1 to damage and +5%% experience when fighting alone."); + "+1 to damage and +5% experience when fighting alone.", + "+1 to damage and +5% experience when fighting alone."); feato(FEAT_BG_NOBLE, "noble background", TRUE, FALSE, FALSE, FEAT_TYPE_BACKGROUND, "Gains/Saves +10% gold from selling or buying items in their home town and has access to Noble-only shops.", "Gains/Saves +10% gold from selling or buying items in their home town and has access to Noble-only shops."); @@ -5292,6 +5305,18 @@ feato(FEAT_MOON_ELF_RACIAL_ADJUSTMENT, "moon elf racial adjustment", TRUE, FALSE feato(FEAT_BG_PIRATE, "pirate background", TRUE, FALSE, FALSE, FEAT_TYPE_BACKGROUND, "Can use the 'extort' command to intimdate people out of money and sometimes items.", "Can use the 'extort' command to intimdate people out of money and sometimes items."); + feato(FEAT_BG_SAGE, "sage background", TRUE, FALSE, FALSE, FEAT_TYPE_BACKGROUND, + "When successfully using lore command on a mob, the sage's party receives a +1 to hit and damage against that mob. Also gains a +2 bonus to lore checks on items.", + "When successfully using lore command on a mob, the sage's party receives a +1 to hit and damage against that mob. Also gains a +2 bonus to lore checks on items."); + feato(FEAT_BG_SAILOR, "sailor background", TRUE, FALSE, FALSE, FEAT_TYPE_BACKGROUND, + "Sailing is free and takes 1/2 as much time. Gain +1 to hit, damage and armor class when in water. +5 to fishing skill.", + "Sailing is free and takes 1/2 as much time. Gain +1 to hit, damage and armor class when in water. +5 to fishing skill."); + feato(FEAT_BG_SOLDIER, "soldier background", TRUE, FALSE, FALSE, FEAT_TYPE_BACKGROUND, + "Gains +1 to hitroll and armor class when grouped with another soldier.", + "Gains +1 to hitroll and armor class when grouped with another soldier."); + feato(FEAT_BG_SQUIRE, "squire background", TRUE, FALSE, FALSE, FEAT_TYPE_BACKGROUND, + "Gains access to a hired retainer that can sell items or deliver a message, using the 'retainer' command.", + "Gains access to a hired retainer that can sell items or deliver a message, using the 'retainer' command."); /* self explanatory */ feato(FEAT_LAST_FEAT, "do not take me", FALSE, FALSE, FALSE, FEAT_TYPE_NONE, "placeholder feat", "placeholder feat"); diff --git a/fight.c b/fight.c index 7d7e2b9d..e68a6a6e 100755 --- a/fight.c +++ b/fight.c @@ -1122,6 +1122,19 @@ int compute_armor_class(struct char_data *attacker, struct char_data *ch, if (!IS_NPC(ch) && HAS_DRAGON_BOND_ABIL(ch, 3, DRAGON_BOND_KIN)) bonuses[BONUS_TYPE_MORALE] += 2; + if (HAS_FEAT(ch, FEAT_BG_SAILOR) && IN_WATER(ch)) + { + bonuses[BONUS_TYPE_MORALE] += 1; + } + + if (HAS_FEAT(ch, FEAT_BG_URCHIN) && is_in_hometown(ch)) + { + bonuses[BONUS_TYPE_COMPETENCE] += 1; + } + + if (is_grouped_with_soldier(ch)) + bonuses[BONUS_TYPE_MORALE] += 1; + /* These bonuses to AC apply even against touch attacks or when the monk is * flat-footed. She loses these bonuses when she is immobilized or helpless, * when she wears any armor, when she carries a shield, or when she carries @@ -1853,16 +1866,14 @@ void death_cry(struct char_data *ch) /* this is the default NPC message */ GUI_CMBT_NOTVICT_OPEN(ch, NULL); - act("Your blood freezes as you hear $n's death cry.", - FALSE, ch, 0, 0, TO_ROOM); + act("Your blood freezes as you hear $n's death cry.", FALSE, ch, 0, 0, TO_ROOM); GUI_CMBT_NOTVICT_CLOSE(ch, NULL); for (door = 0; door < DIR_COUNT; door++) { if (CAN_GO(ch, door)) { - send_to_room(world[IN_ROOM(ch)].dir_option[door]->to_room, - "Your blood freezes as you hear someone's death cry.\r\n"); + send_to_room(world[IN_ROOM(ch)].dir_option[door]->to_room, "Your blood freezes as you hear someone's death cry.\r\n"); } } break; @@ -1871,16 +1882,14 @@ void death_cry(struct char_data *ch) else /* this is the default PC message */ { GUI_CMBT_NOTVICT_OPEN(ch, NULL); - act("Your blood freezes as you hear $n's death cry.", - FALSE, ch, 0, 0, TO_ROOM); + act("Your blood freezes as you hear $n's death cry.", FALSE, ch, 0, 0, TO_ROOM); GUI_CMBT_NOTVICT_CLOSE(ch, NULL); for (door = 0; door < DIR_COUNT; door++) { if (CAN_GO(ch, door)) { - send_to_room(world[IN_ROOM(ch)].dir_option[door]->to_room, - "Your blood freezes as you hear someone's death cry.\r\n"); + send_to_room(world[IN_ROOM(ch)].dir_option[door]->to_room, "Your blood freezes as you hear someone's death cry.\r\n"); } } } @@ -2018,10 +2027,14 @@ void raw_kill(struct char_data *ch, struct char_data *killer) if (killer) { if (death_mtrigger(ch, killer)) - death_cry(ch); + { + if (!killer->char_specials.post_combat_messages) + death_cry(ch); + } } else death_cry(ch); + GET_POS(ch) = POS_DEAD; /* end making ordinary commands work in scripts */ @@ -2316,11 +2329,19 @@ static void perform_group_gain(struct char_data *ch, int base, share = MIN(CONFIG_MAX_EXP_GAIN, MAX(1, hap_share)); } - if (share > 1) - send_to_char(ch, "You receive your share of experience -- %d points.\r\n", gain_exp(ch, share, GAIN_EXP_MODE_GROUP)); + if (!ch->char_specials.post_combat_messages) + { + if (share > 1) + send_to_char(ch, "You receive your share of experience -- %d points.\r\n", gain_exp(ch, share, GAIN_EXP_MODE_GROUP)); + else + { + send_to_char(ch, "You receive your share of experience -- one measly little point!\r\n"); + gain_exp(ch, share, GAIN_EXP_MODE_GROUP); + } + } else { - send_to_char(ch, "You receive your share of experience -- one measly little point!\r\n"); + ch->char_specials.post_combat_exp = share; gain_exp(ch, share, GAIN_EXP_MODE_GROUP); } @@ -4857,6 +4878,30 @@ int dam_killed_vict(struct char_data *ch, struct char_data *victim) do_sac(ch->master, "corpse", 0, 0); } + + for (tch = world[IN_ROOM(ch)].people; tch; tch = tch->next_in_room) + { + if (tch->char_specials.post_combat_messages) + { + int post_gold = tch->char_specials.post_combat_gold; + int post_exp = tch->char_specials.post_combat_exp; + int post_accexp = tch->char_specials.post_combat_account_exp; + send_to_char(tch, "\tnYou receive"); + if (post_exp > 0) + send_to_char(tch, " \tY%d EXP", post_exp); + if (post_gold > 0) + send_to_char(tch, " \tC%d GOLD", post_gold); + if (post_accexp > 0) + send_to_char(tch, " \tG%d ACCOUNT EXP", post_accexp); + if (post_exp == 0 && post_gold == 0 && post_accexp == 0) + send_to_char(tch, "\tn Nothing"); + send_to_char(tch, "\tn.\r\n"); + } + tch->char_specials.post_combat_messages = false; + tch->char_specials.post_combat_exp = tch->char_specials.post_combat_gold = tch->char_specials.post_combat_account_exp = 0; + } + + /* all done! */ return (-1); } @@ -4876,7 +4921,7 @@ int damage(struct char_data *ch, struct char_data *victim, int dam, char buf1[MAX_INPUT_LENGTH] = {'\0'}; bool is_ranged = FALSE; struct affected_type af; - struct char_data *eidolon; + struct char_data *eidolon, *tch; /* this is just a dummy check */ if (!ch) @@ -5155,7 +5200,7 @@ int damage(struct char_data *ch, struct char_data *victim, int dam, if (ch != victim && GET_EXP(victim) && (GET_LEVEL(ch) - GET_LEVEL(victim)) <= 3) { if (IS_NPC(ch) && MOB_FLAGGED(ch, MOB_EIDOLON) && ch->master) - gain_exp(ch->master, GET_LEVEL(victim) * dam, GAIN_EXP_MODE_DAMAGE); + gain_exp(ch->master, GET_LEVEL(victim) * dam / 2, GAIN_EXP_MODE_DAMAGE); else gain_exp(ch, GET_LEVEL(victim) * dam, GAIN_EXP_MODE_DAMAGE); } @@ -5275,7 +5320,13 @@ int damage(struct char_data *ch, struct char_data *victim, int dam, "consciousness again.\r\n"); break; case POS_DEAD: - act("$n is dead! R.I.P.", FALSE, victim, 0, 0, TO_ROOM); + for (tch = world[IN_ROOM(ch)].people; tch; tch = tch->next_in_room) + { + if (victim == tch) continue; + if (!IS_NPC(tch) && PRF_FLAGGED(tch, PRF_POST_COMBAT_BRIEF)) + tch->char_specials.post_combat_messages = true; + act("$n is dead! R.I.P.", FALSE, victim, 0, tch, TO_VICT); + } send_to_char(victim, "You are dead! Sorry...\r\n"); break; default: @@ -5958,6 +6009,13 @@ int compute_damage_bonus(struct char_data *ch, struct char_data *vict, dambonus += 1; } + if (HAS_FEAT(ch, FEAT_BG_SAILOR) && IN_WATER(ch)) + { + if (display_mode) + send_to_char(ch, "Sailor In/Near Water: \tR+1\tn\r\n"); + dambonus += 1; + } + if (has_sage_mob_bonus(ch)) { if (display_mode) @@ -5997,19 +6055,19 @@ int compute_damage_bonus(struct char_data *ch, struct char_data *vict, } /* smite evil (remove after one attack) */ - if (affected_by_spell(ch, SKILL_SMITE_EVIL) && vict && IS_EVIL(vict)) + if (affected_by_spell(ch, SKILL_SMITE_EVIL) && vict) { if (display_mode) - send_to_char(ch, "Smite Evil bonus: \tR%d\tn\r\n", CLASS_LEVEL(ch, CLASS_PALADIN)); - dambonus += CLASS_LEVEL(ch, CLASS_PALADIN) * smite_evil_target_type(vict); + send_to_char(ch, "Smite Evil bonus: \tR%d\tn\r\n", get_smite_evil_level(ch) * smite_evil_target_type(vict)); + dambonus += get_smite_evil_level(ch) * smite_evil_target_type(vict); } /* smite good (remove after one attack) */ - if (affected_by_spell(ch, SKILL_SMITE_GOOD) && vict && IS_GOOD(vict)) + if (affected_by_spell(ch, SKILL_SMITE_GOOD) && vict) { if (display_mode) - send_to_char(ch, "Smite Good bonus: \tR%d\tn\r\n", CLASS_LEVEL(ch, CLASS_BLACKGUARD)); + send_to_char(ch, "Smite Good bonus: \tR%d\tn\r\n", get_smite_good_level(ch) * smite_good_target_type(vict)); - dambonus += CLASS_LEVEL(ch, CLASS_BLACKGUARD) * smite_good_target_type(vict); + dambonus += get_smite_good_level(ch) * smite_good_target_type(vict); } /* destructive smite (remove after one attack) */ if (affected_by_spell(ch, SKILL_SMITE_DESTRUCTION) && vict) @@ -7315,6 +7373,7 @@ int compute_hit_damage(struct char_data *ch, struct char_data *victim, #define STONESKIN_ABSORB 15 #define IRONSKIN_ABSORB 50 #define EPIC_WARDING_ABSORB 75 +#define DARK_BLESSING_ABSORB 10 /* this function takes ch (attacker) against victim (defender) who has inflicted dam damage and will reduce damage by X depending on the type @@ -7622,8 +7681,7 @@ void weapon_poison(struct char_data *ch, struct char_data *victim, if (TRLX_PSN_LVL(ch) <= 0) TRLX_PSN_LVL(ch) = 1; - TRLX_PSN_HIT(ch) - --; + TRLX_PSN_HIT(ch)--; if (TRLX_PSN_HIT(ch) < 0) TRLX_PSN_HIT(ch) = 0; if (TRLX_PSN_HIT(ch) > MAX_PSN_HIT) @@ -8321,6 +8379,20 @@ int compute_attack_bonus_full(struct char_data *ch, /* Attacker */ bonuses[BONUS_TYPE_MORALE] += 1; } + if (HAS_FEAT(ch, FEAT_BG_SAILOR) && IN_WATER(ch)) + { + if (display) + send_to_char(ch, "+1: %-50s\r\n", "Sailor In/Near Water"); + bonuses[BONUS_TYPE_MORALE] += 1; + } + + if (is_grouped_with_soldier(ch)) + { + if (display) + send_to_char(ch, "+1: %-50s\r\n", "Soldiers Grouped Together"); + bonuses[BONUS_TYPE_MORALE] += 1; + } + if (has_sage_mob_bonus(ch)) { if (display) @@ -10523,6 +10595,20 @@ int handle_successful_attack(struct char_data *ch, struct char_data *victim, if (ch && victim && (wielded || missile || IS_TRELUX(ch)) && !victim_is_dead) weapon_poison(ch, victim, wielded, missile); + if (IS_NPC(ch) && MOB_FLAGGED(ch, MOB_ABIL_POISON)) + { + act("The creature's \tGpoison\tn courses through you.", FALSE, victim, 0, 0, TO_ROOM); + call_magic(ch, victim, 0, POISON_TYPE_WYVERN, 0, GET_LEVEL(ch), CAST_WEAPON_POISON); + return dam; + } + + if (IS_NPC(ch) && MOB_FLAGGED(ch, MOB_ABIL_CORRUPTION) && dice(1, 5) == 1) + { + act("The creature's \tDcorruption\tn courses through you.", FALSE, victim, 0, 0, TO_ROOM); + call_magic(ch, victim, 0, MOB_ABILITY_CORRUPTION, 0, GET_LEVEL(ch), CAST_INNATE); + return dam; + } + /* special weapon (or gloves for monk) procedures. Need to implement something similar for the new system. */ if (ch && victim && wielded && !victim_is_dead) weapon_special(wielded, ch, hit_msg); @@ -11486,7 +11572,7 @@ int perform_attacks(struct char_data *ch, int mode, int phase) mileage out of striking-type casters. In this case we assume if the player is blasting they are using ranged. Otherwise if they're blasting and using hideous blow, they are doing melee. */ - if (BLASTING(ch) && GET_ELDRITCH_SHAPE(ch) != WARLOCK_HIDEOUS_BLOW) + if (PRF_FLAGGED(ch, PRF_AUTOBLAST) && GET_ELDRITCH_SHAPE(ch) != WARLOCK_HIDEOUS_BLOW) { ranged_attacks += bonus_mainhand_attacks; if (is_tanking(ch)) @@ -12774,7 +12860,7 @@ void perform_violence(struct char_data *ch, int phase) if (FIGHTING(ch) && AFF_FLAGGED(FIGHTING(ch), AFF_REPULSION) && !is_using_ranged_weapon(ch, TRUE) && !IS_CASTING(ch) && - !BLASTING(ch) && + (!IS_NPC(ch) && !PRF_FLAGGED(ch, PRF_AUTOBLAST)) && find_in_list(ch, FIGHTING(ch)->char_specials.repulse_blacklist) != NULL) { // We need to find a new target. diff --git a/handler.c b/handler.c index 9d26001e..8079d0d4 100755 --- a/handler.c +++ b/handler.c @@ -1746,7 +1746,7 @@ int invalid_align(struct char_data *ch, struct obj_data *obj) return TRUE; if (OBJ_FLAGGED(obj, ITEM_ANTI_GOOD) && IS_GOOD(ch)) return TRUE; - if (OBJ_FLAGGED(obj, ITEM_ANTI_NEUTRAL) && IS_NEUTRAL_ANY(ch)) + if (OBJ_FLAGGED(obj, ITEM_ANTI_NEUTRAL) && IS_NEUTRAL(ch)) return TRUE; if (OBJ_FLAGGED(obj, ITEM_ANTI_LAWFUL) && IS_LAWFUL(ch)) return TRUE; diff --git a/help.c b/help.c index ab850da2..39a26c3f 100644 --- a/help.c +++ b/help.c @@ -24,6 +24,7 @@ #include "deities.h" #include "act.h" #include "evolutions.h" +#include "backgrounds.h" /* puts -'s instead of spaces */ void space_to_minus(char *str) @@ -315,6 +316,16 @@ ACMDU(do_help) } } + for (i = 1; i < NUM_BACKGROUNDS; i++) + { + if (is_abbrev(home_arg, background_list[i].name)) + { + show_background_help(ch, i); + free(raw_argument); + return; + } + } + if ((entries = search_help(argument, GET_LEVEL(ch))) == NULL) { /* Check alchemist discoveries for relevant entries! */ diff --git a/interpreter.c b/interpreter.c index b5a7f8c2..61002dd4 100755 --- a/interpreter.c +++ b/interpreter.c @@ -69,6 +69,7 @@ #include "deities.h" #include "mudlim.h" #include "backgrounds.h" +#include "roleplay.h" /* local (file scope) functions */ static int perform_dupe_check(struct descriptor_data *d); @@ -148,6 +149,7 @@ cpp_extern const struct command_info cmd_info[] = { {"apotheosis", "apoth", POS_STANDING, do_sorcerer_arcane_apotheosis, 1, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, {"areas", "are", POS_DEAD, do_areas, 0, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, {"assist", "as", POS_FIGHTING, do_assist, 1, 0, FALSE, ACTION_NONE, {0, 0}, NULL}, + {"assistblast", "assistblast", POS_FIGHTING, do_assistblast, 1, 0, FALSE, ACTION_NONE, {1, 0}, can_eldritch_blast}, {"ask", "ask", POS_RECLINING, do_spec_comm, 0, SCMD_ASK, TRUE, ACTION_NONE, {0, 0}, NULL}, {"astat", "ast", POS_DEAD, do_astat, LVL_IMMORT, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, {"attach", "attach", POS_DEAD, do_attach, LVL_BUILDER, 0, FALSE, ACTION_NONE, {0, 0}, NULL}, @@ -177,7 +179,7 @@ cpp_extern const struct command_info cmd_info[] = { {"abilityset", "abilityset", POS_SLEEPING, do_abilityset, LVL_IMPL, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, {"autocraft", "autocraft", POS_STANDING, do_not_here, 1, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, {"adjure", "adjure", POS_RESTING, do_gen_preparation, 0, SCMD_ADJURE, FALSE, ACTION_NONE, {0, 0}, NULL}, - {"autoblast", "autoblast", POS_FIGHTING, do_autoblast, 1, 0, FALSE, ACTION_NONE, {1, 0}, can_eldritch_blast}, + {"autoblast", "autoblast", POS_FIGHTING, do_gen_tog, 1, SCMD_AUTO_BLAST, FALSE, ACTION_NONE, {1, 0}, can_eldritch_blast}, {"autofire", "autofire", POS_FIGHTING, do_autofire, 1, 0, FALSE, ACTION_NONE, {0, 0}, NULL}, {"applyoil", "applyoil", POS_STANDING, do_applyoil, 1, 0, FALSE, ACTION_STANDARD | ACTION_MOVE, {6, 6}, NULL}, {"applypoison", "applypoison", POS_STANDING, do_applypoison, 1, 0, FALSE, ACTION_STANDARD | ACTION_MOVE, {6, 6}, NULL}, @@ -429,6 +431,7 @@ cpp_extern const struct command_info cmd_info[] = { {"genriver", "genriver", POS_SLEEPING, do_genriver, LVL_STAFF, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, {"give", "giv", POS_RECLINING, do_give, 0, 0, FALSE, ACTION_NONE, {0, 0}, NULL}, {"goto", "go", POS_SLEEPING, do_goto, LVL_IMMORT, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, + {"goals", "goals", POS_SLEEPING, do_goals, 0, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, {"gold", "gol", POS_RECLINING, do_gold, 0, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, {"gossip", "gos", POS_SLEEPING, do_gen_comm, 0, SCMD_GOSSIP, TRUE, ACTION_NONE, {0, 0}, NULL}, @@ -516,7 +519,7 @@ cpp_extern const struct command_info cmd_info[] = { /* {"command", "sort_as", minimum_position, *command_pointer, minimum_level, subcmd, ignore_wait, actions_required, {action_cooldowns}, *command_check_pointer},*/ - {"kill", "k", POS_FIGHTING, do_kill, 0, 0, FALSE, ACTION_STANDARD, {6, 0}, NULL}, + {"kill", "k", POS_FIGHTING, do_hit, 0, SCMD_HIT, FALSE, ACTION_STANDARD, {6, 0}, NULL}, {"kapaksaliva", "kapaksaliva", POS_FIGHTING, do_kapak_saliva, 0, 0, FALSE, ACTION_SWIFT, {6, 0}, NULL}, {"kick", "ki", POS_FIGHTING, do_process_attack, 1, AA_KICK, FALSE, ACTION_NONE, {6, 0}, can_kick}, {"keycheck", "keycheck", POS_STANDING, do_keycheck, LVL_IMMORT, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, @@ -626,6 +629,7 @@ cpp_extern const struct command_info cmd_info[] = { {"poisonbreath", "poisonb", POS_FIGHTING, do_poisonbreath, 1, 0, FALSE, ACTION_STANDARD, {6, 0}, can_poisonbreath}, {"poisontouch", "poisont", POS_FIGHTING, do_poisontouch, 1, 0, FALSE, ACTION_STANDARD, {0, 0}, NULL}, {"policy", "pol", POS_DEAD, do_gen_ps, 0, SCMD_POLICIES, TRUE, ACTION_NONE, {0, 0}, NULL}, + {"postcombatbrief", "postcombatbrief", POS_SLEEPING, do_gen_tog, 0, SCMD_POST_COMBAT_BRIEF, TRUE, ACTION_NONE, {0, 0}, NULL}, {"pour", "pour", POS_STANDING, do_pour, 0, SCMD_POUR, FALSE, ACTION_NONE, {0, 0}, NULL}, {"powers", "powers", POS_RECLINING, do_spells, 1, SCMD_POWERS, FALSE, ACTION_NONE, {0, 0}, NULL}, {"powerslist", "powerslist", POS_RECLINING, do_spelllist, 1, SCMD_POWERS, FALSE, ACTION_NONE, {0, 0}, NULL}, @@ -695,6 +699,7 @@ cpp_extern const struct command_info cmd_info[] = { {"rescue", "resc", POS_FIGHTING, do_rescue, 1, 0, FALSE, ACTION_STANDARD | ACTION_MOVE, {6, 6}, can_rescue}, {"resistances", "res", POS_DEAD, do_affects, 0, SCMD_RESISTANCES, TRUE, ACTION_NONE, {0, 0}, NULL}, {"restore", "resto", POS_DEAD, do_restore, LVL_GRSTAFF, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, + {"retainer", "retainer", POS_DEAD, do_retainer, 0, 0, FALSE, ACTION_NONE, {0, 0}, NULL}, {"return", "retu", POS_DEAD, do_return, 0, 0, FALSE, ACTION_NONE, {0, 0}, NULL}, {"redit", "redit", POS_DEAD, do_oasis_redit, LVL_BUILDER, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, {"reglist", "reglist", POS_DEAD, do_oasis_list, LVL_BUILDER, SCMD_OASIS_REGLIST, TRUE, ACTION_NONE, {0, 0}, NULL}, @@ -702,6 +707,7 @@ cpp_extern const struct command_info cmd_info[] = { {"rlist", "rlist", POS_DEAD, do_oasis_list, LVL_BUILDER, SCMD_OASIS_RLIST, TRUE, ACTION_NONE, {0, 0}, NULL}, {"rcopy", "rcopy", POS_DEAD, do_oasis_copy, LVL_STAFF, CON_REDIT, TRUE, ACTION_NONE, {0, 0}, NULL}, {"roomflags", "roomflags", POS_DEAD, do_gen_tog, LVL_IMMORT, SCMD_SHOWVNUMS, TRUE, ACTION_NONE, {0, 0}, NULL}, + {"roomvnum", "roomvnum", POS_DEAD, do_roomvnum, LVL_IMMORT, SCMD_SHOWVNUMS, TRUE, ACTION_NONE, {0, 0}, NULL}, {"respec", "respec", POS_STANDING, do_respec, 1, 0, FALSE, ACTION_NONE, {0, 0}, NULL}, {"recharge", "recharge", POS_STANDING, do_recharge, 1, 0, FALSE, ACTION_NONE, {0, 0}, NULL}, {"resize", "resize", POS_STANDING, do_not_here, 1, 0, FALSE, ACTION_NONE, {0, 0}, NULL}, @@ -716,10 +722,17 @@ cpp_extern const struct command_info cmd_info[] = { {"races", "races", POS_DEAD, do_race, 0, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, {"racefix", "racefix", POS_DEAD, do_racefix, 0, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, {"rank", "rank", POS_DEAD, do_rank, 0, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, - {"rp", "rp", POS_DEAD, do_gen_tog, 0, SCMD_RP, TRUE, ACTION_NONE, {0, 0}, NULL}, + {"rpsheet", "rp", POS_DEAD, do_rpsheet, 0, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, + {"rpset", "rpset", POS_DEAD, do_gen_tog, 0, SCMD_RP, TRUE, ACTION_NONE, {0, 0}, NULL}, + {"rpbackground", "rpbackground", POS_DEAD, do_showrpinfo, 0, SCMD_RP_BG_STORY, TRUE, ACTION_NONE, {0, 0}, NULL}, + {"rpbonds", "rpbonds", POS_DEAD, do_showrpinfo, 0, SCMD_RP_BONDS, TRUE, ACTION_NONE, {0, 0}, NULL}, + {"rpdescription", "rpdescription", POS_DEAD, do_showrpinfo, 0, SCMD_RP_DESC, TRUE, ACTION_NONE, {0, 0}, NULL}, + {"rpflaws", "rpflaws", POS_DEAD, do_showrpinfo, 0, SCMD_RP_FLAWS, TRUE, ACTION_NONE, {0, 0}, NULL}, + {"rpgoals", "rpgoals", POS_DEAD, do_showrpinfo, 0, SCMD_RP_GOALS, TRUE, ACTION_NONE, {0, 0}, NULL}, + {"rpideals", "rpideals", POS_DEAD, do_showrpinfo, 0, SCMD_RP_IDEALS, TRUE, ACTION_NONE, {0, 0}, NULL}, + {"rppersonality", "rppersonality", POS_DEAD, do_showrpinfo, 0, SCMD_RP_PERSONALITY, TRUE, ACTION_NONE, {0, 0}, NULL}, {"resetpassword", "resetpassword", POS_DEAD, do_resetpassword, LVL_IMPL, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, {"rsay", "rs", POS_RECLINING, do_rsay, 0, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, - /* {"command", "sort_as", minimum_position, *command_pointer, minimum_level, subcmd, ignore_wait, actions_required, {action_cooldowns}, *command_check_pointer},*/ {"sacrifice", "sac", POS_RECLINING, do_sac, 0, 0, FALSE, ACTION_NONE, {0, 0}, NULL}, @@ -754,7 +767,8 @@ cpp_extern const struct command_info cmd_info[] = { {"setworldsect", "setw", POS_DEAD, do_setworldsect, LVL_GRSTAFF, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, {"shadowcast", "shc", POS_SITTING, do_gen_cast, 1, SCMD_CAST_SHADOW, FALSE, ACTION_MOVE, {0, 6}, NULL}, {"shadowform", "shf", POS_SITTING, do_gen_tog, 1, SCMD_SHADOWFORM, FALSE, ACTION_MOVE, {0, 6}, NULL}, - {"shout", "sho", POS_RECLINING, do_gen_comm, 0, SCMD_SHOUT, TRUE, ACTION_NONE, {0, 0}, NULL}, + {"shortcut", "shortcut", POS_DEAD, do_shortcut, 0, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, + {"shout", "shout", POS_RECLINING, do_gen_comm, 0, SCMD_SHOUT, TRUE, ACTION_NONE, {0, 0}, NULL}, {"show", "show", POS_DEAD, do_show, LVL_IMMORT, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, {"showblockers", "showblockers", POS_DEAD, do_show_blockers, LVL_IMMORT, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, {"showwearoff", "showwearoff", POS_DEAD, do_showwearoff, LVL_IMMORT, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, @@ -2148,7 +2162,7 @@ void nanny(struct descriptor_data *d, char *arg) { int load_result = 0; /* Overloaded variable */ int player_i = 0; - int i = 0; /* incrementor */ + int i = 0, l = 0; /* incrementor */ /* OasisOLC states */ struct @@ -3085,8 +3099,8 @@ switch (load_result) if (is_abbrev(arg, "quit") || is_abbrev(arg, "Quit")) { write_to_output(d, "Homeland region selection aborted.\r\n"); - STATE(d) = CON_MENU; - write_to_output(d, "%s", CONFIG_MENU); + STATE(d) = CON_CHAR_RP_MENU; + show_character_rp_menu(d); return; } @@ -3127,7 +3141,7 @@ switch (load_result) i = 1; while (i < NUM_REGIONS) { - if (!is_selectable_region(i)) continue; + if (!is_selectable_region(i)) { i++; continue; } write_to_output(d, "%-2d) %-20s ", i, regions[i]); if (((i - 1) % 3) == 2) send_to_char(d->character, "\r\n"); @@ -3147,9 +3161,8 @@ switch (load_result) return; } - write_to_output(d, "%s", CONFIG_MENU); - - STATE(d) = CON_MENU; + STATE(d) = CON_CHAR_RP_MENU; + show_character_rp_menu(d); break; case CON_QCLASS: @@ -3502,20 +3515,114 @@ switch (load_result) write_to_output(d, "\r\nDo you wish to have the recommend preferences flags enabled? Ie. Autoloot, Show Dice Rolls, Etc.) "); STATE(d) = CON_SETPREFS; + break; - /* make sure the last log is updated correctly. */ - GET_PREF(d->character) = rand_number(1, 128000); - GET_HOST(d->character) = strdup(d->host); + case CON_CHARACTER_GOALS_IDEAS: + switch (*arg) + { + case '1': + + choose_random_roleplay_goal(d->character); + write_to_output(d, "\r\n"); + write_to_output(d, "Enter 1 to see another example or Q to proceed and edit your character goals: "); + return; + case 'q': case 'Q': + show_character_goal_edit(d); + STATE(d) = CON_CHARACTER_GOALS_ENTER; + return; + default: + write_to_output(d, "\r\n"); + write_to_output(d, "Enter 1 to see another example or Q to proceed and edit your character goals: "); + return; + } + break; - mudlog(NRM, LVL_STAFF, TRUE, "%s [%s] new player.", GET_NAME(d->character), d->host); + case CON_CHARACTER_PERSONALITY_IDEAS: + if (*arg == 'Q' || *arg == 'q') + { + show_character_personality_edit(d); + STATE(d) = CON_CHARACTER_PERSONALITY_ENTER; + return; + } + if (atoi(arg) >= 1 && atoi(arg) < NUM_BACKGROUNDS) + { + choose_random_roleplay_personality(d->character, backgrounds_listed_alphabetically[atoi(arg)]); + write_to_output(d, "\r\n"); + write_to_output(d, "Enter a background number to see another example or Q to proceed and edit your character personality: "); + return; + } + else + { + write_to_output(d, "\r\n"); + write_to_output(d, "Enter a background number to see another example or Q to proceed and edit your character personality: "); + return; + } + break; - /* Add to the list of 'recent' players (since last reboot) */ - if (AddRecentPlayer(GET_NAME(d->character), d->host, TRUE, FALSE) == FALSE) + case CON_CHARACTER_IDEALS_IDEAS: + if (*arg == 'Q' || *arg == 'q') { - mudlog(BRF, MAX(LVL_IMMORT, GET_INVIS_LEV(d->character)), TRUE, - "Failure to AddRecentPlayer (returned FALSE)."); + show_character_ideals_edit(d); + STATE(d) = CON_CHARACTER_IDEALS_ENTER; + return; } + if (atoi(arg) >= 1 && atoi(arg) < NUM_BACKGROUNDS) + { + choose_random_roleplay_ideals(d->character, backgrounds_listed_alphabetically[atoi(arg)]); + write_to_output(d, "\r\n"); + write_to_output(d, "Enter a background number to see another example or Q to proceed and edit your character ideals: "); + return; + } + else + { + write_to_output(d, "\r\n"); + write_to_output(d, "Enter a background number to see another example or Q to proceed and edit your character ideals: "); + return; + } + break; + case CON_CHARACTER_BONDS_IDEAS: + if (*arg == 'Q' || *arg == 'q') + { + show_character_ideals_edit(d); + STATE(d) = CON_CHARACTER_BONDS_ENTER; + return; + } + if (atoi(arg) >= 1 && atoi(arg) < NUM_BACKGROUNDS) + { + choose_random_roleplay_bonds(d->character, backgrounds_listed_alphabetically[atoi(arg)]); + write_to_output(d, "\r\n"); + write_to_output(d, "Enter a background number to see another example or Q to proceed and edit your character bonds: "); + return; + } + else + { + write_to_output(d, "\r\n"); + write_to_output(d, "Enter a background number to see another example or Q to proceed and edit your character bonds: "); + return; + } + break; + + case CON_CHARACTER_FLAWS_IDEAS: + if (*arg == 'Q' || *arg == 'q') + { + show_character_flaws_edit(d); + STATE(d) = CON_CHARACTER_FLAWS_ENTER; + return; + } + if (atoi(arg) >= 1 && atoi(arg) < NUM_BACKGROUNDS) + { + choose_random_roleplay_flaws(d->character, backgrounds_listed_alphabetically[atoi(arg)]); + write_to_output(d, "\r\n"); + write_to_output(d, "Enter a background number to see another example or Q to proceed and edit your character flaws: "); + return; + } + else + { + write_to_output(d, "\r\n"); + write_to_output(d, "Enter a background number to see another example or Q to proceed and edit your character flaws: "); + return; + } break; case CON_SETPREFS: @@ -3544,6 +3651,7 @@ switch (load_result) SET_BIT_AR(PRF_FLAGS(d->character), PRF_DISPGOLD); SET_BIT_AR(PRF_FLAGS(d->character), PRF_DISPMEMTIME); SET_BIT_AR(PRF_FLAGS(d->character), PRF_DISPTIME); + SET_BIT_AR(PRF_FLAGS(d->character), PRF_CAREFUL_PET); GET_WIMP_LEV(d->character) = 10; } else if (!strcmp(arg, "no") || !strcmp(arg, "NO")) @@ -3555,11 +3663,22 @@ switch (load_result) write_to_output(d, "Please enter yes or no.\r\n"); return; } + + /* make sure the last log is updated correctly. */ + GET_PREF(d->character) = rand_number(1, 128000); + GET_HOST(d->character) = strdup(d->host); + + mudlog(NRM, LVL_STAFF, TRUE, "%s [%s] new player.", GET_NAME(d->character), d->host); + + /* Add to the list of 'recent' players (since last reboot) */ + if (AddRecentPlayer(GET_NAME(d->character), d->host, TRUE, FALSE) == FALSE) + { + mudlog(BRF, MAX(LVL_IMMORT, GET_INVIS_LEV(d->character)), TRUE, + "Failure to AddRecentPlayer (returned FALSE)."); + } - /* print message of the day to player */ - write_to_output(d, "\r\n"); - write_to_output(d, "%s\r\n*** PRESS RETURN: ", motd); - STATE(d) = CON_RMOTD; + display_rp_decide_menu(d); + STATE(d) = CON_CHAR_RP_DECIDE; break; case CON_RMOTD: /* read CR after printing motd */ @@ -3609,6 +3728,189 @@ switch (load_result) HandleStateGenericDescsParseMenuChoice(d, arg); break; + case CON_CHARACTER_AGE_SELECT: + HandleStateCharacterAgeParseMenuChoice(d, arg); + break; + + case CON_CHARACTER_FACTION_SELECT: + HandleStateCharacterFactionParseMenuChoice(d, arg); + break; + + case CON_CHARACTER_HOMETOWN_SELECT: + HandleStateCharacterHometownParseMenuChoice(d, arg); + break; + + case CON_CHARACTER_DEITY_SELECT: + HandleStateCharacterDeityParseMenuChoice(d, arg); + break; + + case CON_CHARACTER_DEITY_CONFIRM: + HandleStateCharacterDeityConfirmParseMenuChoice(d, arg); + break; + + case CON_CHAR_RP_DECIDE: + HandleStateCharacterRPDecideParseMenuChoice(d, arg); + break; + + case CON_CHAR_RP_MENU: + switch (*arg) + { + case '0': + show_short_description_main_menu(d); + break; + case '1': + show_character_long_description_menu(d); + break; + case '2': + show_character_background_story_menu(d); + break; + case '3': + show_character_background_archtype_menu(d); + break; + case '4': + show_character_goal_idea_menu(d->character); + STATE(d) = CON_CHARACTER_GOALS_IDEAS; + break; + case '5': + show_character_personality_idea_menu(d->character); + STATE(d) = CON_CHARACTER_PERSONALITY_IDEAS; + break; + case '6': + show_character_ideals_idea_menu(d->character); + STATE(d) = CON_CHARACTER_IDEALS_IDEAS; + break; + case '7': + show_character_bonds_idea_menu(d->character); + STATE(d) = CON_CHARACTER_BONDS_IDEAS; + break; + case '8': + show_character_flaws_idea_menu(d->character); + STATE(d) = CON_CHARACTER_FLAWS_IDEAS; + break; + case '9': + if (IS_DRACONIAN(d->character)) + { + send_to_char(d->character, "Draconians cannot change their age, and are always considered adult.\r\n"); + return; + } + if (d->character->player_specials->saved.character_age_saved) + { + write_to_output(d, "You have already selected your character's age. To change, please contact a staff member.\r\n"); + return; + } + display_age_menu(d); + STATE(d) = CON_CHARACTER_AGE_SELECT; + break; + case 'A': case 'a': + + show_homeland_region_main_menu(d); + break; + case 'B': case 'b': + if (GET_CLAN(d->character) > 0) + { + send_to_char(d->character, "You have already chosen a faction. You can resign in-game or aska a staff membe rfor help.\r\n"); + return; + } + display_faction_menu(d); + STATE(d) = CON_CHARACTER_FACTION_SELECT; + break; + case 'C': case 'c': + if (GET_HOMETOWN(d->character)) + { + send_to_char(d->character, "You have already selected a hometown. Please contact a staff member if you would like to change it.\r\n"); + return; + } + display_hometown_menu(d); + STATE(d) = CON_CHARACTER_HOMETOWN_SELECT; + break; + case 'D': case 'd': + if (GET_DEITY(d->character)) + { + send_to_char(d->character, "You have already selected a deity. Please contact a staff member if you would like to change it.\r\n"); + return; + } + display_deity_menu(d); + STATE(d) = CON_CHARACTER_DEITY_SELECT; + break; + case 'Q': case 'q': + write_to_output(d, "%s", CONFIG_MENU); + STATE(d) = CON_MENU; + break; + default: + write_to_output(d, "\r\nThat's not a menu choice!\r\n"); + show_character_rp_menu(d); + break; + } + break; + + case CON_BACKGROUND_ARCHTYPE: + + for (l = 0; *(arg + l); l++) + { + /* convert to lower case */ + *(arg + l) = LOWER(*(arg + l)); + if (*(arg + l) == ' ') + *(arg + l) = '-'; + } + + if (is_abbrev(arg, "quit")) + { + show_character_rp_menu(d); + STATE(d) = CON_CHAR_RP_MENU; + return; + } + + for (i = 1; i < NUM_BACKGROUNDS; i++) + { + if (is_abbrev(arg, background_list[i].name)) + { + GET_BACKGROUND(d->character) = i; + break; + } + } + + if (i >= NUM_BACKGROUNDS) + { + write_to_output(d, "That is not a valid background archtype. Please select again: "); + return; + } + + show_background_help(d->character, GET_BACKGROUND(d->character)); + + write_to_output(d, "\r\n"); + write_to_output(d, "Do you wish to choose this background archtype? (Y|N) "); + + STATE(d) = CON_BACKGROUND_ARCHTYPE_CONFIRM; + break; + + case CON_BACKGROUND_ARCHTYPE_CONFIRM: + if (UPPER(*arg) == 'Y') + { + write_to_output(d, "\r\nBackground Confirmed!\r\n"); + SET_FEAT(d->character, background_list[GET_BACKGROUND(d->character)].feat, 1); + show_character_rp_menu(d); + STATE(d) = CON_CHAR_RP_MENU; + return; + } + else if (UPPER(*arg) != 'N') + { + write_to_output(d, "\r\nY)es to confirm N)o to reselect.\r\n"); + write_to_output(d, "Do you want to select this background? (y/n) : "); + STATE(d) = CON_BACKGROUND_ARCHTYPE_CONFIRM; + return; + } + else + { + if (GET_BACKGROUND(d->character) > 0) + { + SET_FEAT(d->character, background_list[GET_BACKGROUND(d->character)].feat, 0); + GET_BACKGROUND(d->character) = 0; + } + show_character_background_archtype_menu(d); + return; + } + break; + case CON_MENU: { /* get selection from main menu */ @@ -3667,127 +3969,10 @@ switch (load_result) break; case '2': - if (d->character->player.description) - { - write_to_output(d, "Current description:\r\n%s", d->character->player.description); - /* Don't free this now... so that the old description gets loaded as the - * current buffer in the editor. Do setup the ABORT buffer here, however. */ - d->backstr = strdup(d->character->player.description); - } - write_to_output(d, "Enter the new text you'd like others to see when they look at you.\r\n"); - send_editor_help(d); - d->str = &d->character->player.description; - d->max_str = PLR_DESC_LENGTH; - STATE(d) = CON_PLR_DESC; + show_character_rp_menu(d); + STATE(d) = CON_CHAR_RP_MENU; break; -#if defined(CAMPAIGN_FR) || defined(CAMPAIGN_DL) - case '3': - if (d->character->player.background) - { - write_to_output(d, "Current Character Background:\r\n%s", d->character->player.background); - /* Don't free this now... so that the old background gets loaded as the - * current buffer in the editor. Do setup the ABORT buffer here, however. */ - d->backstr = strdup(d->character->player.background); - } - write_to_output(d, "Enter your character background story.\r\n"); - send_editor_help(d); - d->str = &d->character->player.background; - d->max_str = PLR_BG_LENGTH; - STATE(d) = CON_PLR_BG; - break; - -#if defined(CAMPAIGN_FR) - case '4': - - if (GET_REGION(d->character)) - { - write_to_output(d, "\r\n\tcYou have already chosen a homeland region. To change it you will need to ask a staff member to do it.\r\n\r\n\tn"); - return; - } - - write_to_output(d, "\tcRegions of Faerun\tn\r\n\r\n"); - for (i = 1; i < NUM_REGIONS; i++) - { - write_to_output(d, "%-2d) %-20s ", i, regions[i]); - if (((i - 1) % 3) == 2) - send_to_char(d->character, "\r\n"); - } - if (((i - 1) % 3) != 2) - send_to_char(d->character, "\r\n"); - write_to_output(d, "\r\n\r\nRegion selection is mainly a role playign choice, but it also awards an associated language and\r\n" - "may be integrated into future game systems.\r\n"); - write_to_output(d, "Type 'quit' to exit out of region selection.\r\n"); - write_to_output(d, "\r\nRegion Selection (select %d for 'Sword Coast' if you do not know what to pick): ", REGION_THE_SWORD_COAST); - - STATE(d) = CON_QREGION; - break; -#elif defined(CAMPAIGN_DL) - case '4': - - if (GET_REGION(d->character)) - { - write_to_output(d, "\r\n\tcYou have already chosen a homeland region. To change it you will need to ask a staff member to do it.\r\n\r\n\tn"); - return; - } - - write_to_output(d, "\tcRegions of Ansalon\tn\r\n\r\n"); - i = 1; - while (i < NUM_REGIONS) - { - if (!is_selectable_region(i)) continue; - write_to_output(d, "%-2d) %-20s ", i, regions[i]); - if (((i - 1) % 3) == 2) - send_to_char(d->character, "\r\n"); - i++; - } - if (((i - 1) % 3) != 2) - send_to_char(d->character, "\r\n"); - write_to_output(d, "\r\n\r\nRegion selection is mainly a role playign choice, but it also awards an associated language and\r\n" - "may be integrated into future game systems.\r\n"); - write_to_output(d, "Type 'quit' to exit out of region selection.\r\n"); - write_to_output(d, "\r\nRegion Selection (select %d for 'Abanasinia' if you do not know what to pick): ", REGION_ABANASINIA); - - STATE(d) = CON_QREGION; - break; -#else - write_to_output(d, "That is not an option at this time.\r\n"); -#endif - - case '5': - if (GET_PC_DESCRIPTOR_1(d->character) > 0 && GET_PC_ADJECTIVE_1(d->character) > 0) - { - send_to_char(d->character, "\r\n"); - send_to_char(d->character, "You have already chosen your description. To change it you'll need to request a description reset from a staff member.\r\n"); - send_to_char(d->character, "\r\n"); - break; - } - send_to_char(d->character, "\r\n"); - send_to_char(d->character, "SET CHARACTER SHORT DESCRIPTION: PRESS ENTER\r\n"); - send_to_char(d->character, "\r\n"); - STATE(d) = CON_GEN_DESCS_INTRO; - break; - - case '6': - page_string(d, background, 0); - STATE(d) = CON_RMOTD; - break; - - case '7': - write_to_output(d, "\r\nEnter your old password: "); - // echo_off(d); - ProtocolNoEcho(d, true); - STATE(d) = CON_CHPWD_GETOLD; - break; - - case '8': - write_to_output(d, "\r\nEnter your password for verification: "); - // echo_off(d); - ProtocolNoEcho(d, true); - STATE(d) = CON_DELCNF1; - break; -#else - case '3': page_string(d, background, 0); STATE(d) = CON_RMOTD; @@ -3806,7 +3991,7 @@ switch (load_result) ProtocolNoEcho(d, true); STATE(d) = CON_DELCNF1; break; -#endif + default: write_to_output(d, "\r\nThat's not a menu choice!\r\n%s", CONFIG_MENU); break; @@ -3895,3 +4080,170 @@ switch (load_result) break; } } + +void show_character_rp_menu(struct descriptor_data *d) +{ + write_to_output(d, "\tc"); + draw_line(d->character, 80, '-', '-'); + text_line(d->character, "\tWCHARACTER OPTIONS MENU\tc", 80, '-', '-'); + draw_line(d->character, 80, '-', '-'); + write_to_output(d, "\tn"); + + write_to_output(d, "\tW0)\tC Set your character short description.\tn\r\n"); + write_to_output(d, "\tW1)\tC Enter character description.\tn\r\n"); + write_to_output(d, "\tW2)\tC Enter character background story.\tn\r\n"); + write_to_output(d, "\tW3)\tC Set your character background archtype.\tn\r\n"); + write_to_output(d, "\tW4)\tC Set your character goals.\tn\r\n"); + write_to_output(d, "\tW5)\tC Set your character personality.\tn\r\n"); + write_to_output(d, "\tW6)\tC Set your character ideals.\tn\r\n"); + write_to_output(d, "\tW7)\tC Set your character bonds.\tn\r\n"); + write_to_output(d, "\tW8)\tC Set your character flaws.\tn\r\n"); + write_to_output(d, "\tW9)\tC Set your character age.\tn\r\n"); + write_to_output(d, "\tWA)\tC Choose character homeland region.\tn\r\n"); + write_to_output(d, "\tWB)\tC Set your character faction.\tn\r\n"); + write_to_output(d, "\tWC)\tC Set your character home city.\tn\r\n"); + write_to_output(d, "\tWD)\tC Set your character deity.\tn\r\n"); + + write_to_output(d, "\tWQ)\tC Quit to main game menu.\tn\r\n"); + + draw_line(d->character, 80, '-', '-'); + write_to_output(d, "\tn"); + +} + +void show_homeland_region_main_menu(struct descriptor_data *d) +{ + int i; + + #if defined(CAMPAIGN_FR) + if (GET_REGION(d->character)) + { + write_to_output(d, "\r\n\tcYou have already chosen a homeland region. To change it you will need to ask a staff member to do it.\r\n\r\n\tn"); + return; + } + + write_to_output(d, "\tcRegions of Faerun\tn\r\n\r\n"); + for (i = 1; i < NUM_REGIONS; i++) + { + write_to_output(d, "%-2d) %-20s ", i, regions[i]); + if (((i - 1) % 3) == 2) + send_to_char(d->character, "\r\n"); + } + if (((i - 1) % 3) != 2) + send_to_char(d->character, "\r\n"); + write_to_output(d, "\r\n\r\nRegion selection is mainly a role playign choice, but it also awards an associated language and\r\n" + "may be integrated into future game systems.\r\n"); + write_to_output(d, "Type 'quit' to exit out of region selection.\r\n"); + write_to_output(d, "\r\nRegion Selection (select %d for 'Sword Coast' if you do not know what to pick): ", REGION_THE_SWORD_COAST); + + STATE(d) = CON_QREGION; +#elif defined(CAMPAIGN_DL) + + if (GET_REGION(d->character)) + { + write_to_output(d, "\r\n\tcYou have already chosen a homeland region. To change it you will need to ask a staff member to do it.\r\n\r\n\tn"); + return; + } + + write_to_output(d, "\tcRegions of Ansalon\tn\r\n\r\n"); + i = 1; + while (i < NUM_REGIONS) + { + if (!is_selectable_region(i)) {i++; continue; } + write_to_output(d, "%-2d) %-20s ", i, regions[i]); + if (((i - 1) % 3) == 2) + send_to_char(d->character, "\r\n"); + i++; + } + if (((i - 1) % 3) != 2) + send_to_char(d->character, "\r\n"); + write_to_output(d, "\r\n\r\nRegion selection is mainly a role playign choice, but it also awards an associated language and\r\n" + "may be integrated into future game systems.\r\n"); + write_to_output(d, "Type 'quit' to exit out of region selection.\r\n"); + write_to_output(d, "\r\nRegion Selection (select %d for 'Abanasinia' if you do not know what to pick): ", REGION_ABANASINIA); + + STATE(d) = CON_QREGION; +#else + write_to_output(d, "That is not an option at this time.\r\n"); +#endif +} + +void show_character_long_description_menu(struct descriptor_data *d) +{ + if (d->character->player.description) + { + write_to_output(d, "Current description:\r\n%s", d->character->player.description); + /* Don't free this now... so that the old description gets loaded as the + * current buffer in the editor. Do setup the ABORT buffer here, however. */ + d->backstr = strdup(d->character->player.description); + } + write_to_output(d, "Enter the new text you'd like others to see when they look at you.\r\n"); + send_editor_help(d); + d->str = &d->character->player.description; + d->max_str = PLR_DESC_LENGTH; + STATE(d) = CON_PLR_DESC; +} + +void show_character_background_story_menu(struct descriptor_data *d) +{ + if (d->character->player.background) + { + write_to_output(d, "Current Character Background:\r\n%s", d->character->player.background); + /* Don't free this now... so that the old background gets loaded as the + * current buffer in the editor. Do setup the ABORT buffer here, however. */ + d->backstr = strdup(d->character->player.background); + } + write_to_output(d, "Enter your character background story.\r\n"); + send_editor_help(d); + d->str = &d->character->player.background; + d->max_str = PLR_BG_LENGTH; + STATE(d) = CON_PLR_BG; +} + +void show_short_description_main_menu(struct descriptor_data *d) +{ + if (GET_PC_DESCRIPTOR_1(d->character) > 0 && GET_PC_ADJECTIVE_1(d->character) > 0) + { + send_to_char(d->character, "\r\n"); + send_to_char(d->character, "You have already chosen your description. To change it you'll need to request a description reset from a staff member.\r\n"); + send_to_char(d->character, "\r\n"); + } + else + { + send_to_char(d->character, "\r\n"); + send_to_char(d->character, "SET CHARACTER SHORT DESCRIPTION: PRESS ENTER\r\n"); + send_to_char(d->character, "\r\n"); + STATE(d) = CON_GEN_DESCS_INTRO; + } +} + +void show_character_background_archtype_menu(struct descriptor_data *d) +{ + + int i = 0; + + if (GET_BACKGROUND(d->character) > 0) + { + write_to_output(d, "You have already chosen a background archtype. You can reset it by respeccing.\r\n"); + return; + } + + write_to_output(d, "In addition to a background story, a character can also have a background archytype.\r\n"); + write_to_output(d, "Though this has a mechanical benefit in the way of improved skills and new abilities or\r\n"); + write_to_output(d, "benefits, you should choose something that fits your character concept.\r\n"); + write_to_output(d, "\r\n"); + + for (i = 1; i < NUM_BACKGROUNDS; i++) + { + write_to_output(d, "%s\r\n", background_list[backgrounds_listed_alphabetically[i]].name); + } + + write_to_output(d, "\r\n"); + write_to_output(d, "quit\r\n"); + + write_to_output(d, "\r\n"); + write_to_output(d, "Enter the name of the background you would like: "); + + STATE(d) = CON_BACKGROUND_ARCHTYPE; + +} \ No newline at end of file diff --git a/interpreter.h b/interpreter.h index d64d0f80..12cd6083 100755 --- a/interpreter.h +++ b/interpreter.h @@ -55,6 +55,14 @@ void show_account_menu(struct descriptor_data *d); void remove_char_from_account(struct char_data *ch, struct account_data *account); char *get_char_account_name(char *name); + +void show_character_rp_menu(struct descriptor_data *d); +void show_short_description_main_menu(struct descriptor_data *d); +void show_character_long_description_menu(struct descriptor_data *d); +void show_homeland_region_main_menu(struct descriptor_data *d); +void show_character_background_story_menu(struct descriptor_data *d); +void show_character_background_archtype_menu(struct descriptor_data *d); + ACMD_DECL(do_account); /* ACMDs available through interpreter.c */ @@ -157,6 +165,14 @@ struct alias_data #define SCMD_DIALOGUE_INTIMIDATE 2 #define SCMD_DIALOGUE_BLUFF 3 +#define SCMD_RP_DESC 1 +#define SCMD_RP_PERSONALITY 2 +#define SCMD_RP_GOALS 3 +#define SCMD_RP_IDEALS 4 +#define SCMD_RP_BONDS 5 +#define SCMD_RP_FLAWS 6 +#define SCMD_RP_BG_STORY 7 + /* Necessary for CMD_IS macro. Borland needs the structure defined first * so it has been moved down here. */ /* Global buffering system */ diff --git a/limits.c b/limits.c index afebf189..0a4fdfa6 100755 --- a/limits.c +++ b/limits.c @@ -1062,7 +1062,10 @@ int gain_exp(struct char_data *ch, int gain, int mode) { if (gain >= 1000 && GET_ACCEXP_DESC(ch) <= 99999999) { - send_to_char(ch, "You gain %d account experience points!\r\n", (gain / 1000)); + if (!ch->char_specials.post_combat_messages) + send_to_char(ch, "You gain %d account experience points!\r\n", (gain / 1000)); + else + ch->char_specials.post_combat_account_exp = gain / 1000; change_account_xp(ch, (gain / 1000)); } } @@ -1072,8 +1075,18 @@ int gain_exp(struct char_data *ch, int gain, int mode) { if (gain >= 3000 && GET_ACCEXP_DESC(ch) <= 99999999) { - if (gain / 3000 >= 4) /*reduce spam*/ - send_to_char(ch, "You gain %d account experience points!\r\n", (gain / 3000)); + + if (!ch->char_specials.post_combat_messages) + { + if (gain / 3000 >= 4) + { + send_to_char(ch, "You gain %d account experience points!\r\n", (gain / 3000)); + } + } + else + { + ch->char_specials.post_combat_account_exp = gain / 3000; + } change_account_xp(ch, (gain / 3000)); } } @@ -1594,6 +1607,15 @@ void update_player_misc(void) } } + if (GET_RETAINER_COOLDOWN(ch) > 0) + { + GET_RETAINER_COOLDOWN(ch)--; + if (GET_RETAINER_COOLDOWN(ch) == 0) + { + send_to_char(ch, "You can now call your retainer again.\r\n"); + } + } + if (HAS_FEAT(ch, FEAT_DETECT_ALIGNMENT)) SET_BIT_AR(AFF_FLAGS(ch), AFF_DETECT_ALIGN); @@ -2336,7 +2358,8 @@ void update_damage_and_effects_over_time(void) SET_BIT_AR(AFF_FLAGS(ch), AFF_WATER_BREATH); // This code handles ability score damage which can be healed with various 'restoration' spells - if (GET_STR(ch) <= 0 || GET_DEX(ch) <= 0 || GET_INT(ch) <= 0 || GET_WIS(ch) <= 0 || GET_CHA(ch) <= 0 || GET_CON(ch) <= 0) + if (GET_STR(ch) <= 0 || GET_DEX(ch) <= 0 || GET_INT(ch) <= 0 || GET_WIS(ch) <= 0 || + GET_CHA(ch) <= 0 || GET_CON(ch) <= 0) { struct affected_type af; new_affect(&af); diff --git a/magic.c b/magic.c index 8adc397c..04e0fd3f 100755 --- a/magic.c +++ b/magic.c @@ -104,7 +104,7 @@ int compute_spell_res(struct char_data *ch, struct char_data *vict, int modifier if (affected_by_spell(vict, SKILL_INNER_FIRE)) resist = MAX(resist, 25); - if (affected_by_spell(vict, SPELL_HOLY_AURA) && IS_EVIL(ch)) + if (affected_by_spell(vict, SPELL_HOLY_AURA) && ch && IS_EVIL(ch)) resist = MAX(resist, 25); if (IS_AFFECTED(vict, AFF_SPELL_RESISTANT)) @@ -274,7 +274,7 @@ int compute_mag_saves(struct char_data *vict, int type, int modifier) saves += modifier; } - return MIN(99, MAX(saves, 0)); + return MIN(99, saves); } // TRUE = resisted @@ -296,11 +296,12 @@ int mag_savingthrow_full(struct char_data *ch, struct char_data *vict, int challenge = 10, // 10 is base DC diceroll = d20(vict), stat_bonus = 0, - savethrow = compute_mag_saves(vict, type, modifier) + diceroll; + savethrow = 0; struct affected_type *af = NULL; if (has_teamwork_feat(vict, FEAT_DUCK_AND_COVER) && type == SAVING_REFL) diceroll = MAX(diceroll, d20(vict)); + savethrow = compute_mag_saves(vict, type, modifier) + diceroll; if (type == SAVING_REFL && (get_speed(vict, false) - 10) > get_speed(ch, false)) @@ -537,6 +538,8 @@ int mag_savingthrow_full(struct char_data *ch, struct char_data *vict, } } + savethrow = MAX(1, savethrow); + if (diceroll != 1 && (savethrow >= challenge || diceroll == 20)) { if (diceroll == 20) @@ -1073,6 +1076,14 @@ int mag_damage(int level, struct char_data *ch, struct char_data *victim, size_dice = 6; bonus = 0; break; + + case MOB_ABILITY_CORRUPTION: + save = SAVING_FORT; + element = DAM_NEGATIVE; + num_dice = 1; + size_dice = 6; + bonus = 0; + break; /*******************************************\ || ------------ WARLOCK POWERS ----------- || @@ -3287,6 +3298,24 @@ void mag_affects_full(int level, struct char_data *ch, struct char_data *victim, // misc + case MOB_ABILITY_CORRUPTION: + if (mag_savingthrow_full(ch, victim, SAVING_FORT, 0, casttype, level, ENCHANTMENT, spellnum)) + { + return; + } + af[0].location = APPLY_DEX; + af[0].duration = 1; + af[0].modifier = -2; + af[1].location = APPLY_CON; + af[1].duration = 1; + af[1].modifier = -2; + af[1].location = APPLY_DEX; + af[1].duration = 1; + af[1].modifier = -2; + to_vict = "You feel corruption tearing apart your very essence."; + to_room = "$n looks seriously ill!"; + break; + case SPELL_MINOR_RAPID_BUFF: if (GET_LEVEL(ch) > 10) { @@ -4758,10 +4787,14 @@ void mag_affects_full(int level, struct char_data *ch, struct char_data *victim, case WARLOCK_SEE_THE_UNSEEN: + af[0].location = APPLY_SPECIAL; + af[0].modifier = 1; af[0].duration = 3600; SET_BIT_AR(af[0].bitvector, AFF_DARKVISION); + af[1].location = APPLY_SPECIAL; + af[1].modifier = 1; af[1].duration = 3600; - SET_BIT_AR(af[0].bitvector, AFF_DETECT_INVIS); + SET_BIT_AR(af[1].bitvector, AFF_DETECT_INVIS); to_vict = "You can now see into the shadows and things not meant to be seen."; break; @@ -4796,6 +4829,26 @@ void mag_affects_full(int level, struct char_data *ch, struct char_data *victim, if (!victim) victim = ch; + if (affected_by_spell(victim, SPELL_STONESKIN) || + affected_by_spell(victim, SPELL_IRONSKIN) || + affected_by_spell(victim, SPELL_EPIC_WARDING)) + { + send_to_char(ch, "They already have a better ward active.\r\n"); + return; + } + + if (has_dr_affect(victim, WARLOCK_DARK_FORESIGHT) || affected_by_spell(victim, WARLOCK_DARK_FORESIGHT)) + { + send_to_char(ch, "The target already has this affect.\r\n"); + return; + } + + af[0].location = APPLY_DR; + af[0].duration = 100; + af[0].modifier = 10; + + GET_STONESKIN(victim) = MIN(150, 10 * GET_WARLOCK_LEVEL(ch)); + CREATE(new_dr, struct damage_reduction_type, 1); new_dr->bypass_cat[0] = DR_BYPASS_CAT_MATERIAL; @@ -4813,7 +4866,7 @@ void mag_affects_full(int level, struct char_data *ch, struct char_data *victim, new_dr->feat = FEAT_UNDEFINED; new_dr->next = GET_DR(victim); GET_DR(victim) = new_dr; - to_room = "Your senses become enhanced with visions of the future."; + to_vict = "Your senses become enhanced with visions of the future."; break; case WARLOCK_RETRIBUTIVE_INVISIBILITY: @@ -7024,6 +7077,15 @@ void mag_affects_full(int level, struct char_data *ch, struct char_data *victim, { affect_from_char(victim, SPELL_STONESKIN); } + if (affected_by_spell(victim, WARLOCK_DARK_FORESIGHT)) + { + affect_from_char(victim, WARLOCK_DARK_FORESIGHT); + } + if (affected_by_spell(victim, SPELL_EPIC_WARDING)) + { + send_to_char(ch, "They already have a better ward active.\r\n"); + return; + } SET_BIT_AR(af[0].bitvector, AFF_WARDED); af[0].duration = 600; @@ -7970,7 +8032,8 @@ void mag_affects_full(int level, struct char_data *ch, struct char_data *victim, case SPELL_STONESKIN: if (affected_by_spell(victim, SPELL_EPIC_WARDING) || - affected_by_spell(victim, SPELL_IRONSKIN)) + affected_by_spell(victim, SPELL_IRONSKIN) || + affected_by_spell(victim, WARLOCK_DARK_FORESIGHT)) { send_to_char(ch, "A magical ward is already in effect on target.\r\n"); return; @@ -8030,14 +8093,14 @@ void mag_affects_full(int level, struct char_data *ch, struct char_data *victim, case RACIAL_ABILITY_CRYSTAL_BODY: - /* Remove the dr. */ - for (dr = GET_DR(ch); dr != NULL; dr = dr->next) + /* Remove the dr. */ + for (dr = GET_DR(ch); dr != NULL; dr = dr->next) + { + if (dr->spell == spellnum) { - if (dr->spell == spellnum) - { - REMOVE_FROM_LIST(dr, GET_DR(ch), next); - } + REMOVE_FROM_LIST(dr, GET_DR(ch), next); } + } af[0].location = APPLY_DR; af[0].modifier = 3; @@ -8711,7 +8774,7 @@ static void perform_mag_groups(int level, struct char_data *ch, mag_affects(level, ch, tch, obj, SPELL_DAZE_MONSTER, savetype, casttype, 0); break; case ABILITY_CHANNEL_POSITIVE_ENERGY: - if (!IS_UNDEAD(tch)) + if (!IS_UNDEAD(tch) && !is_player_grouped(ch, tch)) mag_points(compute_channel_energy_level(ch), ch, tch, obj, ABILITY_CHANNEL_POSITIVE_ENERGY, savetype, casttype); break; case ABILITY_CHANNEL_NEGATIVE_ENERGY: @@ -9516,7 +9579,7 @@ void mag_areas(int level, struct char_data *ch, struct obj_data *obj, if (aoeOK(ch, tch, spellnum)) { - if (spellnum == ABILITY_CHANNEL_POSITIVE_ENERGY && !IS_UNDEAD(tch)) + if (spellnum == ABILITY_CHANNEL_POSITIVE_ENERGY && (!IS_UNDEAD(tch) || is_player_grouped(ch, tch))) continue; else if (spellnum == ABILITY_CHANNEL_NEGATIVE_ENERGY && IS_UNDEAD(tch)) continue; diff --git a/modify.c b/modify.c index e1e3db83..3c9c8cbf 100755 --- a/modify.c +++ b/modify.c @@ -36,6 +36,11 @@ static int count_pages(char *str, struct char_data *ch); static void playing_string_cleanup(struct descriptor_data *d, int action); static void exdesc_string_cleanup(struct descriptor_data *d, int action); static void bg_string_cleanup(struct descriptor_data *d, int action); +static void goal_string_cleanup(struct descriptor_data *d, int action); +static void personality_string_cleanup(struct descriptor_data *d, int action); +static void ideals_string_cleanup(struct descriptor_data *d, int action); +static void bonds_string_cleanup(struct descriptor_data *d, int action); +static void flaws_string_cleanup(struct descriptor_data *d, int action); void new_mail_string_cleanup(struct descriptor_data *d, int action); @@ -232,6 +237,11 @@ void string_add(struct descriptor_data *d, char *str) case CON_IBTEDIT: case CON_NEWMAIL: case CON_PLR_BG: + case CON_CHARACTER_GOALS_ENTER: + case CON_CHARACTER_PERSONALITY_ENTER: + case CON_CHARACTER_IDEALS_ENTER: + case CON_CHARACTER_BONDS_ENTER: + case CON_CHARACTER_FLAWS_ENTER: free(*d->str); *d->str = d->backstr; d->backstr = NULL; @@ -274,6 +284,11 @@ void string_add(struct descriptor_data *d, char *str) {CON_TRIGEDIT, trigedit_string_cleanup}, {CON_PLR_DESC, exdesc_string_cleanup}, {CON_PLR_BG, bg_string_cleanup}, + {CON_CHARACTER_GOALS_ENTER, goal_string_cleanup}, + {CON_CHARACTER_PERSONALITY_ENTER, personality_string_cleanup}, + {CON_CHARACTER_IDEALS_ENTER, ideals_string_cleanup}, + {CON_CHARACTER_BONDS_ENTER, bonds_string_cleanup}, + {CON_CHARACTER_FLAWS_ENTER, flaws_string_cleanup}, {CON_PLAYING, playing_string_cleanup}, {CON_HEDIT, hedit_string_cleanup}, {CON_QEDIT, qedit_string_cleanup}, @@ -410,8 +425,8 @@ static void exdesc_string_cleanup(struct descriptor_data *d, int action) if (action == STRINGADD_ABORT) write_to_output(d, "Description aborted.\r\n"); - write_to_output(d, "%s", CONFIG_MENU); - STATE(d) = CON_MENU; + show_character_rp_menu(d); + STATE(d) = CON_CHAR_RP_MENU; } static void bg_string_cleanup(struct descriptor_data *d, int action) @@ -419,8 +434,53 @@ static void bg_string_cleanup(struct descriptor_data *d, int action) if (action == STRINGADD_ABORT) write_to_output(d, "Background aborted.\r\n"); - write_to_output(d, "%s", CONFIG_MENU); - STATE(d) = CON_MENU; + show_character_rp_menu(d); + STATE(d) = CON_CHAR_RP_MENU; +} + +static void goal_string_cleanup(struct descriptor_data *d, int action) +{ + if (action == STRINGADD_ABORT) + write_to_output(d, "Goals editing aborted.\r\n"); + + show_character_rp_menu(d); + STATE(d) = CON_CHAR_RP_MENU; +} + +static void personality_string_cleanup(struct descriptor_data *d, int action) +{ + if (action == STRINGADD_ABORT) + write_to_output(d, "Personality editing aborted.\r\n"); + + show_character_rp_menu(d); + STATE(d) = CON_CHAR_RP_MENU; +} + +static void ideals_string_cleanup(struct descriptor_data *d, int action) +{ + if (action == STRINGADD_ABORT) + write_to_output(d, "Ideals editing aborted.\r\n"); + + show_character_rp_menu(d); + STATE(d) = CON_CHAR_RP_MENU; +} + +static void bonds_string_cleanup(struct descriptor_data *d, int action) +{ + if (action == STRINGADD_ABORT) + write_to_output(d, "Bonds editing aborted.\r\n"); + + show_character_rp_menu(d); + STATE(d) = CON_CHAR_RP_MENU; +} + +static void flaws_string_cleanup(struct descriptor_data *d, int action) +{ + if (action == STRINGADD_ABORT) + write_to_output(d, "Flaws editing aborted.\r\n"); + + show_character_rp_menu(d); + STATE(d) = CON_CHAR_RP_MENU; } /* Modification of character skills. */ diff --git a/objsave.c b/objsave.c index c77376c1..658d5de9 100755 --- a/objsave.c +++ b/objsave.c @@ -869,7 +869,6 @@ static int Crash_save(struct obj_data *obj, struct char_data *ch, FILE *fp, int // Like crash save but for pets static int Crash_save_pet(struct obj_data *obj, struct char_data *ch, struct char_data *owner, long int pet_idnum, int location) { - struct obj_data *tmp; int result; if (obj) @@ -1803,10 +1802,10 @@ obj_save_data *objsave_parse_objects(FILE *fl) struct extra_descr_data *new_desc; char error[40]; snprintf(error, sizeof(error) - 1, "rent(Edes): %s", temp->name); - if (temp->item_number != NOTHING && /* Regular object */ - temp->ex_description && /* with ex_desc == prototype */ - (temp->ex_description == - obj_proto[real_object(temp->item_number)].ex_description)) + // if (temp->item_number != NOTHING && // Regular object + // temp->ex_description && // with ex_desc == prototype + // (temp->ex_description == + // obj_proto[real_object(temp->item_number)].ex_description)) temp->ex_description = NULL; CREATE(new_desc, struct extra_descr_data, 1); new_desc->keyword = fread_string(fl, error); @@ -2145,10 +2144,10 @@ obj_save_data *objsave_parse_objects_db(char *name, room_vnum house_vnum) struct extra_descr_data *new_desc; char error[40]; snprintf(error, sizeof(error) - 1, "rent(Edes): %s", temp->name); - if (temp->item_number != NOTHING && /* Regular object */ - temp->ex_description && /* with ex_desc == prototype */ - (temp->ex_description == - obj_proto[real_object(temp->item_number)].ex_description)) + // if (temp->item_number != NOTHING && // Regular object // + // temp->ex_description && // with ex_desc == prototype // + // (temp->ex_description == + // obj_proto[real_object(temp->item_number)].ex_description)) temp->ex_description = NULL; CREATE(new_desc, struct extra_descr_data, 1); free(*line); @@ -3061,11 +3060,11 @@ obj_save_data *objsave_parse_objects_db_pet(char *name, long int pet_idnum) struct extra_descr_data *new_desc; char error[40]; snprintf(error, sizeof(error) - 1, "rent(Edes): %s", temp->name); - if (temp->item_number != NOTHING && /* Regular object */ - temp->ex_description && /* with ex_desc == prototype */ - (temp->ex_description == - obj_proto[real_object(temp->item_number)].ex_description)) - temp->ex_description = NULL; + // if (temp->item_number != NOTHING && // Regular object + // temp->ex_description && // with ex_desc == prototype + // (temp->ex_description == + // obj_proto[real_object(temp->item_number)].ex_description)) + temp->ex_description = NULL; CREATE(new_desc, struct extra_descr_data, 1); free(*line); ++line; diff --git a/players.c b/players.c index 20ecdba9..04c133bb 100755 --- a/players.c +++ b/players.c @@ -381,17 +381,24 @@ int load_char(const char *name, struct char_data *ch) for (i = 0; i < NUM_SFEATS; i++) ch->char_specials.saved.school_feats[i] = 0; + ch->char_specials.post_combat_exp = ch->char_specials.post_combat_gold = ch->char_specials.post_combat_account_exp = 0; + + BLASTING(ch) = FALSE; + for (i = 0; i < NUM_CLASSES; i++) { GET_CLASS_FEATS(ch, i) = 0; GET_EPIC_CLASS_FEATS(ch, i) = 0; } + GET_HOMETOWN(ch) = 0; GET_FEAT_POINTS(ch) = 0; GET_EPIC_FEAT_POINTS(ch) = 0; destroy_spell_prep_queue(ch); destroy_innate_magic_queue(ch); destroy_spell_collection(ch); destroy_known_spells(ch); + GET_CH_AGE(ch) = 0; + ch->player_specials->saved.character_age_saved = false; GET_REAL_SIZE(ch) = PFDEF_SIZE; IS_MORPHED(ch) = PFDEF_MORPHED; GET_SEX(ch) = PFDEF_SEX; @@ -453,6 +460,8 @@ int load_char(const char *name, struct char_data *ch) GET_FIGHT_TO_THE_DEATH_COOLDOWN(ch) = 0; GET_DRAGON_BOND_TYPE(ch) = 0; GET_DRAGON_RIDER_DRAGON_TYPE(ch) = 0; + GET_FORAGE_COOLDOWN(ch) = 0; + GET_RETAINER_COOLDOWN(ch) = 0; for (i = 0; i < MAX_CURRENT_QUESTS; i++) { /* loop through all the character's quest slots */ @@ -461,7 +470,11 @@ int load_char(const char *name, struct char_data *ch) } GET_IMM_TITLE(ch) = NULL; - + ch->player.goals = NULL; + ch->player.personality = NULL; + ch->player.ideals = NULL; + ch->player.bonds = NULL; + ch->player.flaws = NULL; GET_HP_REGEN(ch) = 0; GET_MV_REGEN(ch) = 0; GET_PSP_REGEN(ch) = 0; @@ -694,6 +707,10 @@ int load_char(const char *name, struct char_data *ch) load_affects(fl, ch); else if (!strcmp(tag, "Alin")) GET_ALIGNMENT(ch) = atoi(line); + else if (!strcmp(tag, "Age ")) + GET_CH_AGE(ch) = atoi(line); + else if (!strcmp(tag, "AgeS")) + (ch)->player_specials->saved.character_age_saved = atoi(line); else if (!strcmp(tag, "Alis")) read_aliases_ascii(fl, ch, atoi(line)); break; @@ -703,8 +720,12 @@ int load_char(const char *name, struct char_data *ch) GET_BAD_PWS(ch) = atoi(line); else if (!strcmp(tag, "BGnd")) GET_BACKGROUND(ch) = atoi(line); + else if (!strcmp(tag, "Bond")) + ch->player.bonds = fread_string(fl, buf2); else if (!strcmp(tag, "Bag1")) GET_BAG_NAME(ch, 1) = strdup(line); + else if (!strcmp(tag, "Blst")) + BLASTING(ch) = atoi(line); else if (!strcmp(tag, "Bag2")) GET_BAG_NAME(ch, 2) = strdup(line); else if (!strcmp(tag, "Bag3")) @@ -885,8 +906,12 @@ int load_char(const char *name, struct char_data *ch) GET_FACTION_STANDING(ch, FACTION_ADVENTURERS) = atol(line); else if (!strcmp(tag, "Feat")) load_feats(fl, ch); + else if (!strcmp(tag, "FrgC")) + GET_FORAGE_COOLDOWN(ch) = atoi(line); else if (!strcmp(tag, "FLGT")) FLEETING_GLANCE_TIMER(ch) = atoi(line); + else if (!strcmp(tag, "Flaw")) + ch->player.flaws = fread_string(fl, buf2); else if (!strcmp(tag, "FdBn")) ch->player_specials->saved.fiendish_boons = atoi(line); else if (!strcmp(tag, "FLGU")) @@ -922,6 +947,8 @@ int load_char(const char *name, struct char_data *ch) GRASP_OF_THE_DEAD_TIMER(ch) = atoi(line); else if (!strcmp(tag, "GODU")) GRASP_OF_THE_DEAD_USES(ch) = atoi(line); + else if (!strcmp(tag, "Goal")) + ch->player.goals = fread_string(fl, buf2); break; case 'H': @@ -935,6 +962,8 @@ int load_char(const char *name, struct char_data *ch) GET_HOLY_WEAPON_TYPE(ch) = atoi(line); else if (!strcmp(tag, "Home")) GET_REGION(ch) = atoi(line); + else if (!strcmp(tag, "HomT")) + GET_HOMETOWN(ch) = atoi(line); else if (!strcmp(tag, "Host")) { if (GET_HOST(ch)) @@ -952,6 +981,8 @@ int load_char(const char *name, struct char_data *ch) case 'I': if (!strcmp(tag, "Id ")) GET_IDNUM(ch) = atol(line); + else if (!strcmp(tag, "Idel")) + ch->player.ideals = fread_string(fl, buf2); else if (!strcmp(tag, "InMa")) load_innate_magic_queue(fl, ch); else if (!strcmp(tag, "Int ")) @@ -1111,6 +1142,8 @@ int load_char(const char *name, struct char_data *ch) PIXIE_DUST_USES(ch) = atoi(line); else if (!strcmp(tag, "PxDT")) PIXIE_DUST_TIMER(ch) = atoi(line); + else if (!strcmp(tag, "Pers")) + ch->player.personality = fread_string(fl, buf2); break; case 'Q': @@ -1185,6 +1218,8 @@ int load_char(const char *name, struct char_data *ch) GET_1ST_RESTRICTED_SCHOOL(ch) = atoi(line); else if (!strcmp(tag, "RSc2")) GET_2ND_RESTRICTED_SCHOOL(ch) = atoi(line); + else if (!strcmp(tag, "RetC")) + GET_RETAINER_COOLDOWN(ch) = atoi(line); break; case 'S': @@ -1501,6 +1536,38 @@ void save_char(struct char_data *ch, int mode) strip_cr(buf); fprintf(fl, "BGrd:\n%s~\n", buf); } + if (ch->player.goals && *ch->player.goals) + { + strlcpy(buf, ch->player.goals, sizeof(buf)); + strip_cr(buf); + fprintf(fl, "Goal:\n%s~\n", buf); + } + if (ch->player.personality && *ch->player.personality) + { + strlcpy(buf, ch->player.personality, sizeof(buf)); + strip_cr(buf); + fprintf(fl, "Pers:\n%s~\n", buf); + } + if (ch->player.ideals && *ch->player.ideals) + { + strlcpy(buf, ch->player.ideals, sizeof(buf)); + strip_cr(buf); + fprintf(fl, "Idel:\n%s~\n", buf); + } + if (ch->player.bonds && *ch->player.bonds) + { + strlcpy(buf, ch->player.bonds, sizeof(buf)); + strip_cr(buf); + fprintf(fl, "Bond:\n%s~\n", buf); + } + if (ch->player.flaws && *ch->player.flaws) + { + strlcpy(buf, ch->player.flaws, sizeof(buf)); + strip_cr(buf); + fprintf(fl, "Flaw:\n%s~\n", buf); + } + if (BLASTING(ch)) + fprintf(fl, "Blst: 1\n"); if (POOFIN(ch)) fprintf(fl, "PfIn: %s\n", POOFIN(ch)); if (POOFOUT(ch)) @@ -1553,6 +1620,7 @@ void save_char(struct char_data *ch, int mode) fprintf(fl, "Spek: %d\n", SPEAKING(ch)); fprintf(fl, "Home: %d\n", GET_REGION(ch)); + fprintf(fl, "HomT: %d\n", GET_HOMETOWN(ch)); fprintf(fl, "DAd1: %d\n", GET_PC_ADJECTIVE_1(ch)); fprintf(fl, "DAd2: %d\n", GET_PC_ADJECTIVE_2(ch)); fprintf(fl, "DDs1: %d\n", GET_PC_DESCRIPTOR_1(ch)); @@ -1573,6 +1641,10 @@ void save_char(struct char_data *ch, int mode) fprintf(fl, "Wate: %d\n", GET_WEIGHT(ch)); if (GET_ALIGNMENT(ch) != PFDEF_ALIGNMENT) fprintf(fl, "Alin: %d\n", GET_ALIGNMENT(ch)); + if (GET_CH_AGE(ch) != 0) + fprintf(fl, "Age : %d\n", GET_CH_AGE(ch)); + if ((ch)->player_specials->saved.character_age_saved != 0) + fprintf(fl, "AgeS: %d\n", (ch)->player_specials->saved.character_age_saved); if (GET_TEMPLATE(ch) != PFDEF_TEMPLATE) fprintf(fl, "Tmpl: %d\n", GET_TEMPLATE(ch)); // Faction mission system @@ -1778,13 +1850,16 @@ void save_char(struct char_data *ch, int mode) if (IS_MORPHED(ch) != PFDEF_MORPHED) fprintf(fl, "Mrph: %d\n", IS_MORPHED(ch)); if (MERGE_FORMS_TIMER(ch) != 0) - fprintf(fl, "EidC: %d\n", MERGE_FORMS_TIMER(ch)); + fprintf(fl, "MFrm: %d\n", MERGE_FORMS_TIMER(ch)); if (GET_EIDOLON_BASE_FORM(ch) != 0) fprintf(fl, "EidB: %d\n", GET_EIDOLON_BASE_FORM(ch)); if (CALL_EIDOLON_COOLDOWN(ch) != 0) - fprintf(fl, "MFrm: %d\n", CALL_EIDOLON_COOLDOWN(ch)); + fprintf(fl, "EidC: %d\n", CALL_EIDOLON_COOLDOWN(ch)); + if (GET_FORAGE_COOLDOWN(ch) != 0) + fprintf(fl, "FrgC: %d\n", GET_FORAGE_COOLDOWN(ch)); + if (GET_RETAINER_COOLDOWN(ch) != 0) + fprintf(fl, "RetC: %d\n", GET_RETAINER_COOLDOWN(ch)); fprintf(fl, "God : %d\n", GET_DEITY(ch)); - if (GET_AUTOCQUEST_VNUM(ch) != PFDEF_AUTOCQUEST_VNUM) fprintf(fl, "Cvnm: %d\n", GET_AUTOCQUEST_VNUM(ch)); if (GET_AUTOCQUEST_MAKENUM(ch) != PFDEF_AUTOCQUEST_MAKENUM) diff --git a/prefedit.c b/prefedit.c index fedf6075..473e7bda 100755 --- a/prefedit.c +++ b/prefedit.c @@ -78,6 +78,8 @@ static void prefedit_save_to_char(struct descriptor_data *d) GET_PAGE_LENGTH(vict) = OLC_PREFS(d)->page_length; GET_SCREEN_WIDTH(vict) = OLC_PREFS(d)->screen_width; + BLASTING(vict) = PRF_FLAGGED(vict, PRF_AUTOBLAST); + save_char(vict, 0); } else @@ -231,7 +233,9 @@ static void prefedit_extra_disp_toggles_menu(struct descriptor_data *d) /* Line 6 (6) - Condensed Combat Mode */ "%s7%s) Careful with Pets %s[%s%3s%s] %sF%s) Contain AoEs %s[%s%3s%s]\r\n" /* Line 7 (7) - Careful with Pets Toggle */ - "%s8%s) Reject Rage Spell %s[%s%3s%s]\r\n", + "%s8%s) Reject Rage Spell %s[%s%3s%s] %sG%s) Flag Self as Non-Roleplayer %s[%s%3s%s]\r\n" + /* Line 8 (8) No Rage Spell */ + "%sH%s) Shorten Post Combat Text%s[%s%3s%s] %sI%s) Automatic Eldritch Blast %s[%s%3s%s]\r\n", /* Line 8 (8) No Rage Spell */ /*******1********/ CBYEL(d->character, C_NRM), CCNRM(d->character, C_NRM), CCCYN(d->character, C_NRM), @@ -299,7 +303,19 @@ static void prefedit_extra_disp_toggles_menu(struct descriptor_data *d) CBYEL(d->character, C_NRM), CCNRM(d->character, C_NRM), CCCYN(d->character, C_NRM), PREFEDIT_FLAGGED(PRF_NO_RAGE) ? CBGRN(d->character, C_NRM) : CBRED(d->character, C_NRM), - ONOFF(PREFEDIT_FLAGGED(PRF_NO_RAGE)), CCCYN(d->character, C_NRM) + ONOFF(PREFEDIT_FLAGGED(PRF_NO_RAGE)), CCCYN(d->character, C_NRM), + /**/ + CBYEL(d->character, C_NRM), CCNRM(d->character, C_NRM), CCCYN(d->character, C_NRM), + PREFEDIT_FLAGGED(PRF_NON_ROLEPLAYER) ? CBGRN(d->character, C_NRM) : CBRED(d->character, C_NRM), + ONOFF(PREFEDIT_FLAGGED(PRF_NON_ROLEPLAYER)), CCCYN(d->character, C_NRM), + /*******H*********/ + CBYEL(d->character, C_NRM), CCNRM(d->character, C_NRM), CCCYN(d->character, C_NRM), + PREFEDIT_FLAGGED(PRF_POST_COMBAT_BRIEF) ? CBGRN(d->character, C_NRM) : CBRED(d->character, C_NRM), + ONOFF(PREFEDIT_FLAGGED(PRF_POST_COMBAT_BRIEF)), CCCYN(d->character, C_NRM), + /**/ + CBYEL(d->character, C_NRM), CCNRM(d->character, C_NRM), CCCYN(d->character, C_NRM), + PREFEDIT_FLAGGED(PRF_AUTOBLAST) ? CBGRN(d->character, C_NRM) : CBRED(d->character, C_NRM), + ONOFF(PREFEDIT_FLAGGED(PRF_AUTOBLAST)), CCCYN(d->character, C_NRM) /*end*/); @@ -1029,6 +1045,21 @@ void prefedit_parse(struct descriptor_data *d, char *arg) TOGGLE_BIT_AR(PREFEDIT_GET_FLAGS, PRF_CONTAIN_AOE); break; + case 'g': + case 'G': + TOGGLE_BIT_AR(PREFEDIT_GET_FLAGS, PRF_NON_ROLEPLAYER); + break; + + case 'h': + case 'H': + TOGGLE_BIT_AR(PREFEDIT_GET_FLAGS, PRF_POST_COMBAT_BRIEF); + break; + + case 'i': + case 'I': + TOGGLE_BIT_AR(PREFEDIT_GET_FLAGS, PRF_AUTOBLAST); + break; + default: send_to_char(d->character, "Invalid Choice, try again (Q to Quit to main menu): "); return; diff --git a/premadebuilds.c b/premadebuilds.c index 98fbe152..77142208 100644 --- a/premadebuilds.c +++ b/premadebuilds.c @@ -508,6 +508,16 @@ void set_premade_stats(struct char_data *ch, int chclass, int level) break; } + if (level == 1) + { + GET_REAL_STR(ch) += character_age_attributes[GET_CH_AGE(ch)][0]; + GET_REAL_CON(ch) += character_age_attributes[GET_CH_AGE(ch)][2]; + GET_REAL_INT(ch) += character_age_attributes[GET_CH_AGE(ch)][3]; + GET_REAL_WIS(ch) += character_age_attributes[GET_CH_AGE(ch)][4]; + GET_REAL_DEX(ch) += character_age_attributes[GET_CH_AGE(ch)][1]; + GET_REAL_CHA(ch) += character_age_attributes[GET_CH_AGE(ch)][5]; + } + if (IS_HUMAN(ch) && level == 1) add_human_premade_stats(ch, chclass); } diff --git a/roleplay.c b/roleplay.c new file mode 100644 index 00000000..807942c3 --- /dev/null +++ b/roleplay.c @@ -0,0 +1,1672 @@ +// These are miscellanous functions and features that +// contribute to the various role playing systems in +// the game. Not all 'role play' features are found in +// this file, however. + +#include "conf.h" +#include "sysdep.h" +#include "structs.h" +#include "utils.h" +#include "comm.h" +#include "spells.h" +#include "handler.h" +#include "db.h" +#include "interpreter.h" +#include "constants.h" +#include "backgrounds.h" +#include "treasure.h" +#include "handler.h" +#include "fight.h" +#include "spec_procs.h" +#include "clan.h" +#include "dg_scripts.h" +#include "feats.h" +#include "constants.h" +#include "improved-edit.h" +#include "roleplay.h" +#include "deities.h" +#include "char_descs.h" +#include "modify.h" + +extern const char * personality_traits[NUM_BACKGROUNDS][10]; +extern const char * character_ideals[NUM_BACKGROUNDS][8]; +extern const char * character_bonds[NUM_BACKGROUNDS][8]; +extern const char * character_flaws[NUM_BACKGROUNDS][8]; + +#define GOAL_DESCRIPTION ("Character goals are an important part of role playing. A character usually has " \ + "multiple goals, some short term, some mid term and some long term. Sometimes " \ + "these goals are interconnected and sometimes they aren't. A goal should have " \ + "an objective, a reason for pursuing it and one or more obstacles to achieving " \ + "the goal. A goal should be something achievable, and it should have a consequence " \ + "to failure. Goals can also change as a character grows and progresses. As a character " \ + "achieves or fails at completing their goals, their goals should be adjusted, with some " \ + "potentially removed while other new ones are added. Recording these here in-game helps " \ + "you establish a solid base for role playing your character, and it assists role-play " \ + "staff in helping you in your person role play stories as well as weave you into more " \ + "wide and global narratives. If you're serious about role play, this is well worth your time.") + +#define PERSONALITY_DESCRIPTION ("Personality traits are small, simple ways to help you set your character apart " \ + "from every other character. Your personality traits should tell you something " \ + "interesting and fun about your character. They should be self-descriptions that " \ + "are specific about what makes your character stand out. \"I'm smart\" is not a " \ + "good trait, because it describes a lot of characters. \"I've read every book in " \ + "Palanthas\" tells you something specific about your character's interests and " \ + "disposition. " \ + "Personality traits might describe the things your character likes, his or her " \ + "past accomplishments, things your character dislikes or fears, your character's " \ + "self-attitude or mannerisms, or the influence of his or her ability scores. " \ + "A useful place to start thinking about personality traits is to look at your " \ + "highest and lowest ability scores and define one trait related to each. Either " \ + "one could be positive or negative: you might work hard to overcome a low score, " \ + "for example, or be cocky about your high score. ") + +#define BONDS_DESCRIPTION ("Bonds represent a character's connections to people, places, and events in the " \ + "world. They tie you to things from your background. They might inspire you to " \ + "heights of heroism, or lead you to act against your own best interests if they " \ + "are threatened. They can work very much like ideals, driving a character's " \ + "motivations and goals. " \ + "Bonds might answer any of these questions: Whom do you care most about? To what " \ + "place do you feel a special connection? What is your most treasured possession? " \ + "Your bonds might be tied to your class, your background, your race, or some " \ + "other aspect of your character's history or personality. You might also gain new " \ + "bonds over the course of your adventures. ") + +#define IDEALS_DESCRIPTION ("Your ideals are the things that you believe in most strongly, the fundamental " \ + "moral and ethical principles that compel you to act as you do. Ideals encompass " \ + "everything from your life goals to your core belief system. " \ + "Ideals might answer any of these questions: What are the principles that you " \ + "will never betray? What would prompt you to make sacrifices? What drives you to " \ + "act and guides your goals and ambitions? What is the single most important thing " \ + "you strive for? " \ + "You can choose any ideals you like, but your character's alignment is a good " \ + "place to start defining them. Each background in this chapter includes six " \ + "suggested ideals. Five of them are linked to aspects of alignment: law, chaos, " \ + "good, evil, and neutrality. The last one has more to do with the particular " \ + "background than with moral or ethical perspectives. ") + +#define FLAWS_DESCRIPTION ("Your character's flaw represents some vice, compulsion, fear, or weakness—in " \ + "particular, anything that someone else could exploit to bring you to ruin or " \ + "cause you to act against your best interests. More significant than negative " \ + "personality traits, a flaw might answer any of these questions: What enrages " \ + "you? What's the one person, concept, or event that you are terrified of? What " \ + "are your vices? ") + +const char * personality_traits[NUM_BACKGROUNDS][10] = +{ + { // none - 0 + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + }, + { // acolyte + "", + "I idolize a particular hero of my faith, and constantly refer to that person's deeds and example.", + "I can find common ground between the fiercest enemies, empathizing with them and always working toward peace.", + "I see omens in every event and action. The gods try to speak to us, we just need to listen.", + "Nothing can shake my optimistic attitude.", + "I quote (or misquote) sacred texts and proverbs in almost every situation.", + "I am tolerant (or intolerant) of other faiths and respect (or condemn) the worship of other gods.", + "I've enjoyed fine food, drink, and high society among my temple's elite. Rough living grates on me.", + "I've spent so long in the temple that I have little practical experience dealing with people in the outside world.", + "" + }, + { // charlatan + "", + "I fall in and out of love easily, and am always pursuing someone.", + "I have a joke for every occasion, especially occasions where humor is inappropriate.", + "Flattery is my preferred trick for getting what I want.", + "I'm a born gambler who can't resist taking a risk for a potential payoff.", + "I lie about almost everything, even when there's no good reason to.", + "Sarcasm and insults are my weapons of choice.", + "I keep multiple holy symbols on me and invoke whatever deity might come in useful at any given moment.", + "I pocket anything I see that might have some value.", + "" + }, + { // criminal + "", + "I always have a plan for what to do when things go wrong.", + "I am always calm, no matter what the situation. I never raise my voice or let my emotions control me.", + "The first thing I do in a new place is note the locations of everything valuable-or where such things could be hidden.", + "I would rather make a new friend than a new enemy.", + "I am incredibly slow to trust. Those who seem the fairest often have the most to hide.", + "I don't pay attention to the risks in a situation. Never tell me the odds.", + "The best way to get me to do something is to tell me I can't do it.", + "I blow up at the slightest insult.", + "" + }, + { // entertainer + "", + "I know a story relevant to almost every situation.", + "Whenever I come to a new place, I collect local rumors and spread gossip.", + "I'm a hopeless romantic, always searching for that 'special someone.'", + "Nobody stays angry at me or around me for long, since I can defuse any amount of tension.", + "I love a good insult, even one directed at me.", + "I get bitter if I'm not the center of attention.", + "I'll settle for nothing less than perfection.", + "I change my mood or my mind as quickly as I change key in a song.", + "" + }, + { // folk hero + "", + "I judge people by their actions, not their words.", + "If someone is in trouble, I'm always ready to lend help.", + "When I set my mind to something, I follow through no matter what gets in my way.", + "I have a strong sense of fair play and always try to find the most equitable solution to arguments.", + "I'm confident in my own abilities and do what I can to instill confidence in others.", + "Thinking is for other people. I prefer action.", + "I misuse long words in an attempt to sound smarter.", + "I get bored easily. When am I going to get on with my destiny?", + "" + }, + { //gladiator + "", + "I know a story relevant to almost every situation.", + "Whenever I come to a new place, I collect local rumors and spread gossip.", + "I'm a hopeless romantic, always searching for that 'special someone.'", + "Nobody stays angry at me or around me for long, since I can defuse any amount of tension.", + "I love a good insult, even one directed at me.", + "I get bitter if I'm not the center of attention.", + "I'll settle for nothing less than perfection.", + "I change my mood or my mind as quickly as I change key in a song.", + "" + }, + { // trader + "", + "I believe that anything worth doing is worth doing right. I can't help it-I'm a perfectionist.", + "I'm a snob who looks down on those who can't appreciate fine art.", + "I always want to know how things work and what makes people tick.", + "I'm full of witty aphorisms and have a proverb for every occasion.", + "I'm rude to people who lack my commitment to hard work and fair play.", + "I like to talk at length about my profession.", + "I don't part with my money easily and will haggle tirelessly to get the best deal possible.", + "I'm well known for my work, and I want to make sure everyone appreciates it. I'm always taken aback when people haven't heard of me.", + "" + }, + { // hermit + "", + "I've been isolated for so long that I rarely speak, preferring gestures and the occasional grunt.", + "I am utterly serene, even in the face of disaster.", + "The leader of my community had something wise to say on every topic, and I am eager to share that wisdom.", + "I feel tremendous empathy for all who suffer.", + "I'm oblivious to etiquette and social expectations.", + "I connect everything that happens to me to a grand, cosmic plan.", + "I often get lost in my own thoughts and contemplation, becoming oblivious to my surroundings.", + "I am working on a grand philosophical theory and love sharing my ideas.", + "" + }, + { // squire + "", + "My eloquent flattery makes everyone I talk to feel like the most wonderful and important person in the world.", + "The common folk love me for my kindness and generosity.", + "No one could doubt by looking at my regal bearing that I am a cut above the unwashed masses.", + "I take great pains to always look my best and follow the latest fashions.", + "I don't like to get my hands dirty, and I won't be caught dead in unsuitable accommodations.", + "Despite my noble birth, I do not place myself above other folk. We all have the same blood.", + "My favor, once lost, is lost forever.", + "If you do me an injury, I will crush you, ruin your name, and salt your fields.", + "" + }, + { // noble + "", + "My eloquent flattery makes everyone I talk to feel like the most wonderful and important person in the world.", + "The common folk love me for my kindness and generosity.", + "No one could doubt by looking at my regal bearing that I am a cut above the unwashed masses.", + "I take great pains to always look my best and follow the latest fashions.", + "I don't like to get my hands dirty, and I won't be caught dead in unsuitable accommodations.", + "Despite my noble birth, I do not place myself above other folk. We all have the same blood.", + "My favor, once lost, is lost forever.", + "If you do me an injury, I will crush you, ruin your name, and salt your fields.", + "" + }, + { // outlander + "", + "I'm driven by a wanderlust that led me away from home.", + "I watch over my friends as if they were a litter of newborn pups.", + "I once ran twenty-five miles without stopping to warn to my clan of an approaching orc horde. I'd do it again if I had to.", + "I have a lesson for every situation, drawn from observing nature.", + "I place no stock in wealthy or well-mannered folk. Money and manners won't save you from a hungry owlbear.", + "I'm always picking things up, absently fiddling with them, and sometimes accidentally breaking them.", + "I feel far more comfortable around animals than people.", + "I was, in fact, raised by wolves.", + "" + }, + { // pirate + "", + "My friends know they can rely on me, no matter what.", + "I work hard so that I can play hard when the work is done.", + "I enjoy sailing into new ports and making new friends over a flagon of ale.", + "I stretch the truth for the sake of a good story.", + "To me, a tavern brawl is a nice way to get to know a new city.", + "I never pass up a friendly wager.", + "My language is as foul as an otyugh nest.", + "I like a job well done, especially if I can convince someone else to do it.", + "" + }, + { // sage + "", + "I use polysyllabic words that convey the impression of great erudition.", + "I've read every book in the world's greatest libraries-or I like to boast that I have.", + "I'm used to helping out those who aren't as smart as I am, and I patiently explain anything and everything to others.", + "There's nothing I like more than a good mystery.", + "I'm willing to listen to every side of an argument before I make my own judgment.", + "I ... speak ... slowly ... when talking ... to idiots, ... which ... almost ... everyone ... is ... compared ... to me.", + "I am horribly, horribly awkward in social situations.", + "I'm convinced that people are always trying to steal my secrets.", + "" + }, + { // sailor + "", + "My friends know they can rely on me, no matter what.", + "I work hard so that I can play hard when the work is done.", + "I enjoy sailing into new ports and making new friends over a flagon of ale.", + "I stretch the truth for the sake of a good story.", + "To me, a tavern brawl is a nice way to get to know a new city.", + "I never pass up a friendly wager.", + "My language is as foul as an otyugh nest.", + "I like a job well done, especially if I can convince someone else to do it.", + "" + }, + { // soldier + "", + "I'm always polite and respectful.", + "I'm haunted by memories of war. I can't get the images of violence out of my mind.", + "I've lost too many friends, and I'm slow to make new ones.", + "I'm full of inspiring and cautionary tales from my military experience relevant to almost every combat situation.", + "I can stare down a hell hound without flinching.", + "I enjoy being strong and like breaking things.", + "I have a crude sense of humor.", + "I face problems head-on. A simple, direct solution is the best path to success.", + "" + }, + { // urchin + "", + "I hide scraps of food and trinkets away in my pockets.", + "I ask a lot of questions.", + "I like to squeeze into small places where no one else can get to me.", + "I sleep with my back to a wall or tree, with everything I own wrapped in a bundle in my arms.", + "I eat like a pig and have bad manners.", + "I think anyone who's nice to me is hiding evil intent.", + "I don't like to bathe.", + "I bluntly say what other people are hinting at or hiding.", + "" + } +}; + +const char * character_ideals[NUM_BACKGROUNDS][8] = +{ + { + "", + "", + "", + "", + "", + "", + "", + "" + }, + { // acolyte + "", + "Tradition. The ancient traditions of worship and sacrifice must be preserved and upheld. (Lawful)", + "Charity. I always try to help those in need, no matter what the personal cost. (Good)", + "Change. We must help bring about the changes the gods are constantly working in the world. (Chaotic)", + "Power. I hope to one day rise to the top of my faith's religious hierarchy. (Lawful)", + "Faith. I trust that my deity will guide my actions. I have faith that if I work hard, things will go well. (Lawful)", + "Aspiration. I seek to prove myself worthy of my god's favor by matching my actions against his or her teachings. (Any)", + "" + }, + { // charlatan + "", + "Independence. I am a free spirit-no one tells me what to do. (Chaotic)", + "Fairness. I never target people who can't afford to lose a few coins. (Lawful)", + "Charity. I distribute the money I acquire to the people who really need it. (Good)", + "Creativity. I never run the same con twice. (Chaotic)", + "Friendship. Material goods come and go. Bonds of friendship last forever. (Good)", + "Aspiration. I'm determined to make something of myself. (Any)", + "" + }, + { // criminal + "", + "Honor. I don't steal from others in the trade. (Lawful)", + "Freedom. Chains are meant to be broken, as are those who would forge them. (Chaotic)", + "Charity. I steal from the wealthy so that I can help people in need. (Good)", + "Greed. I will do whatever it takes to become wealthy. (Evil)", + "People. I'm loyal to my friends, not to any ideals, and everyone else can take a trip down the Styx for all I care. (Neutral)", + "Redemption. There's a spark of good in everyone. (Good)", + "" + }, + { // entertainer + "", + "Beauty. When I perform, I make the world better than it was. (Good)", + "Tradition. The stories, legends, and songs of the past must never be forgotten, for they teach us who we are. (Lawful)", + "Creativity. The world is in need of new ideas and bold action. (Chaotic)", + "Greed. I'm only in it for the money and fame. (Evil)", + "People. I like seeing the smiles on people's faces when I perform. That's all that matters. (Neutral)", + "Honesty. Art should reflect the soul; it should come from within and reveal who we really are. (Any)", + "" + }, + { // folk hero + "", + "Respect. People deserve to be treated with dignity and respect. (Good)", + "Fairness. No one should get preferential treatment before the law, and no one is above the law. (Lawful)", + "Freedom. Tyrants must not be allowed to oppress the people. (Chaotic)", + "Might. If I become strong, I can take what I want-what I deserve. (Evil)", + "Sincerity. There's no good in pretending to be something I'm not. (Neutral)", + "Destiny. Nothing and no one can steer me away from my higher calling. (Any)", + "" + }, + { // gladiator + "", + "Beauty. When I perform, I make the world better than it was. (Good)", + "Tradition. The stories, legends, and songs of the past must never be forgotten, for they teach us who we are. (Lawful)", + "Creativity. The world is in need of new ideas and bold action. (Chaotic)", + "Greed. I'm only in it for the money and fame. (Evil)", + "People. I like seeing the smiles on people's faces when I perform. That's all that matters. (Neutral)", + "Honesty. Art should reflect the soul; it should come from within and reveal who we really are. (Any)", + "" + }, + { // trader + "", + "Community. It is the duty of all people to strengthen the bonds and security of communities. (Lawful)", + "Generosity. My talents were given to me so that I could use them to benefit the world. (Good)", + "Freedom. Everyone should be free to pursue his or her own livelihood. (Chaotic)", + "Greed. I'm only in it for the money. (Evil)", + "People. I'm committed to the people I care about, not to ideals. (Neutral)", + "Aspiration. I work hard to be the best there is at my craft. (Any)", + "" + }, + { // hermit + "", + "Greater Good. My gifts are meant to be shared with all, not used for my own benefit. (Good)", + "Logic. Emotions must not cloud our sense of what is right and true, or our logical thinking. (Lawful)", + "Free Thinking. Inquiry and curiosity are the pillars of progress. (Chaotic)", + "Power. Solitude and contemplation are paths toward mystical or magical power. (Evil)", + "Live and Let Live. Meddling in the affairs of others only causes trouble. (Neutral)", + "Self-Knowledge. If you know yourself, there's nothing left to know. (Any)", + "" + }, + { // squire + "", + "Respect. Respect is due to me because of my position, but all people regardless of station deserve to be treated with dignity. (Good)", + "Responsibility. It is my duty to respect the authority of those above me, just as those below me must respect mine. (Lawful)", + "Independence. I must prove that I can handle myself without the coddling of my family. (Chaotic)", + "Power. If I can attain more power, no one will tell me what to do. (Evil)", + "Family. Blood runs thicker than water. (Any)", + "Noble Obligation. It is my duty to protect and care for the people beneath me. (Good)", + "" + }, + { // noble + "", + "Respect. Respect is due to me because of my position, but all people regardless of station deserve to be treated with dignity. (Good)", + "Responsibility. It is my duty to respect the authority of those above me, just as those below me must respect mine. (Lawful)", + "Independence. I must prove that I can handle myself without the coddling of my family. (Chaotic)", + "Power. If I can attain more power, no one will tell me what to do. (Evil)", + "Family. Blood runs thicker than water. (Any)", + "Noble Obligation. It is my duty to protect and care for the people beneath me. (Good)", + "" + }, + { // outlander + "", + "Change. Life is like the seasons, in constant change, and we must change with it. (Chaotic)", + "Greater Good. It is each person's responsibility to make the most happiness for the whole tribe. (Good)", + "Honor. If I dishonor myself, I dishonor my whole clan. (Lawful)", + "Might. The strongest are meant to rule. (Evil)", + "Nature. The natural world is more important than all the constructs of civilization. (Neutral)", + "Glory. I must earn glory in battle, for myself and my clan. (Any)", + "" + }, + { // pirate + "", + "Respect. The thing that keeps a ship together is mutual respect between captain and crew. (Good)", + "Fairness. We all do the work, so we all share in the rewards. (Lawful)", + "Freedom. The sea is freedom-the freedom to go anywhere and do anything. (Chaotic)", + "Mastery. I'm a predator, and the other ships on the sea are my prey. (Evil)", + "People. I'm committed to my crewmates, not to ideals. (Neutral)", + "Aspiration. Someday I'll own my own ship and chart my own destiny. (Any", + "" + }, + { // sage + "", + "Knowledge. The path to power and self-improvement is through knowledge. (Neutral)", + "Beauty. What is beautiful points us beyond itself toward what is true. (Good)", + "Logic. Emotions must not cloud our logical thinking. (Lawful)", + "No Limits. Nothing should fetter the infinite possibility inherent in all existence. (Chaotic)", + "Power. Knowledge is the path to power and domination. (Evil)", + "Self-Improvement. The goal of a life of study is the betterment of oneself. (Any)", + "" + }, + { // sailor + "", + "Respect. The thing that keeps a ship together is mutual respect between captain and crew. (Good)", + "Fairness. We all do the work, so we all share in the rewards. (Lawful)", + "Freedom. The sea is freedom-the freedom to go anywhere and do anything. (Chaotic)", + "Mastery. I'm a predator, and the other ships on the sea are my prey. (Evil)", + "People. I'm committed to my crewmates, not to ideals. (Neutral)", + "Aspiration. Someday I'll own my own ship and chart my own destiny. (Any)", + "" + }, + { // soldier + "", + "Greater Good. Our lot is to lay down our lives in defense of others. (Good)", + "Responsibility. I do what I must and obey just authority. (Lawful)", + "Independence. When people follow orders blindly, they embrace a kind of tyranny. (Chaotic)", + "Might. In life as in war, the stronger force wins. (Evil)", + "Live and Let Live. Ideals aren't worth killing over or going to war for. (Neutral)", + "Nation. My city, nation, or people are all that matter. (Any)", + "" + }, + { // urchin + "", + "Respect. All people, rich or poor, deserve respect. (Good)", + "Community. We have to take care of each other, because no one else is going to do it. (Lawful)", + "Change. The low are lifted up, and the high and mighty are brought down. Change is the nature of things. (Chaotic)", + "Retribution. The rich need to be shown what life and death are like in the gutters. (Evil)", + "People. I help the people who help me - that's what keeps us alive. (Neutral)", + "Aspiration. I'm going to prove that I'm worthy of a better life.", + "" + } +}; + +const char * character_bonds[NUM_BACKGROUNDS][8] = +{ + { + "", + "", + "", + "", + "", + "", + "", + "" + }, + { // acolyte + "", + "I would die to recover an ancient relic of my faith that was lost long ago.", + "I will someday get revenge on the corrupt temple hierarchy who branded me a heretic.", + "I owe my life to the priest who took me in when my parents died.", + "Everything I do is for the common people.", + "I will do anything to protect the temple where I served.", + "I seek to preserve a sacred text that my enemies consider heretical and seek to destroy.", + "" + }, + { // charlatan + "", + "I fleeced the wrong person and must work to ensure that this individual never crosses paths with me or those I care about.", + "I owe everything to my mentor-a horrible person who's probably rotting in jail somewhere.", + "Somewhere out there, I have a child who doesn't know me. I'm making the world better for him or her.", + "I come from a noble family, and one day I'll reclaim my lands and title from those who stole them from me.", + "A powerful person killed someone I love. Some day soon, I'll have my revenge.", + "I swindled and ruined a person who didn't deserve it. I seek to atone for my misdeeds but might never be able to forgive myself.", + "" + }, + { // criminal + "", + "I'm trying to pay off an old debt I owe to a generous benefactor.", + "My ill-gotten gains go to support my family.", + "Something important was taken from me, and I aim to steal it back.", + "I will become the greatest thief that ever lived.", + "I'm guilty of a terrible crime. I hope I can redeem myself for it.", + "Someone I loved died because of a mistake I made. That will never happen again.", + "" + }, + { // entertainer + "", + "My instrument is my most treasured possession, and it reminds me of someone I love.", + "Someone stole my precious instrument, and someday I'll get it back.", + "I want to be famous, whatever it takes.", + "I idolize a hero of the old tales and measure my deeds against that person's.", + "I will do anything to prove myself superior to my hated rival.", + "I would do anything for the other members of my old troupe.", + "" + }, + { // folk hero + "", + "I have a family, but I have no idea where they are. One day, I hope to see them again.", + "I worked the land, I love the land, and I will protect the land.", + "A proud noble once gave me a horrible beating, and I will take my revenge on any bully I encounter.", + "My tools are symbols of my past life, and I carry them so that I will never forget my roots.", + "I protect those who cannot protect themselves.", + "I wish my childhood sweetheart had come with me to pursue my destiny.", + "" + }, + { // gladiator + "", + "My instrument is my most treasured possession, and it reminds me of someone I love.", + "Someone stole my precious instrument, and someday I'll get it back.", + "I want to be famous, whatever it takes.", + "I idolize a hero of the old tales and measure my deeds against that person's.", + "I will do anything to prove myself superior to my hated rival.", + "I would do anything for the other members of my old troupe.", + "" + }, + { // trader + "", + "The workshop where I learned my trade is the most important place in the world to me.", + "I created a great work for someone, and then found them unworthy to receive it. I'm still looking for someone worthy.", + "I owe my guild a great debt for forging me into the person I am today.", + "I pursue wealth to secure someone's love.", + "One day I will return to my guild and prove that I am the greatest artisan of them all.", + "I will get revenge on the evil forces that destroyed my place of business and ruined my livelihood.", + "" + }, + { // hermit + "", + "Nothing is more important than the other members of my hermitage, order, or association.", + "I entered seclusion to hide from the ones who might still be hunting me. I must someday confront them.", + "I'm still seeking the enlightenment I pursued in my seclusion, and it still eludes me.", + "I entered seclusion because I loved someone I could not have.", + "Should my discovery come to light, it could bring ruin to the world.", + "My isolation gave me great insight into a great evil that only I can destroy.", + "" + }, + { // squire + "", + "I will face any challenge to win the approval of my family.", + "My house's alliance with another noble family must be sustained at all costs.", + "Nothing is more important than the other members of my family.", + "I am in love with the heir of a family that my family despises.", + "My loyalty to my sovereign is unwavering.", + "The common folk must see me as a hero of the people.", + "" + }, + { // noble + "", + "I will face any challenge to win the approval of my family.", + "My house's alliance with another noble family must be sustained at all costs.", + "Nothing is more important than the other members of my family.", + "I am in love with the heir of a family that my family despises.", + "My loyalty to my sovereign is unwavering.", + "The common folk must see me as a hero of the people.", + "" + }, + { // outlander + "", + "My family, clan, or tribe is the most important thing in my life, even when they are far from me.", + "An injury to the unspoiled wilderness of my home is an injury to me.", + "I will bring terrible wrath down on the evildoers who destroyed my homeland.", + "I am the last of my tribe, and it is up to me to ensure their names enter legend.", + "I suffer awful visions of a coming disaster and will do anything to prevent it.", + "It is my duty to provide children to sustain my tribe.", + "" + }, + { // pirate + "", + "I'm loyal to my captain first, everything else second.", + "The ship is most important-crewmates and captains come and go.", + "I'll always remember my first ship.", + "In a harbor town, I have a paramour whose eyes nearly stole me from the sea.", + "I was cheated out of my fair share of the profits, and I want to get my due.", + "Ruthless pirates murdered my captain and crewmates, plundered our ship, and left me to die. Vengeance will be mine.", + "" + }, + { // sage + "", + "It is my duty to protect my students.", + "I have an ancient text that holds terrible secrets that must not fall into the wrong hands.", + "I work to preserve a library, university, scriptorium, or monastery.", + "My life's work is a series of tomes related to a specific field of lore.", + "I've been searching my whole life for the answer to a certain question.", + "I sold my soul for knowledge. I hope to do great deeds and win it back.", + "" + }, + { // sailor + "", + "I'm loyal to my captain first, everything else second.", + "The ship is most important-crewmates and captains come and go.", + "I'll always remember my first ship.", + "In a harbor town, I have a paramour whose eyes nearly stole me from the sea.", + "I was cheated out of my fair share of the profits, and I want to get my due.", + "Ruthless pirates murdered my captain and crewmates, plundered our ship, and left me to die. Vengeance will be mine.", + "" + }, + { // soldier + "", + "I would still lay down my life for the people I served with.", + "Someone saved my life on the battlefield. To this day, I will never leave a friend behind.", + "My honor is my life.", + "I'll never forget the crushing defeat my company suffered or the enemies who dealt it.", + "Those who fight beside me are those worth dying for.", + "I fight for those who cannot fight for themselves.", + "" + }, + { // urchin + "", + "My town or city is my home, and I'll fight to defend it.", + "I sponsor an orphanage to keep others from enduring what I was forced to endure.", + "I owe my survival to another urchin who taught me to live on the streets.", + "I owe a debt I can never repay to the person who took pity on me.", + "I escaped my life of poverty by robbing an important person, and I'm wanted for it.", + "No one else should have to endure the hardships I've been through.", + "" + } +}; + +const char * character_flaws[NUM_BACKGROUNDS][8] = +{ + { + "", + "", + "", + "", + "", + "", + "", + "" + }, + { // acolyte + "", + "I judge others harshly, and myself even more severely.", + "I put too much trust in those who wield power within my temple's hierarchy.", + "My piety sometimes leads me to blindly trust those that profess faith in my god.", + "I am inflexible in my thinking.", + "I am suspicious of strangers and expect the worst of them.", + "Once I pick a goal, I become obsessed with it to the detriment of everything else in my life.", + "" + }, + { // charlatan + "", + "I can't resist a pretty face.", + "I'm always in debt. I spend my ill-gotten gains on decadent luxuries faster than I bring them in...", + "I'm convinced that no one could ever fool me the way I fool others.", + "I'm too greedy for my own good. I can't resist taking a risk if there's money involved.", + "I can't resist swindling people who are more powerful than me.", + "I hate to admit it and will hate myself for it, but I'll run and preserve my own hide if the going gets tough.", + "" + }, + { // criminal + "", + "When I see something valuable, I can't think about anything but how to steal it.", + "When faced with a choice between money and my friends, I usually choose the money.", + "If there's a plan, I'll forget it. If I don't forget it, I'll ignore it.", + "I have a “tell” that reveals when I'm lying.", + "I turn tail and run when things look bad.", + "An innocent person is in prison for a crime that I committed. I'm okay with that.", + "" + }, + { // entertainer + "", + "I'll do anything to win fame and renown.", + "I'm a sucker for a pretty face.", + "A scandal prevents me from ever going home again. That kind of trouble seems to follow me around.", + "I once satirized a noble who still wants my head. It was a mistake that I will likely repeat.", + "I have trouble keeping my true feelings hidden. My sharp tongue lands me in trouble.", + "Despite my best efforts, I am unreliable to my friends.", + "" + }, + { // folk hero + "", + "The tyrant who rules my land will stop at nothing to see me killed.", + "I'm convinced of the significance of my destiny, and blind to my shortcomings and the risk of failure.", + "The people who knew me when I was young know my shameful secret, so I can never go home again.", + "I have a weakness for the vices of the city, especially hard drink.", + "Secretly, I believe that things would be better if I were a tyrant lording over the land.", + "I have trouble trusting in my allies.", + "" + }, + { // gladiator + "", + "I'll do anything to win fame and renown.", + "I'm a sucker for a pretty face.", + "A scandal prevents me from ever going home again. That kind of trouble seems to follow me around.", + "I once satirized a noble who still wants my head. It was a mistake that I will likely repeat.", + "I have trouble keeping my true feelings hidden. My sharp tongue lands me in trouble.", + "Despite my best efforts, I am unreliable to my friends.", + "" + }, + { // trader + "", + "I'll do anything to get my hands on something rare or priceless.", + "I'm quick to assume that someone is trying to cheat me.", + "No one must ever learn that I once stole money from guild coffers.", + "I'm never satisfied with what I have-I always want more.", + "I would kill to acquire a noble title.", + "I'm horribly jealous of anyone who can outshine my handiwork. Everywhere I go, I'm surrounded by rivals.", + "" + }, + { // hermit + "", + "Now that I've returned to the world, I enjoy its delights a little too much.", + "I harbor bloodthirsty thoughts that my isolation and meditation failed to quell.", + "I am dogmatic in my thoughts and philosophy.", + "I let my need to win arguments overshadow friendships and harmony.", + "I'd risk too much to uncover a lost bit of knowledge.", + "I like keeping secrets and won't share them with anyone.", + "" + }, + { // squire + "", + "I secretly believe that everyone is beneath me.", + "I hide a truly scandalous secret that could ruin my family forever.", + "I too often hear veiled insults and threats in every word addressed to me, and I'm quick to anger.", + "I have an insatiable desire for decadent pleasures.", + "In fact, the world does revolve around me.", + "By my words and actions, I often bring shame to my family.", + "" + }, + { // noble + "", + "I secretly believe that everyone is beneath me.", + "I hide a truly scandalous secret that could ruin my family forever.", + "I too often hear veiled insults and threats in every word addressed to me, and I'm quick to anger.", + "I have an insatiable desire for decadent pleasures.", + "In fact, the world does revolve around me.", + "By my words and actions, I often bring shame to my family.", + "" + }, + { // outlander + "", + "I am too enamored of ale, wine, and other intoxicants.", + "There's no room for caution in a life lived to the fullest.", + "I remember every insult I've received and nurse a silent resentment toward anyone who's ever wronged me.", + "I am slow to trust members of other races, tribes, and societies.", + "Violence is my answer to almost any challenge.", + "Don't expect me to save those who can't save themselves. It is nature's way that the strong thrive and the weak perish.", + "" + }, + { // pirate + "", + "I follow orders, even if I think they're wrong.", + "I'll say anything to avoid having to do extra work.", + "Once someone questions my courage, I never back down no matter how dangerous the situation.", + "Once I start drinking, it's hard for me to stop.", + "I can't help but pocket loose coins and other trinkets I come across.", + "My pride will probably lead to my destruction.", + "" + }, + { // sage + "", + "I am easily distracted by the promise of information.", + "Most people scream and run when they see a demon. I stop and take notes on its anatomy.", + "Unlocking an ancient mystery is worth the price of a civilization.", + "I overlook obvious solutions in favor of complicated ones.", + "I speak without really thinking through my words, invariably insulting others.", + "I can't keep a secret to save my life, or anyone else's.", + "" + }, + { // sailor + "", + "I follow orders, even if I think they're wrong.", + "I'll say anything to avoid having to do extra work.", + "Once someone questions my courage, I never back down no matter how dangerous the situation.", + "Once I start drinking, it's hard for me to stop.", + "I can't help but pocket loose coins and other trinkets I come across.", + "My pride will probably lead to my destruction.", + "" + }, + { // soldier + "", + "The monstrous enemy we faced in battle still leaves me quivering with fear.", + "I have little respect for anyone who is not a proven warrior.", + "I made a terrible mistake in battle that cost many lives-and I would do anything to keep that mistake secret.", + "My hatred of my enemies is blind and unreasoning.", + "I obey the law, even if the law causes misery.", + "I'd rather eat my armor than admit when I'm wrong.", + "" + }, + { // urchin + "", + "If I'm outnumbered, I will run away from a fight.", + "Gold seems like a lot of money to me, and I'll do just about anything for more of it.", + "I will never fully trust anyone other than myself.", + "I'd rather kill someone in their sleep than fight fair.", + "It's not stealing if I need it more than someone else.", + "People who can't take care of themselves get what they deserve.", + "" + } +}; + +void choose_random_roleplay_goal(struct char_data *ch) +{ + + int objective = dice(1, 20), + reason = dice(1, 20), + complication = dice(1, 20); + + if (!ch) return; + + draw_line(ch, 80, '-', '-'); + text_line(ch, "EXAMPLE GOAL OUTLINE", 80, '-', '-'); + draw_line(ch, 80, '-', '-'); + + send_to_char(ch, "%-15s: %s.\r\n", "Objective", character_rp_goal_objectives[objective]); + send_to_char(ch, "%-15s: %s.\r\n", "Reason", character_rp_goal_reasons[reason]); + send_to_char(ch, "%-15s: %s.\r\n", "Complication", character_rp_goal_complications[complication]); + + send_to_char(ch, "\r\n"); + +} + +void choose_random_roleplay_personality(struct char_data *ch, int background) +{ + + if (background < 1 || background >= NUM_BACKGROUNDS) + { + send_to_char(ch, "That is an invalid background.\r\n"); + return; + } + + int choiceOne = 0, choiceTwo = 0; + char buf[200]; + + if (!ch) return; + + draw_line(ch, 80, '-', '-'); + text_line(ch, "EXAMPLE PERSONALITY QUALITIES", 80, '-', '-'); + draw_line(ch, 80, '-', '-'); + + choiceOne = dice(1, 8); + choiceTwo = dice(1, 8); + while (choiceTwo == choiceOne) + choiceTwo = dice(1, 8); + + snprintf(buf, sizeof(buf), "%s", personality_traits[background][choiceOne]); + send_to_char(ch, " %s", strfrmt(buf, 78, 1, 0, 0, 0)); + draw_line(ch, 80, '-', '-'); + snprintf(buf, sizeof(buf), "%s", personality_traits[background][choiceTwo]); + send_to_char(ch, " %s", strfrmt(buf, 78, 1, 0, 0, 0)); + draw_line(ch, 80, '-', '-'); + send_to_char(ch, "\r\n"); + +} + +void choose_random_roleplay_ideals(struct char_data *ch, int background) +{ + + if (background < 1 || background >= NUM_BACKGROUNDS) + { + send_to_char(ch, "That is an invalid background.\r\n"); + return; + } + + int choiceOne = 0, choiceTwo = 0; + char buf[200]; + + if (!ch) return; + + draw_line(ch, 80, '-', '-'); + text_line(ch, "EXAMPLE CHARACTER IDEALS", 80, '-', '-'); + draw_line(ch, 80, '-', '-'); + + choiceOne = dice(1, 6); + choiceTwo = dice(1, 6); + while (choiceTwo == choiceOne) + choiceTwo = dice(1, 6); + + snprintf(buf, sizeof(buf), "%s", character_ideals[background][choiceOne]); + send_to_char(ch, " %s", strfrmt(buf, 78, 1, 0, 0, 0)); + draw_line(ch, 80, '-', '-'); + snprintf(buf, sizeof(buf), "%s", character_ideals[background][choiceTwo]); + send_to_char(ch, " %s", strfrmt(buf, 78, 1, 0, 0, 0)); + draw_line(ch, 80, '-', '-'); + send_to_char(ch, "\r\n"); + +} + +void choose_random_roleplay_bonds(struct char_data *ch, int background) +{ + + if (background < 1 || background >= NUM_BACKGROUNDS) + { + send_to_char(ch, "That is an invalid background.\r\n"); + return; + } + + int choiceOne = 0, choiceTwo = 0; + char buf[200]; + + if (!ch) return; + + draw_line(ch, 80, '-', '-'); + text_line(ch, "EXAMPLE CHARACTER BONDS", 80, '-', '-'); + draw_line(ch, 80, '-', '-'); + + choiceOne = dice(1, 6); + choiceTwo = dice(1, 6); + while (choiceTwo == choiceOne) + choiceTwo = dice(1, 6); + + snprintf(buf, sizeof(buf), "%s", character_bonds[background][choiceOne]); + send_to_char(ch, " %s", strfrmt(buf, 78, 1, 0, 0, 0)); + draw_line(ch, 80, '-', '-'); + snprintf(buf, sizeof(buf), "%s", character_bonds[background][choiceTwo]); + send_to_char(ch, " %s", strfrmt(buf, 78, 1, 0, 0, 0)); + draw_line(ch, 80, '-', '-'); + send_to_char(ch, "\r\n"); + +} + +void choose_random_roleplay_flaws(struct char_data *ch, int background) +{ + + if (background < 1 || background >= NUM_BACKGROUNDS) + { + send_to_char(ch, "That is an invalid background.\r\n"); + return; + } + + int choiceOne = 0, choiceTwo = 0; + char buf[200]; + + if (!ch) return; + + draw_line(ch, 80, '-', '-'); + text_line(ch, "EXAMPLE CHARACTER FLAWS", 80, '-', '-'); + draw_line(ch, 80, '-', '-'); + + choiceOne = dice(1, 6); + choiceTwo = dice(1, 6); + while (choiceTwo == choiceOne) + choiceTwo = dice(1, 6); + + snprintf(buf, sizeof(buf), "%s", character_flaws[background][choiceOne]); + send_to_char(ch, " %s", strfrmt(buf, 78, 1, 0, 0, 0)); + draw_line(ch, 80, '-', '-'); + snprintf(buf, sizeof(buf), "%s", character_flaws[background][choiceTwo]); + send_to_char(ch, " %s", strfrmt(buf, 78, 1, 0, 0, 0)); + draw_line(ch, 80, '-', '-'); + send_to_char(ch, "\r\n"); + +} + +void show_character_goal_idea_menu(struct char_data *ch) +{ + char buf[MAX_STRING_LENGTH]; + + snprintf(buf, sizeof(buf), "%s", GOAL_DESCRIPTION); + send_to_char(ch, "%s\r\n", strfrmt(buf, 80, 1, 0, 0, 0)); + draw_line(ch, 80, '-', '-'); + send_to_char(ch, "First, we've created a system to offer random goal ideas.\r\n"); + send_to_char(ch, "1) Generate a random goal idea.\r\n"); + send_to_char(ch, "Q) Proceed to enter in your character goals.\r\n"); + send_to_char(ch, "Enter Your Choice (1|Q): "); +} + +void show_character_personality_idea_menu(struct char_data *ch) +{ + char buf[MAX_STRING_LENGTH]; + int i = 0; + + snprintf(buf, sizeof(buf), "%s", PERSONALITY_DESCRIPTION); + send_to_char(ch, "%s\r\n", strfrmt(buf, 80, 1, 0, 0, 0)); + draw_line(ch, 80, '-', '-'); + send_to_char(ch, "First, we've created a system to offer random personality ideas. For some random ideas, select a background type.\r\n"); + send_to_char(ch, "You do not need to have chosen the background to select it for personality ideas.\r\n"); + for (i = 1; i < NUM_BACKGROUNDS; i++) + { + send_to_char(ch, "%2d) %s\r\n", i, background_list[backgrounds_listed_alphabetically[i]].name); + } + send_to_char(ch, "Q) Proceed to enter in your character personality.\r\n"); + send_to_char(ch, "Enter Your Choice (1|Q): "); +} + +void show_character_ideals_idea_menu(struct char_data *ch) +{ + char buf[MAX_STRING_LENGTH]; + int i = 0; + + snprintf(buf, sizeof(buf), "%s", IDEALS_DESCRIPTION); + send_to_char(ch, "%s\r\n", strfrmt(buf, 80, 1, 0, 0, 0)); + draw_line(ch, 80, '-', '-'); + send_to_char(ch, "First, we've created a system to offer random ideals ideas. For some random ideas, select a background type.\r\n"); + send_to_char(ch, "You do not need to have chosen the background to select it for ideals ideas.\r\n"); + for (i = 1; i < NUM_BACKGROUNDS; i++) + { + send_to_char(ch, "%2d) %s\r\n", i, background_list[backgrounds_listed_alphabetically[i]].name); + } + send_to_char(ch, "Q) Proceed to enter in your character ideals.\r\n"); + send_to_char(ch, "Enter Your Choice (1|Q): "); +} + +void show_character_bonds_idea_menu(struct char_data *ch) +{ + char buf[MAX_STRING_LENGTH]; + int i = 0; + + snprintf(buf, sizeof(buf), "%s", BONDS_DESCRIPTION); + send_to_char(ch, "%s\r\n", strfrmt(buf, 80, 1, 0, 0, 0)); + draw_line(ch, 80, '-', '-'); + send_to_char(ch, "First, we've created a system to offer random bonds ideas. For some random ideas, select a background type.\r\n"); + send_to_char(ch, "You do not need to have chosen the background to select it for bonds ideas.\r\n"); + for (i = 1; i < NUM_BACKGROUNDS; i++) + { + send_to_char(ch, "%2d) %s\r\n", i, background_list[backgrounds_listed_alphabetically[i]].name); + } + send_to_char(ch, "Q) Proceed to enter in your character bonds.\r\n"); + send_to_char(ch, "Enter Your Choice (1|Q): "); +} + +void show_character_flaws_idea_menu(struct char_data *ch) +{ + char buf[MAX_STRING_LENGTH]; + int i = 0; + + snprintf(buf, sizeof(buf), "%s", FLAWS_DESCRIPTION); + send_to_char(ch, "%s\r\n", strfrmt(buf, 80, 1, 0, 0, 0)); + draw_line(ch, 80, '-', '-'); + send_to_char(ch, "First, we've created a system to offer random flaws ideas. For some random ideas, select a background type.\r\n"); + send_to_char(ch, "You do not need to have chosen the background to select it for flaws ideas.\r\n"); + for (i = 1; i < NUM_BACKGROUNDS; i++) + { + send_to_char(ch, "%2d) %s\r\n", i, background_list[backgrounds_listed_alphabetically[i]].name); + } + send_to_char(ch, "Q) Proceed to enter in your character flaws.\r\n"); + send_to_char(ch, "Enter Your Choice (1|Q): "); +} + +void show_character_goal_edit(struct descriptor_data *d) +{ + if (d->character->player.goals) + { + write_to_output(d, "Current Character Goals:\r\n%s", d->character->player.goals); + d->backstr = strdup(d->character->player.goals); + } + + write_to_output(d, "Enter your character goals.\r\n"); + send_editor_help(d); + d->str = &d->character->player.goals; + d->max_str = PLR_GOALS_LENGTH; + STATE(d) = CON_CHARACTER_GOALS_ENTER; +} + +void show_character_personality_edit(struct descriptor_data *d) +{ + if (d->character->player.personality) + { + write_to_output(d, "Current Character Personality:\r\n%s", d->character->player.personality); + d->backstr = strdup(d->character->player.personality); + } + + write_to_output(d, "Enter your character personality.\r\n"); + send_editor_help(d); + d->str = &d->character->player.personality; + d->max_str = PLR_PERSONALITY_LENGTH; + STATE(d) = CON_CHARACTER_PERSONALITY_ENTER; +} + +void show_character_ideals_edit(struct descriptor_data *d) +{ + if (d->character->player.ideals) + { + write_to_output(d, "Current Character Ideals:\r\n%s", d->character->player.ideals); + d->backstr = strdup(d->character->player.ideals); + } + + write_to_output(d, "Enter your character ideals.\r\n"); + send_editor_help(d); + d->str = &d->character->player.ideals; + d->max_str = PLR_IDEALS_LENGTH; + STATE(d) = CON_CHARACTER_IDEALS_ENTER; +} + +void show_character_bonds_edit(struct descriptor_data *d) +{ + if (d->character->player.bonds) + { + write_to_output(d, "Current Character Bonds:\r\n%s", d->character->player.bonds); + d->backstr = strdup(d->character->player.bonds); + } + + write_to_output(d, "Enter your character bonds.\r\n"); + send_editor_help(d); + d->str = &d->character->player.bonds; + d->max_str = PLR_BONDS_LENGTH; + STATE(d) = CON_CHARACTER_BONDS_ENTER; +} + +void show_character_flaws_edit(struct descriptor_data *d) +{ + if (d->character->player.flaws) + { + write_to_output(d, "Current Character Flaws:\r\n%s", d->character->player.flaws); + d->backstr = strdup(d->character->player.flaws); + } + + write_to_output(d, "Enter your character flaws.\r\n"); + send_editor_help(d); + d->str = &d->character->player.flaws; + d->max_str = PLR_FLAWS_LENGTH; + STATE(d) = CON_CHARACTER_FLAWS_ENTER; +} + +ACMD(do_goals) +{ + char arg[200]; + + if (IS_NPC(ch)) + { + send_to_char(ch, "NPCs do not have recorded goals on their character file.\r\n"); + return; + } + + one_argument(argument, arg, sizeof(arg)); + + if (!*arg) + { + send_to_char(ch, "Your current goals are:\r\n"); + send_to_char(ch, "\r\n"); + send_to_char(ch, "%s\r\n", ch->player.goals ? ch->player.goals : "Not set yet."); + send_to_char(ch, "\r\n"); + send_to_char(ch, "To edit your goals, type 'goals edit'. To generate a random goal idea outline, type 'goal example'.\r\n"); + return; + } + else if (is_abbrev(arg, "example")) + { + send_to_char(ch, "You generate a random goal idea outline: \r\n"); + choose_random_roleplay_goal(ch); + } + else if (is_abbrev(arg, "edit")) + { + send_to_char(ch, "To edit your character goals, type quit, and at the game menu select option 2, then 4.\r\n"); + return; + } + else + { + send_to_char(ch, "That is not a valid option\r\n"); + send_to_char(ch, "To edit your goals, type 'goals edit'. To generate a random goal idea outline, type 'goal example'.\r\n"); + } +} + +void display_age_menu(struct descriptor_data *d) +{ + struct char_data *ch = d->character; + int i, j; + + if (!ch) return; + + send_to_char(ch, "Please select the age of your character from this list. Actual numerical ages differ based on race type.\r\n"); + + for (i = 0; i < NUM_CHARACTER_AGES; i++) + { + send_to_char(ch, "%d) %-15s ", i+1, character_ages[i]); + for (j = 0; j < 6; j++) + { + if (character_age_attributes[i][j] > 0) + { + send_to_char(ch, "+%d %s ", character_age_attributes[i][j], ability_score_names[j]); + } + else if (character_age_attributes[i][j] < 0) + { + send_to_char(ch, "%d %s ", character_age_attributes[i][j], ability_score_names[j]); + } + } + send_to_char(ch, "\r\n"); + } + + send_to_char(ch, "\r\n"); + send_to_char(ch, "Age-based ability score modifiers are applied after setting ability scores in study as part\r\n"); + send_to_char(ch, "of the 1st level study process. If you select your age after level 1, you'll have to respec\r\n"); + send_to_char(ch, "in order to receive the ability score modifiers.\r\n"); + send_to_char(ch, "\r\n"); + send_to_char(ch, "Please select your characters age: "); +} + +void HandleStateCharacterAgeParseMenuChoice(struct descriptor_data *d, char *arg) +{ + int changeStateTo = STATE(d); + struct char_data *ch = d->character; + int age = atoi(arg) - 1; + + switch (age) + { + case 0: + case 1: + case 2: + case 3: + case 4: + ch->player_specials->saved.character_age = age; + ch->player_specials->saved.character_age_saved = true; + send_to_char(ch, "You've decided your character will be: %s.\r\n", character_ages[age]); + changeStateTo = CON_CHAR_RP_MENU; + show_character_rp_menu(d); + break; + default: + send_to_char(ch, "That is not a valid age. Please select again: "); + break; + } + STATE(d) = changeStateTo; +} + +void display_faction_menu(struct descriptor_data *d) +{ + struct char_data *ch = d->character; + int i; + clan_rnum c_n; + char alphabet[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; + + if (!ch) return; + + send_to_char(ch, "\r\n"); + send_to_char(ch, "You character faction, or clan, determines who your allies and enemies are in-character.\r\n" + "Faction membership can also provide other benefits, both in terms of game mechanics as\r\n" + "with role-play opportunities.\r\n" + "\r\n"); + + send_to_char(ch, "0) %-25s A) Help on %s\r\n", "Adventurer/No Faction", "Adventurer/No Faction"); + + for (i = 1; i <= num_of_clans; i++) + { + c_n = real_clan(i); + send_to_char(ch, "%d) %-25s %c) Help on %s\r\n", i, CLAN_NAME(c_n), alphabet[i], CLAN_NAME(c_n)); + } + + send_to_char(ch, "Enter your faction choice: "); +} + +void HandleStateCharacterFactionParseMenuChoice(struct descriptor_data *d, char *arg) +{ + int changeStateTo = STATE(d); + struct char_data *ch = d->character; + bool is_clan = isdigit(*arg); + int clan = atoi(arg); + clan_rnum c_n; + int i = 0; + long v_id; + char letter; + char alphabet[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; + + if (is_clan) + { + + if (clan < 0 || clan > num_of_clans) + { + send_to_char(ch, "That is an invalid selection.\r\n"); + return; + } + + GET_CLAN(ch) = clan; + if (clan == 0) + { + if ((v_id = get_ptable_by_name(strdup(GET_NAME(ch)))) < 0) + { + send_to_char(ch, "There was an error setting your faction as adventurer. Please inform staff ERRCHMNFC001.\r\n"); + return; + } + player_table[v_id].clan = 0; + GET_CLANRANK(ch) = 0; + send_to_char(ch, "You have elected to be of no specific faction and are known as an adventurer.\r\n"); + } + else + { + GET_CLANRANK(ch) = 6; + c_n = real_clan(clan); + set_clan(ch, clan_list[c_n].vnum); + send_to_char(ch, "You have selected the clan %s and your new rank in that clan is %s.\r\n", + CLAN_NAME(c_n), clan_list[c_n].rank_name[5]); + } + changeStateTo = CON_CHAR_RP_MENU; + show_character_rp_menu(d); + } + else + { + send_to_char(ch, "\tC\r\n"); + switch (*arg) + { + case 'a': case 'A': send_to_char(ch, "Adventurers are beholden to no specific faction. They choose their allies and\r\n" + "enemies themselves, and may shift their alliegances accoridng to their personal\r\n" + "agendas and goals.\r\n"); + break; + default: + letter = UPPER(*arg); + for (i = 1; i < 24; i++) + { + if (letter == alphabet[i]) break; + } + if (i >= 24) + { + send_to_char(ch, "That is an invalid selection.\r\n"); + return; + } + if (i < 0 || i > num_of_clans) + { + send_to_char(ch, "That is an invalid selection.\r\n"); + return; + } + c_n = real_clan(i); + send_to_char(ch, "Clan Description for %s:\r\n\r\n%s\r\n\r\n", CLAN_NAME(c_n), clan_list[c_n].description); + break; + } + send_to_char(ch, "\tn\r\n"); + display_faction_menu(d); + } + + STATE(d) = changeStateTo; +} + +void display_hometown_menu(struct descriptor_data *d) +{ + + struct char_data *ch = d->character; + + if (!ch) return; + + send_to_char(ch, "Your character's hometown determines a few things, in addition to the role play aspect.\r\n"); + send_to_char(ch, "It will determine your recall location, donation pit location, as well as tie into various\r\n"); + send_to_char(ch, "other mechanics, such as some background archtype abilities.\r\n"); + send_to_char(ch, "\r\n"); + send_to_char(ch, "1) Palanthas : Home of the Knights of Solamnia & Forces of Whitestone\r\n"); + send_to_char(ch, "2) Sanction : Home of the Dragonarmies\r\n"); + send_to_char(ch, "3) Solace : Free City with No Direct Alleigances\r\n"); + send_to_char(ch, "\r\n"); + send_to_char(ch, "Choose Your Hometown: "); + +} + +void HandleStateCharacterHometownParseMenuChoice(struct descriptor_data *d, char *arg) +{ + int changeStateTo = STATE(d); + struct char_data *ch = d->character; + int hometown = atoi(arg); + + switch (hometown) + { + case 1: + case 2: + case 3: + GET_HOMETOWN(ch) = hometown; + send_to_char(ch, "You've decided your character's hometown will be: %s.\r\n", cities[hometown]); + changeStateTo = CON_CHAR_RP_MENU; + show_character_rp_menu(d); + break; + default: + send_to_char(ch, "That is not a valid hometown. Please select again: "); + break; + } + STATE(d) = changeStateTo; +} + +void display_deity_menu(struct descriptor_data *d) +{ + struct char_data *ch = d->character; + int i; + char dname[50]; + + if (!ch) return; + + send_to_char(ch, " %-25s - %-15s %s\r\n", "Deities of Krynn", "Alignment", "Portfolio"); + for (i = 0; i < 80; i++) + send_to_char(ch, "-"); + send_to_char(ch, "\r\n"); + + for (i = 0; i < NUM_DEITIES; i++) + { + if (deity_list[i].pantheon == DEITY_PANTHEON_NONE) + continue; + + snprintf(dname, sizeof(dname), "%s", deity_list[i].name); + send_to_char(ch, "%2d) %-25s - %-15s - %s\r\n", i, CAP(dname), GET_ALIGN_STRING(deity_list[i].ethos, deity_list[i].alignment), deity_list[i].portfolio); + } + + send_to_char(ch, "\r\n"); + send_to_char(ch, "Select Your Deity: "); + +} + +void display_deity_info(struct descriptor_data *d) +{ + struct char_data *ch = d->character; + char dname[50]; + + if (!ch) return; + + snprintf(dname, sizeof(dname), "%s", deity_list[GET_DEITY(ch)].name); + send_to_char(ch, "\tA%s\r\n\tn", CAP(dname)); + send_to_char(ch, "\r\n"); + send_to_char(ch, "\tAPantheon:\tn %s\r\n", pantheons[deity_list[GET_DEITY(ch)].pantheon]); + send_to_char(ch, "\tAAlignment:\tn %s\r\n", GET_ALIGN_STRING(deity_list[GET_DEITY(ch)].ethos, deity_list[GET_DEITY(ch)].alignment)); + send_to_char(ch, "\tAPortfolio:\tn %s\r\n", deity_list[GET_DEITY(ch)].portfolio); + send_to_char(ch, "\tADescription:\tn\r\n%s\r\n", deity_list[GET_DEITY(ch)].description); + + send_to_char(ch, "\r\n"); + send_to_char(ch, "Do you wish to select this deity? (Y|N) "); +} + +void HandleStateCharacterDeityParseMenuChoice(struct descriptor_data *d, char *arg) +{ + int changeStateTo = STATE(d); + struct char_data *ch = d->character; + int deity = atoi(arg); + + + if (deity >= 0 && deity < NUM_DEITIES) + { + GET_DEITY(ch) = deity; + display_deity_info(d); + changeStateTo = CON_CHARACTER_DEITY_CONFIRM; + } + else + { + send_to_char(ch, "That is not a valid deity. Please select again: "); + } + + STATE(d) = changeStateTo; +} +void HandleStateCharacterDeityConfirmParseMenuChoice(struct descriptor_data *d, char *arg) +{ + int changeStateTo = STATE(d); + struct char_data *ch = d->character; + + switch (*arg) + { + case 'Y': + case 'y': + send_to_char(ch, "You've decided your character's deity will be: %s.\r\n", deity_list[GET_DEITY(ch)].name); + changeStateTo = CON_CHAR_RP_MENU; + show_character_rp_menu(d); + break; + case 'N': + case 'n': + GET_DEITY(ch) = 0; + display_deity_menu(d); + changeStateTo = CON_CHARACTER_DEITY_SELECT; + break; + default: + send_to_char(ch, "That is not a valid selection. Please select again: "); + break; + } + + STATE(d) = changeStateTo; +} + +// shows: +// name, race, gender, age, title, deity, alignment, short description, description, background story, background archtype, +// goals, personality, ideals, bonds, flaws, homeland, faction/clan, home city, deity +ACMD(do_rpsheet) +{ + + char arg[100], buf[100], buf2[100]; + struct char_data *t; + int i; + + one_argument(argument, arg, sizeof(arg)); + + if (!*arg || GET_LEVEL(ch) < LVL_IMMORT) + { + t = ch; + } + else if (!(t = get_char_vis(ch, arg, NULL, FIND_CHAR_WORLD))) + { + send_to_char(ch, "No one by that name currently logged in.\r\n"); + return; + } + + snprintf(buf, sizeof(buf), " RP SHEET FOR %s ", GET_NAME(t)); + + for (i = 0; i < strlen(buf); i++) + buf[i] = toupper(buf[i]); + + send_to_char(ch, "\r\n"); + send_to_char(ch, "\tC"); + text_line(ch, buf, 100, '-', '-'); + send_to_char(ch, "\tC"); + + // Name, Race and Gender + snprintf(buf, sizeof(buf), "%s", race_list[GET_RACE(t)].name); + snprintf(buf2, sizeof(buf2), "%s", genders[GET_SEX(t)]); + send_to_char(ch, "\tcName :\tn %-20s \tcRace :\tn %-20s \tcGender :\tn %s\r\n", GET_NAME(t), CAP(buf), CAP(buf2)); + + // Title + send_to_char(ch, "\tcTitle :\tn %s\r\n", GET_TITLE(t)); + + // Short Description + send_to_char(ch, "\tcShort Desc:\tn %s\r\n", current_short_desc(t)); + + // Age, Alignment, Deity + snprintf(buf, sizeof(buf), "%s", get_align_by_num(GET_ALIGNMENT(t))); + strip_colors(buf); + snprintf(buf2, sizeof(buf2), "%s", character_ages[GET_CH_AGE(t)]); + send_to_char(ch, "\tcAge :\tn %-20s \tcAlignment :\tn %-20s \tcDeity :\tn %-15s\r\n", + CAP(buf2), buf, deity_list[GET_DEITY(t)].name); + + snprintf(buf, sizeof(buf), "%s", background_list[GET_BACKGROUND(t)].name); + send_to_char(ch, "\tcBackground:\tn %-20s \tcFaction :\tn %s\r\n", + CAP(buf), GET_CLAN(t) ? clan_list[GET_CLAN(t)-1].clan_name : "None"); + + // Homeland, Home City + send_to_char(ch, "\tcHomeland :\tn %-20s \tcHometown :\tn %-20s\r\n", + regions[GET_REGION(t)], cities[GET_HOMETOWN(t)]); + + // Description + send_to_char(ch, "\tcDesc :\tn %-3s\r\n", t->player.description ? ((strlen(t->player.description) > 10) ? t->player.description : "Not Set") : "Not Set"); + + // Background Story, Personality, Goals + send_to_char(ch, "\tcBG Story :\tn %-20s \tcPersonality:\tn %-20s \tcGoals :\tn %-3s\r\n", + t->player.background ? ((strlen(t->player.background) > 10) ? "Set" : "Not Set") : "Not Set", + t->player.personality ? ((strlen(t->player.personality) > 10) ? "Set" : "Not Set") : "Not Set", + t->player.goals ? ((strlen(t->player.goals) > 10) ? "Set" : "Not Set") : "Not Set"); + + // Ideals, Bonds, Flaws + send_to_char(ch, "\tcIdeals :\tn %-20s \tcBonds :\tn %-20s \tcFlaws :\tn %-3s\r\n", + t->player.ideals ? ((strlen(t->player.ideals) > 10) ? "Set" : "Not Set") : "Not Set", + t->player.bonds ? ((strlen(t->player.bonds) > 10) ? "Set" : "Not Set") : "Not Set", + t->player.flaws ? ((strlen(t->player.flaws) > 10) ? "Set" : "Not Set") : "Not Set"); + + send_to_char(ch, "\tC"); + draw_line(ch, 100, '-', '-'); + send_to_char(ch, "\tn"); + send_to_char(ch, "To see extra info, type: (rpdescription|rpbackground|rppersonality|rpgoals|rpideals|rpbonds|rpflaws)\r\n"); + send_to_char(ch, "To toggle your role-play flag on and off type: rpset\r\n"); + send_to_char(ch, "\tC"); + draw_line(ch, 100, '-', '-'); + send_to_char(ch, "\tn"); + send_to_char(ch, "\r\n"); +} + +ACMD(do_showrpinfo) +{ + + char arg[100], buf[100], buf2[100]; + char *text_out = NULL; + struct char_data *t; + int i; + + one_argument(argument, arg, sizeof(arg)); + + if (!*arg || GET_LEVEL(ch) < LVL_IMMORT) + { + t = ch; + } + else if (!(t = get_char_vis(ch, arg, NULL, FIND_CHAR_WORLD))) + { + send_to_char(ch, "No one by that name currently logged in.\r\n"); + return; + } + + snprintf(buf, sizeof(buf), "%s", GET_NAME(t)); + + for (i = 0; i < strlen(buf); i++) + buf[i] = toupper(buf[i]); + + switch (subcmd) + { + case SCMD_RP_DESC: snprintf(buf2, sizeof(buf2), " DESCRIPTION FOR %s ", buf); text_out = t->player.description; break; + case SCMD_RP_PERSONALITY: snprintf(buf2, sizeof(buf2), " PERSONALITY FOR %s ", buf); text_out = t->player.personality; break; + case SCMD_RP_GOALS: snprintf(buf2, sizeof(buf2), " GOALS FOR %s ", buf); text_out = t->player.goals; break; + case SCMD_RP_IDEALS: snprintf(buf2, sizeof(buf2), " IDEALS FOR %s ", buf); text_out = t->player.ideals; break; + case SCMD_RP_BONDS: snprintf(buf2, sizeof(buf2), " BONDS FOR %s ", buf); text_out = t->player.bonds; break; + case SCMD_RP_FLAWS: snprintf(buf2, sizeof(buf2), " FLAWS FOR %s ", buf); text_out = t->player.flaws; break; + case SCMD_RP_BG_STORY: snprintf(buf2, sizeof(buf2), " BACKGROUND FOR %s ", buf); text_out = t->player.background; break; + default: + send_to_char(ch, "That rp info doesn't exist. Please inform a staff member ERRRPSHOWINFO001.\r\n"); + return; + } + + send_to_char(ch, "\tC\r\n"); + text_line(ch, buf2, 100, '-', '-'); + send_to_char(ch, "\tn"); + send_to_char(ch, "%s", text_out == NULL ? "Not Set" : text_out); + send_to_char(ch, "\tC\r\n"); + draw_line(ch, 100, '-', '-'); + send_to_char(ch, "\tn\r\n"); + +} + +void display_rp_decide_menu(struct descriptor_data *d) +{ + struct char_data *ch = d->character; + + if (!ch) return; + + send_to_char(ch, "\r\n" + + "\tCChronicles of Krynn is a Role Play Focused MUD. \tnWhat that means is that the staff's focus is\r\n" + "on creating overarching role-play themes and stories, and assisting players with their individual\r\n" + "character stories. \tcHowever role-play is not mandatory\tn, and we only ask that non-role-players respect\r\n" + "the role play of others in their vicinity and not disrupt it.\r\n" + "\r\n" + "At this moment you have three choices:\r\n" + "\r\n" + "\tc1)\tn Flag yourself a non-role-player and enter the game.\r\n" + "\tc2)\tn Flag yourself a role-player and enter in additonal character info.\r\n" + "\tc3)\tn Delay this decision and enter the game.\r\n" + "\r\n" + "This extra character info can be entered at any time, and you can enter as little or as much as\r\n" + "you like. You can also flag yourself a role-player or non-role-player at any time in-game.\r\n" + "The extra character info includes: short and long descriptions, background archtype, background story, deity, \r\n" + "homeland, hometown, faction, character age, personality, goals, ideals, bonds and flaws.\r\n" + "\r\n" + "\tcPlease Enter Your Choice: \tn" + ); + +} + +void HandleStateCharacterRPDecideParseMenuChoice(struct descriptor_data *d, char *arg) +{ + int changeStateTo = STATE(d); + struct char_data *ch = d->character; + + switch (*arg) + { + case '1': + send_to_char(ch, "You've elected to be a non-role-player and can now enter the game.\r\n"); + SET_BIT_AR(PRF_FLAGS(ch), PRF_NON_ROLEPLAYER); + write_to_output(d, "\r\n"); + write_to_output(d, "%s\r\n*** PRESS RETURN: ", motd); + changeStateTo = CON_RMOTD; + break; + case '2': + send_to_char(ch, "You've elected to be a role-player and can now enter in your additional character info.\r\n"); + SET_BIT_AR(PRF_FLAGS(ch), PRF_RP); + changeStateTo = CON_CHAR_RP_MENU; + show_character_rp_menu(d); + break; + case '3': + send_to_char(ch, "You've decided to delay your decision about role playing, and can now enter the game.\r\n"); + write_to_output(d, "\r\n"); + write_to_output(d, "%s\r\n*** PRESS RETURN: ", motd); + changeStateTo = CON_RMOTD; + break; + default: + send_to_char(ch, "That is not a valid selection. Please select again: "); + break; + } + + STATE(d) = changeStateTo; +} \ No newline at end of file diff --git a/roleplay.h b/roleplay.h new file mode 100644 index 00000000..69ca5c48 --- /dev/null +++ b/roleplay.h @@ -0,0 +1,43 @@ + + +void choose_random_roleplay_goal(struct char_data *ch); +void choose_random_roleplay_personality(struct char_data *ch, int background); +void choose_random_roleplay_ideals(struct char_data *ch, int background); +void choose_random_roleplay_bonds(struct char_data *ch, int background); +void choose_random_roleplay_flaws(struct char_data *ch, int background); + +void show_character_goal_idea_menu(struct char_data *ch); +void show_character_goal_edit(struct descriptor_data *d); +void show_character_personality_edit(struct descriptor_data *d); +void show_character_ideals_edit(struct descriptor_data *d); +void show_character_flaws_edit(struct descriptor_data *d); +void show_character_personality_idea_menu(struct char_data *ch); +void show_character_ideals_idea_menu(struct char_data *ch); +void show_character_bonds_idea_menu(struct char_data *ch); +void show_character_flaws_idea_menu(struct char_data *ch); + +void display_age_menu(struct descriptor_data *d); +void display_faction_menu(struct descriptor_data *d); +void display_hometown_menu(struct descriptor_data *d); +void display_deity_menu(struct descriptor_data *d); +void display_deity_info(struct descriptor_data *d); +void display_rp_decide_menu(struct descriptor_data *d); + +void HandleStateCharacterHometownParseMenuChoice(struct descriptor_data *d, char *arg); +void HandleStateCharacterAgeParseMenuChoice(struct descriptor_data *d, char *arg); +void HandleStateCharacterFactionParseMenuChoice(struct descriptor_data *d, char *arg); +void HandleStateCharacterDeityParseMenuChoice(struct descriptor_data *d, char *arg); +void HandleStateCharacterDeityConfirmParseMenuChoice(struct descriptor_data *d, char *arg); +void HandleStateCharacterRPDecideParseMenuChoice(struct descriptor_data *d, char *arg); + +ACMD_DECL(do_goals); +ACMD_DECL(do_rpsheet); +ACMD_DECL(do_showrpinfo); + +#define CHARACTER_AGE_ADULT 0 +#define CHARACTER_AGE_YOUNG 1 +#define CHARACTER_AGE_MIDDLE_AGED 2 +#define CHARACTER_AGE_OLD 3 +#define CHARACTER_AGE_VENERABLE 4 + +#define NUM_CHARACTER_AGES 5 \ No newline at end of file diff --git a/spec_procs.c b/spec_procs.c index 943a1dbd..4a329cbc 100755 --- a/spec_procs.c +++ b/spec_procs.c @@ -912,6 +912,9 @@ int compute_ability_full(struct char_data *ch, int abilityNum, bool recursive) value += 1; } + if (HAS_FEAT(ch, FEAT_BG_SAILOR) && abilityNum == ABILITY_CRAFT_FISHING) + value += 5; + if (affected_by_spell(ch, PSIONIC_INFLICT_PAIN)) value += get_char_affect_modifier(ch, PSIONIC_INFLICT_PAIN, APPLY_HITROLL); // this should return a negative number, so + a - is - if (affected_by_spell(ch, SPELL_HEROISM)) @@ -1425,18 +1428,6 @@ int compute_ability_full(struct char_data *ch, int abilityNum, bool recursive) case ABILITY_CRAFT_METALWORKING: value += GET_INT_BONUS(ch); return value; - case ABILITY_KNOWLEDGE_ARCANA: - case ABILITY_KNOWLEDGE_ENGINEERING: - case ABILITY_KNOWLEDGE_DUNGEONEERING: - case ABILITY_KNOWLEDGE_GEOGRAPHY: - case ABILITY_KNOWLEDGE_HISTORY: - case ABILITY_KNOWLEDGE_LOCAL: - case ABILITY_KNOWLEDGE_NATURE: - case ABILITY_KNOWLEDGE_NOBILITY: - case ABILITY_KNOWLEDGE_RELIGION: - case ABILITY_KNOWLEDGE_PLANES: - value += GET_INT_BONUS(ch); - return value; default: return -1; } @@ -1507,10 +1498,6 @@ void list_abilities(struct char_data *ch, int ability_type) start_ability = START_CRAFT_ABILITIES; end_ability = END_CRAFT_ABILITIES + 1; break; - case ABILITY_TYPE_KNOWLEDGE: - start_ability = START_KNOWLEDGE_ABILITIES; - end_ability = END_KNOWLEDGE_ABILITIES + 1; - break; default: log("SYSERR: list_abilities called with invalid ability_type: %d", ability_type); start_ability = 1; diff --git a/spell_parser.c b/spell_parser.c index c66fd564..54e7a5be 100755 --- a/spell_parser.c +++ b/spell_parser.c @@ -469,13 +469,19 @@ int call_magic(struct char_data *caster, struct char_data *cvict, if (cvict && IS_UNDEAD(cvict)) { + if (!is_player_grouped(caster, cvict)) + { + switch (spellnum) + { + case SPELL_CURE_LIGHT: spellnum = SPELL_CAUSE_LIGHT_WOUNDS; break; + case SPELL_CURE_MODERATE: spellnum = SPELL_CAUSE_MODERATE_WOUNDS; break; + case SPELL_CURE_SERIOUS: spellnum = SPELL_CAUSE_SERIOUS_WOUNDS; break; + case SPELL_CURE_CRITIC: spellnum = SPELL_CAUSE_CRITICAL_WOUNDS; break; + case SPELL_HEAL: spellnum = SPELL_HARM; break; + } + } switch (spellnum) { - case SPELL_CURE_LIGHT: spellnum = SPELL_CAUSE_LIGHT_WOUNDS; break; - case SPELL_CURE_MODERATE: spellnum = SPELL_CAUSE_MODERATE_WOUNDS; break; - case SPELL_CURE_SERIOUS: spellnum = SPELL_CAUSE_SERIOUS_WOUNDS; break; - case SPELL_CURE_CRITIC: spellnum = SPELL_CAUSE_CRITICAL_WOUNDS; break; - case SPELL_HEAL: spellnum = SPELL_HARM; break; case SPELL_CAUSE_LIGHT_WOUNDS: spellnum = SPELL_CURE_LIGHT; break; case SPELL_CAUSE_MODERATE_WOUNDS: spellnum = SPELL_CURE_MODERATE; break; case SPELL_CAUSE_SERIOUS_WOUNDS: spellnum = SPELL_CURE_SERIOUS; break; @@ -4583,10 +4589,10 @@ void mag_assign_spells(void) TAR_IGNORE, FALSE, MAG_MANUAL, NULL, 1, 1, NOSCHOOL, 7, FALSE); spellabilo(WARLOCK_DARK_FORESIGHT, "dark foresight", 0, 0, 0, POS_FIGHTING, - TAR_IGNORE, FALSE, MAG_MANUAL, - NULL, 1, 1, NOSCHOOL, 9, FALSE); + TAR_CHAR_ROOM, FALSE, MAG_AFFECTS, + "You no longer possess dark foresight.", 1, 1, NOSCHOOL, 9, FALSE); spellabilo(WARLOCK_RETRIBUTIVE_INVISIBILITY, "retributive invisibility", 0, 0, 0, POS_FIGHTING, - TAR_IGNORE, FALSE, MAG_MANUAL, + TAR_CHAR_ROOM, FALSE, MAG_AFFECTS, NULL, 1, 1, NOSCHOOL, 6, FALSE); spellabilo(WARLOCK_WORD_OF_CHANGING, "word of changing", 0, 0, 0, POS_FIGHTING, TAR_IGNORE, FALSE, MAG_MANUAL, @@ -5140,6 +5146,9 @@ spello(SPELL_IDENTIFY, "!UNUSED!", 0, 0, 0, 0, spello(POISON_TYPE_DROW_STRONG, "strong drow poison", 1, 1, 1, POS_FIGHTING, TAR_CHAR_ROOM | TAR_NOT_SELF, TRUE, MAG_AFFECTS, "The strong drow poison fully passes through your system.", 1, 1, NOSCHOOL, FALSE); + spello(MOB_ABILITY_CORRUPTION, "corrupting attack", 1, 1, 1, POS_FIGHTING, TAR_CHAR_ROOM | TAR_NOT_SELF, TRUE, MAG_DAMAGE | MAG_AFFECTS, + "The corrupting affect fully passes through your system.", 1, 1, NOSCHOOL, FALSE); + spello(POISON_TYPE_WYVERN, "wyvern poison", 1, 1, 1, POS_FIGHTING, TAR_CHAR_ROOM | TAR_NOT_SELF, TRUE, MAG_DAMAGE | MAG_AFFECTS, "The wyvern poison fully passes through your system.", 1, 1, NOSCHOOL, FALSE); spello(POISON_TYPE_PURPLE_WORM, "purple worm poison", 1, 1, 1, POS_FIGHTING, TAR_CHAR_ROOM | TAR_NOT_SELF, TRUE, MAG_DAMAGE | MAG_AFFECTS, diff --git a/spells.h b/spells.h index 96529cff..043c4eb3 100755 --- a/spells.h +++ b/spells.h @@ -687,6 +687,7 @@ #define AFFECT_GLORYS_CALL 1279 #define SPELL_AFFECT_CREEPING_DOOM_BITE 1280 #define ABILITY_ENTERTAIN_INSPIRATION 1281 +#define MOB_ABILITY_CORRUPTION 1282 // 1470 to 1493 are poisons with room saved for more poisons up to 1498 @@ -1376,39 +1377,13 @@ #define ABILITY_CRAFT_TRAPMAKING 42 #define ABILITY_CRAFT_POISONMAKING 43 #define ABILITY_CRAFT_METALWORKING 44 +#define ABILITY_CRAFT_FISHING 45 +#define ABILITY_CRAFT_COOKING 46 +#define ABILITY_CRAFT_BREWING 47 -#define END_CRAFT_ABILITIES 44 +#define END_CRAFT_ABILITIES 47 +#define NUM_ABILITIES 47 /* End Crafting Abilities */ - -/* Start Knowledge Abilities */ -#define START_KNOWLEDGE_ABILITIES 45 - -#define ABILITY_KNOWLEDGE_ARCANA 45 -#define ABILITY_KNOWLEDGE_ENGINEERING 46 -#define ABILITY_KNOWLEDGE_DUNGEONEERING 47 -#define ABILITY_KNOWLEDGE_GEOGRAPHY 48 -#define ABILITY_KNOWLEDGE_HISTORY 49 -#define ABILITY_KNOWLEDGE_LOCAL 50 -#define ABILITY_KNOWLEDGE_NATURE 51 -#define ABILITY_KNOWLEDGE_NOBILITY 52 -#define ABILITY_KNOWLEDGE_RELIGION 53 -#define ABILITY_KNOWLEDGE_PLANES 54 - -#define END_KNOWLEDGE_ABILITIES 54 - -/* The abilities below have 'subabilities', basically - * the skill is broken down into many many sub skills - * each of which can be chosen for a train. Not yet - * Implemented. */ -/* -#define ABILITY_CRAFT 29 -#define ABILITY_KNOWLEDGE 30 -#define ABILITY_PROFESSION 32 -#define ABILITY_SPEAK_LANGUAGE 33 -*/ - -#define NUM_ABILITIES 55 /* Number of defined abilities */ -/* MAX_ABILITIES = 200 */ /*-------------------------------------------------------------------------*/ // ******** DAM_ ********* diff --git a/structs.h b/structs.h index 27398930..95b18923 100755 --- a/structs.h +++ b/structs.h @@ -1129,8 +1129,9 @@ #define MOB_BLOCK_GOOD 92 #define MOB_GENIEKIND 93 #define MOB_C_DRAGON 94 +#define MOB_RETAINER 95 /**********************/ -#define NUM_MOB_FLAGS 95 +#define NUM_MOB_FLAGS 96 /**********************/ /**********************/ @@ -1223,6 +1224,9 @@ #define MOB_PALADIN_MOUNT_SMALL 91 #define MOB_EPIC_PALADIN_MOUNT 79 #define MOB_EPIC_PALADIN_MOUNT_SMALL 92 +#define MOB_EPIC_BLACKGUARD_MOUNT 20803 +#define MOB_BLACKGUARD_MOUNT 20804 +#define MOB_ADV_BLACKGUARD_MOUNT 20805 #define MAX_MERCS 3 /*** end misc defines ****/ /**********************/ @@ -1302,9 +1306,12 @@ #define PRF_AUTO_STORE 70 // will automatically store consumables upon acquisition #define PRF_AUTO_GROUP 71 #define PRF_CONTAIN_AOE 72 +#define PRF_NON_ROLEPLAYER 73 +#define PRF_POST_COMBAT_BRIEF 74 +#define PRF_AUTOBLAST 75 /** Total number of available PRF flags */ -#define NUM_PRF_FLAGS 73 +#define NUM_PRF_FLAGS 76 /* Affect bits: used in char_data.char_specials.saved.affected_by */ /* WARNING: In the world files, NEVER set the bits marked "R" ("Reserved") */ @@ -1549,7 +1556,27 @@ #define CON_SETPREFS 61 -#define NUM_CON_STATES 62 +#define CON_CHAR_RP_MENU 62 +#define CON_BACKGROUND_ARCHTYPE 63 +#define CON_BACKGROUND_ARCHTYPE_CONFIRM 64 +#define CON_CHARACTER_GOALS_IDEAS 65 +#define CON_CHARACTER_GOALS_ENTER 66 +#define CON_CHARACTER_PERSONALITY_IDEAS 67 +#define CON_CHARACTER_PERSONALITY_ENTER 68 +#define CON_CHARACTER_IDEALS_IDEAS 69 +#define CON_CHARACTER_IDEALS_ENTER 70 +#define CON_CHARACTER_BONDS_IDEAS 71 +#define CON_CHARACTER_BONDS_ENTER 72 +#define CON_CHARACTER_FLAWS_IDEAS 73 +#define CON_CHARACTER_FLAWS_ENTER 74 +#define CON_CHARACTER_AGE_SELECT 75 +#define CON_CHARACTER_FACTION_SELECT 76 +#define CON_CHARACTER_HOMETOWN_SELECT 77 +#define CON_CHARACTER_DEITY_SELECT 78 +#define CON_CHARACTER_DEITY_CONFIRM 79 +#define CON_CHAR_RP_DECIDE 80 + +#define NUM_CON_STATES 81 /* Character equipment positions: used as index for char_data.equipment[] */ /* NOTE: Don't confuse these constants with the ITEM_ bitvectors @@ -2762,12 +2789,16 @@ #define FEAT_BG_SAILOR 1120 #define FEAT_BG_SOLDIER 1121 #define FEAT_BG_URCHIN 1122 +#define FEAT_IMPROVED_CRUELTIES 1123 +#define FEAT_ADVANCED_CRUELTIES 1124 +#define FEAT_MASTER_CRUELTIES 1125 +#define FEAT_EPIC_CRUELTIES 1126 /**************/ /** reserved above feat# + 1**/ -#define FEAT_LAST_FEAT 1123 +#define FEAT_LAST_FEAT 1127 /** FEAT_LAST_FEAT + 1 ***/ -#define NUM_FEATS 1124 +#define NUM_FEATS 1128 /** absolute cap **/ #define MAX_FEATS 1500 /*****/ @@ -3973,6 +4004,11 @@ #define MAX_COMPLETED_QUESTS 1024 /**< Maximum number of completed quests allowed */ #define MAX_ANGER 100 /**< Maximum mob anger/frustration as percentage */ #define PLR_BG_LENGTH MAX_STRING_LENGTH /**< Max length for PC background story */ +#define PLR_GOALS_LENGTH MAX_STRING_LENGTH +#define PLR_PERSONALITY_LENGTH MAX_STRING_LENGTH +#define PLR_IDEALS_LENGTH MAX_STRING_LENGTH +#define PLR_BONDS_LENGTH MAX_STRING_LENGTH +#define PLR_FLAWS_LENGTH MAX_STRING_LENGTH /* this is the value we are sending to act when we want it condensed (condensed combat toggle) -zusuk */ #define ACT_CONDENSE_VALUE -1234 @@ -4385,6 +4421,11 @@ struct char_player_data char *eidolon_detaildescription; bool weaponSpellProc; char *imm_title; // custom title for staff members + char *goals; // character role play goals + char *personality; // character role play personality + char *ideals; // character role play ideals + char *bonds; // character role play bonds + char *flaws; // character role play flaws }; /** Character abilities. Different instances of this structure are used for @@ -4443,7 +4484,7 @@ struct char_special_data_saved int act[PM_ARRAY_MAX]; /**< act flags for NPC's; player flag for PC's */ int affected_by[AF_ARRAY_MAX]; /**< Bitvector for spells/skills affected by */ int warding[MAX_WARDING]; // saved warding spells like stoneskin - ubyte spec_abil[MAX_CLASSES]; // spec abilities (ex. lay on hands) + int spec_abil[MAX_CLASSES]; // spec abilities (ex. lay on hands) struct damage_reduction_type *damage_reduction; /**< Damage Reduction */ @@ -4630,6 +4671,11 @@ struct char_special_data bool is_charmie; int sage_mob_vnum; + + bool post_combat_messages; + int post_combat_exp; + int post_combat_gold; + int post_combat_account_exp; }; /* old memorization struct */ @@ -4876,6 +4922,9 @@ struct player_special_data_saved int hometown; int forage_cooldown; + int retainer_cooldown; + int character_age; + bool character_age_saved; }; /** Specials needed only by PCs, not NPCs. Space for this structure is @@ -4963,6 +5012,7 @@ struct player_special_data char *forge_as_signature; int forge_check; + char *retainer_mail_recipient; }; /** Special data used by NPCs, not PCs */ diff --git a/study.c b/study.c index 041d8349..74f7e94b 100644 --- a/study.c +++ b/study.c @@ -1514,13 +1514,13 @@ static void set_stats_menu(struct descriptor_data *d) "to reset your characters stats to try a different configuration.\r\n" "Change made to base stat: 1 2 3 4 5 6 7 8 9 10\r\n" "Point cost : 1 2 3 4 5 6 8 10 13 16\r\n" - " Base | Race Mod | Final\r\n" - "%s 0%s) Strength: %2d%s | %6s%s%d | %d\r\n" - "%s 1%s) Dexterity: %2d%s | %6s%s%d | %d\r\n" - "%s 2%s) Constitution: %2d%s | %6s%s%d | %d\r\n" - "%s 3%s) Intelligence: %2d%s | %6s%s%d | %d\r\n" - "%s 4%s) Wisdom: %2d%s | %6s%s%d | %d\r\n" - "%s 5%s) Charisma: %2d%s | %6s%s%d | %d\r\n" + " Base | Race Mod | Age Mod |Final\r\n" + "%s 0%s) Strength: %2d%s | %6s%s%d | %5s%s%d | %d\r\n" + "%s 1%s) Dexterity: %2d%s | %6s%s%d | %5s%s%d | %d\r\n" + "%s 2%s) Constitution: %2d%s | %6s%s%d | %5s%s%d | %d\r\n" + "%s 3%s) Intelligence: %2d%s | %6s%s%d | %5s%s%d | %d\r\n" + "%s 4%s) Wisdom: %2d%s | %6s%s%d | %5s%s%d | %d\r\n" + "%s 5%s) Charisma: %2d%s | %6s%s%d | %5s%s%d | %d\r\n" "%sPoints Left: %d%s\r\n" "\r\n" "%s H%s) Help - Info on What Each Ability Score Does.\r\n" @@ -1538,17 +1538,35 @@ static void set_stats_menu(struct descriptor_data *d) mgn, nrm, /* empty line */ grn, nrm, LEVELUP(d->character)->str, nrm, "", get_race_stat(GET_RACE(d->character), R_STR_MOD) >= 0 ? "+" : "", - get_race_stat(GET_RACE(d->character), R_STR_MOD), get_race_stat(GET_RACE(d->character), R_STR_MOD) + LEVELUP(d->character)->str, + get_race_stat(GET_RACE(d->character), R_STR_MOD), + "", character_age_attributes[GET_CH_AGE(d->character)][0] >= 0 ? "+" : "", character_age_attributes[GET_CH_AGE(d->character)][0], + get_race_stat(GET_RACE(d->character), R_STR_MOD) + LEVELUP(d->character)->str + character_age_attributes[GET_CH_AGE(d->character)][0], + grn, nrm, LEVELUP(d->character)->dex, nrm, "", get_race_stat(GET_RACE(d->character), R_DEX_MOD) >= 0 ? "+" : "", - get_race_stat(GET_RACE(d->character), R_DEX_MOD), get_race_stat(GET_RACE(d->character), R_DEX_MOD) + LEVELUP(d->character)->dex, + get_race_stat(GET_RACE(d->character), R_DEX_MOD), + "", character_age_attributes[GET_CH_AGE(d->character)][1] >= 0 ? "+" : "", character_age_attributes[GET_CH_AGE(d->character)][1], + get_race_stat(GET_RACE(d->character), R_DEX_MOD) + LEVELUP(d->character)->dex + character_age_attributes[GET_CH_AGE(d->character)][1], + grn, nrm, LEVELUP(d->character)->con, nrm, "", get_race_stat(GET_RACE(d->character), R_CON_MOD) >= 0 ? "+" : "", - get_race_stat(GET_RACE(d->character), R_CON_MOD), get_race_stat(GET_RACE(d->character), R_CON_MOD) + LEVELUP(d->character)->con, + get_race_stat(GET_RACE(d->character), R_CON_MOD), + "", character_age_attributes[GET_CH_AGE(d->character)][2] >= 0 ? "+" : "", character_age_attributes[GET_CH_AGE(d->character)][2], + get_race_stat(GET_RACE(d->character), R_CON_MOD) + LEVELUP(d->character)->con + character_age_attributes[GET_CH_AGE(d->character)][2], + grn, nrm, LEVELUP(d->character)->inte, nrm, "", get_race_stat(GET_RACE(d->character), R_INTEL_MOD) >= 0 ? "+" : "", - get_race_stat(GET_RACE(d->character), R_INTEL_MOD), get_race_stat(GET_RACE(d->character), R_INTEL_MOD) + LEVELUP(d->character)->inte, + get_race_stat(GET_RACE(d->character), R_INTEL_MOD), + "", character_age_attributes[GET_CH_AGE(d->character)][3] >= 0 ? "+" : "", character_age_attributes[GET_CH_AGE(d->character)][3], + get_race_stat(GET_RACE(d->character), R_INTEL_MOD) + LEVELUP(d->character)->inte + character_age_attributes[GET_CH_AGE(d->character)][3], + grn, nrm, LEVELUP(d->character)->wis, nrm, "", get_race_stat(GET_RACE(d->character), R_WIS_MOD) >= 0 ? "+" : "", - get_race_stat(GET_RACE(d->character), R_WIS_MOD), get_race_stat(GET_RACE(d->character), R_WIS_MOD) + LEVELUP(d->character)->wis, + get_race_stat(GET_RACE(d->character), R_WIS_MOD), + "", character_age_attributes[GET_CH_AGE(d->character)][4] >= 0 ? "+" : "", character_age_attributes[GET_CH_AGE(d->character)][4], + get_race_stat(GET_RACE(d->character), R_WIS_MOD) + LEVELUP(d->character)->wis + character_age_attributes[GET_CH_AGE(d->character)][4], + grn, nrm, LEVELUP(d->character)->cha, nrm, "", get_race_stat(GET_RACE(d->character), R_CHA_MOD) >= 0 ? "+" : "", - get_race_stat(GET_RACE(d->character), R_CHA_MOD), get_race_stat(GET_RACE(d->character), R_CHA_MOD) + LEVELUP(d->character)->cha, + get_race_stat(GET_RACE(d->character), R_CHA_MOD), + "", character_age_attributes[GET_CH_AGE(d->character)][5] >= 0 ? "+" : "", character_age_attributes[GET_CH_AGE(d->character)][5], + get_race_stat(GET_RACE(d->character), R_CHA_MOD) + LEVELUP(d->character)->cha + character_age_attributes[GET_CH_AGE(d->character)][5], + grn, stat_points_left(d->character), nrm, /* empty line */ grn, nrm, @@ -2370,7 +2388,8 @@ static void main_skills_disp_menu(struct descriptor_data *d) for (i = 0; i < NUM_SKILLS_IN_GAME; i++) { send_to_char(ch, "%-18s [%2d] \tC[%2d]\tn %s\r\n", - ability_names[skills_alphabetic[i]], GET_ABILITY(ch, skills_alphabetic[i]), compute_ability(ch, skills_alphabetic[i]), + ability_names[skills_alphabetic[i]], GET_ABILITY(ch, skills_alphabetic[i]) + LEVELUP(ch)->skills[skills_alphabetic[i]], + compute_ability(ch, skills_alphabetic[i]), cross_names[modify_class_ability(ch, skills_alphabetic[i], GET_CLASS(ch))]); } @@ -3115,6 +3134,7 @@ void study_parse(struct descriptor_data *d, char *arg) // let's update trains if (GET_LEVELUP_BOOST_STATS(ch, 3) > 0) intel_bonus += ((GET_REAL_INT(ch) + 1) % 2) ? 0 : 1; + GET_LEVELUP_SKILL_POINTS(ch) += intel_bonus; display_main_menu(d); return; @@ -5115,14 +5135,15 @@ void study_parse(struct descriptor_data *d, char *arg) break; } // We're applying racial bonuses now instead of in init_start_char in class.c + // same with age modifiers if (!HAS_SET_STATS_STUDY(ch)) { - LEVELUP(d->character)->con += get_race_stat(GET_RACE(ch), R_CON_MOD); - LEVELUP(d->character)->str += get_race_stat(GET_RACE(ch), R_STR_MOD); - LEVELUP(d->character)->dex += get_race_stat(GET_RACE(ch), R_DEX_MOD); - LEVELUP(d->character)->inte += get_race_stat(GET_RACE(ch), R_INTEL_MOD); - LEVELUP(d->character)->wis += get_race_stat(GET_RACE(ch), R_WIS_MOD); - LEVELUP(d->character)->cha += get_race_stat(GET_RACE(ch), R_CHA_MOD); + LEVELUP(d->character)->con += get_race_stat(GET_RACE(ch), R_CON_MOD) + character_age_attributes[GET_CH_AGE(ch)][2]; + LEVELUP(d->character)->str += get_race_stat(GET_RACE(ch), R_STR_MOD) + character_age_attributes[GET_CH_AGE(ch)][0]; + LEVELUP(d->character)->dex += get_race_stat(GET_RACE(ch), R_DEX_MOD) + character_age_attributes[GET_CH_AGE(ch)][1]; + LEVELUP(d->character)->inte += get_race_stat(GET_RACE(ch), R_INTEL_MOD) + character_age_attributes[GET_CH_AGE(ch)][3]; + LEVELUP(d->character)->wis += get_race_stat(GET_RACE(ch), R_WIS_MOD) + character_age_attributes[GET_CH_AGE(ch)][4]; + LEVELUP(d->character)->cha += get_race_stat(GET_RACE(ch), R_CHA_MOD) + character_age_attributes[GET_CH_AGE(ch)][5]; HAS_SET_STATS_STUDY(ch) = TRUE; } // let's update trains diff --git a/transport.c b/transport.c index e7c48d2c..7b3e681c 100644 --- a/transport.c +++ b/transport.c @@ -320,7 +320,7 @@ ACMDU(do_sail) skip_spaces(&argument); - int i = 0; + int i = 0, cost; char buf[200]; bool found = false; @@ -357,7 +357,10 @@ ACMDU(do_sail) if (GET_ROOM_VNUM(IN_ROOM(ch)) != atoi(sailing_locales[i][1]) && valid_sailing_travel(here, i)) { found = true; - send_to_char(ch, "%-35s %4s %10d %10d (%s)\r\n", sailing_locales[i][0], sailing_locales[i][2], get_distance(ch, i, here, TRAVEL_SAILING), get_travel_time(ch, 10, i, here, TRAVEL_SAILING), sailing_locales[i][4]); + cost = atoi(sailing_locales[i][2]); + if (HAS_FEAT(ch, FEAT_BG_SAILOR)) + cost = 0; + send_to_char(ch, "%-35s %4d %10d %10d (%s)\r\n", sailing_locales[i][0], cost, get_distance(ch, i, here, TRAVEL_SAILING), get_travel_time(ch, 10, i, here, TRAVEL_SAILING), sailing_locales[i][4]); } i++; } @@ -387,15 +390,22 @@ ACMDU(do_sail) if (is_abbrev(argument, sailing_locales[i][0])) { found = true; - if (GET_GOLD(ch) < atoi(sailing_locales[i][2])) + cost = atoi(sailing_locales[i][2]); + if (HAS_FEAT(ch, FEAT_BG_SAILOR)) + cost = 0; + if (cost == 0) + { + send_to_char(ch, "The sailor waves you aboard free of charge.\r\n"); + } + else if (GET_GOLD(ch) < cost) { - send_to_char(ch, "You are denied boarding as you cannot pay the fee of %s.\r\n", sailing_locales[i][2]); + send_to_char(ch, "You are denied boarding as you cannot pay the fee of %dmake.\r\n", cost); return; } else { - send_to_char(ch, "You give the ship's captain your fee of %s.\r\n", sailing_locales[i][2]); - GET_GOLD(ch) -= atoi(sailing_locales[i][2]); + send_to_char(ch, "You give the ship's captain your fee of %d.\r\n", cost); + GET_GOLD(ch) -= cost; } room_rnum to_room = NOWHERE; snprintf(buf, sizeof(buf), "%s", sailing_locales[i][1]); @@ -822,6 +832,9 @@ int get_travel_time(struct char_data *ch, int speed, int locale, int here, int t distance /= speed; #endif + if (HAS_FEAT(ch, FEAT_BG_SAILOR)) + distance /= 2; + return distance; } diff --git a/util/plrtoascii.c b/util/plrtoascii.c index 09b2335b..28f1fea3 100755 --- a/util/plrtoascii.c +++ b/util/plrtoascii.c @@ -102,7 +102,7 @@ struct player_special_data_saved_plrtoascii ubyte abilities[MAX_ABILITIES + 1]; // ability array ubyte boosts; // stat boosts left - ubyte spec_abil[MAX_CLASSES]; // spec ability (daily resets) + int spec_abil[MAX_CLASSES]; // spec ability (daily resets) ubyte spare2; ubyte morphed; // morph form ubyte page_length; diff --git a/utils.c b/utils.c index 45a29b91..6b9ce912 100755 --- a/utils.c +++ b/utils.c @@ -841,6 +841,27 @@ bool is_room_outdoors(room_rnum room_number) return TRUE; } +bool is_in_water(struct char_data *ch) +{ + if (IN_ROOM(ch) == NOWHERE) + return false; + + switch (world[IN_ROOM(ch)].sector_type) + { + case SECT_BEACH: + case SECT_OCEAN: + case SECT_RIVER: + case SECT_SEAPORT: + case SECT_UD_NOSWIM: + case SECT_UD_WATER: + case SECT_WATER_NOSWIM: + case SECT_WATER_SWIM: + case SECT_UNDERWATER: + return true; + } + return false; +} + bool is_in_wilderness(struct char_data *ch) { if (!OUTDOORS(ch)) @@ -7181,12 +7202,12 @@ int smite_evil_target_type(struct char_data *ch) return 0; if (!IS_EVIL(ch)) - return 0; + return 1; if (IS_DRAGON(ch) || IS_OUTSIDER(ch) || IS_UNDEAD(ch)) - return 2; + return 3; - return 1; + return 2; } int smite_good_target_type(struct char_data *ch) @@ -7195,14 +7216,14 @@ int smite_good_target_type(struct char_data *ch) return 0; if (!IS_GOOD(ch)) - return 0; + return 1; if (IS_DRAGON(ch) || IS_OUTSIDER(ch) || CLASS_LEVEL(ch, CLASS_CLERIC) > 0 || CLASS_LEVEL(ch, CLASS_PALADIN) > 0) - return 2; + return 3; - return 1; + return 2; } /** This will run every 6 seconds as well as whenever a new affect is added or removed @@ -9593,4 +9614,117 @@ bool has_sage_mob_bonus(struct char_data *ch) return result; } +bool is_grouped_with_soldier(struct char_data *ch) +{ + + struct char_data *tch; + + if (!ch) + return false; + + if (IN_ROOM(ch) == NOWHERE) + return false; + + if (IS_NPC(ch)) + return false; + + if (!HAS_FEAT(ch, FEAT_BG_SOLDIER)) + return false; + + for (tch = world[IN_ROOM(ch)].people; tch; tch = tch->next_in_room) + { + if (ch == tch) continue; + if (GROUP(tch) != GROUP(ch)) continue; + return true; + } + return false; +} + +bool is_retainer_in_room(struct char_data *ch) +{ + struct char_data *tch; + + if (!ch) + return false; + + if (IN_ROOM(ch) == NOWHERE) + return false; + + if (IS_NPC(ch)) + return false; + + if (!HAS_FEAT(ch, FEAT_BG_SQUIRE)) + return false; + + for (tch = world[IN_ROOM(ch)].people; tch; tch = tch->next_in_room) + { + if (!IS_NPC(tch)) continue; + if (tch->master != ch) continue; + if (!MOB_FLAGGED(tch, MOB_RETAINER)) continue; + return true; + } + return false; +} + +struct char_data *get_retainer_from_room(struct char_data *ch) +{ + struct char_data *tch; + + if (!ch) + return NULL; + + if (IN_ROOM(ch) == NOWHERE) + return NULL; + + if (IS_NPC(ch)) + return NULL; + + if (!HAS_FEAT(ch, FEAT_BG_SQUIRE)) + return NULL; + + for (tch = world[IN_ROOM(ch)].people; tch; tch = tch->next_in_room) + { + if (!IS_NPC(tch)) continue; + if (tch->master != ch) continue; + if (!MOB_FLAGGED(tch, MOB_RETAINER)) continue; + return tch; + } + return NULL; +} + +int get_smite_evil_level(struct char_data *ch) +{ + int smite_level = 0; + + smite_level += CLASS_LEVEL(ch, CLASS_PALADIN); + smite_level += CLASS_LEVEL(ch, CLASS_KNIGHT_OF_THE_SWORD); + + return smite_level; +} + +int get_smite_good_level(struct char_data *ch) +{ + int smite_level = 0; + + smite_level += CLASS_LEVEL(ch, CLASS_BLACKGUARD); + smite_level += CLASS_LEVEL(ch, CLASS_KNIGHT_OF_THE_SKULL); + + return smite_level; +} + +bool has_dr_affect(struct char_data *ch, int spell) +{ + if (!ch) return false; + + struct damage_reduction_type *dr; + for (dr = GET_DR(ch); dr != NULL; dr = dr->next) + { + if (dr->spell == spell) + { + return true; + } + } + return false; +} + /* EoF */ diff --git a/utils.h b/utils.h index 9630e36f..06b6a0ee 100755 --- a/utils.h +++ b/utils.h @@ -160,6 +160,7 @@ bool affected_by_aura_of_faith(struct char_data *ch); bool affected_by_aura_of_depravity(struct char_data *ch); bool affected_by_aura_of_righteousness(struct char_data *ch); bool is_fear_spell(int spellnum); +bool is_grouped_with_soldier(struct char_data *ch); bool is_crafting_skill(int skillnum); bool is_selectable_region(int region); int get_knowledge_skill_from_creature_type(int race_type); @@ -213,6 +214,8 @@ void set_alignment(struct char_data *ch, int alignment); bool is_spellcasting_class(int class_name); int get_spellcasting_class(struct char_data *ch); bool valid_pet_name(char *name); +bool is_retainer_in_room(struct char_data *ch); +struct char_data *get_retainer_from_room(struct char_data *ch); int count_spellcasting_classes(struct char_data *ch); void auto_sort_obj(struct char_data *ch, struct obj_data *obj); void auto_store_obj(struct char_data *ch, struct obj_data *obj); @@ -235,6 +238,7 @@ void basic_mud_vlog(const char *format, va_list args); int touch(const char *path); void mudlog(int type, int level, int file, const char *str, ...) __attribute__((format(printf, 4, 5))); int rand_number(int from, int to); +bool is_in_water(struct char_data *ch); float rand_float(float from, float to); bool do_not_list_spell(int spellnum); void set_x_y_coords(int start, int *x, int *y, int *room); @@ -257,6 +261,9 @@ int get_line(FILE *fl, char *buf); int get_filename(char *filename, size_t fbufsize, int mode, const char *orig_name); const char *get_wearoff(int abilnum); time_t mud_time_to_secs(struct time_info_data *now); +int get_smite_evil_level(struct char_data *ch); +bool has_dr_affect(struct char_data *ch, int spell); +int get_smite_good_level(struct char_data *ch); struct time_info_data *age(struct char_data *ch); int num_pc_in_room(struct room_data *room); void core_dump_real(const char *who, int line); @@ -751,6 +758,9 @@ void char_from_furniture(struct char_data *ch); #define IS_PAL_MOUNT(ch) (MOB_FLAGGED(ch, MOB_C_MOUNT) && \ AFF_FLAGGED(ch, AFF_CHARM) && \ ch->master) +#define IS_BKG_MOUNT(ch) (MOB_FLAGGED(ch, MOB_C_MOUNT) && \ + AFF_FLAGGED(ch, AFF_CHARM) && \ + ch->master) #define IS_COMPANION(ch) (MOB_FLAGGED(ch, MOB_C_ANIMAL) && \ AFF_FLAGGED(ch, AFF_CHARM) && \ ch->master) @@ -946,6 +956,8 @@ void char_from_furniture(struct char_data *ch); /** Sex of ch. */ #define GET_SEX(ch) ((ch)->player.sex) +#define GET_CH_AGE(ch) (ch->player_specials->saved.character_age) + /* absolute stat cap */ #define STAT_CAP 50 @@ -2215,6 +2227,7 @@ int ACTUAL_BAB(struct char_data *ch); /** Defines if ch is outdoors or not. */ #define OUTDOORS(ch) (is_outdoors(ch)) +#define IN_WATER(ch) (is_in_water(ch)) #define IN_WILDERNESS(ch) (is_in_wilderness(ch)) #define ROOM_OUTDOORS(room) (is_room_outdoors(room)) #define OUTSIDE(ch) (is_outdoors(ch)) @@ -2639,9 +2652,12 @@ bool has_reach(struct char_data *ch); #define GET_HOMETOWN(ch) (ch->player_specials->saved.hometown) #define GET_FORAGE_COOLDOWN(ch) (ch->player_specials->saved.forage_cooldown) +#define GET_RETAINER_COOLDOWN(ch) (ch->player_specials->saved.retainer_cooldown) #define GET_SAGE_MOB_VNUM(ch) (ch->char_specials.sage_mob_vnum) +#define GET_RETAINER_MAIL_RECIPIENT(ch) (ch->player_specials->retainer_mail_recipient) + #endif /* _UTILS_H_ */ /*EOF*/