mirror of
https://github.com/tbamud/tbamud.git
synced 2026-03-26 14:16:33 +01:00
Add basic combat skills
This commit is contained in:
parent
16cd1fac05
commit
3560427902
4 changed files with 168 additions and 33 deletions
49
src/class.c
49
src/class.c
|
|
@ -946,6 +946,7 @@ void do_start(struct char_data *ch)
|
|||
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);
|
||||
break;
|
||||
|
||||
case CLASS_CLERIC:
|
||||
|
|
@ -980,6 +981,7 @@ void do_start(struct char_data *ch)
|
|||
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);
|
||||
break;
|
||||
|
||||
case CLASS_THIEF:
|
||||
|
|
@ -988,6 +990,9 @@ void do_start(struct char_data *ch)
|
|||
SET_SKILL(ch, SKILL_STEAL, 5);
|
||||
SET_SKILL(ch, SKILL_BACKSTAB, 5);
|
||||
SET_SKILL(ch, SKILL_PICK_LOCK, 5);
|
||||
SET_SKILL(ch, SKILL_UNARMED, 5);
|
||||
SET_SKILL(ch, SKILL_SHIELD_USE, 5);
|
||||
SET_SKILL(ch, SKILL_PIERCING_WEAPONS, 5);
|
||||
break;
|
||||
|
||||
case CLASS_WARRIOR:
|
||||
|
|
@ -995,7 +1000,11 @@ void do_start(struct char_data *ch)
|
|||
SET_SKILL(ch, SKILL_RESCUE, 5);
|
||||
SET_SKILL(ch, SKILL_BANDAGE, 5);
|
||||
SET_SKILL(ch, SKILL_BASH, 5);
|
||||
SET_SKILL(ch, SKILL_WHIRLWIND, 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);
|
||||
break;
|
||||
|
||||
case CLASS_BARBARIAN:
|
||||
|
|
@ -1003,6 +1012,9 @@ void do_start(struct char_data *ch)
|
|||
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);
|
||||
break;
|
||||
|
||||
case CLASS_RANGER:
|
||||
|
|
@ -1011,6 +1023,10 @@ void do_start(struct char_data *ch)
|
|||
SET_SKILL(ch, SKILL_BANDAGE, 5);
|
||||
SET_SKILL(ch, SKILL_TRACK, 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_SHIELD_USE, 5);
|
||||
break;
|
||||
|
||||
case CLASS_BARD:
|
||||
|
|
@ -1019,6 +1035,9 @@ void do_start(struct char_data *ch)
|
|||
SET_SKILL(ch, SKILL_BANDAGE, 5);
|
||||
SET_SKILL(ch, SKILL_TRACK, 5);
|
||||
SET_SKILL(ch, SKILL_PICK_LOCK, 5);
|
||||
SET_SKILL(ch, SKILL_UNARMED, 5);
|
||||
SET_SKILL(ch, SKILL_PIERCING_WEAPONS, 5);
|
||||
SET_SKILL(ch, SKILL_SHIELD_USE, 5);
|
||||
break;
|
||||
|
||||
case CLASS_DRUID:
|
||||
|
|
@ -1027,6 +1046,9 @@ void do_start(struct char_data *ch)
|
|||
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);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -1197,6 +1219,7 @@ void init_spell_levels(void)
|
|||
spell_level(SPELL_FLY, CLASS_MAGIC_USER, 1);
|
||||
spell_level(SPELL_ENCHANT_WEAPON, CLASS_MAGIC_USER, 1);
|
||||
spell_level(SPELL_CLONE, CLASS_MAGIC_USER, 1);
|
||||
spell_level(SKILL_UNARMED, CLASS_MAGIC_USER, 1);
|
||||
|
||||
/* CLERICS */
|
||||
spell_level(SPELL_CURE_LIGHT, CLASS_CLERIC, 1);
|
||||
|
|
@ -1230,6 +1253,7 @@ void init_spell_levels(void)
|
|||
spell_level(SPELL_HARM, CLASS_CLERIC, 1);
|
||||
spell_level(SPELL_GROUP_HEAL, CLASS_CLERIC, 1);
|
||||
spell_level(SPELL_REMOVE_CURSE, CLASS_CLERIC, 1);
|
||||
spell_level(SKILL_SHIELD_USE, CLASS_CLERIC, 1);
|
||||
|
||||
/* THIEVES */
|
||||
spell_level(SKILL_SNEAK, CLASS_THIEF, 1);
|
||||
|
|
@ -1238,20 +1262,29 @@ void init_spell_levels(void)
|
|||
spell_level(SKILL_STEAL, CLASS_THIEF, 1);
|
||||
spell_level(SKILL_HIDE, CLASS_THIEF, 1);
|
||||
spell_level(SKILL_TRACK, CLASS_THIEF, 1);
|
||||
spell_level(SKILL_UNARMED, CLASS_THIEF, 1);
|
||||
spell_level(SKILL_PIERCING_WEAPONS, CLASS_THIEF, 1);
|
||||
spell_level(SKILL_SHIELD_USE, CLASS_THIEF, 1);
|
||||
|
||||
/* WARRIORS */
|
||||
spell_level(SKILL_KICK, CLASS_WARRIOR, 1);
|
||||
spell_level(SKILL_RESCUE, CLASS_WARRIOR, 1);
|
||||
spell_level(SKILL_BANDAGE, CLASS_WARRIOR, 1);
|
||||
spell_level(SKILL_TRACK, CLASS_WARRIOR, 1);
|
||||
spell_level(SKILL_BASH, CLASS_WARRIOR, 1);
|
||||
spell_level(SKILL_WHIRLWIND, CLASS_WARRIOR, 1);
|
||||
spell_level(SKILL_UNARMED, CLASS_WARRIOR, 1);
|
||||
spell_level(SKILL_SLASHING_WEAPONS, CLASS_WARRIOR, 1);
|
||||
spell_level(SKILL_PIERCING_WEAPONS, CLASS_WARRIOR, 1);
|
||||
spell_level(SKILL_BLUDGEONING_WEAPONS, CLASS_WARRIOR, 1);
|
||||
spell_level(SKILL_SHIELD_USE, CLASS_WARRIOR, 1);
|
||||
|
||||
/* BARBARIANS */
|
||||
spell_level(SKILL_KICK, CLASS_BARBARIAN, 1);
|
||||
spell_level(SKILL_RESCUE, CLASS_BARBARIAN, 1);
|
||||
spell_level(SKILL_BANDAGE, CLASS_BARBARIAN, 1);
|
||||
spell_level(SKILL_WHIRLWIND, CLASS_BARBARIAN, 1);
|
||||
spell_level(SKILL_UNARMED, CLASS_BARBARIAN, 1);
|
||||
spell_level(SKILL_SLASHING_WEAPONS, CLASS_BARBARIAN, 1);
|
||||
spell_level(SKILL_BLUDGEONING_WEAPONS, CLASS_BARBARIAN, 1);
|
||||
|
||||
/* RANGERS */
|
||||
spell_level(SKILL_SNEAK, CLASS_RANGER, 1);
|
||||
|
|
@ -1259,6 +1292,10 @@ void init_spell_levels(void)
|
|||
spell_level(SKILL_BANDAGE, CLASS_RANGER, 1);
|
||||
spell_level(SKILL_TRACK, CLASS_RANGER, 1);
|
||||
spell_level(SKILL_BASH, CLASS_RANGER, 1);
|
||||
spell_level(SKILL_UNARMED, CLASS_RANGER, 1);
|
||||
spell_level(SKILL_SLASHING_WEAPONS, CLASS_RANGER, 1);
|
||||
spell_level(SKILL_PIERCING_WEAPONS, CLASS_RANGER, 1);
|
||||
spell_level(SKILL_SHIELD_USE, CLASS_RANGER, 1);
|
||||
|
||||
/* BARDS */
|
||||
spell_level(SPELL_ARMOR, CLASS_BARD, 1);
|
||||
|
|
@ -1266,6 +1303,9 @@ void init_spell_levels(void)
|
|||
spell_level(SKILL_BANDAGE, CLASS_BARD, 1);
|
||||
spell_level(SKILL_TRACK, CLASS_BARD, 1);
|
||||
spell_level(SKILL_PICK_LOCK, CLASS_BARD, 1);
|
||||
spell_level(SKILL_UNARMED, CLASS_BARD, 1);
|
||||
spell_level(SKILL_PIERCING_WEAPONS, CLASS_BARD, 1);
|
||||
spell_level(SKILL_SHIELD_USE, CLASS_BARD, 1);
|
||||
|
||||
/* DRUIDS */
|
||||
spell_level(SPELL_DETECT_INVIS, CLASS_DRUID, 1);
|
||||
|
|
@ -1273,6 +1313,9 @@ void init_spell_levels(void)
|
|||
spell_level(SPELL_LOCATE_OBJECT, CLASS_DRUID, 1);
|
||||
spell_level(SKILL_BANDAGE, CLASS_DRUID, 1);
|
||||
spell_level(SKILL_TRACK, CLASS_DRUID, 1);
|
||||
spell_level(SKILL_UNARMED, CLASS_DRUID, 1);
|
||||
spell_level(SKILL_PIERCING_WEAPONS, CLASS_DRUID, 1);
|
||||
spell_level(SKILL_SHIELD_USE, CLASS_DRUID, 1);
|
||||
}
|
||||
|
||||
/* This is the exp given to implementors -- it must always be greater than the
|
||||
|
|
|
|||
142
src/fight.c
142
src/fight.c
|
|
@ -64,6 +64,53 @@ static void solo_gain(struct char_data *ch, struct char_data *victim);
|
|||
static char *replace_string(const char *str, const char *weapon_singular, const char *weapon_plural);
|
||||
static int compute_thaco(struct char_data *ch, struct char_data *vict);
|
||||
|
||||
/* Map the current attack (unarmed/weapon damage type) to SKILL_* constant. */
|
||||
static int weapon_family_skill_num(struct char_data *ch, struct obj_data *wielded, int w_type) {
|
||||
/* Unarmed? */
|
||||
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.
|
||||
Adjust the cases below to match your game's TYPE_* values. */
|
||||
switch (w_type) {
|
||||
/* --- Piercing family --- */
|
||||
case TYPE_STAB:
|
||||
case TYPE_PIERCE:
|
||||
case TYPE_WHIP:
|
||||
case TYPE_STING:
|
||||
return SKILL_PIERCING_WEAPONS;
|
||||
|
||||
/* --- Slashing family --- */
|
||||
case TYPE_SLASH:
|
||||
case TYPE_MAUL:
|
||||
case TYPE_CLAW:
|
||||
return SKILL_SLASHING_WEAPONS;
|
||||
|
||||
/* --- Bludgeoning family --- */
|
||||
case TYPE_BLUDGEON:
|
||||
case TYPE_CRUSH:
|
||||
case TYPE_THRASH:
|
||||
case TYPE_POUND:
|
||||
return SKILL_BLUDGEONING_WEAPONS;
|
||||
|
||||
/* Fallback */
|
||||
default:
|
||||
return SKILL_UNARMED;
|
||||
}
|
||||
}
|
||||
|
||||
/* Map SKILL_* constants to the strings your gain_skill(name, failure) expects. */
|
||||
static const char *skill_name_for_gain(int skillnum) {
|
||||
switch (skillnum) {
|
||||
case SKILL_UNARMED: return "unarmed";
|
||||
case SKILL_PIERCING_WEAPONS: return "piercing weapons";
|
||||
case SKILL_SLASHING_WEAPONS: return "slashing weapons";
|
||||
case SKILL_BLUDGEONING_WEAPONS: return "bludgeoning weapons";
|
||||
case SKILL_SHIELD_USE: return "shield use";
|
||||
default: return "unarmed";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define IS_WEAPON(type) (((type) >= TYPE_HIT) && ((type) < TYPE_SUFFERING))
|
||||
/* The Fight related routines */
|
||||
|
|
@ -776,7 +823,8 @@ static int compute_thaco(struct char_data *ch, struct char_data *victim)
|
|||
void hit(struct char_data *ch, struct char_data *victim, int type)
|
||||
{
|
||||
struct obj_data *wielded = GET_EQ(ch, WEAR_WIELD);
|
||||
int w_type, victim_ac, calc_thaco, dam, diceroll;
|
||||
int w_type, victim_ac, calc_thaco, diceroll;
|
||||
int dam;
|
||||
|
||||
/* Check that the attacker and victim exist */
|
||||
if (!ch || !victim) return;
|
||||
|
|
@ -812,51 +860,84 @@ void hit(struct char_data *ch, struct char_data *victim, int type)
|
|||
|
||||
/* report for debugging if necessary */
|
||||
if (CONFIG_DEBUG_MODE >= NRM)
|
||||
send_to_char(ch, "\t1Debug:\r\n \t2Thaco: \t3%d\r\n \t2AC: \t3%d\r\n \t2Diceroll: \t3%d\tn\r\n",
|
||||
send_to_char(ch, "\t1Debug:\r\n \t2Thaco: \t3%d\r\n \t2AC: \t3%d\r\n \t2Diceroll: \t3%d\tn\r\n",
|
||||
calc_thaco, victim_ac, diceroll);
|
||||
|
||||
/* Decide whether this is a hit or a miss.
|
||||
* Victim asleep = hit, otherwise:
|
||||
* 1 = Automatic miss.
|
||||
* 2..19 = Checked vs. AC.
|
||||
* 20 = Automatic hit. */
|
||||
if (diceroll == 20 || !AWAKE(victim))
|
||||
/* -----------------------------------------------------------
|
||||
* To-hit & Shield bonuses:
|
||||
* - Natural 20 = auto hit, 1 = auto miss (keep unchanged)
|
||||
* - Otherwise, modify the *roll* with:
|
||||
* + (attacker skill / 10) // attack bonus
|
||||
* - (defender shield / 10) // shield reduces attacker's roll
|
||||
* Bonuses < 1 count as zero.
|
||||
* ----------------------------------------------------------- */
|
||||
if (diceroll == 20 || !AWAKE(victim)) {
|
||||
dam = TRUE;
|
||||
else if (diceroll == 1)
|
||||
} else if (diceroll == 1) {
|
||||
dam = FALSE;
|
||||
else
|
||||
dam = (calc_thaco - diceroll <= victim_ac);
|
||||
} else {
|
||||
int d_adj = diceroll;
|
||||
|
||||
if (!dam)
|
||||
/* Attacker’s family skill */
|
||||
int atk_skillnum = weapon_family_skill_num(ch, wielded, w_type);
|
||||
int atk_skill = (atk_skillnum > 0) ? GET_SKILL(ch, atk_skillnum) : 0;
|
||||
int atk_bonus = atk_skill / 10; /* e.g., 0..10 */
|
||||
if (atk_bonus < 1) atk_bonus = 0; /* ignore < 1 */
|
||||
|
||||
/* Defender shield */
|
||||
int sh_bonus = 0;
|
||||
if (GET_EQ(victim, WEAR_SHIELD)) {
|
||||
int sh_skill = GET_SKILL(victim, SKILL_SHIELD_USE);
|
||||
sh_bonus = sh_skill / 10;
|
||||
if (sh_bonus < 1) sh_bonus = 0;
|
||||
}
|
||||
|
||||
d_adj += atk_bonus;
|
||||
d_adj -= sh_bonus;
|
||||
|
||||
/* NOTE: do not force auto-1/20 from adjusted roll; we keep raw auto logic above. */
|
||||
dam = (calc_thaco - d_adj <= victim_ac);
|
||||
|
||||
if (CONFIG_DEBUG_MODE >= NRM) {
|
||||
send_to_char(ch, " \t2Atk bonus: \t3%d\t2 Shield red: \t3%d\t2 Adj roll: \t3%d\tn\r\n",
|
||||
atk_bonus, sh_bonus, d_adj);
|
||||
}
|
||||
}
|
||||
|
||||
/* Skill gains: once per swing, after hit/miss known */
|
||||
{
|
||||
/* Attacker gains in the family skill used */
|
||||
int atk_skillnum = weapon_family_skill_num(ch, wielded, w_type);
|
||||
const char *atk_skill_name = skill_name_for_gain(atk_skillnum);
|
||||
gain_skill(ch, (char *)atk_skill_name, dam ? FALSE : TRUE);
|
||||
|
||||
/* Defender gains in shield use if wearing a shield */
|
||||
if (GET_EQ(victim, WEAR_SHIELD)) {
|
||||
/* If miss → shield succeeded (failure=FALSE). If hit → shield failed (failure=TRUE). */
|
||||
gain_skill(victim, "shield use", dam ? TRUE : FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (!dam) {
|
||||
/* the attacker missed the victim */
|
||||
damage(ch, victim, 0, type == SKILL_BACKSTAB ? SKILL_BACKSTAB : w_type);
|
||||
else {
|
||||
damage(ch, victim, 0, (type == SKILL_BACKSTAB) ? SKILL_BACKSTAB : w_type);
|
||||
} else {
|
||||
/* okay, we know the guy has been hit. now calculate damage.
|
||||
* Start with the damage bonuses: the damroll and strength apply */
|
||||
dam = str_app[STRENGTH_APPLY_INDEX(ch)].todam;
|
||||
dam += GET_DAMROLL(ch);
|
||||
|
||||
/* Maybe holding arrow? */
|
||||
/* Weapon or bare hands? */
|
||||
if (wielded && GET_OBJ_TYPE(wielded) == ITEM_WEAPON) {
|
||||
/* Add weapon-based damage if a weapon is being wielded */
|
||||
dam += dice(GET_OBJ_VAL(wielded, 1), GET_OBJ_VAL(wielded, 2));
|
||||
} else {
|
||||
/* If no weapon, add bare hand damage instead */
|
||||
if (IS_NPC(ch))
|
||||
dam += dice(ch->mob_specials.damnodice, ch->mob_specials.damsizedice);
|
||||
else
|
||||
dam += rand_number(0, 2); /* Max 2 bare hand damage for players */
|
||||
if (IS_NPC(ch))
|
||||
dam += dice(ch->mob_specials.damnodice, ch->mob_specials.damsizedice);
|
||||
else
|
||||
dam += rand_number(0, 2); /* Max 2 bare hand damage for players */
|
||||
}
|
||||
|
||||
/* Include a damage multiplier if victim isn't ready to fight:
|
||||
* Position sitting 1.33 x normal
|
||||
* Position resting 1.66 x normal
|
||||
* Position sleeping 2.00 x normal
|
||||
* Position stunned 2.33 x normal
|
||||
* Position incap 2.66 x normal
|
||||
* Position mortally 3.00 x normal
|
||||
* Note, this is a hack because it depends on the particular
|
||||
* values of the POSITION_XXX constants. */
|
||||
/* Position-based damage multiplier (unchanged) */
|
||||
if (GET_POS(victim) < POS_FIGHTING)
|
||||
dam *= 1 + (POS_FIGHTING - GET_POS(victim)) / 3;
|
||||
|
||||
|
|
@ -873,6 +954,7 @@ void hit(struct char_data *ch, struct char_data *victim, int type)
|
|||
hitprcnt_mtrigger(victim);
|
||||
}
|
||||
|
||||
|
||||
/* control the fights going on. Called every 2 seconds from comm.c. */
|
||||
void perform_violence(void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -929,5 +929,10 @@ void mag_assign_spells(void) {
|
|||
skillo(SKILL_TRACK, "track");
|
||||
skillo(SKILL_WHIRLWIND, "whirlwind");
|
||||
skillo(SKILL_BANDAGE, "bandage");
|
||||
skillo(SKILL_UNARMED, "unarmed fighting");
|
||||
skillo(SKILL_SHIELD_USE, "shield use");
|
||||
skillo(SKILL_PIERCING_WEAPONS, "piercing weapons");
|
||||
skillo(SKILL_SLASHING_WEAPONS, "slashing weapons");
|
||||
skillo(SKILL_BLUDGEONING_WEAPONS, "bludgeoning weapons");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -111,6 +111,11 @@
|
|||
#define SKILL_STEAL 139 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SKILL_TRACK 140 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SKILL_BANDAGE 141 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SKILL_UNARMED 142 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SKILL_SHIELD_USE 143 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SKILL_PIERCING_WEAPONS 144 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SKILL_SLASHING_WEAPONS 145 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SKILL_BLUDGEONING_WEAPONS 146 /* Reserved Skill[] DO NOT CHANGE */
|
||||
|
||||
/* New skills may be added here up to MAX_SKILLS (200) */
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue