Rework spell notes and several other common messages.

* Spell notes are now an enum instead of a magic integer.
* The functions are now defined in iLiving instead of cCreature, meaning they can be called on PCs.
* They now use fmtlib to interpolate the name.
* A creature attacking themself now prints "Name attacks themself" instead of "Name attacks Name".
This commit is contained in:
2025-08-02 22:50:46 -04:00
committed by Celtic Minstrel
parent a4b30a9843
commit 7451e25739
12 changed files with 327 additions and 306 deletions

View File

@@ -2156,7 +2156,7 @@ void do_monster_turn() {
if(cur_monst->summon_time == 1) {
cur_monst->active = eCreatureStatus::DEAD;
cur_monst->ap = 0;
cur_monst->spell_note(17);
cur_monst->spell_note(eSpellNote::DISAPPEARS);
}
move_to_zero(cur_monst->summon_time);
}
@@ -2529,7 +2529,7 @@ void do_monster_turn() {
if(what_summon) r1 = get_ran(1, abil.summon.min, abil.summon.max);
else r1 = 0;
if(r1 && summon_monster(what_summon, cur_monst->cur_loc,abil.summon.len,cur_monst->attitude,cur_monst->is_friendly())) {
cur_monst->spell_note(33);
cur_monst->spell_note(eSpellNote::SUMMONS);
play_sound(61);
bool failed = false;
while(--r1 && !failed) {
@@ -2578,7 +2578,7 @@ void do_monster_turn() {
}
if(cur_monst->status[eStatus::ASLEEP] == 1)
cur_monst->spell_note(29);
cur_monst->spell_note(eSpellNote::AWAKE);
move_to_zero(cur_monst->status[eStatus::ASLEEP]);
move_to_zero(cur_monst->status[eStatus::PARALYZED]);
move_to_zero(cur_monst->status[eStatus::INVISIBLE]);
@@ -2660,7 +2660,7 @@ void monster_attack(short who_att,iLiving* target) {
for(const auto& att : attacker->a)
if(att.dice != 0) {
attacker->print_attacks(target);
attacker->print_attacks(*target);
break;
}
@@ -2903,44 +2903,44 @@ void monst_fire_missile(short m_num,short bless,std::pair<eMonstAbil,uAbility> a
if(pc_target != nullptr)
add_string_to_buf(" Shoots at " + pc_target->name + '.');
else if(m_target != nullptr)
m_target->spell_note(12);
m_target->spell_note(eSpellNote::SHOOTS);
break;
case eMonstMissile::SPEAR:
if(pc_target != nullptr)
add_string_to_buf(" Throws spear at " + pc_target->name + '.');
else if(m_target != nullptr)
m_target->spell_note(13);
m_target->spell_note(eSpellNote::THROWS_SPEAR);
break;
case eMonstMissile::RAZORDISK:
if(pc_target != nullptr)
add_string_to_buf(" Throws razordisk at " + pc_target->name + '.');
else if(m_target != nullptr)
m_target->spell_note(15);
m_target->spell_note(eSpellNote::THROWS_RAZORDISK);
break;
case eMonstMissile::SPINE:
if(pc_target != nullptr)
add_string_to_buf(" Fires spines at " + pc_target->name + '.');
else if(m_target != nullptr)
m_target->spell_note(32);
m_target->spell_note(eSpellNote::SPINES);
break;
case eMonstMissile::DART:
if(pc_target != nullptr)
add_string_to_buf(" Throws dart at " + pc_target->name + '.');
else if(m_target != nullptr)
m_target->spell_note(53);
m_target->spell_note(eSpellNote::THROWS_DART);
break;
case eMonstMissile::ROCK:
case eMonstMissile::BOULDER:
if(pc_target != nullptr)
add_string_to_buf(" Throws rock at " + pc_target->name + '.');
else if(m_target != nullptr)
m_target->spell_note(14);
m_target->spell_note(eSpellNote::THROWS_ROCK);
break;
case eMonstMissile::KNIFE:
if(pc_target != nullptr)
add_string_to_buf(" Throws knife at " + pc_target->name + '.');
else if(m_target != nullptr)
m_target->spell_note(54);
m_target->spell_note(eSpellNote::THROWS_KNIFE);
break;
}
if(abil.second.missile.type == eMonstMissile::ARROW || abil.second.missile.type == eMonstMissile::RAPID_ARROW || abil.second.missile.type == eMonstMissile::BOLT)
@@ -2972,14 +2972,14 @@ void monst_fire_missile(short m_num,short bless,std::pair<eMonstAbil,uAbility> a
// TODO: Should we pass in the monster's actual race here?
damage_pc(*pc_target,r2,eDamageType::WEAPON,eRace::UNKNOWN,13);
} else if(m_target != nullptr) {
m_target->spell_note(16);
m_target->spell_note(eSpellNote::HITS);
damage_monst(*m_target,7,r2,eDamageType::WEAPON,13);
}
} else {
if(pc_target != nullptr)
add_string_to_buf(" Misses " + pc_target->name + '.');
else if(m_target != nullptr)
m_target->spell_note(18);
m_target->spell_note(eSpellNote::MISSES);
}
if(pc_target != nullptr) {
if(cInvenSlot spec_item = pc_target->has_abil_equip(eItemAbil::HIT_CALL_SPECIAL)) {
@@ -3005,13 +3005,13 @@ void monst_fire_missile(short m_num,short bless,std::pair<eMonstAbil,uAbility> a
if(pc_target != nullptr)
add_string_to_buf(" Throws web at " + pc_target->name + '.');
else if(m_target != nullptr)
m_target->spell_note(58);
m_target->spell_note(eSpellNote::THROWS_WEB);
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(pc_target != nullptr) add_string_to_buf(" Hits " + pc_target->name + " with heat ray!");
else if(m_target != nullptr)
m_target->spell_note(55);
m_target->spell_note(eSpellNote::FIRES_RAY);
run_a_missile(source, targ_space, 13, 0, 51, 0, 0, 100);
uAbility proxy = {true};
proxy.gen.strength = abil.second.special.extra3;
@@ -3063,21 +3063,21 @@ void monst_fire_missile(short m_num,short bless,std::pair<eMonstAbil,uAbility> a
if(pc_target != nullptr)
add_string_to_buf(" Fires ray at " + pc_target->name + '.');
else if(m_target != nullptr)
m_target->spell_note(55);
m_target->spell_note(eSpellNote::FIRES_RAY);
break;
case eMonstGen::GAZE:
snd = 43;
if(pc_target != nullptr)
add_string_to_buf(" Gazes at " + pc_target->name + '.');
else if(m_target != nullptr)
m_target->spell_note(56);
m_target->spell_note(eSpellNote::GAZES2);
break;
case eMonstGen::BREATH:
snd = 44;
if(pc_target != nullptr)
add_string_to_buf(" Breathes on " + pc_target->name + '.');
else if(m_target != nullptr)
m_target->spell_note(57);
m_target->spell_note(eSpellNote::BREATHES_ON);
break;
case eMonstGen::SPIT:
path_type = 1;
@@ -3085,7 +3085,7 @@ void monst_fire_missile(short m_num,short bless,std::pair<eMonstAbil,uAbility> a
if(pc_target != nullptr)
add_string_to_buf(" Spits at " + pc_target->name + '.');
else if(m_target != nullptr)
m_target->spell_note(59);
m_target->spell_note(eSpellNote::SPITS);
break;
}
if(abil.second.gen.pic < 0) play_sound(snd);
@@ -3188,7 +3188,7 @@ void monst_basic_abil(short m_num, std::pair<eMonstAbil,uAbility> abil, iLiving*
add_string_to_buf(" Drains " + pc_target->name + '.');
pc_target->cur_sp = percent(pc_target->cur_sp, abil.second.gen.strength);
} else {
m_target->spell_note(11);
m_target->spell_note(eSpellNote::DRAINS);
// TODO: If mp < 4 it used to set monster's skill to 1. Should that be restored?
m_target->mp = percent(m_target->mp, abil.second.gen.strength);
}
@@ -3246,7 +3246,7 @@ bool monst_breathe(cCreature *caster,location targ_space,uAbility abil) {
run_a_missile(l,targ_space,abil.gen.pic,0,44,0,0,100);
else play_sound(44);
caster->breathe_note();
caster->spell_note(eSpellNote::BREATHES);
short level = get_ran(abil.gen.strength,1,8);
if(!is_combat())
level = level / 3;
@@ -3873,7 +3873,7 @@ bool monst_cast_priest(cCreature *caster,short targ) {
break;
case eSpell::AVATAR:
play_sound(24);
caster->spell_note(26);
caster->spell_note(eSpellNote::AVATAR);
caster->avatar();
break;
case eSpell::DIVINE_THUD:
@@ -5121,7 +5121,7 @@ void process_force_cage(location loc, short i, short adjust) {
if(!which_m.is_friendly() && get_ran(1,1,100) < which_m.mu * 10 + which_m.cl * 4 + 5 + adjust) {
// TODO: This sound is not right
play_sound(60);
which_m.spell_note(50);
which_m.spell_note(eSpellNote::BREAKS_FORCECAGE);
break_force_cage(loc);
}
} else if(i < 0) {

View File

@@ -850,7 +850,7 @@ void monst_inflict_fields(short which_monst) {
break;
}
if(univ.town.is_web(where_check.x,where_check.y) && which_m->m_type != eRace::BUG) {
which_m->spell_note(19);
which_m->spell_note(eSpellNote::WEBBED);
r1 = get_ran(1,2,3);
which_m->web(r1);
univ.town.set_web(where_check.x,where_check.y,false);
@@ -967,7 +967,7 @@ static bool monst_check_one_special_terrain(location where_check,short mode,shor
// Monster breaks the barrier
// TODO: Are these barrier sounds right?
play_sound(60);
which_m->spell_note(49);
which_m->spell_note(eSpellNote::BREAKS_BARRIER);
univ.town.set_fire_barr(where_check.x,where_check.y,false);
}
else {
@@ -982,7 +982,7 @@ static bool monst_check_one_special_terrain(location where_check,short mode,shor
&& (!univ.town->strong_barriers)) {
// Monster breaks the barrier
play_sound(60);
which_m->spell_note(49);
which_m->spell_note(eSpellNote::BREAKS_BARRIER);
univ.town.set_force_barr(where_check.x,where_check.y,false);
}
else can_enter = false;
@@ -1094,11 +1094,11 @@ void record_monst(cCreature* which_m, bool forced) {
// TODO: Are these two sounds right?
else if(r1 > cCreature::charm_odds[which_m->level / 2] || which_m->abil[eMonstAbil::SPLITS].active
|| which_m->m_type == eRace::IMPORTANT) {
which_m->spell_note(10);
which_m->spell_note(eSpellNote::RESISTS);
play_sound(68);
}
else {
which_m->spell_note(24);
which_m->spell_note(eSpellNote::RECORDED);
r1 = get_ran(1,0,univ.party.imprisoned_monst.size() - 1);
if(univ.party.imprisoned_monst[r1] == 0)
univ.party.imprisoned_monst[r1] = which_m->number;
@@ -1183,7 +1183,7 @@ bool summon_monster(mon_num_t which,location where,short duration,eAttitude give
univ.town.monst[spot].summon_time = duration;
univ.town.monst[spot].party_summoned = by_party;
univ.town.monst[spot].spell_note(21);
univ.town.monst[spot].spell_note(eSpellNote::SUMMONED);
return true;
}

View File

@@ -1520,7 +1520,7 @@ void do_mindduel(short pc_num,cCreature *monst) {
balance--;
if(monst->mp == 0) {
monst->status[eStatus::DUMB] += 2;
monst->spell_note(22);
monst->spell_note(eSpellNote::DUMBFOUNDED);
if(monst->status[eStatus::DUMB] > 7) {
kill_monst(*monst,pc_num);
}

View File

@@ -1512,7 +1512,7 @@ short damage_monst(cCreature& victim, short who_hit, short how_much, eDamageType
if(how_much <= 0) {
if(is_combat())
victim.spell_note(7);
victim.spell_note(eSpellNote::UNDAMAGED);
if(how_much <= 0 && (dam_type == eDamageType::WEAPON || dam_type == eDamageType::UNDEAD || dam_type == eDamageType::DEMON)) {
draw_terrain(2);
play_sound(2);
@@ -1536,7 +1536,7 @@ short damage_monst(cCreature& victim, short who_hit, short how_much, eDamageType
if((which_spot = place_monster(victim.number,where_put)) < univ.town.monst.size()) {
static_cast<cTownperson&>(univ.town.monst[which_spot]) = victim;
univ.town.monst[which_spot].health = victim.health;
victim.spell_note(27);
victim.spell_note(eSpellNote::SPLITS);
}
}
if(who_hit < 7)
@@ -1555,7 +1555,7 @@ short damage_monst(cCreature& victim, short who_hit, short how_much, eDamageType
}
if(victim.health < 0) {
victim.killed_msg();
victim.spell_note(eSpellNote::DIES);
kill_monst(victim,who_hit);
}
else {
@@ -1580,7 +1580,7 @@ short damage_monst(cCreature& victim, short who_hit, short how_much, eDamageType
}
void petrify_monst(cCreature& which_m,int strength) {
which_m.spell_note(9);
which_m.spell_note(eSpellNote::GAZES);
short r1 = get_ran(1,0,20);
r1 += which_m.level / 4;
r1 += which_m.status[eStatus::BLESS_CURSE];
@@ -1588,9 +1588,9 @@ void petrify_monst(cCreature& which_m,int strength) {
// TODO: This should probably do something similar to charm_monst with the magic resistance
if(r1 > 14 || which_m.resist[eDamageType::MAGIC] == 0)
which_m.spell_note(10);
which_m.spell_note(eSpellNote::RESISTS);
else {
which_m.spell_note(8);
which_m.spell_note(eSpellNote::STONED);
kill_monst(which_m,7,eMainStatus::STONE);
}
}
@@ -2863,8 +2863,8 @@ void affect_spec(const runtime_state& ctx) {
else pc.heal(-spec.ex1a);
if(cCreature* who = dynamic_cast<cCreature*>(&pc)) {
if(spec.ex1b == 0)
who->spell_note(41);
else who->spell_note(42);
who->spell_note(eSpellNote::HEALED);
else who->spell_note(eSpellNote::DRAINED_HP);
}
break;
case eSpecType::AFFECT_SP:
@@ -2873,8 +2873,8 @@ void affect_spec(const runtime_state& ctx) {
else pc.drain_sp(spec.ex1a, spec.ex1c);
if(cCreature* who = dynamic_cast<cCreature*>(&pc)) {
if(spec.ex1b == 0)
who->spell_note(43);
else who->spell_note(44);
who->spell_note(eSpellNote::SP_RECHARGED);
else who->spell_note(eSpellNote::DRAINED_SP);
}
break;
case eSpecType::AFFECT_XP:
@@ -2944,18 +2944,18 @@ void affect_spec(const runtime_state& ctx) {
if(who.is_alive() && spec.ex1b > 0) {
switch(spec.ex1a) {
case 0:
who.spell_note(46);
who.spell_note(eSpellNote::DIES);
kill_monst(who,7,eMainStatus::DEAD);
break;
case 1:
who.spell_note(51);
who.spell_note(eSpellNote::OBLITERATED);
kill_monst(who,7,eMainStatus::DUST);
break;
case 2:
if(spec.ex1c > 0)
petrify_monst(who,spec.ex1c);
else {
who.spell_note(8);
who.spell_note(eSpellNote::STONED);
kill_monst(who,7,eMainStatus::STONE);
}
break;
@@ -2967,7 +2967,7 @@ void affect_spec(const runtime_state& ctx) {
// Bring back to life
else if(who.active == eCreatureStatus::DEAD && spec.ex1b == 0) {
who.active = eCreatureStatus::IDLE;
who.spell_note(45);
who.spell_note(eSpellNote::REVIVED);
}
}
break;

View File

@@ -132,9 +132,9 @@ void cCreature::poison(int how_much) {
}
apply_status(eStatus::POISON, how_much);
if(how_much >= 0)
spell_note((how_much == 0) ? 10 : 4);
spell_note((how_much == 0) ? eSpellNote::RESISTS : eSpellNote::POISONED);
else
spell_note(34);
spell_note(eSpellNote::CURED);
}
@@ -142,18 +142,18 @@ void cCreature::acid(int how_much) {
how_much = magic_adjust(how_much);
apply_status(eStatus::ACID, how_much);
if(how_much >= 0)
spell_note(31);
spell_note(eSpellNote::ACID);
else
spell_note(48);
spell_note(eSpellNote::CLEANS_ACID);
}
void cCreature::slow(int how_much) {
how_much = magic_adjust(how_much);
apply_status(eStatus::HASTE_SLOW, -how_much);
if(how_much >= 0)
spell_note((how_much == 0) ? 10 : 2);
spell_note((how_much == 0) ? eSpellNote::RESISTS : eSpellNote::SLOWED);
else
spell_note(35);
spell_note(eSpellNote::HASTED);
}
@@ -161,9 +161,9 @@ void cCreature::curse(int how_much) {
how_much = magic_adjust(how_much);
apply_status(eStatus::BLESS_CURSE, -how_much);
if(how_much >= 0)
spell_note((how_much == 0) ? 10 : 5);
spell_note((how_much == 0) ? eSpellNote::RESISTS : eSpellNote::CURSED);
else
spell_note(36);
spell_note(eSpellNote::BLESSED);
}
@@ -171,9 +171,9 @@ void cCreature::web(int how_much) {
how_much = magic_adjust(how_much);
apply_status(eStatus::WEBS, how_much);
if(how_much >= 0)
spell_note((how_much == 0) ? 10 : 19);
spell_note((how_much == 0) ? eSpellNote::RESISTS : eSpellNote::WEBBED);
else
spell_note(37);
spell_note(eSpellNote::CLEANS_WEBS);
}
@@ -181,9 +181,9 @@ void cCreature::scare(int how_much) {
how_much = magic_adjust(how_much);
morale -= how_much;
if(how_much >= 0)
spell_note((how_much == 0) ? 10 : 1);
spell_note((how_much == 0) ? eSpellNote::RESISTS : eSpellNote::SCARED);
else
spell_note(47);
spell_note(eSpellNote::RALLIES);
}
@@ -191,9 +191,9 @@ void cCreature::disease(int how_much) {
how_much = magic_adjust(how_much);
apply_status(eStatus::DISEASE, how_much);
if(how_much >= 0)
spell_note((how_much == 0) ? 10 : 25);
spell_note((how_much == 0) ? eSpellNote::RESISTS : eSpellNote::DISEASED);
else
spell_note(38);
spell_note(eSpellNote::FEEL_BETTER);
}
@@ -201,9 +201,9 @@ void cCreature::dumbfound(int how_much) {
how_much = magic_adjust(how_much);
apply_status(eStatus::DUMB, how_much);
if(how_much >= 0)
spell_note((how_much == 0) ? 10 : 22);
spell_note((how_much == 0) ? eSpellNote::RESISTS : eSpellNote::DUMBFOUNDED);
else
spell_note(39);
spell_note(eSpellNote::MIND_CLEAR);
}
@@ -237,24 +237,24 @@ void cCreature::sleep(eStatus which_status,int amount,int penalty) {
if(r1 > charm_odds[level / 2]) {
//one_sound(68);
spell_note(10);
spell_note(eSpellNote::RESISTS);
}
else {
if(which_status == eStatus::CHARM) {
if(amount <= 0 || amount > 3) amount = 2;
attitude = eAttitude(amount);
spell_note(23);
spell_note(eSpellNote::CHARMED);
} else if(which_status == eStatus::FORCECAGE) {
status[eStatus::FORCECAGE] = amount;
spell_note(52);
spell_note(eSpellNote::TRAPPED);
} else {
status[which_status] = amount;
if(which_status == eStatus::ASLEEP && (amount >= 0))
spell_note(28);
spell_note(eSpellNote::ASLEEP);
if(which_status == eStatus::PARALYZED && (amount >= 0))
spell_note(30);
spell_note(eSpellNote::PARALYZED);
if(amount < 0)
spell_note(40);
spell_note(eSpellNote::ALERT);
}
//one_sound(53);
}
@@ -283,6 +283,10 @@ location cCreature::get_loc() const {
return cur_loc;
}
std::string cCreature::get_name() const {
return m_name;
}
bool cCreature::is_shielded() const {
if(status[eStatus::MARTYRS_SHIELD] > 0)
return true;
@@ -385,236 +389,3 @@ void cCreature::readFrom(const cTagFile_Page& page) {
page["DIRECTION"] >> direction;
active = alert ? eCreatureStatus::ALERTED : eCreatureStatus::IDLE;
}
void cCreature::print_attacks(iLiving* target) const {
if(!print_result) return;
std::string msg = m_name;
msg += " attacks ";
if(cPlayer* who = dynamic_cast<cPlayer*>(target))
msg += who->name;
else if(cCreature* monst = dynamic_cast<cCreature*>(target))
msg += monst->m_name;
else msg += "you";
print_result(msg);
}
void cCreature::spell_note(int which_mess) const {
if(!print_result) return;
std::string msg = m_name;
switch(which_mess) {
case 1:
msg = " " + msg + " scared.";
break;
case 2:
msg = " " + msg + " slowed.";
break;
case 3:
msg = " " + msg + " weakened.";
break;
case 4:
msg = " " + msg + " poisoned.";
break;
case 5:
msg = " " + msg + " cursed.";
break;
case 6:
msg = " " + msg + " ravaged.";
break;
case 7:
msg = " " + msg + " undamaged.";
break;
case 8:
msg = " " + msg + " is stoned.";
break;
case 9:
msg = " Gazes at " + msg + '.';
break;
case 10:
msg = " " + msg + " resists.";
break;
case 11:
msg = " Drains " + msg + '.';
break;
case 12:
msg = " Shoots at " + msg + '.';
break;
case 13:
msg = " Throws spear at " + msg + '.';
break;
case 14:
msg = " Throws rock at " + msg + '.';
break;
case 15:
msg = " Throws razordisk at " + msg + '.';
break;
case 16:
msg = " Hits " + msg + '.';
break;
case 17:
msg = " " + msg + " disappears.";
break;
case 18:
msg = " Misses " + msg + '.';
break;
case 19:
msg = " " + msg + " is webbed.";
break;
case 20:
msg = " " + msg + " chokes.";
break;
case 21:
msg = " " + msg + " summoned.";
break;
case 22:
msg = " " + msg + " is dumbfounded.";
break;
case 23:
msg = " " + msg + " is charmed.";
break;
case 24:
msg = " " + msg + " is recorded.";
break;
case 25:
msg = " " + msg + " is diseased.";
break;
case 26:
msg = " " + msg + " is an avatar!";
break;
case 27:
msg = " " + msg + " splits!";
break;
case 28:
msg = " " + msg + " falls asleep.";
break;
case 29:
msg = " " + msg + " wakes up.";
break;
case 30:
msg = " " + msg + " paralyzed.";
break;
case 31:
msg = " " + msg + " covered with acid.";
break;
case 32:
msg = " Fires spines at " + msg + '.';
break;
case 33:
msg = " " + msg + " summons aid.";
break;
case 34:
msg = " " + msg + " is cured.";
break;
case 35:
msg = " " + msg + " is hasted.";
break;
case 36:
msg = " " + msg + " is blessed.";
break;
case 37:
msg = " " + msg + " cleans webs.";
break;
case 38:
msg = " " + msg + " feels better.";
break;
case 39:
msg = " " + msg + " mind cleared.";
break;
case 40:
msg = " " + msg + " feels alert.";
break;
case 41:
msg = " " + msg + " is healed.";
break;
case 42:
msg = " " + msg + " drained of health.";
break;
case 43:
msg = " " + msg + " magic recharged.";
break;
case 44:
msg = " " + msg + " drained of magic.";
break;
case 45:
msg = " " + msg + " returns to life!";
break;
case 46:
msg = " " + msg + " dies.";
break;
case 47:
msg = " " + msg + " rallies its courage.";
break;
case 48:
msg = " " + msg + " cleans off acid.";
break;
case 49:
msg = " " + msg + " breaks barrier.";
break;
case 50:
msg = " " + msg + " breaks force cage.";
break;
case 51:
msg = " " + msg + " is obliterated!";
break;
case 52:
msg = " " + msg + " is trapped!";
break;
case 53:
msg = " Throws dart at " + msg + '.';
break;
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;
default:
msg += ": Unknown action " + std::to_string(which_mess);
}
if(which_mess > 0)
print_result((char *) msg.c_str());
}
void cCreature::cast_spell_note(eSpell spell) const {
if(!print_result) return;
print_result(m_name + " casts:");
print_result(" " + (*spell).name());
}
void cCreature::breathe_note() const {
if(!print_result) return;
print_result(m_name + " breathes.");
}
void cCreature::damaged_msg(int how_much,int how_much_spec) const {
if(!print_result) return;
std::ostringstream sout;
sout << " " << m_name << " takes " << how_much;
if(how_much_spec > 0)
sout << '+' << how_much_spec;
print_result(sout.str());
}
void cCreature::killed_msg() const {
if(!print_result) return;
print_result(" " + m_name + " dies.");
}

View File

@@ -61,15 +61,10 @@ public:
bool is_shielded() const override;
int get_shared_dmg(int base_dmg) const override;
location get_loc() const override;
std::string get_name() const override;
int magic_adjust(int base);
void spell_note(int which) const;
void cast_spell_note(eSpell spell) const;
void print_attacks(iLiving* target) const;
void breathe_note() const;
void damaged_msg(int how_much, int extra) const;
void killed_msg() const;
bool on_space(location loc) const;
void import_legacy(legacy::creature_data_type old);

View File

@@ -10,6 +10,7 @@
#include <algorithm>
#include <tuple>
#include <fmt/format.h>
#include "mathutil.hpp"
void iLiving::apply_status(eStatus which, int how_much) {
@@ -63,3 +64,224 @@ iLiving::iLiving(const iLiving& other)
{}
void(* iLiving::print_result)(std::string) = nullptr;
void iLiving::spell_note(eSpellNote which_mess) const {
if(!print_result) return;
std::string msg;
switch(which_mess) {
case eSpellNote::SCARED:
msg = " {} scared.";
break;
case eSpellNote::SLOWED:
msg = " {} slowed.";
break;
case eSpellNote::WEAKENED:
msg = " {} weakened.";
break;
case eSpellNote::POISONED:
msg = " {} poisoned.";
break;
case eSpellNote::CURSED:
msg = " {} cursed.";
break;
case eSpellNote::RAVAGED:
msg = " {} ravaged.";
break;
case eSpellNote::UNDAMAGED:
msg = " {} undamaged.";
break;
case eSpellNote::STONED:
msg = " {} is stoned.";
break;
case eSpellNote::GAZES:
msg = " Gazes at {}.";
break;
case eSpellNote::RESISTS:
msg = " {} resists.";
break;
case eSpellNote::DRAINS:
msg = " Drains {}.";
break;
case eSpellNote::SHOOTS:
msg = " Shoots at {}.";
break;
case eSpellNote::THROWS_SPEAR:
msg = " Throws spear at {}.";
break;
case eSpellNote::THROWS_ROCK:
msg = " Throws rock at {}.";
break;
case eSpellNote::THROWS_RAZORDISK:
msg = " Throws razordisk at {}.";
break;
case eSpellNote::HITS:
msg = " Hits {}.";
break;
case eSpellNote::DISAPPEARS:
msg = " {} disappears.";
break;
case eSpellNote::MISSES:
msg = " Misses {}.";
break;
case eSpellNote::WEBBED:
msg = " {} is webbed.";
break;
case eSpellNote::CHOKES:
msg = " {} chokes.";
break;
case eSpellNote::SUMMONED:
msg = " {} summoned.";
break;
case eSpellNote::DUMBFOUNDED:
msg = " {} is dumbfounded.";
break;
case eSpellNote::CHARMED:
msg = " {} is charmed.";
break;
case eSpellNote::RECORDED:
msg = " {} is recorded.";
break;
case eSpellNote::DISEASED:
msg = " {} is diseased.";
break;
case eSpellNote::AVATAR:
msg = " {} is an avatar!";
break;
case eSpellNote::SPLITS:
msg = " {} splits!";
break;
case eSpellNote::ASLEEP:
msg = " {} falls asleep.";
break;
case eSpellNote::AWAKE:
msg = " {} wakes up.";
break;
case eSpellNote::PARALYZED:
msg = " {} paralyzed.";
break;
case eSpellNote::ACID:
msg = " {} covered with acid.";
break;
case eSpellNote::SPINES:
msg = " Fires spines at {}.";
break;
case eSpellNote::SUMMONS:
msg = " {} summons aid.";
break;
case eSpellNote::CURED:
msg = " {} is cured.";
break;
case eSpellNote::HASTED:
msg = " {} is hasted.";
break;
case eSpellNote::BLESSED:
msg = " {} is blessed.";
break;
case eSpellNote::CLEANS_WEBS:
msg = " {} cleans webs.";
break;
case eSpellNote::FEEL_BETTER:
msg = " {} feels better.";
break;
case eSpellNote::MIND_CLEAR:
msg = " {} mind cleared.";
break;
case eSpellNote::ALERT:
msg = " {} feels alert.";
break;
case eSpellNote::HEALED:
msg = " {} is healed.";
break;
case eSpellNote::DRAINED_HP:
msg = " {} drained of health.";
break;
case eSpellNote::SP_RECHARGED:
msg = " {} magic recharged.";
break;
case eSpellNote::DRAINED_SP:
msg = " {} drained of magic.";
break;
case eSpellNote::REVIVED:
msg = " {} returns to life!";
break;
case eSpellNote::DIES:
msg = " {} dies.";
break;
case eSpellNote::RALLIES:
msg = " {} rallies its courage.";
break;
case eSpellNote::CLEANS_ACID:
msg = " {} cleans off acid.";
break;
case eSpellNote::BREAKS_BARRIER:
msg = " {} breaks barrier.";
break;
case eSpellNote::BREAKS_FORCECAGE:
msg = " {} breaks force cage.";
break;
case eSpellNote::OBLITERATED:
msg = " {} is obliterated!";
break;
case eSpellNote::TRAPPED:
msg = " {} is trapped!";
break;
case eSpellNote::THROWS_DART:
msg = " Throws dart at {}.";
break;
case eSpellNote::THROWS_KNIFE:
msg = " Throws knife at {}.";
break;
case eSpellNote::FIRES_RAY:
msg = " Fires ray at {}.";
break;
case eSpellNote::GAZES2:
msg = " Gazes at {}.";
break;
case eSpellNote::BREATHES_ON:
msg = " Breathes on {}.";
break;
case eSpellNote::THROWS_WEB:
msg = " Throws web at {}.";
break;
case eSpellNote::SPITS:
msg = " Spits at {}.";
break;
case eSpellNote::BREATHES:
msg = " {} breaths.";
break;
default:
msg += "{}: Unknown action " + std::to_string(int(which_mess));
}
if(which_mess != eSpellNote::NONE)
print_result(fmt::format(msg, get_name()));
}
void iLiving::print_attacks(const iLiving& target) const {
if(!print_result) return;
std::string target_name;
if(&target == this) {
target_name = "themself";
} else target_name = target.get_name();
print_result(fmt::format("{} attacks {}", get_name(), target_name));
}
void iLiving::cast_spell_note(eSpell spell) const {
if(!print_result) return;
print_result(fmt::format("{} casts:", get_name()));
print_result(fmt::format(" {}", (*spell).name()));
}
void iLiving::damaged_msg(int how_much,int how_much_spec) const {
if(!print_result) return;
if(how_much_spec > 0)
print_result(fmt::format(" {} takes {}+{}", get_name(), how_much, how_much_spec));
else print_result(fmt::format(" {} takes {}", get_name(), how_much));
}

View File

@@ -14,6 +14,23 @@
#include "location.hpp"
#include "damage.hpp"
#include "spell.hpp"
enum class eSpellNote {
NONE = 0,
SCARED = 1, SLOWED = 2, WEAKENED = 3, POISONED = 4, CURSED = 5,
RAVAGED = 6, UNDAMAGED = 7, STONED = 8, GAZES = 9, RESISTS = 10,
DRAINS = 11, SHOOTS = 12, THROWS_SPEAR = 13, THROWS_ROCK = 14, THROWS_RAZORDISK = 15,
HITS = 16, DISAPPEARS = 17, MISSES = 18, WEBBED = 19, CHOKES = 20,
SUMMONED = 21, DUMBFOUNDED = 22, CHARMED = 23, RECORDED = 24, DISEASED = 25,
AVATAR = 26, SPLITS = 27, ASLEEP = 28, AWAKE = 29, PARALYZED = 30,
ACID = 31, SPINES = 32, SUMMONS = 33, CURED = 34, HASTED = 35,
BLESSED = 36, CLEANS_WEBS = 37, FEEL_BETTER = 38, MIND_CLEAR = 39, ALERT = 40,
HEALED = 41, DRAINED_HP = 42, SP_RECHARGED = 43, DRAINED_SP = 44, REVIVED = 45,
DIES = 46, RALLIES = 47, CLEANS_ACID = 48, BREAKS_BARRIER = 49, BREAKS_FORCECAGE = 50,
OBLITERATED = 51, TRAPPED = 52, THROWS_DART = 53, THROWS_KNIFE = 54, FIRES_RAY = 55,
GAZES2 = 56, BREATHES_ON = 57, THROWS_WEB = 58, SPITS = 59, BREATHES = 60,
};
class iLiving {
public:
@@ -53,6 +70,12 @@ public:
virtual int get_magic() const = 0;
virtual int get_level() const = 0;
virtual location get_loc() const = 0;
virtual std::string get_name() const = 0;
void spell_note(eSpellNote note) const;
void cast_spell_note(eSpell spell) const;
void print_attacks(const iLiving& target) const;
void damaged_msg(int how_much, int extra) const;
iLiving();
iLiving(const iLiving& other);

View File

@@ -575,6 +575,10 @@ location cParty::get_loc() const {
return town_loc;
}
std::string cParty::get_name() const {
return "you";
}
int cParty::calc_day() const {
return (age / 3700) + 1;
}

View File

@@ -163,6 +163,7 @@ public:
bool is_shielded() const override;
int get_shared_dmg(int base_dmg) const override;
location get_loc() const override;
std::string get_name() const override;
void apply_status(eStatus which, int how_much) override;
void heal(int how_much) override;

View File

@@ -398,6 +398,10 @@ location cPlayer::get_loc() const {
return combat_pos;
}
std::string cPlayer::get_name() const {
return name;
}
int cPlayer::get_health() const {
return cur_health;
}
@@ -1388,4 +1392,4 @@ void cPlayer::readFrom(const cTagFile& file, bool preview) {
items[i].readFrom(page);
}
}
}
}

View File

@@ -132,6 +132,7 @@ public:
int get_magic() const override;
int get_level() const override;
location get_loc() const override;
std::string get_name() const override;
void finish_create();
void void_sanctuary() override;