Finish support of generalized status effects (probably)
- Negative dumbfounding increases effective magic skills; works on monsters too (though it already did) - Martyr's Shield no longer permanent on monsters - Invisible status effect works on monsters (same as permanent invisibility) - Poisoned weapon status effect works on monsters (adds poison to their first melee attack) - Restore Mind spell no longer removes negative dumbfounding - Invulnerability status effect works on monsters (same as permanent invulnerability, and stacks with it) - Magic resistance status effect works on monsters (halves fire/cold damage) - Negative magic resistance doubles magic/cold damage (both on PCs and monsters)
This commit is contained in:
@@ -2449,6 +2449,10 @@ void do_monster_turn() {
|
||||
cur_monst->spell_note(29);
|
||||
move_to_zero(cur_monst->status[eStatus::ASLEEP]);
|
||||
move_to_zero(cur_monst->status[eStatus::PARALYZED]);
|
||||
move_to_zero(cur_monst->status[eStatus::INVISIBLE]);
|
||||
move_to_zero(cur_monst->status[eStatus::INVULNERABLE]);
|
||||
move_to_zero(cur_monst->status[eStatus::MAGIC_RESISTANCE]);
|
||||
move_to_zero(cur_monst->status[eStatus::MARTYRS_SHIELD]);
|
||||
|
||||
if(univ.party.age % 2 == 0) {
|
||||
move_to_zero(cur_monst->status[eStatus::BLESS_CURSE]);
|
||||
@@ -2513,7 +2517,7 @@ void monster_attack(short who_att,iLiving* target) {
|
||||
// Draw attacker frames
|
||||
if((is_combat())
|
||||
&& (center_on_monst || !monsters_going)) {
|
||||
if(!attacker->invisible)
|
||||
if(!attacker->invisible && attacker->status[eStatus::INVISIBLE] <= 0)
|
||||
frame_space(attacker->cur_loc,0,attacker->x_width,attacker->y_width);
|
||||
frame_space(target->get_loc(),1,1,1);
|
||||
}
|
||||
@@ -2522,10 +2526,13 @@ void monster_attack(short who_att,iLiving* target) {
|
||||
|
||||
if(attacker->a[0].dice != 0 || attacker->a[1].dice != 0 || attacker->a[2].dice != 0)
|
||||
attacker->print_attacks(target);
|
||||
|
||||
// Some things depend on whether it's a player or a monster.
|
||||
cCreature* m_target = dynamic_cast<cCreature*>(target);
|
||||
cPlayer* pc_target = dynamic_cast<cPlayer*>(target);
|
||||
|
||||
// Check sanctuary
|
||||
// TODO: What about monster permanent invisibility?
|
||||
if(target->status[eStatus::INVISIBLE] > 0) {
|
||||
if(target->status[eStatus::INVISIBLE] > 0 || (m_target != nullptr && m_target->invisible)) {
|
||||
r1 = get_ran(1,1,100);
|
||||
if(r1 > hit_chance[attacker->level / 2]) {
|
||||
add_string_to_buf(" Can't find target!");
|
||||
@@ -2538,10 +2545,6 @@ void monster_attack(short who_att,iLiving* target) {
|
||||
// sprintf ((char *) create_line, " Attacks %s.",(char *) univ.party[target].name);
|
||||
// add_string_to_buf((char *) create_line);
|
||||
|
||||
// Some things depend on whether it's a player or a monster.
|
||||
cCreature* m_target = dynamic_cast<cCreature*>(target);
|
||||
cPlayer* pc_target = dynamic_cast<cPlayer*>(target);
|
||||
|
||||
// if target monster friendly to party, make able to attack
|
||||
if(m_target != nullptr && m_target->attitude == 0)
|
||||
m_target->attitude = 2;
|
||||
@@ -2604,6 +2607,12 @@ void monster_attack(short who_att,iLiving* target) {
|
||||
damage_monst(who_att, who_hit, dmg, eDamageType::MAGIC,0);
|
||||
}
|
||||
|
||||
if(i == 0 && attacker->status[eStatus::POISONED_WEAPON] > 0) {
|
||||
short poison_amt = attacker->status[eStatus::POISONED_WEAPON];
|
||||
target->poison(poison_amt);
|
||||
move_to_zero(attacker->status[eStatus::POISONED_WEAPON]);
|
||||
}
|
||||
|
||||
for(auto& abil : attacker->abil) {
|
||||
if(!abil.second.active) continue;
|
||||
if(getMonstAbilCategory(abil.first) != eMonstAbilCat::GENERAL)
|
||||
@@ -3130,7 +3139,7 @@ bool monst_cast_mage(cCreature *caster,short targ) {
|
||||
|
||||
eSpell spell;
|
||||
|
||||
level = max(1,caster->mu - caster->status[eStatus::DUMB]) - 1;
|
||||
level = minmax(1,7,caster->mu - caster->status[eStatus::DUMB]) - 1;
|
||||
|
||||
target = find_fireball_loc(caster->cur_loc,1,(caster->attitude % 2 == 1) ? 0 : 1,&target_levels);
|
||||
friend_levels_near = (caster->attitude % 2 != 1) ? count_levels(caster->cur_loc,3) : -1 * count_levels(caster->cur_loc,3);
|
||||
@@ -3448,7 +3457,7 @@ bool monst_cast_priest(cCreature *caster,short targ) {
|
||||
if(univ.town.is_antimagic(caster->cur_loc.x,caster->cur_loc.y)) {
|
||||
return false;
|
||||
}
|
||||
level = max(1,caster->cl - caster->status[eStatus::DUMB]) - 1;
|
||||
level = minmax(1,7,caster->cl - caster->status[eStatus::DUMB]) - 1;
|
||||
|
||||
eSpell spell;
|
||||
|
||||
|
@@ -186,7 +186,7 @@ void draw_monsters() {
|
||||
}
|
||||
if(is_town() || is_combat()) {
|
||||
for(i = 0; i < univ.town.monst.size(); i++)
|
||||
if(univ.town.monst[i].active != 0 && !univ.town.monst[i].invisible)
|
||||
if(univ.town.monst[i].active != 0 && !univ.town.monst[i].invisible && univ.town.monst[i].status[eStatus::INVISIBLE] <= 0)
|
||||
if(point_onscreen(center,univ.town.monst[i].cur_loc) && party_can_see_monst(i)) {
|
||||
check_if_monst_seen(univ.town.monst[i].number, univ.town.monst[i].cur_loc);
|
||||
where_draw.x = univ.town.monst[i].cur_loc.x - center.x + 4;
|
||||
|
@@ -1204,6 +1204,10 @@ void do_priest_spell(short pc_num,eSpell spell_num,bool freebie) {
|
||||
break;
|
||||
|
||||
case eSpell::RESTORE_MIND:
|
||||
if(univ.party[target].status[eStatus::DUMB] <= 0) {
|
||||
sout << " isn't dumbfounded!";
|
||||
break;
|
||||
}
|
||||
sout << " restored.";
|
||||
r1 = 1 + get_ran(1,0,2) + adj / 2;
|
||||
univ.party[target].status[eStatus::DUMB] = max(0,univ.party[target].status[eStatus::DUMB] - r1);
|
||||
@@ -1698,12 +1702,15 @@ bool pc_can_cast_spell(short pc_num,eSpell spell_num) {
|
||||
eSkill type = (*spell_num).type;
|
||||
|
||||
level = (*spell_num).level;
|
||||
int effective_skill = univ.party[pc_num].skill(type);
|
||||
if(univ.party[pc_num].status[eStatus::DUMB] < 0)
|
||||
effective_skill -= univ.party[pc_num].status[eStatus::DUMB];
|
||||
|
||||
if(overall_mode >= MODE_TALKING)
|
||||
return false; // From Windows version. It does kinda make sense, though this function shouldn't even be called in these modes.
|
||||
if(!isMage(spell_num) && !isPriest(spell_num))
|
||||
return false;
|
||||
if(univ.party[pc_num].skill(type) < level)
|
||||
if(effective_skill < level)
|
||||
return false;
|
||||
if(univ.party[pc_num].main_status != eMainStatus::ALIVE)
|
||||
return false;
|
||||
@@ -2594,10 +2601,14 @@ bool damage_pc(short which_pc,short how_much,eDamageType damage_type,eRace type_
|
||||
how_much = 0;
|
||||
|
||||
// Mag. res helps w. fire and cold
|
||||
// TODO: Why doesn't this help with magic damage?
|
||||
if((damage_type == eDamageType::FIRE || damage_type == eDamageType::COLD) &&
|
||||
univ.party[which_pc].status[eStatus::MAGIC_RESISTANCE] > 0)
|
||||
how_much = how_much / 2;
|
||||
// TODO: Why doesn't this help with magic damage!?
|
||||
if(damage_type == eDamageType::FIRE || damage_type == eDamageType::COLD) {
|
||||
int magic_res = univ.party[which_pc].status[eStatus::MAGIC_RESISTANCE];
|
||||
if(magic_res > 0)
|
||||
how_much /= 2;
|
||||
else if(magic_res < 0)
|
||||
how_much *= 2;
|
||||
}
|
||||
|
||||
// major resistance
|
||||
if((damage_type == eDamageType::FIRE || damage_type == eDamageType::POISON || damage_type == eDamageType::MAGIC || damage_type == eDamageType::COLD)
|
||||
|
@@ -1397,7 +1397,18 @@ bool damage_monst(short which_m, short who_hit, short how_much, eDamageType dam_
|
||||
// Invulnerable?
|
||||
if(dam_type != eDamageType::SPECIAL && victim->invuln)
|
||||
how_much = how_much / 10;
|
||||
if(dam_type != eDamageType::SPECIAL && victim->status[eStatus::INVULNERABLE] > 0)
|
||||
how_much /= 10;
|
||||
|
||||
// Mag. res helps w. fire and cold
|
||||
// TODO: Why doesn't this help with magic damage!?
|
||||
if(dam_type == eDamageType::FIRE || dam_type == eDamageType::COLD) {
|
||||
int magic_res = victim->status[eStatus::MAGIC_RESISTANCE];
|
||||
if(magic_res > 0)
|
||||
how_much /= 2;
|
||||
else if(magic_res < 0)
|
||||
how_much *= 2;
|
||||
}
|
||||
|
||||
r1 = get_ran(1,0,(victim->armor * 5) / 4);
|
||||
r1 += victim->level / 4;
|
||||
|
@@ -503,6 +503,11 @@ void display_party() {
|
||||
win_draw_string(mainPtr,pc_status_rect[cur_rect],"Magic Resistant",eTextMode::WRAP,style);
|
||||
cur_rect++;
|
||||
}
|
||||
if(univ.party[i].status[eStatus::MAGIC_RESISTANCE] < 0)
|
||||
if(cur_rect <= 9) {
|
||||
win_draw_string(mainPtr,pc_status_rect[cur_rect],"Magic Vulnerable",eTextMode::WRAP,style);
|
||||
cur_rect++;
|
||||
}
|
||||
if(univ.party[i].status[eStatus::WEBS] > 0)
|
||||
if(cur_rect <= 9) {
|
||||
win_draw_string(mainPtr,pc_status_rect[cur_rect],"Webbed",eTextMode::WRAP,style);
|
||||
@@ -523,6 +528,11 @@ void display_party() {
|
||||
win_draw_string(mainPtr,pc_status_rect[cur_rect],"Dumbfounded",eTextMode::WRAP,style);
|
||||
cur_rect++;
|
||||
}
|
||||
if(univ.party[i].status[eStatus::DUMB] < 0)
|
||||
if(cur_rect <= 9) {
|
||||
win_draw_string(mainPtr,pc_status_rect[cur_rect],"Enlightened",eTextMode::WRAP,style);
|
||||
cur_rect++;
|
||||
}
|
||||
if(univ.party[i].status[eStatus::MARTYRS_SHIELD] > 0)
|
||||
if(cur_rect <= 9) {
|
||||
win_draw_string(mainPtr,pc_status_rect[cur_rect],"Martyr's Shield",eTextMode::WRAP,style);
|
||||
@@ -533,6 +543,11 @@ void display_party() {
|
||||
win_draw_string(mainPtr,pc_status_rect[cur_rect],"Asleep",eTextMode::WRAP,style);
|
||||
cur_rect++;
|
||||
}
|
||||
if(univ.party[i].status[eStatus::ASLEEP] < 0)
|
||||
if(cur_rect <= 9) {
|
||||
win_draw_string(mainPtr,pc_status_rect[cur_rect],"Hyperactive",eTextMode::WRAP,style);
|
||||
cur_rect++;
|
||||
}
|
||||
if(univ.party[i].status[eStatus::PARALYZED] > 0)
|
||||
if(cur_rect <= 9) {
|
||||
win_draw_string(mainPtr,pc_status_rect[cur_rect],"Paralyzed",eTextMode::WRAP,style);
|
||||
|
Reference in New Issue
Block a user