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 struct monst *find_targ(struct monst *, int, int, int);
|
||||||
static int find_friends(struct monst *, struct monst *, int);
|
static int find_friends(struct monst *, struct monst *, int);
|
||||||
static struct monst *best_target(struct monst *);
|
static struct monst *best_target(struct monst *);
|
||||||
|
static int pet_ranged_attk(struct monst *);
|
||||||
static long score_targ(struct monst *, struct monst *);
|
static long score_targ(struct monst *, struct monst *);
|
||||||
static boolean can_reach_location(struct monst *, coordxy, coordxy, coordxy,
|
static boolean can_reach_location(struct monst *, coordxy, coordxy, coordxy,
|
||||||
coordxy);
|
coordxy);
|
||||||
@@ -854,6 +855,81 @@ best_target(struct monst *mtmp) /* Pet */
|
|||||||
return best_targ;
|
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):
|
/* Return values (same as m_move):
|
||||||
* 0: did not move, but can still attack and do other stuff.
|
* 0: did not move, but can still attack and do other stuff.
|
||||||
* 1: moved, possibly can attack.
|
* 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
|
* now's the time for ranged attacks. Note that the pet can move
|
||||||
* after it performs its ranged attack. Should this be changed?
|
* after it performs its ranged attack. Should this be changed?
|
||||||
*/
|
*/
|
||||||
{
|
if ((i = pet_ranged_attk(mtmp)) != MMOVE_NOTHING)
|
||||||
struct monst *mtarg;
|
return i;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
newdogpos:
|
newdogpos:
|
||||||
if (nix != omx || niy != omy) {
|
if (nix != omx || niy != omy) {
|
||||||
|
|||||||
Reference in New Issue
Block a user