From 1efb08dafd9aa03d479d6df7507bcb6e6dbbce1e Mon Sep 17 00:00:00 2001 From: kinther Date: Sun, 28 Dec 2025 15:11:37 -0800 Subject: [PATCH] Cap skill levels, fix imm combat, remove plr_killer and plr_thief flags --- README.md | 25 ++- lib/world/trg/0.trg | 6 + lib/world/trg/index | 1 + src/act.informative.c | 11 -- src/act.offensive.c | 11 +- src/act.wizard.c | 28 ++- src/cedit.c | 11 -- src/class.c | 399 ++++++++++++++++++++++++------------------ src/class.h | 2 + src/config.c | 7 - src/config.h | 1 - src/constants.c | 4 +- src/db.c | 7 +- src/dg_variables.c | 24 --- src/fight.c | 112 ++++++++---- src/fight.h | 1 - src/limits.c | 12 +- src/magic.c | 13 +- src/spec_procs.c | 12 -- src/spells.c | 24 --- src/structs.h | 5 +- src/utils.h | 1 - 22 files changed, 366 insertions(+), 351 deletions(-) diff --git a/README.md b/README.md index 682532d..d613d35 100644 --- a/README.md +++ b/README.md @@ -46,16 +46,31 @@ Features in Miranthas MUD Alpha release: Features to be implemented in the next few releases: -* Race/species selection -* Subclass selection +* Race/species selection and stat ranges (elves have higher dex, dwarves have higher str, etc) +* Subclass selection to personalize character further +* Prioritized stats during character generation +* Combat is slowed down so it isn't over in < 15 seconds (unless you're far outmatched) +* Mounts added to help with long trips +* Wagons added to help with caravans +* Plantlife introduced +* Updated lockpicking skill +* Trap as a skill - one focused on city and one focused on desert +* Poisons and antidotes +* New alcohol and drugs/stimulants +* Skimmers/ships to traverse difficult terrain +* New elemental classes +* Introduction of gathering mana/magic for sorceror class +* Highly modified magic system +* Components for some magical spells +* Reading/writing limited to specific castes of society +* Haggling and bartering system * New calendar and moon cycles * Heat based on time of day increases/decreases, changing hunger/thirst levels -* Sandstorms -* Shaded rooms +* Sandstorms limiting visibility +* Shaded rooms providing bonuses to regeneration * Criminal system for cities and jails * Basic Psionics * Basic crafting system -* Continued skill and spell improvements * Apartment rentals for storing your loot * Enhanced quest system * Dialogue trees with NPC's diff --git a/lib/world/trg/0.trg b/lib/world/trg/0.trg index 185c943..ffda257 100644 --- a/lib/world/trg/0.trg +++ b/lib/world/trg/0.trg @@ -1 +1,7 @@ +#1 +Test~ +0 q 1 +~ +* No Script +~ $~ diff --git a/lib/world/trg/index b/lib/world/trg/index index 695b3a8..95df992 100644 --- a/lib/world/trg/index +++ b/lib/world/trg/index @@ -1,4 +1,5 @@ 0.trg 1.trg 2.trg + $ diff --git a/src/act.informative.c b/src/act.informative.c index 33dc482..04c2183 100644 --- a/src/act.informative.c +++ b/src/act.informative.c @@ -1589,8 +1589,6 @@ ACMD(do_who) continue; if (!CAN_SEE(ch, tch) || GET_LEVEL(tch) < low || GET_LEVEL(tch) > high) continue; - if (outlaws && !PLR_FLAGGED(tch, PLR_KILLER) && !PLR_FLAGGED(tch, PLR_THIEF)) - continue; if (questwho && !PRF_FLAGGED(tch, PRF_QUEST)) continue; if (localwho && world[IN_ROOM(ch)].zone != world[IN_ROOM(tch)].zone) @@ -1635,8 +1633,6 @@ ACMD(do_who) continue; if (!CAN_SEE(ch, tch) || GET_LEVEL(tch) < low || GET_LEVEL(tch) > high) continue; - if (outlaws && !PLR_FLAGGED(tch, PLR_KILLER) && !PLR_FLAGGED(tch, PLR_THIEF)) - continue; if (questwho && !PRF_FLAGGED(tch, PRF_QUEST)) continue; if (localwho && world[IN_ROOM(ch)].zone != world[IN_ROOM(tch)].zone) @@ -1709,10 +1705,6 @@ ACMD(do_who) send_to_char(ch, " (noshout)"); if (PRF_FLAGGED(tch, PRF_QUEST)) send_to_char(ch, " (quest)"); - if (PLR_FLAGGED(tch, PLR_THIEF)) - send_to_char(ch, " (THIEF)"); - if (PLR_FLAGGED(tch, PLR_KILLER)) - send_to_char(ch, " (KILLER)"); send_to_char(ch, "\r\n"); } } @@ -1820,9 +1812,6 @@ ACMD(do_users) continue; if (!CAN_SEE(ch, tch) || GET_LEVEL(tch) < low || GET_LEVEL(tch) > high) continue; - if (outlaws && !PLR_FLAGGED(tch, PLR_KILLER) && - !PLR_FLAGGED(tch, PLR_THIEF)) - continue; if (showclass && !(showclass & (1 << GET_CLASS(tch)))) continue; if (GET_INVIS_LEV(tch) > GET_LEVEL(ch)) diff --git a/src/act.offensive.c b/src/act.offensive.c index 3d59499..61bdf03 100644 --- a/src/act.offensive.c +++ b/src/act.offensive.c @@ -54,8 +54,6 @@ ACMD(do_assist) else if (!CAN_SEE(ch, opponent)) act("You can't see who is fighting $M!", FALSE, ch, 0, helpee, TO_CHAR); /* prevent accidental pkill */ - else if (!CONFIG_PK_ALLOWED && !IS_NPC(opponent)) - send_to_char(ch, "You cannot kill other players.\r\n"); else { send_to_char(ch, "You join the fight!\r\n"); act("$N assists you!", 0, helpee, 0, ch, TO_CHAR); @@ -82,9 +80,6 @@ ACMD(do_hit) } else if (AFF_FLAGGED(ch, AFF_CHARM) && (ch->master == vict)) act("$N is just such a good friend, you simply can't hit $M.", FALSE, ch, 0, vict, TO_CHAR); else { - if (!CONFIG_PK_ALLOWED && !IS_NPC(vict) && !IS_NPC(ch)) - check_killer(ch, vict); - if ((GET_POS(ch) == POS_STANDING) && (vict != FIGHTING(ch))) { if (GET_DEX(ch) > GET_DEX(vict) || (GET_DEX(ch) == GET_DEX(vict) && rand_number(1, 2) == 1)) /* if faster */ hit(ch, vict, TYPE_UNDEFINED); /* first */ @@ -150,7 +145,7 @@ ACMD(do_backstab) return; } /* Only piercing weapons allowed */ - if (GET_OBJ_VAL(weap, 3) != TYPE_PIERCE - TYPE_HIT) { + if (GET_OBJ_VAL(weap, 2) != TYPE_PIERCE - TYPE_HIT) { send_to_char(ch, "Only piercing weapons can be used for backstabbing.\r\n"); return; } @@ -187,14 +182,14 @@ ACMD(do_backstab) /* Keeping this logic really simple so it can be adjusted later if need be */ if (crit_success) { /* Simple crit = 2x damage */ - int base = dice(GET_OBJ_VAL(weap, 1), GET_OBJ_VAL(weap, 2)); + int base = dice(GET_OBJ_VAL(weap, 0), GET_OBJ_VAL(weap, 1)); int dmg = base + GET_ABILITY_MOD(GET_DEX(ch)); if (dmg < 1) dmg = 1; dmg *= 2; damage(ch, vict, dmg, SKILL_BACKSTAB); } else { /* Hit but not crit = 1.5x damage */ - int base = dice(GET_OBJ_VAL(weap, 1), GET_OBJ_VAL(weap, 2)); + int base = dice(GET_OBJ_VAL(weap, 0), GET_OBJ_VAL(weap, 1)); int dmg = base + GET_ABILITY_MOD(GET_DEX(ch)); if (dmg < 1) dmg = 1; dmg *= 1.5; diff --git a/src/act.wizard.c b/src/act.wizard.c index 794c3fa..f3943a0 100644 --- a/src/act.wizard.c +++ b/src/act.wizard.c @@ -3302,16 +3302,8 @@ ACMD(do_wizutil) GET_DEX(vict), GET_CON(vict), GET_CHA(vict)); break; case SCMD_PARDON: - if (!PLR_FLAGGED(vict, PLR_THIEF) && !PLR_FLAGGED(vict, PLR_KILLER)) { - send_to_char(ch, "Your victim is not flagged.\r\n"); - return; - } - REMOVE_BIT_AR(PLR_FLAGS(vict), PLR_THIEF); - REMOVE_BIT_AR(PLR_FLAGS(vict), PLR_KILLER); - send_to_char(ch, "Pardoned.\r\n"); - send_to_char(vict, "You have been pardoned by the Gods!\r\n"); - mudlog(BRF, MAX(LVL_GOD, GET_INVIS_LEV(ch)), TRUE, "(GC) %s pardoned by %s", GET_NAME(vict), GET_NAME(ch)); - break; + send_to_char(ch, "Criminal flags are currently disabled.\r\n"); + return; case SCMD_MUTE: result = PLR_TOG_CHK(vict, PLR_NOSHOUT); mudlog(BRF, MAX(LVL_GOD, GET_INVIS_LEV(ch)), TRUE, "(GC) Mute %s for %s by %s.", @@ -3783,7 +3775,7 @@ static struct set_struct { { "int", LVL_BUILDER, BOTH, NUMBER }, { "invis", LVL_GOD, PC, NUMBER }, { "invstart", LVL_BUILDER, PC, BINARY }, - { "killer", LVL_GOD, PC, BINARY }, + { "unused0", LVL_GOD, PC, BINARY }, { "level", LVL_GRGOD, BOTH, NUMBER }, /* 25 */ { "loadroom", LVL_BUILDER, PC, MISC }, { "mana", LVL_BUILDER, BOTH, NUMBER }, @@ -3808,7 +3800,7 @@ static struct set_struct { { "siteok", LVL_GOD, PC, BINARY }, { "skill", LVL_GOD, BOTH, NUMBER }, { "str", LVL_BUILDER, BOTH, NUMBER }, - { "thief", LVL_GOD, PC, BINARY }, + { "unused1", LVL_GOD, PC, BINARY }, { "thirst", LVL_BUILDER, BOTH, MISC }, /* 50 */ { "variable", LVL_GRGOD, PC, MISC }, { "weight", LVL_BUILDER, BOTH, NUMBER }, @@ -4024,9 +4016,9 @@ static int perform_set(struct char_data *ch, struct char_data *vict, int mode, c case 21: /* invistart */ SET_OR_REMOVE(PLR_FLAGS(vict), PLR_INVSTART); break; - case 22: /* killer */ - SET_OR_REMOVE(PLR_FLAGS(vict), PLR_KILLER); - break; + case 22: /* unused0 (removed killer flag) */ + send_to_char(ch, "That flag is no longer in use.\r\n"); + return (0); case 23: /* level */ if ((!IS_NPC(vict) && value > GET_LEVEL(ch)) || value > LVL_IMPL) { send_to_char(ch, "You can't do that.\r\n"); @@ -4273,9 +4265,9 @@ static int perform_set(struct char_data *ch, struct char_data *vict, int mode, c vict->real_abils.str = value; affect_total(vict); break; - case 47: /* thief */ - SET_OR_REMOVE(PLR_FLAGS(vict), PLR_THIEF); - break; + case 47: /* unused1 (removed thief flag) */ + send_to_char(ch, "That flag is no longer in use.\r\n"); + return (0); case 48: /* thirst */ if (!str_cmp(val_arg, "off")) { GET_COND(vict, THIRST) = -1; diff --git a/src/cedit.c b/src/cedit.c index 8feba55..af0bb5c 100644 --- a/src/cedit.c +++ b/src/cedit.c @@ -79,7 +79,6 @@ static void cedit_setup(struct descriptor_data *d) /* Copy the current configuration from the config_info to this one and copy * the game play options from the configuration info struct. */ - OLC_CONFIG(d)->play.pk_allowed = CONFIG_PK_ALLOWED; OLC_CONFIG(d)->play.pt_allowed = CONFIG_PT_ALLOWED; OLC_CONFIG(d)->play.level_can_shout = CONFIG_LEVEL_CAN_SHOUT; OLC_CONFIG(d)->play.tunnel_size = CONFIG_TUNNEL_SIZE; @@ -177,7 +176,6 @@ static void cedit_save_internally(struct descriptor_data *d) /* see if we need to reassign spec procs on rooms */ int reassign = (CONFIG_DTS_ARE_DUMPS != OLC_CONFIG(d)->play.dts_are_dumps); /* Copy the data back from the descriptor to the config_info structure. */ - CONFIG_PK_ALLOWED = OLC_CONFIG(d)->play.pk_allowed; CONFIG_PT_ALLOWED = OLC_CONFIG(d)->play.pt_allowed; CONFIG_LEVEL_CAN_SHOUT = OLC_CONFIG(d)->play.level_can_shout; CONFIG_TUNNEL_SIZE = OLC_CONFIG(d)->play.tunnel_size; @@ -326,8 +324,6 @@ int save_config( IDXTYPE nowhere ) "* [ Game Play Options ]\n" ); - fprintf(fl, "* Is player killing allowed on the mud?\n" - "pk_allowed = %d\n\n", CONFIG_PK_ALLOWED); fprintf(fl, "* Is player thieving allowed on the mud?\n" "pt_allowed = %d\n\n", CONFIG_PT_ALLOWED); fprintf(fl, "* What is the minimum level a player can shout/gossip/etc?\n" @@ -591,7 +587,6 @@ static void cedit_disp_game_play_options(struct descriptor_data *d) write_to_output(d, "\r\n\r\n" - "%sA%s) Player Killing Allowed : %s%s\r\n" "%sB%s) Player Thieving Allowed : %s%s\r\n" "%sC%s) Minimum Level To Shout : %s%d\r\n" "%sE%s) Tunnel Size : %s%d\r\n" @@ -617,7 +612,6 @@ static void cedit_disp_game_play_options(struct descriptor_data *d) "%s8%s) Scripts on PC's : %s%s\r\n" "%sQ%s) Exit To The Main Menu\r\n" "Enter your choice : ", - grn, nrm, cyn, CHECK_VAR(OLC_CONFIG(d)->play.pk_allowed), grn, nrm, cyn, CHECK_VAR(OLC_CONFIG(d)->play.pt_allowed), grn, nrm, cyn, OLC_CONFIG(d)->play.level_can_shout, grn, nrm, cyn, OLC_CONFIG(d)->play.tunnel_size, @@ -844,11 +838,6 @@ void cedit_parse(struct descriptor_data *d, char *arg) case CEDIT_GAME_OPTIONS_MENU: switch (*arg) { - case 'a': - case 'A': - TOGGLE_VAR(OLC_CONFIG(d)->play.pk_allowed); - break; - case 'b': case 'B': TOGGLE_VAR(OLC_CONFIG(d)->play.pt_allowed); diff --git a/src/class.c b/src/class.c index 69da305..02d0719 100644 --- a/src/class.c +++ b/src/class.c @@ -234,6 +234,231 @@ void roll_real_abils(struct char_data *ch) ch->aff_abils = ch->real_abils; } +/* Per-class skill caps */ +#define DEFAULT_CLASS_SKILL_MAX 90 + +static int class_skill_maxes[NUM_CLASSES][MAX_SKILLS + 1]; +static bool class_skill_caps_ready = FALSE; + +static int clamp_skill_max(int max) +{ + if (max < 0) + return 0; + if (max > 100) + return 100; + return max; +} + +static void apply_class_skill(int chclass, struct char_data *ch, int skill, int start, int max) +{ + if (ch) + SET_SKILL(ch, skill, start); + if (chclass >= 0 && chclass < NUM_CLASSES && skill >= 0 && skill <= MAX_SKILLS) + class_skill_maxes[chclass][skill] = clamp_skill_max(max); +} + +static void apply_class_skills(int chclass, struct char_data *ch) +{ + switch (chclass) { + + case CLASS_SORCEROR: + apply_class_skill(chclass, ch, SPELL_MAGIC_MISSILE, 5, 90); + apply_class_skill(chclass, ch, SPELL_DETECT_INVIS, 5, 90); + apply_class_skill(chclass, ch, SPELL_DETECT_MAGIC, 5, 90); + apply_class_skill(chclass, ch, SPELL_CHILL_TOUCH, 5, 90); + apply_class_skill(chclass, ch, SPELL_INFRAVISION, 5, 90); + apply_class_skill(chclass, ch, SPELL_INVISIBLE, 5, 90); + apply_class_skill(chclass, ch, SPELL_ARMOR, 5, 90); + apply_class_skill(chclass, ch, SPELL_BURNING_HANDS, 5, 90); + apply_class_skill(chclass, ch, SPELL_LOCATE_OBJECT, 5, 90); + apply_class_skill(chclass, ch, SPELL_STRENGTH, 5, 90); + apply_class_skill(chclass, ch, SPELL_SHOCKING_GRASP, 5, 90); + apply_class_skill(chclass, ch, SPELL_SLEEP, 5, 90); + apply_class_skill(chclass, ch, SPELL_LIGHTNING_BOLT, 5, 90); + apply_class_skill(chclass, ch, SPELL_BLINDNESS, 5, 90); + apply_class_skill(chclass, ch, SPELL_DETECT_POISON, 5, 90); + apply_class_skill(chclass, ch, SPELL_COLOR_SPRAY, 5, 90); + apply_class_skill(chclass, ch, SPELL_ENERGY_DRAIN, 5, 90); + apply_class_skill(chclass, ch, SPELL_CURSE, 5, 90); + apply_class_skill(chclass, ch, SPELL_POISON, 5, 90); + apply_class_skill(chclass, ch, SPELL_FIREBALL, 5, 90); + apply_class_skill(chclass, ch, SPELL_CHARM, 5, 90); + apply_class_skill(chclass, ch, SPELL_IDENTIFY, 5, 90); + apply_class_skill(chclass, ch, SPELL_FLY, 5, 90); + apply_class_skill(chclass, ch, SPELL_ENCHANT_WEAPON, 5, 90); + apply_class_skill(chclass, ch, SPELL_CLONE, 5, 90); + apply_class_skill(chclass, ch, SKILL_UNARMED, 5, 90); + apply_class_skill(chclass, ch, SKILL_ARCANA, 5, 90); + apply_class_skill(chclass, ch, SKILL_HISTORY, 5, 90); + apply_class_skill(chclass, ch, SKILL_INSIGHT, 5, 90); + break; + + case CLASS_CLERIC: + apply_class_skill(chclass, ch, SPELL_CURE_LIGHT, 5, 90); + apply_class_skill(chclass, ch, SPELL_ARMOR, 5, 90); + apply_class_skill(chclass, ch, SPELL_CREATE_FOOD, 5, 90); + apply_class_skill(chclass, ch, SPELL_CREATE_WATER, 5, 90); + apply_class_skill(chclass, ch, SPELL_DETECT_POISON, 5, 90); + apply_class_skill(chclass, ch, SPELL_DETECT_ALIGN, 5, 90); + apply_class_skill(chclass, ch, SPELL_CURE_BLIND, 5, 90); + apply_class_skill(chclass, ch, SPELL_BLESS, 5, 90); + apply_class_skill(chclass, ch, SPELL_DETECT_INVIS, 5, 90); + apply_class_skill(chclass, ch, SPELL_BLINDNESS, 5, 90); + apply_class_skill(chclass, ch, SPELL_INFRAVISION, 5, 90); + apply_class_skill(chclass, ch, SPELL_PROT_FROM_EVIL, 5, 90); + apply_class_skill(chclass, ch, SPELL_POISON, 5, 90); + apply_class_skill(chclass, ch, SPELL_GROUP_ARMOR, 5, 90); + apply_class_skill(chclass, ch, SPELL_CURE_CRITIC, 5, 90); + apply_class_skill(chclass, ch, SPELL_SUMMON, 5, 90); + apply_class_skill(chclass, ch, SPELL_REMOVE_POISON, 5, 90); + apply_class_skill(chclass, ch, SPELL_IDENTIFY, 5, 90); + apply_class_skill(chclass, ch, SPELL_WORD_OF_RECALL, 5, 90); + apply_class_skill(chclass, ch, SPELL_DARKNESS, 5, 90); + apply_class_skill(chclass, ch, SPELL_EARTHQUAKE, 5, 90); + apply_class_skill(chclass, ch, SPELL_DISPEL_EVIL, 5, 90); + apply_class_skill(chclass, ch, SPELL_DISPEL_GOOD, 5, 90); + apply_class_skill(chclass, ch, SPELL_SANCTUARY, 5, 90); + apply_class_skill(chclass, ch, SPELL_CALL_LIGHTNING, 5, 90); + apply_class_skill(chclass, ch, SPELL_HEAL, 5, 90); + apply_class_skill(chclass, ch, SPELL_CONTROL_WEATHER, 5, 90); + apply_class_skill(chclass, ch, SPELL_SENSE_LIFE, 5, 90); + apply_class_skill(chclass, ch, SPELL_HARM, 5, 90); + apply_class_skill(chclass, ch, SPELL_GROUP_HEAL, 5, 90); + apply_class_skill(chclass, ch, SPELL_REMOVE_CURSE, 5, 90); + apply_class_skill(chclass, ch, SKILL_SHIELD_USE, 5, 90); + apply_class_skill(chclass, ch, SKILL_ACROBATICS, 5, 90); + apply_class_skill(chclass, ch, SKILL_ARCANA, 5, 90); + apply_class_skill(chclass, ch, SKILL_RELIGION, 5, 90); + break; + + case CLASS_ROGUE: + apply_class_skill(chclass, ch, SKILL_STEALTH, 5, 90); + apply_class_skill(chclass, ch, SKILL_TRACK, 5, 90); + apply_class_skill(chclass, ch, SKILL_BACKSTAB, 5, 90); + apply_class_skill(chclass, ch, SKILL_PICK_LOCK, 5, 90); + apply_class_skill(chclass, ch, SKILL_SLEIGHT_OF_HAND, 5, 90); + apply_class_skill(chclass, ch, SKILL_UNARMED, 5, 90); + apply_class_skill(chclass, ch, SKILL_SHIELD_USE, 5, 90); + apply_class_skill(chclass, ch, SKILL_PIERCING_WEAPONS, 5, 90); + apply_class_skill(chclass, ch, SKILL_PERCEPTION, 5, 90); + apply_class_skill(chclass, ch, SKILL_ACROBATICS, 5, 90); + apply_class_skill(chclass, ch, SKILL_DECEPTION, 5, 90); + apply_class_skill(chclass, ch, SKILL_INVESTIGATION, 5, 90); + break; + + case CLASS_FIGHTER: + apply_class_skill(chclass, ch, SKILL_KICK, 5, 90); + apply_class_skill(chclass, ch, SKILL_RESCUE, 5, 90); + apply_class_skill(chclass, ch, SKILL_BANDAGE, 5, 90); + apply_class_skill(chclass, ch, SKILL_BASH, 5, 90); + apply_class_skill(chclass, ch, SKILL_UNARMED, 5, 90); + apply_class_skill(chclass, ch, SKILL_SLASHING_WEAPONS, 5, 90); + apply_class_skill(chclass, ch, SKILL_PIERCING_WEAPONS, 5, 90); + apply_class_skill(chclass, ch, SKILL_BLUDGEONING_WEAPONS, 5, 90); + apply_class_skill(chclass, ch, SKILL_SHIELD_USE, 5, 90); + apply_class_skill(chclass, ch, SKILL_PERCEPTION, 5, 90); + apply_class_skill(chclass, ch, SKILL_ATHLETICS, 5, 90); + apply_class_skill(chclass, ch, SKILL_INTIMIDATION, 5, 90); + apply_class_skill(chclass, ch, SKILL_SURVIVAL, 5, 90); + break; + + case CLASS_BARBARIAN: + apply_class_skill(chclass, ch, SKILL_KICK, 5, 90); + apply_class_skill(chclass, ch, SKILL_RESCUE, 5, 90); + apply_class_skill(chclass, ch, SKILL_BANDAGE, 5, 90); + apply_class_skill(chclass, ch, SKILL_WHIRLWIND, 5, 90); + apply_class_skill(chclass, ch, SKILL_UNARMED, 5, 90); + apply_class_skill(chclass, ch, SKILL_PIERCING_WEAPONS, 5, 90); + apply_class_skill(chclass, ch, SKILL_BLUDGEONING_WEAPONS, 5, 90); + apply_class_skill(chclass, ch, SKILL_PERCEPTION, 5, 90); + apply_class_skill(chclass, ch, SKILL_ATHLETICS, 5, 90); + apply_class_skill(chclass, ch, SKILL_INTIMIDATION, 5, 90); + break; + + case CLASS_RANGER: + apply_class_skill(chclass, ch, SKILL_BANDAGE, 5, 90); + apply_class_skill(chclass, ch, SKILL_TRACK, 5, 90); + apply_class_skill(chclass, ch, SKILL_BASH, 5, 90); + apply_class_skill(chclass, ch, SKILL_SLEIGHT_OF_HAND, 5, 90); + apply_class_skill(chclass, ch, SKILL_UNARMED, 5, 90); + apply_class_skill(chclass, ch, SKILL_SLASHING_WEAPONS, 5, 90); + apply_class_skill(chclass, ch, SKILL_PIERCING_WEAPONS, 5, 90); + apply_class_skill(chclass, ch, SKILL_SHIELD_USE, 5, 90); + apply_class_skill(chclass, ch, SKILL_PERCEPTION, 5, 90); + apply_class_skill(chclass, ch, SKILL_NATURE, 5, 90); + apply_class_skill(chclass, ch, SKILL_ANIMAL_HANDLING, 5, 90); + apply_class_skill(chclass, ch, SKILL_SURVIVAL, 5, 90); + apply_class_skill(chclass, ch, SKILL_ATHLETICS, 5, 90); + apply_class_skill(chclass, ch, SKILL_PERSUASION, 5, 90); + apply_class_skill(chclass, ch, SKILL_STEALTH, 5, 90); + break; + + case CLASS_BARD: + apply_class_skill(chclass, ch, SPELL_ARMOR, 5, 90); + apply_class_skill(chclass, ch, SPELL_IDENTIFY, 5, 90); + apply_class_skill(chclass, ch, SKILL_BANDAGE, 5, 90); + apply_class_skill(chclass, ch, SKILL_TRACK, 5, 90); + apply_class_skill(chclass, ch, SKILL_PICK_LOCK, 5, 90); + apply_class_skill(chclass, ch, SKILL_SLEIGHT_OF_HAND, 5, 90); + apply_class_skill(chclass, ch, SKILL_UNARMED, 5, 90); + apply_class_skill(chclass, ch, SKILL_PIERCING_WEAPONS, 5, 90); + apply_class_skill(chclass, ch, SKILL_SHIELD_USE, 5, 90); + apply_class_skill(chclass, ch, SKILL_PERCEPTION, 5, 90); + apply_class_skill(chclass, ch, SKILL_ACROBATICS, 5, 90); + apply_class_skill(chclass, ch, SKILL_HISTORY, 5, 90); + apply_class_skill(chclass, ch, SKILL_INVESTIGATION, 5, 90); + apply_class_skill(chclass, ch, SKILL_SURVIVAL, 5, 90); + apply_class_skill(chclass, ch, SKILL_STEALTH, 5, 90); + break; + + case CLASS_DRUID: + apply_class_skill(chclass, ch, SPELL_DETECT_INVIS, 5, 90); + apply_class_skill(chclass, ch, SPELL_DETECT_MAGIC, 5, 90); + apply_class_skill(chclass, ch, SPELL_LOCATE_OBJECT, 5, 90); + apply_class_skill(chclass, ch, SKILL_BANDAGE, 5, 90); + apply_class_skill(chclass, ch, SKILL_TRACK, 5, 90); + apply_class_skill(chclass, ch, SKILL_UNARMED, 5, 90); + apply_class_skill(chclass, ch, SKILL_PIERCING_WEAPONS, 5, 90); + apply_class_skill(chclass, ch, SKILL_SHIELD_USE, 5, 90); + apply_class_skill(chclass, ch, SKILL_PERCEPTION, 5, 90); + apply_class_skill(chclass, ch, SKILL_ACROBATICS, 5, 90); + apply_class_skill(chclass, ch, SKILL_ARCANA, 5, 90); + apply_class_skill(chclass, ch, SKILL_HISTORY, 5, 90); + apply_class_skill(chclass, ch, SKILL_INSIGHT, 5, 90); + apply_class_skill(chclass, ch, SKILL_INVESTIGATION, 5, 90); + apply_class_skill(chclass, ch, SKILL_PERSUASION, 5, 90); + apply_class_skill(chclass, ch, SKILL_RELIGION, 5, 90); + apply_class_skill(chclass, ch, SKILL_SURVIVAL, 5, 90); + break; + } +} + +void init_class_skill_caps(void) +{ + int chclass, skill; + + for (chclass = 0; chclass < NUM_CLASSES; chclass++) { + for (skill = 0; skill <= MAX_SKILLS; skill++) + class_skill_maxes[chclass][skill] = DEFAULT_CLASS_SKILL_MAX; + } + + for (chclass = 0; chclass < NUM_CLASSES; chclass++) + apply_class_skills(chclass, NULL); + + class_skill_caps_ready = TRUE; +} + +int class_skill_max(int chclass, int skillnum) +{ + if (!class_skill_caps_ready) + return DEFAULT_CLASS_SKILL_MAX; + if (chclass < 0 || chclass >= NUM_CLASSES) + return DEFAULT_CLASS_SKILL_MAX; + if (skillnum < 0 || skillnum > MAX_SKILLS) + return DEFAULT_CLASS_SKILL_MAX; + return class_skill_maxes[chclass][skillnum]; +} + void grant_class_skills(struct char_data *ch, bool reset) { int i; @@ -248,179 +473,7 @@ void grant_class_skills(struct char_data *ch, bool reset) if (GET_CLASS(ch) < CLASS_SORCEROR || GET_CLASS(ch) >= NUM_CLASSES) return; - switch (GET_CLASS(ch)) { - - case CLASS_SORCEROR: - SET_SKILL(ch, SPELL_MAGIC_MISSILE, 5); - SET_SKILL(ch, SPELL_DETECT_INVIS, 5); - SET_SKILL(ch, SPELL_DETECT_MAGIC, 5); - SET_SKILL(ch, SPELL_CHILL_TOUCH, 5); - SET_SKILL(ch, SPELL_INFRAVISION, 5); - SET_SKILL(ch, SPELL_INVISIBLE, 5); - SET_SKILL(ch, SPELL_ARMOR, 5); - SET_SKILL(ch, SPELL_BURNING_HANDS, 5); - SET_SKILL(ch, SPELL_LOCATE_OBJECT, 5); - SET_SKILL(ch, SPELL_STRENGTH, 5); - SET_SKILL(ch, SPELL_SHOCKING_GRASP, 5); - SET_SKILL(ch, SPELL_SLEEP, 5); - SET_SKILL(ch, SPELL_LIGHTNING_BOLT, 5); - SET_SKILL(ch, SPELL_BLINDNESS, 5); - SET_SKILL(ch, SPELL_DETECT_POISON, 5); - SET_SKILL(ch, SPELL_COLOR_SPRAY, 5); - SET_SKILL(ch, SPELL_ENERGY_DRAIN, 5); - SET_SKILL(ch, SPELL_CURSE, 5); - SET_SKILL(ch, SPELL_POISON, 5); - SET_SKILL(ch, SPELL_FIREBALL, 5); - SET_SKILL(ch, SPELL_CHARM, 5); - SET_SKILL(ch, SPELL_IDENTIFY, 5); - SET_SKILL(ch, SPELL_FLY, 5); - SET_SKILL(ch, SPELL_ENCHANT_WEAPON, 5); - SET_SKILL(ch, SPELL_CLONE, 5); - SET_SKILL(ch, SKILL_UNARMED, 5); - SET_SKILL(ch, SKILL_ARCANA, 5); - SET_SKILL(ch, SKILL_HISTORY, 5); - SET_SKILL(ch, SKILL_INSIGHT, 5); - break; - - case CLASS_CLERIC: - SET_SKILL(ch, SPELL_CURE_LIGHT, 5); - SET_SKILL(ch, SPELL_ARMOR, 5); - SET_SKILL(ch, SPELL_CREATE_FOOD, 5); - SET_SKILL(ch, SPELL_CREATE_WATER, 5); - SET_SKILL(ch, SPELL_DETECT_POISON, 5); - SET_SKILL(ch, SPELL_DETECT_ALIGN, 5); - SET_SKILL(ch, SPELL_CURE_BLIND, 5); - SET_SKILL(ch, SPELL_BLESS, 5); - SET_SKILL(ch, SPELL_DETECT_INVIS, 5); - SET_SKILL(ch, SPELL_BLINDNESS, 5); - SET_SKILL(ch, SPELL_INFRAVISION, 5); - SET_SKILL(ch, SPELL_PROT_FROM_EVIL, 5); - SET_SKILL(ch, SPELL_POISON, 5); - SET_SKILL(ch, SPELL_GROUP_ARMOR, 5); - SET_SKILL(ch, SPELL_CURE_CRITIC, 5); - SET_SKILL(ch, SPELL_SUMMON, 5); - SET_SKILL(ch, SPELL_REMOVE_POISON, 5); - SET_SKILL(ch, SPELL_IDENTIFY, 5); - SET_SKILL(ch, SPELL_WORD_OF_RECALL, 5); - SET_SKILL(ch, SPELL_DARKNESS, 5); - SET_SKILL(ch, SPELL_EARTHQUAKE, 5); - SET_SKILL(ch, SPELL_DISPEL_EVIL, 5); - SET_SKILL(ch, SPELL_DISPEL_GOOD, 5); - SET_SKILL(ch, SPELL_SANCTUARY, 5); - SET_SKILL(ch, SPELL_CALL_LIGHTNING, 5); - SET_SKILL(ch, SPELL_HEAL, 5); - SET_SKILL(ch, SPELL_CONTROL_WEATHER, 5); - SET_SKILL(ch, SPELL_SENSE_LIFE, 5); - SET_SKILL(ch, SPELL_HARM, 5); - SET_SKILL(ch, SPELL_GROUP_HEAL, 5); - SET_SKILL(ch, SPELL_REMOVE_CURSE, 5); - SET_SKILL(ch, SKILL_SHIELD_USE, 5); - SET_SKILL(ch, SKILL_ACROBATICS, 5); - SET_SKILL(ch, SKILL_ARCANA, 5); - SET_SKILL(ch, SKILL_RELIGION, 5); - break; - - case CLASS_ROGUE: - SET_SKILL(ch, SKILL_STEALTH, 5); - SET_SKILL(ch, SKILL_TRACK, 5); - SET_SKILL(ch, SKILL_BACKSTAB, 5); - SET_SKILL(ch, SKILL_PICK_LOCK, 5); - SET_SKILL(ch, SKILL_SLEIGHT_OF_HAND, 5); - SET_SKILL(ch, SKILL_UNARMED, 5); - SET_SKILL(ch, SKILL_SHIELD_USE, 5); - SET_SKILL(ch, SKILL_PIERCING_WEAPONS, 5); - SET_SKILL(ch, SKILL_PERCEPTION, 5); - SET_SKILL(ch, SKILL_ACROBATICS, 5); - SET_SKILL(ch, SKILL_DECEPTION, 5); - SET_SKILL(ch, SKILL_INVESTIGATION, 5); - break; - - case CLASS_FIGHTER: - SET_SKILL(ch, SKILL_KICK, 5); - SET_SKILL(ch, SKILL_RESCUE, 5); - SET_SKILL(ch, SKILL_BANDAGE, 5); - SET_SKILL(ch, SKILL_BASH, 5); - SET_SKILL(ch, SKILL_UNARMED, 5); - SET_SKILL(ch, SKILL_SLASHING_WEAPONS, 5); - SET_SKILL(ch, SKILL_PIERCING_WEAPONS, 5); - SET_SKILL(ch, SKILL_BLUDGEONING_WEAPONS, 5); - SET_SKILL(ch, SKILL_SHIELD_USE, 5); - SET_SKILL(ch, SKILL_PERCEPTION, 5); - SET_SKILL(ch, SKILL_ATHLETICS, 5); - SET_SKILL(ch, SKILL_INTIMIDATION, 5); - SET_SKILL(ch, SKILL_SURVIVAL, 5); - break; - - case CLASS_BARBARIAN: - SET_SKILL(ch, SKILL_KICK, 5); - SET_SKILL(ch, SKILL_RESCUE, 5); - SET_SKILL(ch, SKILL_BANDAGE, 5); - SET_SKILL(ch, SKILL_WHIRLWIND, 5); - SET_SKILL(ch, SKILL_UNARMED, 5); - SET_SKILL(ch, SKILL_PIERCING_WEAPONS, 5); - SET_SKILL(ch, SKILL_BLUDGEONING_WEAPONS, 5); - SET_SKILL(ch, SKILL_PERCEPTION, 5); - SET_SKILL(ch, SKILL_ATHLETICS, 5); - SET_SKILL(ch, SKILL_INTIMIDATION, 5); - break; - - case CLASS_RANGER: - SET_SKILL(ch, SKILL_BANDAGE, 5); - SET_SKILL(ch, SKILL_TRACK, 5); - SET_SKILL(ch, SKILL_BASH, 5); - SET_SKILL(ch, SKILL_SLEIGHT_OF_HAND, 5); - SET_SKILL(ch, SKILL_UNARMED, 5); - SET_SKILL(ch, SKILL_SLASHING_WEAPONS, 5); - SET_SKILL(ch, SKILL_PIERCING_WEAPONS, 5); - SET_SKILL(ch, SKILL_SHIELD_USE, 5); - SET_SKILL(ch, SKILL_PERCEPTION, 5); - SET_SKILL(ch, SKILL_NATURE, 5); - SET_SKILL(ch, SKILL_ANIMAL_HANDLING, 5); - SET_SKILL(ch, SKILL_SURVIVAL, 5); - SET_SKILL(ch, SKILL_ATHLETICS, 5); - SET_SKILL(ch, SKILL_PERSUASION, 5); - SET_SKILL(ch, SKILL_STEALTH, 5); - break; - - case CLASS_BARD: - SET_SKILL(ch, SPELL_ARMOR, 5); - SET_SKILL(ch, SPELL_IDENTIFY, 5); - SET_SKILL(ch, SKILL_BANDAGE, 5); - SET_SKILL(ch, SKILL_TRACK, 5); - SET_SKILL(ch, SKILL_PICK_LOCK, 5); - SET_SKILL(ch, SKILL_SLEIGHT_OF_HAND, 5); - SET_SKILL(ch, SKILL_UNARMED, 5); - SET_SKILL(ch, SKILL_PIERCING_WEAPONS, 5); - SET_SKILL(ch, SKILL_SHIELD_USE, 5); - SET_SKILL(ch, SKILL_PERCEPTION, 5); - SET_SKILL(ch, SKILL_ACROBATICS, 5); - SET_SKILL(ch, SKILL_HISTORY, 5); - SET_SKILL(ch, SKILL_INVESTIGATION, 5); - SET_SKILL(ch, SKILL_SURVIVAL, 5); - SET_SKILL(ch, SKILL_STEALTH, 5); - break; - - case CLASS_DRUID: - SET_SKILL(ch, SPELL_DETECT_INVIS, 5); - SET_SKILL(ch, SPELL_DETECT_MAGIC, 5); - SET_SKILL(ch, SPELL_LOCATE_OBJECT, 5); - SET_SKILL(ch, SKILL_BANDAGE, 5); - SET_SKILL(ch, SKILL_TRACK, 5); - SET_SKILL(ch, SKILL_UNARMED, 5); - SET_SKILL(ch, SKILL_PIERCING_WEAPONS, 5); - SET_SKILL(ch, SKILL_SHIELD_USE, 5); - SET_SKILL(ch, SKILL_PERCEPTION, 5); - SET_SKILL(ch, SKILL_ACROBATICS, 5); - SET_SKILL(ch, SKILL_ARCANA, 5); - SET_SKILL(ch, SKILL_HISTORY, 5); - SET_SKILL(ch, SKILL_INSIGHT, 5); - SET_SKILL(ch, SKILL_INVESTIGATION, 5); - SET_SKILL(ch, SKILL_PERSUASION, 5); - SET_SKILL(ch, SKILL_RELIGION, 5); - SET_SKILL(ch, SKILL_SURVIVAL, 5); - break; - } - + apply_class_skills(GET_CLASS(ch), ch); } /* Some initializations for characters, including initial skills */ diff --git a/src/class.h b/src/class.h index 0502604..6c82a38 100644 --- a/src/class.h +++ b/src/class.h @@ -23,6 +23,8 @@ int parse_class(char arg); void roll_real_abils(struct char_data *ch); bool has_save_proficiency(int class_num, int ability); void grant_class_skills(struct char_data *ch, bool reset); +void init_class_skill_caps(void); +int class_skill_max(int chclass, int skillnum); /* Global variables */ diff --git a/src/config.c b/src/config.c index c9f8967..40dc346 100644 --- a/src/config.c +++ b/src/config.c @@ -39,13 +39,6 @@ /* Can Scripts be attached to players? */ int script_players = NO; -/* pk_allowed sets the tone of the entire game. If pk_allowed is set to NO, - * then players will not be allowed to kill, summon, charm, or sleep other - * players, as well as a variety of other "asshole player" protections. However, - * if you decide you want to have an all-out knock-down drag-out PK Mud, just - * set pk_allowed to YES - and anything goes. */ -int pk_allowed = NO; - /* Is playerthieving allowed? */ int pt_allowed = NO; diff --git a/src/config.h b/src/config.h index 0d69ad8..d7a65a0 100644 --- a/src/config.h +++ b/src/config.h @@ -14,7 +14,6 @@ #define _CONFIG_H_ /* Global variable declarations, all settable by cedit */ -extern int pk_allowed; extern int script_players; extern int pt_allowed; extern int level_can_shout; diff --git a/src/constants.c b/src/constants.c index 0bc0ac7..500c29c 100644 --- a/src/constants.c +++ b/src/constants.c @@ -189,8 +189,8 @@ const char *position_types[] = { * @pre Must be in the same order as the defines. * Must end array with a single newline. */ const char *player_bits[] = { - "KILLER", - "THIEF", + "UNUSED0", + "UNUSED1", "FROZEN", "DONTSET", "WRITING", diff --git a/src/db.c b/src/db.c index 7cf3153..8f76516 100644 --- a/src/db.c +++ b/src/db.c @@ -30,6 +30,7 @@ #include "genolc.h" #include "genobj.h" /* for free_object_strings */ #include "config.h" /* for the default config values. */ +#include "class.h" #include "fight.h" #include "modify.h" #include "shop.h" @@ -748,6 +749,7 @@ void boot_db(void) log("Assigning spell and skill levels."); init_spell_levels(); + init_class_skill_caps(); log("Sorting command list and spells."); sort_commands(); @@ -4128,7 +4130,6 @@ static void load_default_config( void ) /* This function is called only once, at boot-time. We assume config_info is * empty. -Welcor */ /* Game play options. */ - CONFIG_PK_ALLOWED = pk_allowed; CONFIG_PT_ALLOWED = pt_allowed; CONFIG_LEVEL_CAN_SHOUT = level_can_shout; CONFIG_TUNNEL_SIZE = tunnel_size; @@ -4388,9 +4389,7 @@ void load_config( void ) break; case 'p': - if (!str_cmp(tag, "pk_allowed")) - CONFIG_PK_ALLOWED = num; - else if (!str_cmp(tag, "protocol_negotiation")) + if (!str_cmp(tag, "protocol_negotiation")) CONFIG_PROTOCOL_NEGOTIATION = num; else if (!str_cmp(tag, "pt_allowed")) CONFIG_PT_ALLOWED = num; diff --git a/src/dg_variables.c b/src/dg_variables.c index ef7bff4..6ce2445 100644 --- a/src/dg_variables.c +++ b/src/dg_variables.c @@ -801,30 +801,6 @@ void find_replacement(void *go, struct script_data *sc, trig_data *trig, } } } - else if (!str_cmp(field, "is_killer")) { - if (subfield && *subfield) { - if (!str_cmp("on", subfield)) - SET_BIT_AR(PLR_FLAGS(c), PLR_KILLER); - else if (!str_cmp("off", subfield)) - REMOVE_BIT_AR(PLR_FLAGS(c), PLR_KILLER); - } - if (PLR_FLAGGED(c, PLR_KILLER)) - strcpy(str, "1"); - else - strcpy(str, "0"); - } - else if (!str_cmp(field, "is_thief")) { - if (subfield && *subfield) { - if (!str_cmp("on", subfield)) - SET_BIT_AR(PLR_FLAGS(c), PLR_THIEF); - else if (!str_cmp("off", subfield)) - REMOVE_BIT_AR(PLR_FLAGS(c), PLR_THIEF); - } - if (PLR_FLAGGED(c, PLR_THIEF)) - strcpy(str, "1"); - else - strcpy(str, "0"); - } break; case 'l': if (!str_cmp(field, "level")) { diff --git a/src/fight.c b/src/fight.c index ca6632b..0f9b384 100644 --- a/src/fight.c +++ b/src/fight.c @@ -72,8 +72,8 @@ static int roll_damage(struct char_data *ch, struct char_data *victim, int dam = 0; if (wielded && GET_OBJ_TYPE(wielded) == ITEM_WEAPON) { - int ndice = GET_OBJ_VAL(wielded, 1); /* #dice */ - int sdice = GET_OBJ_VAL(wielded, 2); /* sides */ + int ndice = GET_OBJ_VAL(wielded, 0); /* #dice */ + int sdice = GET_OBJ_VAL(wielded, 1); /* sides */ dam = dice(ndice, sdice); dam += GET_ABILITY_MOD(GET_STR(ch)); /* STR adds to weapon damage */ } else { @@ -92,7 +92,7 @@ static int weapon_family_skill_num(struct char_data *ch, struct obj_data *wielde if (!wielded || GET_OBJ_TYPE(wielded) != ITEM_WEAPON) return SKILL_UNARMED; - /* NOTE: w_type here is TYPE_HIT + GET_OBJ_VAL(wielded, 3) or mob attack type + TYPE_HIT. + /* NOTE: w_type here is TYPE_HIT + GET_OBJ_VAL(wielded, 2) or mob attack type + TYPE_HIT. Adjust the cases below to match your game's TYPE_* values. */ switch (w_type) { /* --- Piercing family --- */ @@ -176,20 +176,6 @@ void update_pos(struct char_data *victim) GET_POS(victim) = POS_STUNNED; } -void check_killer(struct char_data *ch, struct char_data *vict) -{ - if (PLR_FLAGGED(vict, PLR_KILLER) || PLR_FLAGGED(vict, PLR_THIEF)) - return; - if (PLR_FLAGGED(ch, PLR_KILLER) || IS_NPC(ch) || IS_NPC(vict) || ch == vict) - return; - - SET_BIT_AR(PLR_FLAGS(ch), PLR_KILLER); - send_to_char(ch, "If you want to be a PLAYER KILLER, so be it...\r\n"); - mudlog(BRF, MAX(LVL_IMMORT, MAX(GET_INVIS_LEV(ch), GET_INVIS_LEV(vict))), - TRUE, "PC Killer bit set on %s for initiating attack on %s at %s.", - GET_NAME(ch), GET_NAME(vict), world[IN_ROOM(vict)].name); -} - /* start one char fighting another (yes, it is horrible, I know... ) */ void set_fighting(struct char_data *ch, struct char_data *vict) { @@ -210,8 +196,6 @@ void set_fighting(struct char_data *ch, struct char_data *vict) FIGHTING(ch) = vict; GET_POS(ch) = POS_FIGHTING; - if (!CONFIG_PK_ALLOWED) - check_killer(ch, vict); } /* remove a char from the list of fighting chars */ @@ -363,8 +347,6 @@ struct char_data *i; void die(struct char_data * ch, struct char_data * killer) { if (!IS_NPC(ch)) { - REMOVE_BIT_AR(PLR_FLAGS(ch), PLR_KILLER); - REMOVE_BIT_AR(PLR_FLAGS(ch), PLR_THIEF); } raw_kill(ch, killer); } @@ -634,6 +616,7 @@ int damage(struct char_data *ch, struct char_data *victim, int dam, int attackty char local_buf[256]; struct char_data *tmp_char; struct obj_data *corpse_obj; + int prev_hit = 0; if (GET_POS(victim) <= POS_DEAD) { /* This is "normal"-ish now with delayed extraction. -gg 3/15/2001 */ @@ -659,8 +642,8 @@ int damage(struct char_data *ch, struct char_data *victim, int dam, int attackty return (0); } - /* You can't damage an immortal! */ - if (!IS_NPC(victim) && ((GET_LEVEL(victim) >= LVL_IMMORT) && PRF_FLAGGED(victim, PRF_NOHASSLE))) + /* Immortals cannot be damaged. */ + if (!IS_NPC(victim) && GET_REAL_LEVEL(victim) >= LVL_IMMORT) dam = 0; dam = damage_mtrigger(ch, victim, dam, attacktype); @@ -694,14 +677,9 @@ int damage(struct char_data *ch, struct char_data *victim, int dam, int attackty dam /= 2; /* Check for PK if this is not a PK MUD */ - if (!CONFIG_PK_ALLOWED) { - check_killer(ch, victim); - if (PLR_FLAGGED(ch, PLR_KILLER) && (ch != victim)) - dam = 0; - } - /* Set the maximum damage per round and subtract the hit points */ dam = MAX(MIN(dam, 100), 0); + prev_hit = GET_HIT(victim); GET_HIT(victim) -= dam; update_pos(victim); @@ -826,16 +804,30 @@ int damage(struct char_data *ch, struct char_data *victim, int dam, int attackty void hit(struct char_data *ch, struct char_data *victim, int type) { struct obj_data *wielded = GET_EQ(ch, WEAR_WIELD); + bool wielded_weapon = (wielded && GET_OBJ_TYPE(wielded) == ITEM_WEAPON); struct obj_data *shield = GET_EQ(victim, WEAR_SHIELD); int w_type, d20, attack_mod = 0, target_ac, dam = 0; bool hit_success = FALSE; + bool attacker_immortal, victim_immortal; + bool attacker_is_player, victim_is_player; + int unarmed_die_size = 0; + int unarmed_prof_bonus = 0; + int unarmed_str_mod = 0; /* Basic sanity */ if (!ch || !victim) return; + attacker_is_player = (ch->desc != NULL); + victim_is_player = (victim->desc != NULL); + + attacker_immortal = (attacker_is_player && + (GET_REAL_LEVEL(ch) >= LVL_IMMORT || PRF_FLAGGED(ch, PRF_NOHASSLE))); + victim_immortal = (victim_is_player && + (GET_REAL_LEVEL(victim) >= LVL_IMMORT || PRF_FLAGGED(victim, PRF_NOHASSLE))); + /* Determine attack message type exactly like stock code */ - if (wielded && GET_OBJ_TYPE(wielded) == ITEM_WEAPON) - w_type = GET_OBJ_VAL(wielded, 3) + TYPE_HIT; + if (wielded_weapon) + w_type = GET_OBJ_VAL(wielded, 2) + TYPE_HIT; else { if (IS_NPC(ch) && ch->mob_specials.attack_type != 0) w_type = ch->mob_specials.attack_type + TYPE_HIT; @@ -843,6 +835,39 @@ void hit(struct char_data *ch, struct char_data *victim, int type) w_type = TYPE_HIT; } /* matches stock message mapping */ + if (victim_immortal) { + damage(ch, victim, 0, w_type); + return; + } + + if (attacker_immortal) { + if (wielded_weapon) { + int ndice = GET_OBJ_VAL(wielded, 0); + int sdice = GET_OBJ_VAL(wielded, 1); + dam = (ndice * sdice) + GET_ABILITY_MOD(GET_STR(ch)); + } else { + int prof_bonus = (!IS_NPC(ch)) ? GET_PROFICIENCY(GET_SKILL(ch, SKILL_UNARMED)) : 0; + int str_mod = GET_ABILITY_MOD(GET_STR(ch)); + int die_size; + + switch (prof_bonus) { + case 0: die_size = 4; break; /* untrained */ + case 1: die_size = 6; break; /* trained */ + case 2: die_size = 8; break; /* expert */ + default: die_size = 10; break; /* master or above */ + } + + if (IS_NPC(ch) && prof_bonus <= 0) { + prof_bonus = MIN(6, (GET_LEVEL(ch) / 4)); + } + + dam = die_size + str_mod + prof_bonus; + } + + damage(ch, victim, dam, w_type); + return; + } + /* Roll d20 */ d20 = rand_number(1, 20); @@ -859,7 +884,7 @@ void hit(struct char_data *ch, struct char_data *victim, int type) attack_mod += GET_PROFICIENCY(GET_SKILL(ch, skillnum)); /* --- UNARMED ATTACK HANDLING --- */ - if (!wielded) { + if (!wielded_weapon) { int prof_bonus = (!IS_NPC(ch)) ? GET_PROFICIENCY(GET_SKILL(ch, SKILL_UNARMED)) : 0; int str_mod = GET_ABILITY_MOD(GET_STR(ch)); int die_size; @@ -871,6 +896,7 @@ void hit(struct char_data *ch, struct char_data *victim, int type) case 2: die_size = 8; break; /* expert */ default: die_size = 10; break; /* master or above */ } + unarmed_die_size = die_size; /* NPC fallback scaling */ if (IS_NPC(ch) && prof_bonus <= 0) { @@ -879,9 +905,11 @@ void hit(struct char_data *ch, struct char_data *victim, int type) /* base damage roll for unarmed attacks */ dam = dice(1, die_size) + str_mod + prof_bonus; + unarmed_prof_bonus = prof_bonus; + unarmed_str_mod = str_mod; /* mark attack type for damage() messaging */ - w_type = SKILL_UNARMED + TYPE_HIT; + w_type = TYPE_HIT; } /* Weapon magic (cap +3) */ @@ -901,8 +929,9 @@ void hit(struct char_data *ch, struct char_data *victim, int type) /* Ascending AC target */ target_ac = compute_armor_class_asc(victim); - /* Nat 1/20, then normal resolution */ - if (d20 == 1) hit_success = FALSE; + /* Nat 1/20, then normal resolution (immortals always hit). */ + if (attacker_immortal) hit_success = TRUE; + else if (d20 == 1) hit_success = FALSE; else if (d20 == 20) hit_success = TRUE; else hit_success = ((d20 + attack_mod) >= target_ac); @@ -912,13 +941,22 @@ void hit(struct char_data *ch, struct char_data *victim, int type) * If we are unarmed, dam was already rolled above. * If wielding a weapon, roll normally. */ - if (wielded) + if (wielded_weapon) dam = roll_damage(ch, victim, wielded, w_type); + if (attacker_immortal) { + if (wielded_weapon) { + int ndice = GET_OBJ_VAL(wielded, 0); + int sdice = GET_OBJ_VAL(wielded, 1); + dam = (ndice * sdice) + GET_ABILITY_MOD(GET_STR(ch)); + } else if (unarmed_die_size > 0) { + dam = unarmed_die_size + unarmed_str_mod + unarmed_prof_bonus; + } + } /* --- SHIELD BLOCK CHECK --- * Only happens if an attack actually lands. */ - if (shield) { + if (shield && !attacker_immortal) { int def_prof = (!IS_NPC(victim)) ? GET_PROFICIENCY(GET_SKILL(victim, SKILL_SHIELD_USE)) : 0; int block_chance = def_prof * 10; /* 0–60% total chance to block an attack */ diff --git a/src/fight.h b/src/fight.h index e24bc16..865d1c2 100644 --- a/src/fight.h +++ b/src/fight.h @@ -22,7 +22,6 @@ struct attack_hit_type { /* Functions available in fight.c */ void appear(struct char_data *ch); -void check_killer(struct char_data *ch, struct char_data *vict); int compute_armor_class(struct char_data *ch); int damage(struct char_data *ch, struct char_data *victim, int dam, int attacktype); void death_cry(struct char_data *ch); diff --git a/src/limits.c b/src/limits.c index b9f42fd..69f594f 100644 --- a/src/limits.c +++ b/src/limits.c @@ -209,12 +209,13 @@ void run_autowiz(void) /* Requires: find_skill_num(), GET_WIS(), wis_app[], GET_SKILL(), SET_SKILL(), rand_number() * Cooldown: 1 hour - 5 * WIS bonus minutes (floored at 0) * Rolls: failure -> 1..20, success -> 1..100 - * Cap: 90% (change MIN(90, ...) if you want a different cap) + * Cap: per-class max (see class.c) */ void gain_skill(struct char_data *ch, char *skill, bool success) { int skill_num, base, roll, increase; int wisb, cd_seconds; + int cap; time_t now; if (IS_NPC(ch)) @@ -233,8 +234,11 @@ void gain_skill(struct char_data *ch, char *skill, bool success) } base = GET_SKILL(ch, skill_num); + cap = class_skill_max(GET_CLASS(ch), skill_num); + if (cap <= 0) + return; /* If already capped, bail early (and don’t start cooldown) */ - if (base >= 90) + if (base >= cap) return; /* Wisdom bonus from wis_app[] (constants.c). Higher = better learning & shorter cooldown. */ @@ -246,7 +250,7 @@ void gain_skill(struct char_data *ch, char *skill, bool success) /* Old 1..400 with (400 - wisb*4) ⇒ scaled: (100 - wisb) */ if (roll >= (100 - wisb)) { increase = base + 1; - SET_SKILL(ch, skill_num, MIN(90, increase)); + SET_SKILL(ch, skill_num, MIN(cap, increase)); /* Cooldown only when an increase actually happens */ cd_seconds = 3600 - (wisb * 5 * 60); /* 1 hour - 5 * WIS minutes */ @@ -259,7 +263,7 @@ void gain_skill(struct char_data *ch, char *skill, bool success) /* Old 1..100 with (100 - wisb) ⇒ scaled: (20 - wisb) */ if (roll >= (20 - wisb)) { increase = base + 1; - SET_SKILL(ch, skill_num, MIN(90, increase)); + SET_SKILL(ch, skill_num, MIN(cap, increase)); /* Cooldown only when an increase actually happens */ cd_seconds = 3600 - (wisb * 5 * 60); /* 1 hour - 5 * WIS minutes */ diff --git a/src/magic.c b/src/magic.c index 1cb8fb6..83cd977 100644 --- a/src/magic.c +++ b/src/magic.c @@ -189,6 +189,7 @@ int mag_damage(int level, struct char_data *ch, struct char_data *victim, int spellnum, int savetype) { int dam = 0; + int save_dc; if (victim == NULL || ch == NULL) return (0); @@ -279,8 +280,12 @@ int mag_damage(int level, struct char_data *ch, struct char_data *victim, } /* switch(spellnum) */ + save_dc = compute_save_dc(ch, level, spellnum); + if (!IS_NPC(ch) && GET_REAL_LEVEL(ch) >= LVL_IMMORT) + save_dc = 1000; + /* divide damage by two if victim makes his saving throw */ - if (mag_savingthrow(victim, savetype, compute_save_dc(ch, level, spellnum))) + if (mag_savingthrow(victim, savetype, save_dc)) dam /= 2; /* and finally, inflict the damage */ @@ -307,6 +312,8 @@ void mag_affects(int level, struct char_data *ch, struct char_data *victim, return; save_dc = compute_save_dc(ch, level, spellnum); + if (!IS_NPC(ch) && GET_REAL_LEVEL(ch) >= LVL_IMMORT) + save_dc = 1000; for (i = 0; i < MAX_SPELL_AFFECTS; i++) { new_affect(&(af[i])); @@ -470,8 +477,6 @@ void mag_affects(int level, struct char_data *ch, struct char_data *victim, break; case SPELL_SLEEP: - if (!CONFIG_PK_ALLOWED && !IS_NPC(ch) && !IS_NPC(victim)) - return; if (MOB_FLAGGED(victim, MOB_NOSLEEP)) return; if (mag_savingthrow(victim, ABIL_WIS, save_dc)) @@ -645,8 +650,6 @@ void mag_areas(int level, struct char_data *ch, int spellnum, int savetype) continue; if (!IS_NPC(tch) && GET_LEVEL(tch) >= LVL_IMMORT) continue; - if (!CONFIG_PK_ALLOWED && !IS_NPC(ch) && !IS_NPC(tch)) - continue; if (!IS_NPC(ch) && IS_NPC(tch) && AFF_FLAGGED(tch, AFF_CHARM)) continue; if (!IS_NPC(tch) && spell_info[spellnum].violent && GROUP(tch) && GROUP(ch) && GROUP(ch) == GROUP(tch)) diff --git a/src/spec_procs.c b/src/spec_procs.c index 5b29ad1..7f3d80e 100644 --- a/src/spec_procs.c +++ b/src/spec_procs.c @@ -488,18 +488,6 @@ SPECIAL(cityguard) for (tch = world[IN_ROOM(ch)].people; tch; tch = tch->next_in_room) { if (!CAN_SEE(ch, tch)) continue; - if (!IS_NPC(tch) && PLR_FLAGGED(tch, PLR_KILLER)) { - act("$n screams 'HEY!!! You're one of those PLAYER KILLERS!!!!!!'", FALSE, ch, 0, 0, TO_ROOM); - hit(ch, tch, TYPE_UNDEFINED); - return (TRUE); - } - - if (!IS_NPC(tch) && PLR_FLAGGED(tch, PLR_THIEF)) { - act("$n screams 'HEY!!! You're one of those PLAYER THIEVES!!!!!!'", FALSE, ch, 0, 0, TO_ROOM); - hit(ch, tch, TYPE_UNDEFINED); - return (TRUE); - } - if (FIGHTING(tch) && GET_ALIGNMENT(tch) < max_evil && (IS_NPC(tch) || IS_NPC(FIGHTING(tch)))) { max_evil = GET_ALIGNMENT(tch); evil = tch; diff --git a/src/spells.c b/src/spells.c index 3c46e29..30b5aa2 100644 --- a/src/spells.c +++ b/src/spells.c @@ -124,28 +124,6 @@ ASPELL(spell_summon) return; } - if (!CONFIG_PK_ALLOWED) { - if (MOB_FLAGGED(victim, MOB_AGGRESSIVE)) { - act("As the words escape your lips and $N travels\r\n" - "through time and space towards you, you realize that $E is\r\n" - "aggressive and might harm you, so you wisely send $M back.", - FALSE, ch, 0, victim, TO_CHAR); - return; - } - if (!IS_NPC(victim) && !PRF_FLAGGED(victim, PRF_SUMMONABLE) && - !PLR_FLAGGED(victim, PLR_KILLER)) { - send_to_char(victim, "%s just tried to summon you to: %s.\r\n" - "This failed because you have summon protection on.\r\n" - "Type NOSUMMON to allow other players to summon you.\r\n", - GET_NAME(ch), world[IN_ROOM(ch)].name); - - send_to_char(ch, "You failed because %s has summon protection on.\r\n", GET_NAME(victim)); - mudlog(BRF, MAX(LVL_IMMORT, MAX(GET_INVIS_LEV(ch), GET_INVIS_LEV(victim))), TRUE, - "%s failed summoning %s to %s.", GET_NAME(ch), GET_NAME(victim), world[IN_ROOM(ch)].name); - return; - } - } - if (MOB_FLAGGED(victim, MOB_NOSUMMON) || (IS_NPC(victim) && mag_savingthrow(victim, SAVING_CHA, save_dc))) { send_to_char(ch, "%s", SUMMON_FAIL); @@ -272,8 +250,6 @@ ASPELL(spell_charm) else if (AFF_FLAGGED(victim, AFF_CHARM) || level < GET_LEVEL(victim)) send_to_char(ch, "You fail.\r\n"); /* player charming another player - no legal reason for this */ - else if (!CONFIG_PK_ALLOWED && !IS_NPC(victim)) - send_to_char(ch, "You fail - shouldn't be doing it anyway.\r\n"); else if (circle_follow(victim, ch)) send_to_char(ch, "Sorry, following in circles is not allowed.\r\n"); else if (mag_savingthrow(victim, SAVING_WIS, save_dc)) diff --git a/src/structs.h b/src/structs.h index 47ed124..03eca5b 100644 --- a/src/structs.h +++ b/src/structs.h @@ -193,8 +193,8 @@ #define NUM_POSITIONS 9 /* Player flags: used by char_data.char_specials.act */ -#define PLR_KILLER 0 /**< Player is a player-killer */ -#define PLR_THIEF 1 /**< Player is a player-thief */ +#define PLR_UNUSED0 0 /**< Reserved (unused) */ +#define PLR_UNUSED1 1 /**< Reserved (unused) */ #define PLR_FROZEN 2 /**< Player is frozen */ #define PLR_DONTSET 3 /**< Don't EVER set (ISNPC bit, set by mud) */ #define PLR_WRITING 4 /**< Player writing (board/mail/olc) */ @@ -1387,7 +1387,6 @@ struct forage_entry { * variables. */ struct game_data { - int pk_allowed; /**< Is player killing allowed? */ int pt_allowed; /**< Is player thieving allowed? */ int level_can_shout; /**< Level player must be to shout. */ int tunnel_size; /**< Number of people allowed in a tunnel.*/ diff --git a/src/utils.h b/src/utils.h index eb91d2d..faf2d40 100644 --- a/src/utils.h +++ b/src/utils.h @@ -1021,7 +1021,6 @@ do \ #define CONFIG_CONFFILE config_info.CONFFILE /** Player killing allowed or not? */ -#define CONFIG_PK_ALLOWED config_info.play.pk_allowed /** Player thieving allowed or not? */ #define CONFIG_PT_ALLOWED config_info.play.pt_allowed /** What level to use the shout command? */