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:
2015-01-27 14:55:51 -05:00
parent ed84ccef19
commit 2933f1e2e7
5 changed files with 61 additions and 15 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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)

View File

@@ -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;

View File

@@ -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);