1
0
Fork 0
mirror of https://codeberg.org/noisytoot/notnotdnethack.git synced 2025-05-14 11:35:04 +01:00

Implement the beast mastery skill, which allows you to improve the attack, damage, and defense of your pets

The skill gains one point of excercise any turn in which at least one of your pets hits a target.

At basic, adds 2 to attack and damage, and 1d2 to AC
Skilled adds 5 to attack and damage, and 1d5 to AC
Expert adds 10 to attack and damage, and 1d10 to AC
This commit is contained in:
Chris-plus-alphanumericgibberish 2015-02-13 03:14:43 -05:00
parent 1c5a53576f
commit 6c1210d59d
8 changed files with 98 additions and 18 deletions

View file

@ -68,8 +68,9 @@
#define P_BARE_HANDED_COMBAT 38
#define P_MARTIAL_ARTS P_BARE_HANDED_COMBAT /* Role distinguishes */
#define P_TWO_WEAPON_COMBAT 39 /* Finally implemented */
#define P_BEAST_MASTERY 40 /* Finally implemented */
#ifdef STEED
#define P_RIDING 40 /* How well you control your steed */
#define P_RIDING 41 /* How well you control your steed */
#define P_LAST_H_TO_H P_RIDING
#else
#define P_LAST_H_TO_H P_TWO_WEAPON_COMBAT

View file

@ -444,6 +444,7 @@ struct you {
uchar wimage; /* to record if you have the image of a Weeping Angel in your mind */
int uinvault;
struct monst *ustuck;
boolean petattacked;
#ifdef STEED
struct monst *usteed;
long ugallop;

View file

@ -442,7 +442,12 @@ moveloop()
else if(!(moves%(u.slowclock - hungerup + 1))) morehungry(1);
}
}
if(u.petattacked){
u.petattacked = FALSE;
use_skill(P_BEAST_MASTERY, 1);
}
if(uclockwork && u.phasengn){
morehungry(10);
}

View file

