Tweak monster ability system to reduce mechanical changes relative to original BoE
This commit is contained in:
@@ -2048,13 +2048,26 @@ void do_monster_turn() {
|
||||
break; // We're looking for ranged attacks
|
||||
if(dist(cur_monst->cur_loc, targ_space) > abil.second.gen.range)
|
||||
break; // Target not in range
|
||||
if(abil.second.gen.type != eMonstGen::RAY && abil.second.gen.type != eMonstGen::BREATH
|
||||
&& monst_adjacent(targ_space, i))
|
||||
if(abil.second.gen.type == eMonstGen::SPIT && monst_adjacent(targ_space, i))
|
||||
break; // Target adjacent; prefer melee attacks
|
||||
if(get_ran(1,1,1000) >= abil.second.gen.odds)
|
||||
break;
|
||||
pick_abil = abil;
|
||||
break;
|
||||
case eMonstAbil::MISSILE_WEB:
|
||||
if(dist(cur_monst->cur_loc, targ_space) > abil.second.special.extra1)
|
||||
break; // Target not in range
|
||||
if(get_ran(1,1,1000) >= abil.second.special.extra2)
|
||||
break;
|
||||
pick_abil = abil;
|
||||
break;
|
||||
case eMonstAbil::RAY_HEAT:
|
||||
if(dist(cur_monst->cur_loc, targ_space) > abil.second.special.extra1)
|
||||
break; // Target not in range
|
||||
if(get_ran(1,1,1000) >= abil.second.special.extra2)
|
||||
break;
|
||||
pick_abil = abil;
|
||||
break;
|
||||
}
|
||||
if(pick_abil.second.active) break;
|
||||
}
|
||||
@@ -2064,16 +2077,13 @@ void do_monster_turn() {
|
||||
monst_fire_missile(i/*,cur_monst->skill*/,cur_monst->status[eStatus::BLESS_CURSE],
|
||||
pick_abil,cur_monst->cur_loc,target);
|
||||
if(pick_abil.first == eMonstAbil::MISSILE) {
|
||||
if(pick_abil.second.missile.type == eMonstMissile::ARROW || pick_abil.second.missile.type == eMonstMissile::BOLT)
|
||||
if(pick_abil.second.missile.type == eMonstMissile::ARROW || pick_abil.second.missile.type == eMonstMissile::BOLT
|
||||
|| pick_abil.second.missile.type == eMonstMissile::SPINE)
|
||||
take_m_ap(3,cur_monst);
|
||||
else take_m_ap(2,cur_monst);
|
||||
} else {
|
||||
if(pick_abil.second.gen.type == eMonstGen::BREATH)
|
||||
take_m_ap(4,cur_monst);
|
||||
else if(pick_abil.second.gen.type == eMonstGen::SPIT)
|
||||
take_m_ap(3,cur_monst);
|
||||
else take_m_ap(2,cur_monst);
|
||||
}
|
||||
} else if(pick_abil.first == eMonstAbil::RAY_HEAT)
|
||||
take_m_ap(1,cur_monst);
|
||||
else take_m_ap(3,cur_monst);
|
||||
had_monst = true;
|
||||
acted_yet = true;
|
||||
}
|
||||
@@ -2647,9 +2657,23 @@ void monst_fire_missile(short m_num,short bless,std::pair<eMonstAbil,uAbility> a
|
||||
if(target < 100) add_string_to_buf(" Misses " + univ.party[target].name + '.');
|
||||
else monst_spell_note(m_target->number,18);
|
||||
}
|
||||
} else if(abil.first == eMonstAbil::MISSILE_WEB) {
|
||||
if(target < 100) add_string_to_buf(" Throws web at " + univ.party[target].name + '.');
|
||||
else monst_spell_note(m_target->number, 58);
|
||||
run_a_missile(source, targ_space, 8, 0, 14, 0, 0, 100);
|
||||
web_space(targ_space.x, targ_space.y);
|
||||
} else if(abil.first == eMonstAbil::RAY_HEAT) {
|
||||
if(target < 100) add_string_to_buf(" Hits " + univ.party[target].name + " with heat ray!");
|
||||
else monst_spell_note(m_target->number, 55);
|
||||
run_a_missile(source, targ_space, 13, 0, 51, 0, 0, 100);
|
||||
uAbility proxy = {true};
|
||||
proxy.gen.strength = abil.second.special.extra3;
|
||||
proxy.gen.type = eMonstGen::RAY;
|
||||
proxy.gen.dmg = eDamageType::FIRE;
|
||||
monst_basic_abil(m_num, {eMonstAbil::DAMAGE, proxy}, target);
|
||||
} else {
|
||||
if(abil.first == eMonstAbil::DRAIN_SP && target < 100 && univ.party[target].cur_sp < 4) {
|
||||
// modify target is target has no sp
|
||||
// modify target if target has no sp
|
||||
for(i = 0; i < 8; i++) {
|
||||
j = get_ran(1,0,5);
|
||||
if(univ.party[j].main_status == eMainStatus::ALIVE && univ.party[j].cur_sp > 4 &&
|
||||
@@ -2667,30 +2691,23 @@ void monst_fire_missile(short m_num,short bless,std::pair<eMonstAbil,uAbility> a
|
||||
case eMonstGen::RAY:
|
||||
snd = 51;
|
||||
if(target < 100) add_string_to_buf(" Fires ray at " + univ.party[target].name + '.');
|
||||
else monst_spell_note(m_target->number, 55); // TODO: Add this note
|
||||
else monst_spell_note(m_target->number, 55);
|
||||
break;
|
||||
case eMonstGen::GAZE:
|
||||
snd = 43;
|
||||
if(target < 100) add_string_to_buf(" Gazes at " + univ.party[target].name + '.');
|
||||
else monst_spell_note(m_target->number, 56); // TODO: Add this note
|
||||
else monst_spell_note(m_target->number, 56);
|
||||
break;
|
||||
case eMonstGen::BREATH:
|
||||
snd = 44;
|
||||
if(target < 100) add_string_to_buf(" Breathes on " + univ.party[target].name + '.');
|
||||
else monst_spell_note(m_target->number, 57); // TODO: Add this note
|
||||
else monst_spell_note(m_target->number, 57);
|
||||
break;
|
||||
case eMonstGen::SPIT:
|
||||
// Special case for "spit web" -> "throws web"
|
||||
if(abil.first == eMonstAbil::FIELD && abil.second.gen.fld == eFieldType::FIELD_WEB) {
|
||||
snd = 14;
|
||||
if(target < 100) add_string_to_buf(" Throws web at " + univ.party[target].name + '.');
|
||||
else monst_spell_note(m_target->number, 58); // TODO: Add this note
|
||||
} else {
|
||||
path_type = 1;
|
||||
snd = 64;
|
||||
if(target < 100) add_string_to_buf(" Spits at " + univ.party[target].name + '.');
|
||||
else monst_spell_note(m_target->number, 59); // TODO: Add this note
|
||||
}
|
||||
path_type = 1;
|
||||
snd = 64;
|
||||
if(target < 100) add_string_to_buf(" Spits at " + univ.party[target].name + '.');
|
||||
else monst_spell_note(m_target->number, 59);
|
||||
break;
|
||||
}
|
||||
if(abil.second.gen.pic < 0) play_sound(snd);
|
||||
|
@@ -1124,6 +1124,21 @@ void monst_spell_note(mon_num_t number,short which_mess) {
|
||||
case 54:
|
||||
msg = " Throws knife at " + msg + '.';
|
||||
break;
|
||||
case 55:
|
||||
msg = " Fires ray at " + msg + '.';
|
||||
break;
|
||||
case 56:
|
||||
msg = " Gazes at " + msg + '.';
|
||||
break;
|
||||
case 57:
|
||||
msg = " Breathes on " + msg + '.';
|
||||
break;
|
||||
case 58:
|
||||
msg = " Throws web at " + msg + '.';
|
||||
break;
|
||||
case 59:
|
||||
msg = " Spits at " + msg + '.';
|
||||
break;
|
||||
}
|
||||
|
||||
if(which_mess > 0)
|
||||
|
@@ -180,8 +180,7 @@ void cMonster::addAbil(eMonstAbilTemplate what, int param) {
|
||||
abil[eMonstAbil::DRAIN_SP].gen = {true, eMonstGen::GAZE, 8, 50, 8, 625};
|
||||
break;
|
||||
case eMonstAbilTemplate::RAY_HEAT:
|
||||
abil[eMonstAbil::DAMAGE].gen = {true, eMonstGen::RAY, 13, 7, 6, 625};
|
||||
abil[eMonstAbil::DAMAGE].gen.dmg = eDamageType::FIRE;
|
||||
abil[eMonstAbil::RAY_HEAT].special = {true, 6, 625, 7};
|
||||
break;
|
||||
case eMonstAbilTemplate::RAY_PARALYSIS:
|
||||
abil[eMonstAbil::STATUS].gen = {true, eMonstGen::RAY, -1, 100, 6, 750};
|
||||
@@ -216,8 +215,7 @@ void cMonster::addAbil(eMonstAbilTemplate what, int param) {
|
||||
abil[eMonstAbil::STATUS].gen.stat = eStatus::ACID;
|
||||
break;
|
||||
case eMonstAbilTemplate::SHOOTS_WEB:
|
||||
abil[eMonstAbil::FIELD].gen = {true, eMonstGen::SPIT, 8, PAT_SINGLE, 4, 375};
|
||||
abil[eMonstAbil::FIELD].gen.fld = eFieldType::FIELD_WEB;
|
||||
abil[eMonstAbil::MISSILE_WEB].special = {true, 4, 375};
|
||||
break;
|
||||
// Touch abilities
|
||||
case eMonstAbilTemplate::TOUCH_POISON:
|
||||
@@ -600,63 +598,59 @@ std::string uAbility::to_string(eMonstAbil key) const {
|
||||
}
|
||||
break;
|
||||
case eMonstAbilCat::GENERAL:
|
||||
if(key == eMonstAbil::FIELD && gen.type == eMonstGen::SPIT && gen.fld == eFieldType::FIELD_WEB) {
|
||||
sout << "Throws webs";
|
||||
} else {
|
||||
switch(key) {
|
||||
case eMonstAbil::STUN: sout << "Stunning"; break;
|
||||
case eMonstAbil::PETRIFY: sout << "Petrifying"; break;
|
||||
case eMonstAbil::DRAIN_SP: sout << "Spell point drain"; break;
|
||||
case eMonstAbil::DRAIN_XP: sout << "Experience drain"; break;
|
||||
case eMonstAbil::KILL: sout << "Death"; break;
|
||||
case eMonstAbil::STEAL_FOOD: sout << "Steals food"; break;
|
||||
case eMonstAbil::STEAL_GOLD: sout << "Steals gold!"; break;
|
||||
case eMonstAbil::FIELD:
|
||||
switch(gen.fld) {
|
||||
case eFieldType::CLOUD_SLEEP: sout << "Sleep"; break;
|
||||
case eFieldType::CLOUD_STINK: sout << "Foul"; break;
|
||||
case eFieldType::WALL_FIRE: sout << "Fiery"; break;
|
||||
case eFieldType::WALL_FORCE: sout << "Charged"; break;
|
||||
case eFieldType::WALL_ICE: sout << "Frosted"; break;
|
||||
case eFieldType::WALL_BLADES: sout << "Thorny"; break;
|
||||
case eFieldType::FIELD_ANTIMAGIC: sout << "Null"; break;
|
||||
case eFieldType::FIELD_WEB: sout << "Web"; break;
|
||||
case eFieldType::FIELD_QUICKFIRE: sout << "Incendiary"; break;
|
||||
}
|
||||
break;
|
||||
case eMonstAbil::DAMAGE:
|
||||
switch(gen.dmg) {
|
||||
case eDamageType::FIRE: sout << "Heat"; break;
|
||||
case eDamageType::COLD: sout << "Icy"; break;
|
||||
case eDamageType::MAGIC: sout << "Shock"; break;
|
||||
case eDamageType::UNBLOCKABLE: sout << "Wounding"; break;
|
||||
case eDamageType::POISON: sout << "Pain"; break;
|
||||
case eDamageType::WEAPON: sout << "Stamina drain"; break;
|
||||
case eDamageType::DEMON: sout << "Unholy"; break;
|
||||
case eDamageType::UNDEAD: sout << "Necrotic"; break;
|
||||
}
|
||||
break;
|
||||
case eMonstAbil::STATUS: case eMonstAbil::STATUS2:
|
||||
switch(gen.stat) {
|
||||
case eStatus::POISON: sout << "Poison"; break;
|
||||
case eStatus::DISEASE: sout << "Infectious"; break;
|
||||
case eStatus::DUMB: sout << "Dumbfounding"; break;
|
||||
case eStatus::WEBS: sout << "Glue"; break;
|
||||
case eStatus::ASLEEP: sout << "Sleep"; break;
|
||||
case eStatus::PARALYZED: sout << "Paralysis"; break;
|
||||
case eStatus::ACID: sout << "Acid"; break;
|
||||
case eStatus::HASTE_SLOW: sout << "Slowing"; break;
|
||||
case eStatus::BLESS_CURSE: sout << "Curse"; break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
switch(gen.type) {
|
||||
case eMonstGen::RAY: sout << " ray"; break;
|
||||
case eMonstGen::TOUCH: sout << " touch"; break;
|
||||
case eMonstGen::GAZE: sout << " gaze"; break;
|
||||
case eMonstGen::BREATH: sout << " breath"; break;
|
||||
case eMonstGen::SPIT: sout << " spit"; break;
|
||||
}
|
||||
switch(key) {
|
||||
case eMonstAbil::STUN: sout << "Stunning"; break;
|
||||
case eMonstAbil::PETRIFY: sout << "Petrifying"; break;
|
||||
case eMonstAbil::DRAIN_SP: sout << "Spell point drain"; break;
|
||||
case eMonstAbil::DRAIN_XP: sout << "Experience drain"; break;
|
||||
case eMonstAbil::KILL: sout << "Death"; break;
|
||||
case eMonstAbil::STEAL_FOOD: sout << "Steals food"; break;
|
||||
case eMonstAbil::STEAL_GOLD: sout << "Steals gold!"; break;
|
||||
case eMonstAbil::FIELD:
|
||||
switch(gen.fld) {
|
||||
case eFieldType::CLOUD_SLEEP: sout << "Sleep"; break;
|
||||
case eFieldType::CLOUD_STINK: sout << "Foul"; break;
|
||||
case eFieldType::WALL_FIRE: sout << "Fiery"; break;
|
||||
case eFieldType::WALL_FORCE: sout << "Charged"; break;
|
||||
case eFieldType::WALL_ICE: sout << "Frosted"; break;
|
||||
case eFieldType::WALL_BLADES: sout << "Thorny"; break;
|
||||
case eFieldType::FIELD_ANTIMAGIC: sout << "Null"; break;
|
||||
case eFieldType::FIELD_WEB: sout << "Web"; break;
|
||||
case eFieldType::FIELD_QUICKFIRE: sout << "Incendiary"; break;
|
||||
}
|
||||
break;
|
||||
case eMonstAbil::DAMAGE:
|
||||
switch(gen.dmg) {
|
||||
case eDamageType::FIRE: sout << "Heat"; break;
|
||||
case eDamageType::COLD: sout << "Icy"; break;
|
||||
case eDamageType::MAGIC: sout << "Shock"; break;
|
||||
case eDamageType::UNBLOCKABLE: sout << "Wounding"; break;
|
||||
case eDamageType::POISON: sout << "Pain"; break;
|
||||
case eDamageType::WEAPON: sout << "Stamina drain"; break;
|
||||
case eDamageType::DEMON: sout << "Unholy"; break;
|
||||
case eDamageType::UNDEAD: sout << "Necrotic"; break;
|
||||
}
|
||||
break;
|
||||
case eMonstAbil::STATUS: case eMonstAbil::STATUS2:
|
||||
switch(gen.stat) {
|
||||
case eStatus::POISON: sout << "Poison"; break;
|
||||
case eStatus::DISEASE: sout << "Infectious"; break;
|
||||
case eStatus::DUMB: sout << "Dumbfounding"; break;
|
||||
case eStatus::WEBS: sout << "Glue"; break;
|
||||
case eStatus::ASLEEP: sout << "Sleep"; break;
|
||||
case eStatus::PARALYZED: sout << "Paralysis"; break;
|
||||
case eStatus::ACID: sout << "Acid"; break;
|
||||
case eStatus::HASTE_SLOW: sout << "Slowing"; break;
|
||||
case eStatus::BLESS_CURSE: sout << "Curse"; break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
switch(gen.type) {
|
||||
case eMonstGen::RAY: sout << " ray"; break;
|
||||
case eMonstGen::TOUCH: sout << " touch"; break;
|
||||
case eMonstGen::GAZE: sout << " gaze"; break;
|
||||
case eMonstGen::BREATH: sout << " breath"; break;
|
||||
case eMonstGen::SPIT: sout << " spit"; break;
|
||||
}
|
||||
if(key == eMonstAbil::DAMAGE) {
|
||||
sout << " (" << gen.strength << ")";
|
||||
@@ -700,6 +694,12 @@ std::string uAbility::to_string(eMonstAbil key) const {
|
||||
case eMonstAbil::ABSORB_SPELLS:
|
||||
sout << "Absorbs spells";
|
||||
break;
|
||||
case eMonstAbil::MISSILE_WEB:
|
||||
sout << "Throws webs";
|
||||
break;
|
||||
case eMonstAbil::RAY_HEAT:
|
||||
sout << "Heat ray (" << special.extra3 << "d6)";
|
||||
break;
|
||||
case eMonstAbil::SPECIAL:
|
||||
case eMonstAbil::DEATH_TRIGGER:
|
||||
sout << "Unusual ability";
|
||||
|
@@ -103,7 +103,7 @@ union uAbility {
|
||||
} radiate;
|
||||
struct {
|
||||
bool active;
|
||||
int extra1, extra2;
|
||||
int extra1, extra2, extra3;
|
||||
} special;
|
||||
std::string to_string(eMonstAbil myKey) const;
|
||||
};
|
||||
|
@@ -151,6 +151,8 @@ enum class eMonstAbil {
|
||||
SPLITS,
|
||||
MARTYRS_SHIELD,
|
||||
ABSORB_SPELLS,
|
||||
MISSILE_WEB,
|
||||
RAY_HEAT,
|
||||
SPECIAL,
|
||||
DEATH_TRIGGER,
|
||||
|
||||
|
Reference in New Issue
Block a user