Split pet ranged attack into separate function
This commit is contained in:
148
src/dogmove.c
148
src/dogmove.c
@@ -18,6 +18,7 @@ static int dog_goal(struct monst *, struct edog *, int, int, int);
|
||||
static struct monst *find_targ(struct monst *, int, int, int);
|
||||
static int find_friends(struct monst *, struct monst *, int);
|
||||
static struct monst *best_target(struct monst *);
|
||||
static int pet_ranged_attk(struct monst *);
|
||||
static long score_targ(struct monst *, struct monst *);
|
||||
static boolean can_reach_location(struct monst *, coordxy, coordxy, coordxy,
|
||||
coordxy);
|
||||
@@ -854,6 +855,81 @@ best_target(struct monst *mtmp) /* Pet */
|
||||
return best_targ;
|
||||
}
|
||||
|
||||
/* Pet considers and maybe executes a ranged attack */
|
||||
static int
|
||||
pet_ranged_attk(struct monst *mtmp)
|
||||
{
|
||||
struct monst *mtarg;
|
||||
int hungry = 0;
|
||||
|
||||
/* How hungry is the pet? */
|
||||
if (!mtmp->isminion) {
|
||||
struct edog *dog = EDOG(mtmp);
|
||||
|
||||
hungry = (gm.moves > (dog->hungrytime + DOG_HUNGRY));
|
||||
}
|
||||
|
||||
/* Identify the best target in a straight line from the pet;
|
||||
* if there is such a target, we'll let the pet attempt an attack.
|
||||
*/
|
||||
mtarg = best_target(mtmp);
|
||||
|
||||
/* Hungry pets are unlikely to use breath/spit attacks */
|
||||
if (mtarg && (!hungry || !rn2(5))) {
|
||||
int mstatus = MM_MISS;
|
||||
|
||||
if (mtarg == &gy.youmonst) {
|
||||
if (mattacku(mtmp))
|
||||
return MMOVE_DIED;
|
||||
/* Treat this as the pet having initiated an attack even if it
|
||||
* didn't, so it will lose its move. This isn't entirely fair,
|
||||
* but mattacku doesn't distinguish between "did not attack"
|
||||
* and "attacked but didn't die" cases, and this is preferable
|
||||
* to letting the pet attack the player and continuing to move.
|
||||
*/
|
||||
mstatus = MM_HIT;
|
||||
} else {
|
||||
mstatus = mattackm(mtmp, mtarg);
|
||||
|
||||
/* Shouldn't happen, really */
|
||||
if (mstatus & MM_AGR_DIED)
|
||||
return MMOVE_DIED;
|
||||
|
||||
/* Allow the targeted nasty to strike back - if
|
||||
* the targeted beast doesn't have a ranged attack,
|
||||
* nothing will happen.
|
||||
*/
|
||||
if ((mstatus & MM_HIT) && !(mstatus & MM_DEF_DIED)
|
||||
&& rn2(4) && mtarg != &gy.youmonst) {
|
||||
|
||||
/* Can monster see? If it can, it can retaliate
|
||||
* even if the pet is invisible, since it'll see
|
||||
* the direction from which the ranged attack came;
|
||||
* if it's blind or unseeing, it can't retaliate
|
||||
*/
|
||||
if (mtarg->mcansee && haseyes(mtarg->data)) {
|
||||
mstatus = mattackm(mtarg, mtmp);
|
||||
if (mstatus & MM_DEF_DIED)
|
||||
return MMOVE_DIED;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Only return 3 if the pet actually made a ranged attack, and
|
||||
* thus should lose the rest of its move.
|
||||
* There's a chain of assumptions here:
|
||||
* 1. score_targ and best_target will never select a monster
|
||||
* that can be attacked in melee, so the mattackm call can
|
||||
* only ever try ranged options
|
||||
* 2. if the only attacks available to mattackm are ranged
|
||||
* options, and the monster cannot make a ranged attack, it
|
||||
* will return MM_MISS.
|
||||
*/
|
||||
if (mstatus != MM_MISS)
|
||||
return MMOVE_DONE;
|
||||
}
|
||||
return MMOVE_NOTHING;
|
||||
}
|
||||
|
||||
/* Return values (same as m_move):
|
||||
* 0: did not move, but can still attack and do other stuff.
|
||||
* 1: moved, possibly can attack.
|
||||
@@ -1130,76 +1206,8 @@ dog_move(register struct monst *mtmp,
|
||||
* now's the time for ranged attacks. Note that the pet can move
|
||||
* after it performs its ranged attack. Should this be changed?
|
||||
*/
|
||||
{
|
||||
struct monst *mtarg;
|
||||
int hungry = 0;
|
||||
|
||||
/* How hungry is the pet? */
|
||||
if (!mtmp->isminion) {
|
||||
struct edog *dog = EDOG(mtmp);
|
||||
|
||||
hungry = (gm.moves > (dog->hungrytime + DOG_HUNGRY));
|
||||
}
|
||||
|
||||
/* Identify the best target in a straight line from the pet;
|
||||
* if there is such a target, we'll let the pet attempt an attack.
|
||||
*/
|
||||
mtarg = best_target(mtmp);
|
||||
|
||||
/* Hungry pets are unlikely to use breath/spit attacks */
|
||||
if (mtarg && (!hungry || !rn2(5))) {
|
||||
int mstatus = MM_MISS;
|
||||
|
||||
if (mtarg == &gy.youmonst) {
|
||||
if (mattacku(mtmp))
|
||||
return MMOVE_DIED;
|
||||
/* Treat this as the pet having initiated an attack even if it
|
||||
* didn't, so it will lose its move. This isn't entirely fair,
|
||||
* but mattacku doesn't distinguish between "did not attack"
|
||||
* and "attacked but didn't die" cases, and this is preferable
|
||||
* to letting the pet attack the player and continuing to move.
|
||||
*/
|
||||
mstatus = MM_HIT;
|
||||
} else {
|
||||
mstatus = mattackm(mtmp, mtarg);
|
||||
|
||||
/* Shouldn't happen, really */
|
||||
if (mstatus & MM_AGR_DIED)
|
||||
return MMOVE_DIED;
|
||||
|
||||
/* Allow the targeted nasty to strike back - if
|
||||
* the targeted beast doesn't have a ranged attack,
|
||||
* nothing will happen.
|
||||
*/
|
||||
if ((mstatus & MM_HIT) && !(mstatus & MM_DEF_DIED)
|
||||
&& rn2(4) && mtarg != &gy.youmonst) {
|
||||
|
||||
/* Can monster see? If it can, it can retaliate
|
||||
* even if the pet is invisible, since it'll see
|
||||
* the direction from which the ranged attack came;
|
||||
* if it's blind or unseeing, it can't retaliate
|
||||
*/
|
||||
if (mtarg->mcansee && haseyes(mtarg->data)) {
|
||||
mstatus = mattackm(mtarg, mtmp);
|
||||
if (mstatus & MM_DEF_DIED)
|
||||
return MMOVE_DIED;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Only return 3 if the pet actually made a ranged attack, and
|
||||
* thus should lose the rest of its move.
|
||||
* There's a chain of assumptions here:
|
||||
* 1. score_targ and best_target will never select a monster
|
||||
* that can be attacked in melee, so the mattackm call can
|
||||
* only ever try ranged options
|
||||
* 2. if the only attacks available to mattackm are ranged
|
||||
* options, and the monster cannot make a ranged attack, it
|
||||
* will return MM_MISS.
|
||||
*/
|
||||
if (mstatus != MM_MISS)
|
||||
return MMOVE_DONE;
|
||||
}
|
||||
}
|
||||
if ((i = pet_ranged_attk(mtmp)) != MMOVE_NOTHING)
|
||||
return i;
|
||||
|
||||
newdogpos:
|
||||
if (nix != omx || niy != omy) {
|
||||
|
||||
Reference in New Issue
Block a user