@ -28,6 +28,7 @@ STATIC_DCL void FDECL(mswingsm, (struct monst *, struct monst *, struct obj *));
STATIC_DCL void FDECL(noises,(struct monst *,struct attack *));
STATIC_DCL void FDECL(missmm,(struct monst *,struct monst *,struct attack *));
STATIC_DCL int FDECL(passivemm, (struct monst *, struct monst *, BOOLEAN_P, int));
STATIC_DCL int NDECL(beastmastery);
/* Needed for the special case of monsters wielding vorpal blades (rare).
* If we use this a lot it should probably be a parameter to mdamagem()
@ -236,6 +237,8 @@ mattackm(magr, mdef)
tmp += 4;
mdef->msleeping = 0;
}
if(magr->mtame && !mdef->mtame) tmp += beastmastery();
/* undetect monsters become un-hidden if they are attacked */
if (mdef->mundetected) {
@ -276,8 +279,10 @@ mattackm(magr, mdef)
if (dist2(magr->mx,magr->my,mdef->mx,mdef->my) > 2)
{
thrwmm(magr, mdef);
if (tmphp > mdef->mhp) res[i] = MM_HIT;
else res[i] = MM_MISS;
if (tmphp > mdef->mhp){
res[i] = MM_HIT;
u.petattacked = TRUE;
} else res[i] = MM_MISS;
if (mdef->mhp < 1) res[i] = MM_DEF_DIED;
if (magr->mhp < 1) res[i] = MM_AGR_DIED;
break;
@ -294,8 +299,10 @@ mattackm(magr, mdef)
is_launcher(MON_WEP(magr))) {
/* implies no melee weapon found */
if(thrwmm(magr, mdef)){
if (tmphp > mdef->mhp) res[i] = MM_HIT;
else res[i] = MM_MISS;
if (tmphp > mdef->mhp){
res[i] = MM_HIT;
u.petattacked = TRUE;
} else res[i] = MM_MISS;
if (mdef->mhp < 1) res[i] = MM_DEF_DIED;
if (magr->mhp < 1) res[i] = MM_AGR_DIED;
break;
@ -354,6 +361,7 @@ meleeattack:
tmp -= hitval(otmp, mdef);
if (strike) {
res[i] = hitmm(magr, mdef, mattk);
if(res[i]) u.petattacked = TRUE;
if((mdef->data == &mons[PM_BLACK_PUDDING] || mdef->data == &mons[PM_BROWN_PUDDING])
&& otmp && objects[otmp->otyp].oc_material == IRON
&& mdef->mhp > 1 && !mdef->mcan)
@ -373,9 +381,10 @@ meleeattack:
case AT_HUGS: /* automatic if prev two attacks succeed */
strike = (i >= 2 && res[i-1] == MM_HIT && res[i-2] == MM_HIT);
if (strike)
if (strike){
res[i] = hitmm(magr, mdef, mattk);
// u.petattacked = TRUE;
}
break;
#ifdef TAME_RANGED_ATTACKS
@ -383,16 +392,20 @@ meleeattack:
if(is_dragon(magr->data)) flags.drgn_brth = 1;
breamm(magr, mdef, mattk);
flags.drgn_brth = 0;
if (tmphp > mdef->mhp) res[i] = MM_HIT;
else res[i] = MM_MISS;
if (tmphp > mdef->mhp){
res[i] = MM_HIT;
u.petattacked = TRUE;
} else res[i] = MM_MISS;
if (mdef->mhp < 1) res[i] = MM_DEF_DIED;
if (magr->mhp < 1) res[i] = MM_AGR_DIED;
break;
case AT_SPIT:
spitmm(magr, mdef, mattk);
if (tmphp > mdef->mhp) res[i] = MM_HIT;
else res[i] = MM_MISS;
if (tmphp > mdef->mhp){
res[i] = MM_HIT;
u.petattacked = TRUE;
} else res[i] = MM_MISS;
if (mdef->mhp < 1) res[i] = MM_DEF_DIED;
if (magr->mhp < 1) res[i] = MM_AGR_DIED;
break;
@ -403,8 +416,10 @@ meleeattack:
if (canseemon(magr)) pline("%s shoots.", Monnam(magr));
for(n = d(mattk->damn, mattk->damd); n > 0; n--) firemm(magr, mdef, mattk);
if(res[i] == MM_MISS){
if (tmphp > mdef->mhp) res[i] = MM_HIT;
else res[i] = MM_MISS;
if (tmphp > mdef->mhp){
res[i] = MM_HIT;
u.petattacked = TRUE;
} else res[i] = MM_MISS;
}
if (mdef->mhp < 1){
res[i] = MM_DEF_DIED;
@ -442,11 +457,13 @@ meleeattack:
case AT_GAZE:
strike = 0; /* will not wake up a sleeper */
res[i] = gazemm(magr, mdef, mattk);
if(res[i]) u.petattacked = TRUE;
break;
case AT_EXPL:
if (distmin(magr->mx,magr->my,mdef->mx,mdef->my) > 1) break;
res[i] = explmm(magr, mdef, mattk);
if(res[i]) u.petattacked = TRUE;
if (is_fern_spore(magr->data)) spore_dies(magr);
if (res[i] == MM_MISS) { /* cancelled--no attack */
strike = 0;
@ -469,10 +486,11 @@ meleeattack:
if (u.uswallow && magr == u.ustuck)
strike = 0;
else {
if ((strike = (tmp > rnd(20+i))))
res[i] = gulpmm(magr, mdef, mattk);
else
missmm(magr, mdef, mattk);
if ((strike = (tmp > rnd(20+i)))){
res[i] = gulpmm(magr, mdef, mattk);
u.petattacked = TRUE;
} else
missmm(magr, mdef, mattk);
}
break;
@ -499,6 +517,7 @@ meleeattack:
else {
res[i] = castmm(magr, mdef, mattk);
}
if(res[i]) u.petattacked = TRUE;
if (res[i] & MM_DEF_DIED)
if( pa == &mons[PM_ASMODEUS] && !rn2(3) ) return 3;
if( pa == &mons[PM_QUINON] ) {
@ -520,6 +539,7 @@ meleeattack:
dist2(magr->mx, magr->my, mdef->mx, mdef->my) < 3)
res[i] = passivemm(magr, mdef, strike, res[i] & MM_DEF_DIED);
if(res[i]) u.petattacked = TRUE;
if (res[i] & MM_DEF_DIED) return res[i];
/*
@ -1685,6 +1705,8 @@ mdamagem(magr, mdef, mattk)
mdef->mstdy -= 1;
}
if(tmp && magr->mtame && !mdef->mtame) tmp += beastmastery();
if((mdef->mhp -= tmp) < 1) {
if (m_at(mdef->mx, mdef->my) == magr) { /* see gulpmm() */
remove_monster(mdef->mx, mdef->my);
@ -2084,6 +2106,19 @@ int aatyp;
return w_mask;
}
STATIC_OVL int
beastmastery()
{
switch (P_SKILL(P_BEAST_MASTERY)) {
case P_ISRESTRICTED: return 0; break;
case P_UNSKILLED: return 0; break;
case P_BASIC: return 2; break;
case P_SKILLED: return 5; break;
case P_EXPERT: return 10; break;
}
}
#endif /* OVLB */
/*mhitm.c*/

View file

@ -3631,6 +3631,7 @@ bindspirit(seal_id)
}break;
case MALPHAS:{
if(u.sealTimeout[MALPHAS-FIRST_SEAL] < moves){
unrestrict_weapon_skill(P_BEAST_MASTERY);
u.sealsActive |= SEAL_MALPHAS;
u.sealsUsed |= SEAL_MALPHAS;
u.spirit[u.sealCounts] = SEAL_MALPHAS;
@ -4074,6 +4075,7 @@ int p_skill;
if(p_skill == P_MATTER_SPELL) return u.sealsActive & SEAL_MARIONETTE? TRUE : FALSE;
if(p_skill == P_RIDING) return u.sealsActive & SEAL_BERITH? TRUE : FALSE;
if(p_skill == P_BARE_HANDED_COMBAT) return u.sealsActive & (SEAL_EURYNOME|SEAL_BUER)? TRUE : FALSE;
if(p_skill == P_BEAST_MASTERY) return u.sealsActive & SEAL_MALPHAS ? TRUE : FALSE;
if(p_skill == P_TWO_WEAPON_COMBAT) return u.specialSealsActive & (SEAL_MISKA)? TRUE : FALSE;
return FALSE;
}

View file

@ -534,6 +534,7 @@ static const struct def_skill Skill_Con[] = {
{ P_ATTACK_SPELL, P_BASIC }, { P_ESCAPE_SPELL, P_EXPERT },
{ P_TWO_WEAPON_COMBAT, P_SKILLED },
{ P_BARE_HANDED_COMBAT, P_SKILLED },
{ P_BEAST_MASTERY, P_BASIC },
{ P_NONE, 0 }
};
#endif /* CONVICT */
@ -550,6 +551,7 @@ static const struct def_skill Skill_H[] = {
{ P_SHURIKEN, P_SKILLED }, { P_UNICORN_HORN, P_EXPERT },
{ P_HEALING_SPELL, P_EXPERT },
{ P_BARE_HANDED_COMBAT, P_BASIC },
{ P_BEAST_MASTERY, P_SKILLED },
{ P_NONE, 0 }
};
@ -567,6 +569,7 @@ static const struct def_skill Skill_Drow_Unarmed[] = {
static const struct def_skill Skill_DP[] = {
{ P_ATTACK_SPELL, P_EXPERT },
{ P_BEAST_MASTERY, P_BASIC },
{ P_NONE, 0 }
};
@ -594,6 +597,7 @@ static const struct def_skill Skill_K[] = {
#endif
{ P_TWO_WEAPON_COMBAT, P_BASIC },
{ P_BARE_HANDED_COMBAT, P_EXPERT },
{ P_BEAST_MASTERY, P_BASIC },
{ P_NONE, 0 }
};
@ -627,6 +631,7 @@ static const struct def_skill Skill_Nob[] = {
{ P_RIDING, P_SKILLED },
#endif
{ P_BARE_HANDED_COMBAT, P_SKILLED },
{ P_BEAST_MASTERY, P_EXPERT },
{ P_NONE, 0 }
};
@ -648,6 +653,7 @@ static const struct def_skill Skill_ENob[] = {
{ P_RIDING, P_SKILLED },
#endif
{ P_BARE_HANDED_COMBAT, P_SKILLED },
{ P_BEAST_MASTERY, P_EXPERT },
{ P_NONE, 0 }
};
@ -670,6 +676,7 @@ static const struct def_skill Skill_DNob[] = {
{ P_RIDING, P_SKILLED },
#endif
{ P_BARE_HANDED_COMBAT, P_SKILLED },
{ P_BEAST_MASTERY, P_EXPERT },
{ P_NONE, 0 }
};
@ -689,6 +696,7 @@ static const struct def_skill Skill_DwaNob[] = {
#endif
{ P_TWO_WEAPON_COMBAT, P_SKILLED },
{ P_BARE_HANDED_COMBAT, P_MASTER },
{ P_BEAST_MASTERY, P_SKILLED },
{ P_NONE, 0 }
};
@ -783,6 +791,7 @@ static const struct def_skill Skill_Ran[] = {
{ P_RIDING, P_BASIC },
#endif
{ P_BARE_HANDED_COMBAT, P_BASIC },
{ P_BEAST_MASTERY, P_SKILLED },
{ P_NONE, 0 }
};
@ -829,6 +838,7 @@ static const struct def_skill Skill_T[] = {
#endif
{ P_TWO_WEAPON_COMBAT, P_BASIC },
{ P_BARE_HANDED_COMBAT, P_BASIC },
{ P_BEAST_MASTERY, P_SKILLED },
{ P_NONE, 0 }
};
#endif /* TOURIST */

View file

@ -30,6 +30,7 @@ STATIC_DCL int FDECL(enhance_skill, (boolean));
#define PN_ESCAPE_SPELL (-13)
#define PN_MATTER_SPELL (-14)
#define PN_HARVEST (-15)
#define PN_BEAST_MASTERY (-16)
static void FDECL(mon_ignite_lightsaber, (struct obj *, struct monst *));
STATIC_DCL void FDECL(give_may_advance_msg, (int));
@ -59,6 +60,7 @@ STATIC_VAR NEARDATA const short skill_names_indices[P_NUM_SKILLS] = {
PN_CLERIC_SPELL, PN_ESCAPE_SPELL,
PN_MATTER_SPELL,
PN_BARE_HANDED, PN_TWO_WEAPONS,
PN_BEAST_MASTERY,
#ifdef STEED
PN_RIDING
#endif
@ -82,6 +84,7 @@ STATIC_VAR NEARDATA const char * const odd_skill_names[] = {
"escape spells",
"matter spells",
"farm implements",
"beast mastery",
};
/* indexed vis `is_martial() */
STATIC_VAR NEARDATA const char * const barehands_or_martial[] = {

View file

@ -6,6 +6,7 @@
STATIC_DCL void FDECL(m_lose_armor, (struct monst *,struct obj *));
STATIC_DCL void FDECL(m_dowear_type, (struct monst *,long, BOOLEAN_P, BOOLEAN_P));
STATIC_DCL int NDECL(def_beastmastery);
const static int CHROMATIC_RES[] = {FIRE_RES, COLD_RES, DISINT_RES, SHOCK_RES, POISON_RES};
const static int EREBOR_RES[] = {FIRE_RES, COLD_RES};
@ -417,6 +418,9 @@ struct monst *mon;
base += base*10;
}
}
if(mon->mtame) base += rnd(def_beastmastery());
return base;
}
@ -446,6 +450,9 @@ struct monst *mon;
base += base*10;
}
}
if(mon->mtame) base += rnd(def_beastmastery());
if(mon->data == &mons[PM_HOD_SEPHIRAH]){
if(uarm) armac += ARM_BONUS(uarm);
if(uarmf) armac += ARM_BONUS(uarmf);
@ -492,6 +499,9 @@ struct monst *mon;
base += base*10;
}
}
if(mon->mtame) base += def_beastmastery();
if(mon->data == &mons[PM_HOD_SEPHIRAH]){
if(uarm) armac += ARM_BONUS(uarm);
if(uarmf) armac += ARM_BONUS(uarmf);
@ -1164,4 +1174,17 @@ long timeout;
if (on_floor) newsym(x, y);
else if (in_invent) update_inventory();
}
STATIC_OVL int
def_beastmastery()
{
switch (P_SKILL(P_BEAST_MASTERY)) {
case P_ISRESTRICTED: return 0; break;
case P_UNSKILLED: return 0; break;
case P_BASIC: return 2; break;
case P_SKILLED: return 5; break;
case P_EXPERT: return 10; break;
}
}
/*worn.c*/