Make monster resistances a percentage and update monster info dialog

- Fix monster roster menu not working
This commit is contained in:
2015-01-17 18:48:10 -05:00
parent cdeb02c214
commit 3852ca37cd
7 changed files with 92 additions and 178 deletions

View File

@@ -384,7 +384,8 @@ static void put_monst_info(cDialog& me, const cCreature& store_m) {
i = 1;
for(auto& abil : store_m.abil) {
if(i > 2) break; // TODO: Support showing more than just the first two abilities
if(i > 4) break; // TODO: Support showing more than just the first four abilities
if(!abil.second.active) continue;
std::string id = "abil" + std::to_string(i);
me[id].setText(abil.second.to_string(abil.first));
i++;
@@ -411,14 +412,13 @@ static void put_monst_info(cDialog& me, const cCreature& store_m) {
me["mage"].setTextToNum(store_m.mu);
me["priest"].setTextToNum(store_m.cl);
// Immunities
dynamic_cast<cLed&>(me["magic-res"]).setState(store_m.magic_res == RESIST_HALF ? led_red : led_off);
dynamic_cast<cLed&>(me["magic-imm"]).setState(store_m.magic_res == RESIST_ALL ? led_red : led_off);
dynamic_cast<cLed&>(me["fire-res"]).setState(store_m.fire_res == RESIST_HALF ? led_red : led_off);
dynamic_cast<cLed&>(me["fire-imm"]).setState(store_m.fire_res == RESIST_ALL ? led_red : led_off);
dynamic_cast<cLed&>(me["cold-res"]).setState(store_m.cold_res == RESIST_HALF ? led_red : led_off);
dynamic_cast<cLed&>(me["cold-imm"]).setState(store_m.cold_res == RESIST_ALL ? led_red : led_off);
dynamic_cast<cLed&>(me["poison-res"]).setState(store_m.poison_res == RESIST_HALF ? led_red : led_off);
dynamic_cast<cLed&>(me["poison-imm"]).setState(store_m.poison_res == RESIST_ALL ? led_red : led_off);
me["magic-res"].setText(std::to_string(100 - store_m.magic_res) + '%');
me["fire-res"].setText(std::to_string(100 - store_m.fire_res) + '%');
me["cold-res"].setText(std::to_string(100 - store_m.cold_res) + '%');
me["poison-res"].setText(std::to_string(100 - store_m.poison_res) + '%');
dynamic_cast<cLed&>(me["mindless"]).setState(store_m.mindless ? led_red : led_off);
dynamic_cast<cLed&>(me["invuln"]).setState(store_m.invuln ? led_red : led_off);
dynamic_cast<cLed&>(me["guard"]).setState(store_m.guard ? led_red : led_off);
}
@@ -446,6 +446,7 @@ static bool display_monst_event_filter(cDialog& me, std::string item_hit, cCreat
if(roster[position % 60].number != on_monst_menu[position]) {
cMonster& monst = univ.scenario.scen_monsters[on_monst_menu[position]];
roster.assign(position % 60, cCreature(on_monst_menu[position]), monst, PSD[SDF_EASY_MODE], univ.difficulty_adjust());
store_m = roster[position % 60];
}
put_monst_info(me, store_m);
return true;
@@ -468,8 +469,7 @@ void display_monst(short array_pos,cCreature *which_m,short mode) {
monstInfo["done"].attachClickHandler(std::bind(&cDialog::toast, &monstInfo, true));
monstInfo.attachClickHandlers(event_filter, {"left", "right"});
// Also add the click handler to the LEDs to suppress normal LED behaviour
monstInfo.attachClickHandlers(event_filter, {"immune1", "immune2", "immune3", "immune4"});
monstInfo.attachClickHandlers(event_filter, {"immune5", "immune6", "immune7", "immune8"});
monstInfo.attachClickHandlers(event_filter, {"guard", "mindless", "invuln"});
if(full_roster) {
// This is a bit hacky - call event handler with dummy ID to ensure the monster details are correctly populated.
@@ -478,32 +478,6 @@ void display_monst(short array_pos,cCreature *which_m,short mode) {
monstInfo["left"].hide();
monstInfo["right"].hide();
}
// TODO: Put these labels in the XML definition
monstInfo.addLabelFor("name", "Name", LABEL_LEFT, 26, true);
monstInfo.addLabelFor("lvl", "Level", LABEL_LEFT, 21, true);
monstInfo.addLabelFor("hp", "Health", LABEL_LEFT, 24, true);
monstInfo.addLabelFor("sp", "Magic Pts.", LABEL_LEFT, 32, true);
monstInfo.addLabelFor("def", "Armor", LABEL_LEFT, 23, true);
monstInfo.addLabelFor("skill", "Skill", LABEL_LEFT, 18, true);
monstInfo.addLabelFor("morale", "Morale", LABEL_LEFT, 23, true);
monstInfo.addLabelFor("ap", "Speed", LABEL_LEFT, 19, true);
monstInfo.addLabelFor("attack1", "Att #1", LABEL_LEFT, 26, true);
monstInfo.addLabelFor("attack2", "Att #2", LABEL_LEFT, 23, true);
monstInfo.addLabelFor("attack3", "Att #3", LABEL_LEFT, 22, true);
monstInfo.addLabelFor("mage", "Mage L.", LABEL_LEFT, 34, true);
monstInfo.addLabelFor("priest", "Priest L.", LABEL_LEFT, 30, true);
monstInfo.addLabelFor("poison", "Poison", LABEL_LEFT, 23, true);
monstInfo.addLabelFor("abil1", "Ability 1", LABEL_LEFT, 29, true);
monstInfo.addLabelFor("abil2", "Ability 2", LABEL_LEFT, 29, true);
// TODO: These could be the actual content text instead of a label, maybe?
monstInfo.addLabelFor("immune1", "Magic Resistant", LABEL_LEFT, 45, false);
monstInfo.addLabelFor("immune2", "Immune To Magic", LABEL_LEFT, 45, false);
monstInfo.addLabelFor("immune3", "Fire Resistant", LABEL_LEFT, 45, false);
monstInfo.addLabelFor("immune4", "Immune To Fire", LABEL_LEFT, 45, false);
monstInfo.addLabelFor("immune5", "Cold Resistant", LABEL_LEFT, 45, false);
monstInfo.addLabelFor("immune6", "Immune To Cold", LABEL_LEFT, 45, false);
monstInfo.addLabelFor("immune7", "Poison Resistant", LABEL_LEFT, 45, false);
monstInfo.addLabelFor("immune8", "Immune To Poison", LABEL_LEFT, 45, false);
put_monst_info(monstInfo, store_m);
monstInfo.run();

View File

@@ -297,34 +297,32 @@ bool monst_hate_spot(short which_m,location *good_loc) {
else if(univ.town.is_ice_wall(loc.x,loc.y)) {
hate_spot = true;
if(have_radiate && which_radiate == eFieldType::WALL_ICE) hate_spot = false;
else if(univ.town.monst[which_m].cold_res == RESIST_ALL) hate_spot = false;
else if(univ.town.monst[which_m].cold_res == 0) hate_spot = false;
}
// Hate fire wall?
else if(univ.town.is_fire_wall(loc.x,loc.y)) {
hate_spot = true;
if(have_radiate && which_radiate == eFieldType::WALL_FIRE) hate_spot = false;
else if(univ.town.monst[which_m].fire_res == RESIST_ALL) hate_spot = false;
else if(univ.town.monst[which_m].fire_res == 0) hate_spot = false;
}
// Note: Monsters used to enter shock walls even if they were merely resistant to magic
// Hate shock wall?
else if(univ.town.is_force_wall(loc.x,loc.y)) {
hate_spot = true;
if(have_radiate && which_radiate == eFieldType::WALL_FORCE) hate_spot = false;
else if(univ.town.monst[which_m].magic_res == RESIST_ALL) hate_spot = false;
else if(univ.town.monst[which_m].magic_res == 0) hate_spot = false;
}
// Hate stink cloud?
else if(univ.town.is_scloud(loc.x,loc.y)) {
hate_spot = true;
if(have_radiate && which_radiate == eFieldType::CLOUD_STINK) hate_spot = false;
else if(univ.town.monst[which_m].magic_res == RESIST_ALL) hate_spot = false;
else if(univ.town.monst[which_m].magic_res == RESIST_HALF) hate_spot = false;
else if(univ.town.monst[which_m].magic_res <= 50) hate_spot = false;
}
// Hate sleep cloud?
else if(univ.town.is_sleep_cloud(loc.x,loc.y)) {
hate_spot = true;
if(have_radiate && which_radiate == eFieldType::CLOUD_SLEEP) hate_spot = false;
else if(univ.town.monst[which_m].magic_res == RESIST_ALL) hate_spot = false;
else if(univ.town.monst[which_m].magic_res == RESIST_HALF) hate_spot = false;
else if(univ.town.monst[which_m].magic_res <= 50) hate_spot = false;
}
// Hate antimagic?
else if(univ.town.is_antimagic(loc.x,loc.y)) {
@@ -1056,13 +1054,13 @@ bool monst_check_special_terrain(location where_check,short mode,short which_mon
case eTerSpec::DAMAGING: // TODO: Update this to check other cases
switch(eDamageType(ter_flag)) {
case eDamageType::FIRE:
return univ.town.monst[which_monst].fire_res == RESIST_ALL;
return univ.town.monst[which_monst].fire_res == 0;
case eDamageType::COLD:
return univ.town.monst[which_monst].cold_res == RESIST_ALL;
return univ.town.monst[which_monst].cold_res == 0;
case eDamageType::MAGIC:
return univ.town.monst[which_monst].magic_res == RESIST_ALL;
return univ.town.monst[which_monst].magic_res == 0;
case eDamageType::POISON:
return univ.town.monst[which_monst].poison_res == RESIST_ALL;
return univ.town.monst[which_monst].poison_res == 0;
default:
return univ.town.monst[which_monst].invuln;
}
@@ -1108,32 +1106,14 @@ void magic_adjust(cCreature *which_m,short *how_much) {
which_m->health = 32767;
else which_m->health += 3;
}
switch(which_m->magic_res) {
case RESIST_HALF:
*how_much /= 2;
break;
case RESIST_ALL:
*how_much = 0;
break;
case RESIST_DOUBLE:
*how_much *= 2;
break;
}
*how_much *= which_m->magic_res;
*how_much /= 100;
}
void poison_monst(cCreature *which_m,short how_much) {
if(how_much > 0) {
switch(which_m->poison_res) {
case RESIST_HALF:
how_much /= 2;
break;
case RESIST_ALL:
monst_spell_note(which_m->number,10);
return;
case RESIST_DOUBLE:
how_much *= 2;
break;
}
how_much *= which_m->poison_res;
how_much /= 100;
}
which_m->status[eStatus::POISON] = min(8, which_m->status[eStatus::POISON] + how_much);
if(how_much >= 0)
@@ -1225,17 +1205,10 @@ void charm_monst(cCreature *which_m,short penalty,eStatus which_status,short amo
which_m->m_type == eRace::STONE || which_m->m_type == eRace::PLANT))
return;
r1 = get_ran(1,1,100);
switch(which_m->magic_res) {
case RESIST_HALF:
r1 *= 2;
break;
case RESIST_ALL:
r1 = 200;
break;
case RESIST_DOUBLE:
r1 /= 2;
break;
}
if(which_m->magic_res > 0) {
r1 *= 100;
r1 /= which_m->magic_res;
} else r1 = 200;
r1 += penalty;
if(which_status == eStatus::ASLEEP)
r1 -= 25;

View File

@@ -1413,56 +1413,20 @@ bool damage_monst(short which_m, short who_hit, short how_much, short how_much_s
victim = &univ.town.monst[which_m];
if(dam_type == eDamageType::MAGIC) {
switch(victim->magic_res) {
case RESIST_HALF:
how_much /= 2;
break;
case RESIST_ALL:
how_much = 0;
break;
case RESIST_DOUBLE:
how_much *= 2;
break;
}
how_much *= victim->magic_res;
how_much /= 100;
}
if(dam_type == eDamageType::FIRE) {
switch(victim->fire_res) {
case RESIST_HALF:
how_much /= 2;
break;
case RESIST_ALL:
how_much = 0;
break;
case RESIST_DOUBLE:
how_much *= 2;
break;
}
how_much *= victim->fire_res;
how_much /= 100;
}
if(dam_type == eDamageType::COLD) {
switch(victim->cold_res) {
case RESIST_HALF:
how_much /= 2;
break;
case RESIST_ALL:
how_much = 0;
break;
case RESIST_DOUBLE:
how_much *= 2;
break;
}
how_much *= victim->cold_res;
how_much /= 100;
}
if(dam_type == eDamageType::POISON) {
switch(victim->poison_res) {
case RESIST_HALF:
how_much /= 2;
break;
case RESIST_ALL:
how_much = 0;
break;
case RESIST_DOUBLE:
how_much *= 2;
break;
}
how_much *= victim->poison_res;
how_much /= 100;
}
// Absorb damage?
@@ -1602,7 +1566,8 @@ void petrify_monst(cCreature* m_target, short strength) {
r1 += m_target->status[eStatus::BLESS_CURSE];
r1 -= strength;
if(r1 > 14 || m_target->magic_res == RESIST_ALL)
// TODO: This should probably do something similar to charm_monst with the magic resistance
if(r1 > 14 || m_target->magic_res == 0)
monst_spell_note(m_target->number,10);
else {
monst_spell_note(m_target->number,8);

View File

@@ -105,21 +105,25 @@ void cMonster::append(legacy::monster_record_type& old){
corpse_item = old.corpse_item;
corpse_item_chance = old.corpse_item_chance;
if(old.immunities & 2)
magic_res = RESIST_ALL;
magic_res = 0;
else if(old.immunities & 1)
magic_res = RESIST_HALF;
magic_res = 50;
else magic_res = 100;
if(old.immunities & 8)
fire_res = RESIST_ALL;
fire_res = 0;
else if(old.immunities & 4)
fire_res = RESIST_HALF;
fire_res = 50;
else fire_res = 100;
if(old.immunities & 32)
cold_res = RESIST_ALL;
cold_res = 0;
else if(old.immunities & 16)
cold_res = RESIST_HALF;
cold_res = 50;
else cold_res = 100;
if(old.immunities & 128)
poison_res = RESIST_ALL;
poison_res = 0;
else if(old.immunities & 64)
poison_res = RESIST_HALF;
poison_res = 50;
else poison_res = 100;
x_width = old.x_width;
y_width = old.y_width;
default_attitude = old.default_attitude;
@@ -143,7 +147,7 @@ void cMonster::addAbil(eMonstAbilTemplate what, int param) {
abil[eMonstAbil::MISSILE].missile = {true, eMonstMissile::ARROW, 3, 2, 7, 4, 8, 750};
break;
case eMonstAbilTemplate::THROWS_SPEARS:
abil[eMonstAbil::MISSILE].missile = {true, eMonstMissile::ARROW, 5, 3, 7, 6, 8, 625};
abil[eMonstAbil::MISSILE].missile = {true, eMonstMissile::SPEAR, 5, 3, 7, 6, 8, 625};
break;
case eMonstAbilTemplate::THROWS_ROCKS1:
abil[eMonstAbil::MISSILE].missile = {true, eMonstMissile::ROCK, 12, 4, 7, 8, 10, 625};
@@ -365,6 +369,7 @@ void cMonster::addAbil(eMonstAbilTemplate what, int param) {
}
cMonster::cMonster(){
magic_res = poison_res = fire_res = cold_res = 100;
// TODO: Fill in
see_str1 = -1;
see_str2 = -1;
@@ -812,14 +817,9 @@ void cMonster::readFrom(std::istream& file) {
line >> temp1 >> temp2;
x_width = temp1;
y_width = temp2;
} else if(cur == "IMMUNE") {
line >> temp1 >> temp2;
magic_res = temp1;
fire_res = temp2;
line >> temp1 >> temp2;
cold_res = temp1;
poison_res = temp2;
} else if(cur == "RACE")
} else if(cur == "IMMUNE")
line >> magic_res >> fire_res >> cold_res >> poison_res;
else if(cur == "RACE")
line >> m_type;
else if(cur == "CORPSEITEM")
line >> corpse_item >> corpse_item_chance;

View File

@@ -70,8 +70,6 @@ inline eDirection& operator++ (eDirection& me, int) {
else return me = (eDirection)(1 + (int)me);
}
enum eResistType {RESIST_NONE, RESIST_HALF, RESIST_ALL, RESIST_DOUBLE};
union uAbility {
bool active;
struct {
@@ -128,10 +126,10 @@ public:
std::map<eMonstAbil, uAbility> abil;
item_num_t corpse_item;
short corpse_item_chance;
unsigned int magic_res : 2;
unsigned int fire_res : 2;
unsigned int cold_res : 2;
unsigned int poison_res : 2;
unsigned int magic_res;
unsigned int fire_res;
unsigned int cold_res;
unsigned int poison_res;
bool mindless : 1;
bool invuln : 1;
bool invisible : 1;

View File

@@ -578,15 +578,6 @@ static void put_monst_abils_in_dlog(cDialog& me, cMonster& store_monst, short wh
me["loot-chance"].setTextToNum(store_monst.corpse_item_chance);
dynamic_cast<cLedGroup&>(me["summon"]).setSelected("s" + boost::lexical_cast<std::string,short>(store_monst.summon_type));
dynamic_cast<cLed&>(me["magic-res"]).setState(store_monst.magic_res == RESIST_HALF ? led_red : led_off);
dynamic_cast<cLed&>(me["magic-imm"]).setState(store_monst.magic_res == RESIST_ALL ? led_red : led_off);
dynamic_cast<cLed&>(me["fire-res"]).setState(store_monst.fire_res == RESIST_HALF ? led_red : led_off);
dynamic_cast<cLed&>(me["fire-imm"]).setState(store_monst.fire_res == RESIST_ALL ? led_red : led_off);
dynamic_cast<cLed&>(me["cold-res"]).setState(store_monst.cold_res == RESIST_HALF ? led_red : led_off);
dynamic_cast<cLed&>(me["cold-imm"]).setState(store_monst.cold_res == RESIST_ALL ? led_red : led_off);
dynamic_cast<cLed&>(me["poison-res"]).setState(store_monst.poison_res == RESIST_HALF ? led_red : led_off);
dynamic_cast<cLed&>(me["poison-imm"]).setState(store_monst.poison_res == RESIST_ALL ? led_red : led_off);
}
static bool save_monst_abils(cDialog& me, cMonster& store_monst) {
@@ -594,14 +585,6 @@ static bool save_monst_abils(cDialog& me, cMonster& store_monst) {
store_monst.corpse_item = me["loot-item"].getTextAsNum();
store_monst.corpse_item_chance = me["loot-chance"].getTextAsNum();
if(dynamic_cast<cLed&>(me["magic-res"]).getState() != led_off) store_monst.magic_res = RESIST_HALF;
if(dynamic_cast<cLed&>(me["magic-imm"]).getState() != led_off) store_monst.magic_res = RESIST_ALL;
if(dynamic_cast<cLed&>(me["fire-res"]).getState() != led_off) store_monst.fire_res = RESIST_HALF;
if(dynamic_cast<cLed&>(me["fire-imm"]).getState() != led_off) store_monst.fire_res = RESIST_ALL;
if(dynamic_cast<cLed&>(me["cold-res"]).getState() != led_off) store_monst.cold_res = RESIST_HALF;
if(dynamic_cast<cLed&>(me["cold-imm"]).getState() != led_off) store_monst.cold_res = RESIST_ALL;
if(dynamic_cast<cLed&>(me["poison-res"]).getState() != led_off) store_monst.poison_res = RESIST_HALF;
if(dynamic_cast<cLed&>(me["poison-imm"]).getState() != led_off) store_monst.poison_res = RESIST_ALL;
return true;
}