diff --git a/attack.c b/attack.c index b1d7f4d..2b48253 100644 --- a/attack.c +++ b/attack.c @@ -592,7 +592,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) int deflected = B_FALSE; int weppassthrough = B_FALSE; int firstisbackstab = B_FALSE; - int blocked = B_FALSE; + int blocked = B_FALSE,dodged = B_FALSE; int hit = B_FALSE; int critical = 0; char wepname[BUFLEN]; @@ -993,8 +993,8 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) } // at this point, will the damage be fatal? we need to know so we - // can determine whether monsters will use feign death ability. - // NOTE: whether or not the atatck is fatal is re-calculated again + // can determine whether monsters will use feign death or dodge abilities. + // NOTE: whether or not the attack is fatal is re-calculated again // later on after damage is applied to ensure that the correct // attack string is displayed ("you hit xxx" vs "you kill xxx"). if (dam[i] >= victim->hp) { @@ -1014,6 +1014,50 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) } } + if (fatal && !feigneddeath && lfhasflag(victim, F_DODGES) && cansee(victim, lf) && hasfreeaction(victim)) { + cell_t *adj; + int candodge = B_FALSE; + + if (isplayer(victim)) { + if (getstamina(victim)) { + candodge = B_TRUE; + } + } else if (onein(3)) { + candodge = B_TRUE; + } + + if (candodge) { + adj = getrandomadjcell(victim->cell, WE_WALKABLE, B_NOEXPAND); + if (adj) { + flag_t *f; + if (isplayer(victim) || cansee(player, victim)) { + if (cansee(player, lf)) { + msg("^w%s dodge%s %s%s attack!",victimname,isplayer(victim) ? "" : "s", + attackername, getpossessive(attackername)); + } else { + msg("^w%s dodge%s an attack!",victimname,isplayer(victim) ? "" : "s"); + } + } else if (isplayer(lf)) { + msg("You attack something, but it dodges!"); + } else if (cansee(player, lf)) { + msg("%s attacks something, but it dodges!", attackername); + } + f = addflag(victim->flags, F_NOTIME, B_TRUE, NA, NA, NULL); + moveto(victim, adj, B_FALSE, B_FALSE); + killflag(f); + + if (isplayer(victim)) { + setstamina(victim, 0); + } + // remember that we dodged, to avoid otehr attack effects like + // heavy blow, etc. + dodged = B_TRUE; + // stop processing now. + break; + } + } + } + if (willheal) { if (cansee(player, victim)) { flag_t *f; @@ -1108,13 +1152,12 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) if (fatal || waskod) break; // stop now! } // end foreach damtype - if (waskod) { loseconsciousness(victim, waskod, lf); } // other effects - if (!isdead(victim) && !blocked) { + if (!isdead(victim) && !blocked && !dodged) { // special weapon effects, as long as you're not doing a heavy blow if (!lfhasflag(lf, F_HEAVYBLOW) && dam[0]) { wepeffects(wep->flags, victim->cell, damflag, dam[0]); @@ -1224,7 +1267,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) } // end if !isdead(victim) // retaliation happens even if victim died - if (!blocked) { + if (!blocked && !dodged) { getflags(victim->flags, retflag, &nretflags, F_RETALIATE, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; @@ -1276,22 +1319,6 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) // train evasion practice(victim, SK_EVASION, 1); - if (lfhasflag(victim, F_DODGES)) { - cell_t *adj; - - adj = getrandomadjcell(victim->cell, WE_WALKABLE, B_NOEXPAND); - if (adj) { - flag_t *f; - if (isplayer(victim) || cansee(player, victim)) { - msg("^w%s dodge%s!",victimname,isplayer(victim) ? "" : "s"); - } - f = addflag(victim->flags, F_NOTIME, B_TRUE, NA, NA, NULL); - moveto(victim, adj, B_FALSE, B_FALSE); - killflag(f); - } - - } - // chance that ai will give up if we can't reach the victim if (!isplayer(lf) && !canreach(lf, victim, NULL)) { if (pctchance(90)) { diff --git a/data.c b/data.c index b57bfb3..0c55584 100644 --- a/data.c +++ b/data.c @@ -12740,6 +12740,7 @@ void initskills(void) { addskilldesc(SK_EVASION, PR_ADEPT, "^gIncreases your EV by 36%.^n", B_FALSE); addskilldesc(SK_EVASION, PR_ADEPT, "^gYou gain the 'snatch' ability.^n", B_FALSE); addskilldesc(SK_EVASION, PR_SKILLED, "^gIncreases your EV by 48%.^n", B_FALSE); + addskilldesc(SK_EVASION, PR_SKILLED, "^gYou now automatically dodge fatal attacks if you have free stamina.^n", B_FALSE); addskilldesc(SK_EVASION, PR_EXPERT, "^gIncreases your EV by 60%.^n", B_FALSE); addskilldesc(SK_EVASION, PR_MASTER, "^gIncreases your EV by 72%.^n", B_FALSE); addskill(SK_FIRSTAID, "First Aid", "Increases your healing rate and reduces duration of poison.", 0); // untrainable diff --git a/lf.c b/lf.c index fabc0ff..2716bf6 100644 --- a/lf.c +++ b/lf.c @@ -9541,6 +9541,8 @@ flag_t *giveskill(lifeform_t *lf, enum SKILL id) { if (isplayer(lf)) { newf = addtempflag(lf->flags, F_CANWILL, OT_A_SNATCH, NA, NA, NULL, FROMSKILL); } + } else if (f->val[1] == PR_SKILLED) { + newf = addtempflag(lf->flags, F_DODGES, B_TRUE, NA, NA, NULL, FROMSKILL); } } else if (id == SK_LORE_ARCANA) { if (f->val[1] == PR_ADEPT) { diff --git a/spell.c b/spell.c index f62e640..68e9104 100644 --- a/spell.c +++ b/spell.c @@ -10878,7 +10878,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ int dir,amt, n; object_t *arm[MAXBODYPARTS]; int narm = 0; - int dam; getlfname(target, lfname); // hit if (cansee(player, target)) {